github.com/rajeev159/opa@v0.45.0/topdown/input_test.go (about)

     1  // Copyright 2016 The OPA Authors.  All rights reserved.
     2  // Use of this source code is governed by an Apache2
     3  // license that can be found in the LICENSE file.
     4  
     5  package topdown
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/open-policy-agent/opa/ast"
    11  )
    12  
    13  func TestMergeTermWithValues(t *testing.T) {
    14  
    15  	tests := []struct {
    16  		note     string
    17  		exist    string
    18  		input    [][2]string
    19  		expected interface{}
    20  	}{
    21  		{
    22  			note:     "var",
    23  			input:    [][2]string{{`input.hello`, `"world"`}},
    24  			expected: `{"hello": "world"}`,
    25  		},
    26  		{
    27  			note:     "multiple vars",
    28  			input:    [][2]string{{`input.a`, `"a"`}, {`input.b`, `"b"`}},
    29  			expected: `{"a": "a", "b": "b"}`,
    30  		},
    31  		{
    32  			note:     "multiple overlapping vars",
    33  			input:    [][2]string{{`input.a.b.c`, `"c"`}, {`input.a.b.d`, `"d"`}, {`input.x.y`, `[]`}},
    34  			expected: `{"a": {"b": {"c": "c", "d": "d"}}, "x": {"y": []}}`,
    35  		},
    36  		{
    37  			note:     "ref value",
    38  			input:    [][2]string{{"input.foo.bar", "data.com.example.widgets[i]"}},
    39  			expected: `{"foo": {"bar": data.com.example.widgets[i]}}`,
    40  		},
    41  		{
    42  			note:     "non-object",
    43  			input:    [][2]string{{"input", "[1,2,3]"}},
    44  			expected: "[1,2,3]",
    45  		},
    46  		{
    47  			note:     "conflicting value",
    48  			input:    [][2]string{{"input", "[1,2,3]"}, {"input.a", "true"}},
    49  			expected: `{"a": true}`,
    50  		},
    51  		{
    52  			note:     "conflicting value, nested trailing terms",
    53  			input:    [][2]string{{"input", "[1,2,3]"}, {"input.a.b", "true"}},
    54  			expected: `{"a": {"b": true}}`,
    55  		},
    56  		{
    57  			note:     "conflicting merge",
    58  			input:    [][2]string{{`input.a.b`, `"c"`}, {`input.a.b.d`, `"d"`}},
    59  			expected: `{"a": {"b": {"d": "d"}}}`,
    60  		},
    61  		{
    62  			note:     "ordered roots",
    63  			input:    [][2]string{{"input", `"a"`}, {"input", `"b"`}},
    64  			expected: `"b"`,
    65  		},
    66  		{
    67  			note:     "bad import path",
    68  			input:    [][2]string{{`input.a[1]`, `1`}},
    69  			expected: errBadPath,
    70  		},
    71  		{
    72  			note:     "existing merge",
    73  			exist:    `{"foo": {"bar": 1}}`,
    74  			input:    [][2]string{{"input.foo.baz", "2"}},
    75  			expected: `{"foo": {"bar": 1, "baz": 2}}`,
    76  		},
    77  		{
    78  			note:     "existing overwrite",
    79  			exist:    `{"a": {"b": 1, "c": 2}}`,
    80  			input:    [][2]string{{"input.a", `{"d": 3}`}},
    81  			expected: `{"a": {"d": 3}}`,
    82  		},
    83  	}
    84  
    85  	for i, tc := range tests {
    86  
    87  		t.Run(tc.note, func(t *testing.T) {
    88  
    89  			pairs := make([][2]*ast.Term, len(tc.input))
    90  
    91  			for j := range tc.input {
    92  				k := ast.MustParseTerm(tc.input[j][0])
    93  				v := ast.MustParseTerm(tc.input[j][1])
    94  				pairs[j] = [...]*ast.Term{k, v}
    95  			}
    96  
    97  			var exist *ast.Term
    98  
    99  			if tc.exist != "" {
   100  				exist = ast.MustParseTerm(tc.exist)
   101  			}
   102  
   103  			input, err := mergeTermWithValues(exist, pairs)
   104  
   105  			switch e := tc.expected.(type) {
   106  			case error:
   107  				if err == nil {
   108  					t.Fatalf("%v (#%d): Expected error %v but got: %v", tc.note, i+1, e, input)
   109  				}
   110  				if err.Error() != e.Error() {
   111  					t.Fatalf("%v (#%d): Expected error %v but got: %v", tc.note, i+1, e, err)
   112  				}
   113  			case string:
   114  				if err != nil {
   115  					t.Fatalf("%v (#%d): Unexpected error: %v", tc.note, i+1, err)
   116  				}
   117  				expected := ast.MustParseTerm(e)
   118  				if expected.Value.Compare(input.Value) != 0 {
   119  					t.Fatalf("%v (#%d): Expected input to equal %v but got: %v", tc.note, i+1, expected, input)
   120  				}
   121  			}
   122  		})
   123  	}
   124  }
   125  
   126  func TestMergeTermWithValuesInputsShouldBeImmutable(t *testing.T) {
   127  
   128  	initial := ast.MustParseTerm(`{"foo": 1}`)
   129  	expInitial := initial.Copy()
   130  	two := ast.MustParseTerm(`2`)
   131  
   132  	result, err := mergeTermWithValues(nil, [][2]*ast.Term{
   133  		{ast.MustParseTerm("input"), initial},
   134  		{ast.MustParseTerm("input.foo"), two},
   135  	})
   136  
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  
   141  	exp := ast.MustParseTerm(`{"foo": 2}`)
   142  
   143  	if !result.Equal(exp) {
   144  		t.Fatalf("expected %v but got %v", exp, result)
   145  	}
   146  
   147  	if !initial.Equal(expInitial) {
   148  		t.Fatalf("expected input value to be unchanged but got %v (expected: %v)", initial, expInitial)
   149  	}
   150  }