Files
Anders Eknert e43ef0a979 Use any in place of interface{} (#7566)
Earlier this evening I tried to run the Go
[modernize](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize)
analyzer on OPA. That didn't go as planned:

- https://github.com/golang/go/issues/73661
- https://github.com/golang/go/issues/73663

While we wait for that to be fixed, I figured an old-fashioned
search-and-replace across the repo may work for at least the
`interface{}` to `any` conversion. That should help make it easier
to see the other fixes as applied by the modernize tool once it has
had those issues resolved.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-05-12 13:57:48 +02:00

153 lines
3.8 KiB
Go

// Copyright 2016 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package topdown
import (
"testing"
"github.com/open-policy-agent/opa/v1/ast"
)
func TestMergeTermWithValues(t *testing.T) {
t.Parallel()
tests := []struct {
note string
exist string
input [][2]string
expected any
}{
{
note: "var",
input: [][2]string{{`input.hello`, `"world"`}},
expected: `{"hello": "world"}`,
},
{
note: "multiple vars",
input: [][2]string{{`input.a`, `"a"`}, {`input.b`, `"b"`}},
expected: `{"a": "a", "b": "b"}`,
},
{
note: "multiple overlapping vars",
input: [][2]string{{`input.a.b.c`, `"c"`}, {`input.a.b.d`, `"d"`}, {`input.x.y`, `[]`}},
expected: `{"a": {"b": {"c": "c", "d": "d"}}, "x": {"y": []}}`,
},
{
note: "ref value",
input: [][2]string{{"input.foo.bar", "data.com.example.widgets[i]"}},
expected: `{"foo": {"bar": data.com.example.widgets[i]}}`,
},
{
note: "non-object",
input: [][2]string{{"input", "[1,2,3]"}},
expected: "[1,2,3]",
},
{
note: "conflicting value",
input: [][2]string{{"input", "[1,2,3]"}, {"input.a", "true"}},
expected: `{"a": true}`,
},
{
note: "conflicting value, nested trailing terms",
input: [][2]string{{"input", "[1,2,3]"}, {"input.a.b", "true"}},
expected: `{"a": {"b": true}}`,
},
{
note: "conflicting merge",
input: [][2]string{{`input.a.b`, `"c"`}, {`input.a.b.d`, `"d"`}},
expected: `{"a": {"b": {"d": "d"}}}`,
},
{
note: "ordered roots",
input: [][2]string{{"input", `"a"`}, {"input", `"b"`}},
expected: `"b"`,
},
{
note: "bad import path",
input: [][2]string{{`input.a[1]`, `1`}},
expected: errBadPath,
},
{
note: "existing merge",
exist: `{"foo": {"bar": 1}}`,
input: [][2]string{{"input.foo.baz", "2"}},
expected: `{"foo": {"bar": 1, "baz": 2}}`,
},
{
note: "existing overwrite",
exist: `{"a": {"b": 1, "c": 2}}`,
input: [][2]string{{"input.a", `{"d": 3}`}},
expected: `{"a": {"d": 3}}`,
},
}
for i, tc := range tests {
t.Run(tc.note, func(t *testing.T) {
t.Parallel()
pairs := make([][2]*ast.Term, len(tc.input))
for j := range tc.input {
k := ast.MustParseTerm(tc.input[j][0])
v := ast.MustParseTerm(tc.input[j][1])
pairs[j] = [...]*ast.Term{k, v}
}
var exist *ast.Term
if tc.exist != "" {
exist = ast.MustParseTerm(tc.exist)
}
input, err := mergeTermWithValues(exist, pairs)
switch e := tc.expected.(type) {
case error:
if err == nil {
t.Fatalf("%v (#%d): Expected error %v but got: %v", tc.note, i+1, e, input)
}
if err.Error() != e.Error() {
t.Fatalf("%v (#%d): Expected error %v but got: %v", tc.note, i+1, e, err)
}
case string:
if err != nil {
t.Fatalf("%v (#%d): Unexpected error: %v", tc.note, i+1, err)
}
expected := ast.MustParseTerm(e)
if expected.Value.Compare(input.Value) != 0 {
t.Fatalf("%v (#%d): Expected input to equal %v but got: %v", tc.note, i+1, expected, input)
}
}
})
}
}
func TestMergeTermWithValuesInputsShouldBeImmutable(t *testing.T) {
t.Parallel()
initial := ast.MustParseTerm(`{"foo": 1}`)
expInitial := initial.Copy()
two := ast.MustParseTerm(`2`)
result, err := mergeTermWithValues(nil, [][2]*ast.Term{
{ast.MustParseTerm("input"), initial},
{ast.MustParseTerm("input.foo"), two},
})
if err != nil {
t.Fatal(err)
}
exp := ast.MustParseTerm(`{"foo": 2}`)
if !result.Equal(exp) {
t.Fatalf("expected %v but got %v", exp, result)
}
if !initial.Equal(expInitial) {
t.Fatalf("expected input value to be unchanged but got %v (expected: %v)", initial, expInitial)
}
}