Skip to content

Commit 8fb7d53

Browse files
Merge pull request #1878 from ChrisRackauckas-Claude/fix-ci-reference-tests
Make order-dependent build-target & latexify reference tests order-invariant
2 parents 547c518 + 61e65d1 commit 8fb7d53

6 files changed

Lines changed: 68 additions & 22 deletions

File tree

test/build_targets.jl

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,65 @@
11
using Symbolics, Test
22
using ReferenceTests
33

4+
# The ordering of operands within commutative `+` and `*` in the generated code
5+
# follows SymbolicUtils' argument sorting, which is benign but has changed across
6+
# versions (e.g. `a * b` vs `b * a`). To keep these tests stable across the CI
7+
# Julia/SymbolicUtils matrix we compare structure modulo that ordering rather than
8+
# byte-for-byte against a reference file. This mirrors the scalar Stan/MATLAB
9+
# tests further down, which were already converted for the same reason.
10+
function normalize_terms(rhs)
11+
summands = map(strip, split(rhs, " + "))
12+
canonical = map(summands) do summand
13+
join(sort(map(strip, split(summand, " * "))), " * ")
14+
end
15+
return sort(canonical)
16+
end
17+
418
@variables t a x(t) y(t)
519
expr = [a*x - x*y,-3y + x*y]
6-
@test_reference "target_functions/1.stan" Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.StanTarget())
720

8-
@test_reference "target_functions/1.c" Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.CTarget(),
21+
# StanTarget structural test (was target_functions/1.stan)
22+
let
23+
sfunc = Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.StanTarget())
24+
@test occursin("vector diffeqf(real t,vector internal_var___u,vector internal_var___p)", sfunc)
25+
@test occursin("vector[2] internal_var___du;", sfunc)
26+
@test occursin("return internal_var___du;", sfunc)
27+
m1 = match(r"internal_var___du\[1\] = (.+);", sfunc)
28+
m2 = match(r"internal_var___du\[2\] = (.+);", sfunc)
29+
@test m1 !== nothing && m2 !== nothing
30+
@test normalize_terms(m1[1]) ==
31+
normalize_terms("internal_var___p[1] * internal_var___u[1] + -1 * internal_var___u[1] * internal_var___u[2]")
32+
@test normalize_terms(m2[1]) ==
33+
normalize_terms("-3 * internal_var___u[2] + internal_var___u[1] * internal_var___u[2]")
34+
end
35+
36+
# CTarget structural test (was target_functions/1.c)
37+
let
38+
cfunc = Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.CTarget(),
939
lhsname=:internal_var___du,
1040
rhsnames=[:internal_var___u,:internal_var___p,:t])
41+
@test occursin("#include <math.h>", cfunc)
42+
@test occursin("void diffeqf(double* internal_var___du, const double* internal_var___u, const double* internal_var___p, const double t)", cfunc)
43+
m1 = match(r"internal_var___du\[0\] = (.+);", cfunc)
44+
m2 = match(r"internal_var___du\[1\] = (.+);", cfunc)
45+
@test m1 !== nothing && m2 !== nothing
46+
@test normalize_terms(m1[1]) ==
47+
normalize_terms("internal_var___p[0] * internal_var___u[0] + -1 * internal_var___u[0] * internal_var___u[1]")
48+
@test normalize_terms(m2[1]) ==
49+
normalize_terms("-3 * internal_var___u[1] + internal_var___u[0] * internal_var___u[1]")
50+
end
1151

12-
@test_reference "target_functions/1.m" Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.MATLABTarget())
52+
# MATLABTarget structural test (was target_functions/1.m)
53+
let
54+
mfunc = Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.MATLABTarget())
55+
@test occursin("diffeqf = @(internal_var___t,internal_var___u)", mfunc)
56+
rows = [m[1] for m in eachmatch(r"([^\[\];\n]+);", mfunc)]
57+
@test length(rows) == 2
58+
@test normalize_terms(rows[1]) ==
59+
normalize_terms("internal_var___p(1) * internal_var___u(1) + -1 * internal_var___u(1) * internal_var___u(2)")
60+
@test normalize_terms(rows[2]) ==
61+
normalize_terms("-3 * internal_var___u(2) + internal_var___u(1) * internal_var___u(2)")
62+
end
1363

1464
@test Symbolics.build_function(expr,[x,y],[a],t,target = Symbolics.CTarget(),
1565
lhsname=:internal_var___du,

test/latexify.jl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,21 @@ Dy = Differential(y)
4747

4848
@test_reference "latexify_refs/equation1.txt" latexify(x ~ y + z)
4949
@test_reference "latexify_refs/equation2.txt" latexify(x ~ Dx(y + z))
50-
@test_reference "latexify_refs/equation5.txt" latexify(AA^2 + AA + 1 + X₁)
50+
51+
# The relative order of the two degree-1 terms AA(x) and X₁(x) in this sum is
52+
# decided by SymbolicUtils' hash-based tie-break, which differs across Julia
53+
# versions, so no single reference string passes on all of them. Compare the set
54+
# of additive terms instead of the exact rendered string. (was equation5.txt)
55+
let
56+
body = strip(replace(string(latexify(AA^2 + AA + 1 + X₁)),
57+
"\\begin{equation}" => "", "\\end{equation}" => ""))
58+
@test sort(strip.(split(body, " + "))) == sort([
59+
"1",
60+
"AA\\left( x \\right)",
61+
"X_1\\left( x \\right)",
62+
"\\left( AA\\left( x \\right) \\right)^{2}",
63+
])
64+
end
5165

5266
@test_reference "latexify_refs/equation_vec1.txt" latexify(
5367
[

test/latexify_refs/equation5.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

test/target_functions/1.c

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/target_functions/1.m

Lines changed: 0 additions & 4 deletions
This file was deleted.

test/target_functions/1.stan

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)