Skip to content

Commit

Permalink
types: ensure Entity marshals to JSON with a consistent ordering
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Jakubowski <[email protected]>
  • Loading branch information
patjakdev committed Sep 26, 2024
1 parent b71df7e commit e796ce2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 13 deletions.
14 changes: 14 additions & 0 deletions internal/testutil/testutil.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package testutil

import (
"bytes"
"encoding/json"
"errors"
"reflect"
)
Expand Down Expand Up @@ -60,3 +62,15 @@ func Panic(t TB, f func()) {
}()
f()
}

// JSONMarshalsTo asserts that obj marshals as JSON to the given string, allowing for formatting differences and
// displaying an easy-to-read diff.
func JSONMarshalsTo[T any](t TB, obj T, want string) {
b, err := json.MarshalIndent(obj, "", "\t")
OK(t, err)

var wantBuf bytes.Buffer
err = json.Indent(&wantBuf, []byte(want), "", "\t")
OK(t, err)
Equals(t, string(b), wantBuf.String())
}
13 changes: 1 addition & 12 deletions types/entities_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package types_test

import (
"bytes"
"encoding/json"
"testing"

Expand All @@ -25,16 +24,6 @@ func TestEntities(t *testing.T) {

}

func assertJSONEquals(t *testing.T, e any, want string) {
b, err := json.MarshalIndent(e, "", "\t")
testutil.OK(t, err)

var wantBuf bytes.Buffer
err = json.Indent(&wantBuf, []byte(want), "", "\t")
testutil.OK(t, err)
testutil.Equals(t, string(b), wantBuf.String())
}

func TestEntitiesJSON(t *testing.T) {
t.Parallel()
t.Run("Marshal", func(t *testing.T) {
Expand All @@ -52,7 +41,7 @@ func TestEntitiesJSON(t *testing.T) {
}
e[ent.UID] = ent
e[ent2.UID] = ent2
assertJSONEquals(
testutil.JSONMarshalsTo(
t,
e,
`[
Expand Down
13 changes: 12 additions & 1 deletion types/entity.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package types

import "encoding/json"
import (
"encoding/json"
"slices"
"strings"
)

// An Entity defines the parents and attributes for an EntityUID.
type Entity struct {
Expand All @@ -17,6 +21,13 @@ func (e Entity) MarshalJSON() ([]byte, error) {
parents = append(parents, ImplicitlyMarshaledEntityUID(p))
return true
})
slices.SortFunc(parents, func(a, b ImplicitlyMarshaledEntityUID) int {
if cmp := strings.Compare(string(a.Type), string(b.Type)); cmp != 0 {
return cmp
}

return strings.Compare(string(a.ID), string(b.ID))
})

m := struct {
UID ImplicitlyMarshaledEntityUID `json:"uid"`
Expand Down
28 changes: 28 additions & 0 deletions types/entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,31 @@ func TestEntityIsZero(t *testing.T) {
})
}
}

func TestEntityMarshalJSON(t *testing.T) {
t.Parallel()
e := types.Entity{
UID: types.NewEntityUID("FooType", "1"),
Parents: types.NewEntityUIDSet(
types.NewEntityUID("BazType", "1"),
types.NewEntityUID("BarType", "2"),
types.NewEntityUID("BarType", "1"),
types.NewEntityUID("QuuxType", "30"),
types.NewEntityUID("QuuxType", "3"),
),
Attributes: types.Record{},
}

testutil.JSONMarshalsTo(t, e,
`{
"uid": {"type":"FooType","id":"1"},
"parents": [
{"type":"BarType","id":"1"},
{"type":"BarType","id":"2"},
{"type":"BazType","id":"1"},
{"type":"QuuxType","id":"3"},
{"type":"QuuxType","id":"30"}
],
"attrs":{}
}`)
}

0 comments on commit e796ce2

Please sign in to comment.