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
17 changes: 14 additions & 3 deletions libs/dyn/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,22 @@ func (v Value) eq(w Value) bool {
// This is safe because we don't allow maps to be mutated.
return &v.v == &w.v
case KindSequence:
// Compare pointers to the underlying slice and slice length.
// This is safe because we don't allow slices to be mutated.
vs := v.v.([]Value)
ws := w.v.([]Value)
return &vs[0] == &ws[0] && len(vs) == len(ws)
lv := len(vs)
lw := len(ws)
// If both slices are empty, they are equal.
if lv == 0 && lw == 0 {
return true
}
// If they have different lengths, they are not equal.
if lv != lw {
return false
}
// They are both non-empty and have the same length.
// Compare pointers to the underlying slice.
// This is safe because we don't allow slices to be mutated.
return &vs[0] == &ws[0]
default:
return v.v == w.v
}
Expand Down
46 changes: 46 additions & 0 deletions libs/dyn/visit_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,29 @@ func TestMapFuncOnMap(t *testing.T) {
assert.ErrorIs(t, err, ref)
}

func TestMapFuncOnMapWithEmptySequence(t *testing.T) {
variants := []dyn.Value{
// empty sequence
dyn.V([]dyn.Value{}),
// non-empty sequence
dyn.V([]dyn.Value{dyn.V(42)}),
}

for i := 0; i < len(variants); i++ {
vin := dyn.V(map[string]dyn.Value{
"key": variants[i],
})

for j := 0; j < len(variants); j++ {
vout, err := dyn.MapByPath(vin, dyn.NewPath(dyn.Key("key")), func(v dyn.Value) (dyn.Value, error) {
return variants[j], nil
})
assert.NoError(t, err)
assert.Equal(t, variants[j], vout.Get("key"))
}
}
}

func TestMapFuncOnSequence(t *testing.T) {
vin := dyn.V([]dyn.Value{
dyn.V(42),
Expand Down Expand Up @@ -115,6 +138,29 @@ func TestMapFuncOnSequence(t *testing.T) {
assert.ErrorIs(t, err, ref)
}

func TestMapFuncOnSequenceWithEmptySequence(t *testing.T) {
variants := []dyn.Value{
// empty sequence
dyn.V([]dyn.Value{}),
// non-empty sequence
dyn.V([]dyn.Value{dyn.V(42)}),
}

for i := 0; i < len(variants); i++ {
vin := dyn.V([]dyn.Value{
variants[i],
})

for j := 0; j < len(variants); j++ {
vout, err := dyn.MapByPath(vin, dyn.NewPath(dyn.Index(0)), func(v dyn.Value) (dyn.Value, error) {
return variants[j], nil
})
assert.NoError(t, err)
assert.Equal(t, variants[j], vout.Index(0))
}
}
}

func TestMapForeachOnMap(t *testing.T) {
vin := dyn.V(map[string]dyn.Value{
"foo": dyn.V(42),
Expand Down