This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new c0d32bdf test: make JSON tests independent of the JSON backend's error
details (#1428)
c0d32bdf is described below
commit c0d32bdfbb2a2f7410e3714c3671ec81320f2b9c
Author: Matt Topol <[email protected]>
AuthorDate: Tue Oct 27 17:04:55 2026 +0000
test: make JSON tests independent of the JSON backend's error details
(#1428)
### Rationale for this change
The Dependabot bump of `github.com/goccy/go-json` to v0.11.2 (#1357)
fails CI. go-json 0.11 is stricter and follows `encoding/json`'s
behaviour for the Go version it is built with, which exposed three tests
that depended on lenient parsing or on backend-specific error details:
- `arrow/compute` `TestIsInDecimal`: the expected array literal is
`[true, false true]` (missing comma); go-json 0.10 accepted it.
- `arrow/array` `TestIntegerArrsJSON` and
`TestRecordBuilderUnmarshalOneReturnUnexpectedEOF`: under Go 1.27's v2
JSON semantics, truncated input is reported as a syntax error
("unexpected end of JSON input") instead of `io.ErrUnexpectedEOF`.
- `parquet/variant` `TestBuilderJSONErrors`: the error message depends
on which tokenizer call first notices the malformed input.
The last two already fail on `main` with the standard-library backend
(`-tags arrow_json_stdlib`, also used for TinyGo) under Go 1.27,
independent of the bump.
### What changes are included in this PR?
Test-only:
- Fix the JSON literal in `TestIsInDecimal`.
- A helper `assertTruncatedJSONError` checks that truncated input is an
error and **not** a clean `io.EOF` — the invariant #1341 added — while
accepting either `io.ErrUnexpectedEOF` or an "unexpected end of JSON
input" syntax error.
- `TestBuilderJSONErrors` keeps all its malformed inputs but only checks
that `ParseJSON` rejects them.
### Are these changes tested?
The affected packages (`arrow/array`, `arrow/compute`,
`parquet/variant`) pass with Go 1.26 and Go 1.27, each with go-json
v0.10.6, go-json v0.11.2 and `-tags arrow_json_stdlib`. Disabling the
`io.EOF` → `io.ErrUnexpectedEOF` conversion in
`RecordBuilder.unmarshalOne` still fails
`TestRecordBuilderUnmarshalOneReturnUnexpectedEOF` ("truncated input
must not be reported as a clean EOF").
### Are there any user-facing changes?
No.
---
arrow/array/util_test.go | 17 ++++++++++++++--
arrow/compute/scalar_set_lookup_test.go | 2 +-
parquet/variant/builder_test.go | 36 +++++++++++++++++----------------
3 files changed, 35 insertions(+), 20 deletions(-)
diff --git a/arrow/array/util_test.go b/arrow/array/util_test.go
index 652a3556..8c0bfe7a 100644
--- a/arrow/array/util_test.go
+++ b/arrow/array/util_test.go
@@ -245,7 +245,7 @@ func TestIntegerArrsJSON(t *testing.T) {
assert.Error(t, err)
_, _, err = array.FromJSON(memory.DefaultAllocator, tt,
strings.NewReader("["))
- assert.ErrorIs(t, err, io.ErrUnexpectedEOF)
+ assertTruncatedJSONError(t, err)
_, _, err = array.FromJSON(memory.DefaultAllocator, tt,
strings.NewReader("0"))
assert.Error(t, err)
@@ -918,6 +918,19 @@ func
TestRecordBuilderUnmarshalOnePreservesUserDecoderOptions(t *testing.T) {
assert.EqualValues(t, int64(9223372036854775807), col.Value(0))
}
+// assertTruncatedJSONError checks that truncated JSON input is reported as an
+// error rather than as a clean end of input. JSON backends differ in how they
+// report truncation: encoding/json before Go 1.27's v2 semantics (and go-json
+// before v0.11) surface io.ErrUnexpectedEOF, while the v2 semantics report a
+// syntax error describing the unexpected end of input.
+func assertTruncatedJSONError(t *testing.T, err error) {
+ t.Helper()
+ require.Error(t, err)
+ assert.False(t, errors.Is(err, io.EOF), "truncated input must not be
reported as a clean EOF: %v", err)
+ assert.True(t, errors.Is(err, io.ErrUnexpectedEOF) ||
strings.Contains(err.Error(), "unexpected end of JSON input"),
+ "expected an unexpected-end-of-input error, got %v", err)
+}
+
func TestRecordBuilderUnmarshalOneReturnUnexpectedEOF(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
defer mem.AssertSize(t, 0)
@@ -932,7 +945,7 @@ func TestRecordBuilderUnmarshalOneReturnUnexpectedEOF(t
*testing.T) {
src := strings.NewReader(`{"a": 9`)
dec := json.NewDecoder(src)
- assert.ErrorIs(t, bldr.UnmarshalOne(dec), io.ErrUnexpectedEOF)
+ assertTruncatedJSONError(t, bldr.UnmarshalOne(dec))
}
func TestDurationBuilderJSONStringInteger(t *testing.T) {
diff --git a/arrow/compute/scalar_set_lookup_test.go
b/arrow/compute/scalar_set_lookup_test.go
index 18b9a78e..5ddd2875 100644
--- a/arrow/compute/scalar_set_lookup_test.go
+++ b/arrow/compute/scalar_set_lookup_test.go
@@ -355,7 +355,7 @@ func (ss *ScalarSetLookupSuite) TestIsInDecimal() {
values := ss.getArr(typ, `["12.3", "78.9"]`)
defer values.Release()
- ss.checkIsIn(in, values, `[true, false true]`,
compute.NullMatchingMatch)
+ ss.checkIsIn(in, values, `[true, false, true]`,
compute.NullMatchingMatch)
}
})
}
diff --git a/parquet/variant/builder_test.go b/parquet/variant/builder_test.go
index 982fa4e9..98a4d7f7 100644
--- a/parquet/variant/builder_test.go
+++ b/parquet/variant/builder_test.go
@@ -826,31 +826,33 @@ func TestBuilderFromJSON(t *testing.T) {
}
}
+// TestBuilderJSONErrors checks that malformed JSON is rejected. The detailed
+// message depends on which JSON backend and Go version tokenizes the input,
+// so only the error wrapping added by ParseJSON is checked.
func TestBuilderJSONErrors(t *testing.T) {
tests := []struct {
- name string
- input string
- wantErr string
+ name string
+ input string
}{
- {"empty string", ``, "unexpected end of JSON input"},
- {"invalid token", `a`, "failed to decode JSON token"},
- {"missing array end", `[1, 2, 3`, "failed to decode JSON array
end"},
- {"invalid array", `[1, "foo", bar`, "failed to decode JSON
token"},
- {"missing elem", `[1,`, "unexpected end of JSON input"},
- {"invalid elem", `[1, 5 }`, "expected end of JSON array, got
}"},
- {"extra delimiter", `]`, "unexpected JSON delimiter"},
- {"invalid key", `{"key": "value", 42: "invalid"}`, "expected
string key in JSON object"},
- {"eof key", `{"key": 1,`, "unexpected end of JSON input"},
- {"invalid token key", `{ab`, "failed to decode JSON key"},
- {"invalid object", `{"key": foo}`, "failed to decode JSON
token"},
- {"invalid object end", `{"key": 123 ]`, "expected end of JSON
object"},
- {"missing object end", `{"key": 123`, "failed to decode JSON
object end"},
+ {"empty string", ``},
+ {"invalid token", `a`},
+ {"missing array end", `[1, 2, 3`},
+ {"invalid array", `[1, "foo", bar`},
+ {"missing elem", `[1,`},
+ {"invalid elem", `[1, 5 }`},
+ {"extra delimiter", `]`},
+ {"invalid key", `{"key": "value", 42: "invalid"}`},
+ {"eof key", `{"key": 1,`},
+ {"invalid token key", `{ab`},
+ {"invalid object", `{"key": foo}`},
+ {"invalid object end", `{"key": 123 ]`},
+ {"missing object end", `{"key": 123`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := variant.ParseJSON(tt.input, false)
- assert.ErrorContains(t, err, tt.wantErr)
+ assert.ErrorContains(t, err, "failed to parse JSON")
})
}
}