aboutsummaryrefslogtreecommitdiff
path: root/columnar/columnar_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'columnar/columnar_test.go')
-rw-r--r--columnar/columnar_test.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/columnar/columnar_test.go b/columnar/columnar_test.go
new file mode 100644
index 0000000..17dc964
--- /dev/null
+++ b/columnar/columnar_test.go
@@ -0,0 +1,118 @@
+// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
+// SPDX-License-Identifier: Apache-2.0
+
+package columnar_test
+
+import (
+ "encoding/json"
+ "sync"
+ "testing"
+
+ "go.xyrillian.de/gg/columnar"
+ . "go.xyrillian.de/gg/internal/test"
+ "go.xyrillian.de/gg/jsonmatch"
+)
+
+func testSuccessfulJSONRoundtrip[V any](t *testing.T, list []V, encoded jsonmatch.Diffable) {
+ buf, err := json.Marshal(columnar.List[V](list))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, diff := range encoded.DiffAgainst(buf) {
+ t.Error(diff.String())
+ }
+
+ var unmarshaled columnar.List[V]
+ err = json.Unmarshal(buf, &unmarshaled)
+ if err != nil {
+ t.Fatal(err)
+ }
+ AssertEqual(t, []V(unmarshaled), list)
+}
+
+func TestJSONRoundtripBasic(t *testing.T) {
+ // try the example from the package docstring
+ type Person struct {
+ ID int `json:"id"`
+ FirstName string `json:"first_name"`
+ LastName string `json:"last_name"`
+ Married bool `json:"married"`
+ }
+
+ testSuccessfulJSONRoundtrip(t,
+ []Person{
+ {ID: 1, FirstName: "Alice", LastName: "Allison", Married: false},
+ {ID: 2, FirstName: "Bob", LastName: "Burger", Married: true},
+ {ID: 3, FirstName: "Carol", LastName: "Callagher", Married: true},
+ },
+ jsonmatch.Object{
+ "id": jsonmatch.Array{1, 2, 3},
+ "first_name": jsonmatch.Array{"Alice", "Bob", "Carol"},
+ "last_name": jsonmatch.Array{"Allison", "Burger", "Callagher"},
+ "married": jsonmatch.Array{false, true, true},
+ },
+ )
+}
+
+func TestJSONRoundtripWithSpecialFields(t *testing.T) {
+ type Point struct {
+ X float64 `json:"x"`
+ Y float64 `json:"y"`
+ }
+ type Event struct {
+ *Point `json:"location"` // embedded field, also with pointer
+ Name string // without tag -> uses field name as key
+ nameMutex sync.RWMutex //nolint:unused // not exported -> ignored
+ }
+
+ testSuccessfulJSONRoundtrip(t,
+ []Event{
+ {Point: &Point{X: 0, Y: 0}, Name: "origin"},
+ {Point: &Point{X: 2, Y: 4}, Name: "somewhere"},
+ },
+ jsonmatch.Object{
+ "location": jsonmatch.Array{jsonmatch.Object{"x": 0, "y": 0}, jsonmatch.Object{"x": 2, "y": 4}},
+ "Name": jsonmatch.Array{"origin", "somewhere"},
+ },
+ )
+}
+
+func TestJSONRoundtripResolvesPointers(t *testing.T) {
+ type Record struct {
+ Foo int
+ Bar int
+ }
+ testSuccessfulJSONRoundtrip(t,
+ []***Record{
+ PointerTo(PointerTo(PointerTo(Record{1, 2}))),
+ PointerTo(PointerTo(PointerTo(Record{2, 4}))),
+ PointerTo(PointerTo(PointerTo(Record{3, 6}))),
+ },
+ jsonmatch.Object{
+ "Foo": jsonmatch.Array{1, 2, 3},
+ "Bar": jsonmatch.Array{2, 4, 6},
+ },
+ )
+}
+
+func TestJSONRoundtripErrors(t *testing.T) {
+ type nothingPublic struct {
+ foo int
+ bar int
+ }
+
+ _, err := json.Marshal(columnar.List[nothingPublic]{{1, 2}})
+ AssertEqual(t, err.Error(), `json: error calling MarshalJSON for type columnar.List[go.xyrillian.de/gg/columnar_test.nothingPublic·5]: columnar_test.nothingPublic has no exported fields`)
+ err = json.Unmarshal([]byte(`{}`), PointerTo(columnar.List[nothingPublic]{}))
+ AssertEqual(t, err.Error(), `columnar_test.nothingPublic has no exported fields`)
+}
+
+func TestJSONUnmarshalFromInconsistentLengths(t *testing.T) {
+ type Record struct {
+ Foo int
+ Bar int
+ }
+
+ err := json.Unmarshal([]byte(`{"Foo":[1,2],"Bar":[3,4,5]}`), PointerTo(columnar.List[Record]{}))
+ AssertEqual(t, err.Error(), `cannot unmarshal from columns with inconsistent lengths [2 3]`)
+}