Skip to content

Commit 7d5f5b3

Browse files
authored
chore: Update the assertClose in test (#617)
port: google/go-jsonnet#855
1 parent dec7e3e commit 7d5f5b3

3 files changed

Lines changed: 46 additions & 10 deletions

File tree

sjsonnet/test/resources/go_test_suite/stdlib_smoke_test.jsonnet

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,30 @@
66
// and the other with all of them.
77

88
local assertClose(a, b) =
9+
// Using 1e-12 as tolerance. Jsonnet uses double-precision floats with machine epsilon of 2**-53 ≈ 1.11e-16.
10+
// This tolerance is ~9000x the machine epsilon, which is quite lenient and should work across
11+
// different platforms and math libraries.
12+
//
13+
// We use a combination of absolute and relative error to handle both small and large values:
14+
// - For values near zero, we use absolute error to avoid division issues
15+
// - For larger values, we use relative error to maintain precision
16+
//
17+
// This correctly handles cases like:
18+
// assertClose(1e-15, 0) - should pass (both are essentially zero)
19+
// assertClose(-100, 0) - should fail (significant difference)
20+
// assertClose(std.sin(std.pi), 0) - should pass (tiny floating point error)
21+
local abs_a = std.abs(a);
22+
local abs_b = std.abs(b);
23+
local diff = std.abs(a - b);
24+
local max_abs = std.max(abs_a, abs_b);
925
local err =
10-
if b == 0 then
11-
a - b
26+
if abs_a == 0 && abs_b == 0 then
27+
0 // Both are exactly zero, so no error
28+
else if max_abs < 1e-12 then
29+
diff // For very small values, use absolute error
1230
else
13-
if a / b - 1 > 0 then a / b - 1 else 1 - a / b;
14-
if err > 0.000005 then
31+
diff / max_abs; // For larger values, use relative error
32+
if err > 1e-12 then
1533
error 'Assertion failed (error ' + err + '). ' + a + ' !~ ' + b
1634
else
1735
true;
@@ -61,7 +79,7 @@ local assertClose(a, b) =
6179
mantissa: std.mantissa(x=5),
6280
floor: std.floor(x=5),
6381
ceil: std.ceil(x=5),
64-
sqrt: std.sqrt(x=5),
82+
sqrt: std.assertEqual(std.sqrt(x=5), 2.23606797749979),
6583
sin: assertClose(std.sin(x=5), -0.9589242746631385),
6684
cos: assertClose(std.cos(x=5), 0.28366218546322625),
6785
tan: assertClose(std.tan(x=5), -3.380515006246586),

sjsonnet/test/resources/go_test_suite/stdlib_smoke_test.jsonnet.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@
249249
"a,b",
250250
"c"
251251
],
252-
"sqrt": 2.23606797749979,
252+
"sqrt": true,
253253
"startsWith": true,
254254
"strReplace": "bba",
255255
"stringChars": [

sjsonnet/test/resources/test_suite/stdlib.jsonnet

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,30 @@ std.assertEqual(std.makeArray(10, function(i) i + 1), [1, 2, 3, 4, 5, 6, 7, 8, 9
3333
std.assertEqual(std.makeArray(0, function(i) null), []) &&
3434

3535
local assertClose(a, b) =
36+
// Using 1e-12 as tolerance. Jsonnet uses double-precision floats with machine epsilon of 2**-53 ≈ 1.11e-16.
37+
// This tolerance is ~9000x the machine epsilon, which is quite lenient and should work across
38+
// different platforms and math libraries.
39+
//
40+
// We use a combination of absolute and relative error to handle both small and large values:
41+
// - For values near zero, we use absolute error to avoid division issues
42+
// - For larger values, we use relative error to maintain precision
43+
//
44+
// This correctly handles cases like:
45+
// assertClose(1e-15, 0) - should pass (both are essentially zero)
46+
// assertClose(-100, 0) - should fail (significant difference)
47+
// assertClose(std.sin(std.pi), 0) - should pass (tiny floating point error)
48+
local abs_a = std.abs(a);
49+
local abs_b = std.abs(b);
50+
local diff = std.abs(a - b);
51+
local max_abs = std.max(abs_a, abs_b);
3652
local err =
37-
if b == 0 then
38-
a - b
53+
if abs_a == 0 && abs_b == 0 then
54+
0 // Both are exactly zero, so no error
55+
else if max_abs < 1e-12 then
56+
diff // For very small values, use absolute error
3957
else
40-
if a / b - 1 > 0 then a / b - 1 else 1 - a / b;
41-
if err > 0.000005 then
58+
diff / max_abs; // For larger values, use relative error
59+
if err > 1e-12 then
4260
error 'Assertion failed (error ' + err + '). ' + a + ' !~ ' + b
4361
else
4462
true;

0 commit comments

Comments
 (0)