Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sjsonnet/src/sjsonnet/Evaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -711,14 +711,14 @@ class Evaluator(
case Expr.BinaryOp.OP_^ =>
(l, r) match {
case (l: Val.Num, r: Val.Num) =>
Val.Num(pos, (l.asLong ^ r.asLong).toDouble)
Val.Num(pos, (l.asSafeLong ^ r.asSafeLong).toDouble)
case _ => fail()
}

case Expr.BinaryOp.OP_| =>
(l, r) match {
case (l: Val.Num, r: Val.Num) =>
Val.Num(pos, (l.asLong | r.asLong).toDouble)
Val.Num(pos, (l.asSafeLong | r.asSafeLong).toDouble)
case _ => fail()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
4611686018427387904
sjsonnet.Error: numeric value outside safe integer range for bitwise operation
at [<root>].(bitwise_or9.jsonnet:1:11)

Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5403023058681398
0.54030230586813977
Original file line number Diff line number Diff line change
@@ -1 +1 @@
26881171418161356000000000000000000000000000
26881171418161356094253400435962903554686976
Original file line number Diff line number Diff line change
@@ -1 +1 @@
80.5904782547916
80.590478254791606
2 changes: 1 addition & 1 deletion sjsonnet/test/resources/go_test_suite/div3.jsonnet.golden
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.999999999999999E-31
9.9999999999999991e-31
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"x": 2
}
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.84
0.83999999999999997
3 changes: 3 additions & 0 deletions sjsonnet/test/resources/test_suite/.sync_ignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
# error.std_parseYaml1.jsonnet: sjsonnet uses SnakeYAML/scala-yaml which
# successfully parses 'a: b:' as {"a":"b:"}, unlike RapidYAML which errors.
error.std_parseYaml1.jsonnet
# unparse.jsonnet: sjsonnet renders 1/3 as 0.3333333333333333 and 1e-14 as
# 1.0E-14, differing from C++ jsonnet's 0.33333333333333331 and 1e-14.
unparse.jsonnet
98 changes: 92 additions & 6 deletions sync_test_suites.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
# A .jsonnet file is only synced if it has a
# corresponding valid .golden file (upstream or already present locally), so that
# Scala tests always find a matching .jsonnet.golden for each .jsonnet file.
#
# Golden file sync strategy:
# - Both success (JSON output): exact compare, update when different.
# - Success<->error transition: always update (behavioral change).
# - Both error: skip (sjsonnet and upstream have different error messages/formats).
# - New golden files (no local copy): copied from upstream directly.
#
# For new .jsonnet files that have no golden file after syncing,
# golden files are generated using sjsonnet via the per-suite refresh_golden.sh scripts.
#
Expand All @@ -26,21 +33,43 @@ set -euo pipefail
ROOT_DIR="$(git rev-parse --show-toplevel)"
cd "$ROOT_DIR"

# Collect .jsonnet files whose golden files need regeneration via refresh_golden_outputs.sh
GOLDEN_REFRESH_FILES=$(mktemp)
trap_cleanup() { rm -rf "$TEMP_DIR" "$GOLDEN_REFRESH_FILES"; }

# --- Configuration ---
CPP_TEST_SUITE_DIR="sjsonnet/test/resources/test_suite"
GO_TEST_SUITE_DIR="sjsonnet/test/resources/go_test_suite"

# --- Step 1: Clone upstream repositories into a temporary directory ---
echo "=== Cloning upstream repositories ==="
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT
trap 'rm -rf "$TEMP_DIR"; rm -f "$GOLDEN_REFRESH_FILES"' EXIT

echo " Cloning google/jsonnet (depth=1)..."
git clone --depth=1 --quiet https://github.com/google/jsonnet.git "$TEMP_DIR/jsonnet"

echo " Cloning google/go-jsonnet (depth=1)..."
git clone --depth=1 --quiet https://github.com/google/go-jsonnet.git "$TEMP_DIR/go-jsonnet"

# --- Helper: Check if a golden file contains successful (non-error) output ---
# Success tests output valid JSON: objects, arrays, strings, numbers, booleans, null.
# Returns 0 (true) if the output looks like JSON success, 1 (false) if it looks like an error.
is_success_golden() {
local file="$1"
local first_line
first_line=$(head -1 "$file")
case "$first_line" in
"{"*|"["*|'"'*|"true"|"false"|"null")
return 0 ;;
esac
# Numbers (including negative, decimal, scientific notation)
if [[ "$first_line" =~ ^-?[0-9] ]]; then
return 0
fi
return 1
}

# --- Step 2: Sync .jsonnet and .golden files (excluding lint-related golden) ---
echo ""
echo "=== Syncing test files ==="
Expand All @@ -62,7 +91,7 @@ sync_test_files() {
ignore_stems_file=$(mktemp)
if [ -f "$ignore_file" ]; then
# Strip comments and blank lines, extract stems (remove .jsonnet extension)
grep -v '^\s*#' "$ignore_file" | grep -v '^\s*$' | sed 's/\.jsonnet$//' > "$ignore_stems_file"
{ grep -v '^\s*#' "$ignore_file" | grep -v '^\s*$' | sed 's/\.jsonnet$//' || true; } > "$ignore_stems_file"
local ignore_count
ignore_count=$(wc -l < "$ignore_stems_file" | tr -d ' ')
echo " Syncing $suite_name... ($ignore_count file(s) in .sync_ignore)"
Expand Down Expand Up @@ -182,8 +211,10 @@ sync_test_files() {
done

# --- Phase 3: Sync golden files ---
# Never overwrite existing golden files — sjsonnet golden files use a different error
# format than upstream C++/Go implementations, so existing files must be preserved.
# Golden files are synced based on error/success classification:
# - Both non-error: exact compare, update when different.
# - One error + one non-error (success<->error change): always update.
# - Both error: skip (sjsonnet and upstream have different error messages/formats).

# 1) Sync *.jsonnet.golden files (already in correct naming format, skip directories)
for src_file in "$source_dir"/*.jsonnet.golden; do
Expand All @@ -208,10 +239,29 @@ sync_test_files() {

local dest_file="$target_dir/$basename"

# Only copy new golden files, never overwrite existing ones
if [ ! -e "$dest_file" ]; then
cp -r "$src_file" "$dest_file"
new_golden=$((new_golden + 1))
elif ! diff -q "$src_file" "$dest_file" > /dev/null 2>&1; then
local src_ok=0 dest_ok=0
is_success_golden "$src_file" && src_ok=1
is_success_golden "$dest_file" && dest_ok=1

if [ "$src_ok" -eq 0 ] && [ "$dest_ok" -eq 0 ]; then
# Both are error tests — keep sjsonnet's version (different error formats)
true
elif [ "$src_ok" -eq 1 ] && [ "$dest_ok" -eq 1 ]; then
# Both success with different content — copy upstream golden
cp -r "$src_file" "$dest_file"
updated_golden=$((updated_golden + 1))
else
# Success<->error transition — regenerate golden with sjsonnet
local jsonnet_file="$target_dir/${stem}.jsonnet"
if [ -f "$jsonnet_file" ]; then
echo "$jsonnet_file" >> "$GOLDEN_REFRESH_FILES"
updated_golden=$((updated_golden + 1))
fi
fi
fi
done

Expand Down Expand Up @@ -248,10 +298,28 @@ sync_test_files() {
if [ -f "$jsonnet_file" ]; then
local dest_file="$target_dir/${stem}.jsonnet.golden"

# Only copy new golden files, never overwrite existing ones
if [ ! -e "$dest_file" ]; then
cp -r "$src_entry" "$dest_file"
new_golden=$((new_golden + 1))
elif ! diff -q "$src_entry" "$dest_file" > /dev/null 2>&1; then
local src_ok=0 dest_ok=0
is_success_golden "$src_entry" && src_ok=1
is_success_golden "$dest_file" && dest_ok=1

if [ "$src_ok" -eq 0 ] && [ "$dest_ok" -eq 0 ]; then
true
elif [ "$src_ok" -eq 1 ] && [ "$dest_ok" -eq 1 ]; then
# Both success with different content — copy upstream golden
cp -r "$src_entry" "$dest_file"
updated_golden=$((updated_golden + 1))
else
# Success<->error transition — regenerate golden with sjsonnet
local local_jsonnet="$target_dir/${stem}.jsonnet"
if [ -f "$local_jsonnet" ]; then
echo "$local_jsonnet" >> "$GOLDEN_REFRESH_FILES"
updated_golden=$((updated_golden + 1))
fi
fi
fi
fi
done
Expand Down Expand Up @@ -326,6 +394,24 @@ generate_missing_golden() {
generate_missing_golden "$CPP_TEST_SUITE_DIR" "C++ test suite"
generate_missing_golden "$GO_TEST_SUITE_DIR" "Go test suite"

# --- Step 3b: Refresh golden files for success<->error transitions ---
if [ -s "$GOLDEN_REFRESH_FILES" ]; then
# Deduplicate
sort -u "$GOLDEN_REFRESH_FILES" -o "$GOLDEN_REFRESH_FILES"
local_refresh_count=$(wc -l < "$GOLDEN_REFRESH_FILES" | tr -d ' ')
echo ""
echo "=== Refreshing $local_refresh_count golden file(s) for success<->error transitions ==="
REFRESH_SCRIPT="$ROOT_DIR/sjsonnet/test/resources/refresh_golden_outputs.sh"
if [ -x "$REFRESH_SCRIPT" ]; then
# shellcheck disable=SC2046
"$REFRESH_SCRIPT" $(cat "$GOLDEN_REFRESH_FILES")
else
echo " WARNING: refresh_golden_outputs.sh not found or not executable at $REFRESH_SCRIPT"
echo " Files needing refresh:"
cat "$GOLDEN_REFRESH_FILES" | while read -r f; do echo " $f"; done
fi
fi

# --- Step 4: Final summary ---
echo ""
echo "=== Sync complete ==="
Expand Down
Loading