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

     1  // Copyright 2019 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 TestFiltersToObject(t *testing.T) {
    14  	cases := []struct {
    15  		note     string
    16  		filters  []string
    17  		expected string
    18  	}{
    19  		{
    20  			note:     "base",
    21  			filters:  []string{`"a/b/c"`},
    22  			expected: `{"a": {"b": {"c": null}}}`,
    23  		},
    24  		{
    25  			note:     "root prefixed",
    26  			filters:  []string{`"a/b/c"`},
    27  			expected: `{"a": {"b": {"c": null}}}`,
    28  		},
    29  		{
    30  			note:     "trailing slash",
    31  			filters:  []string{`"a/b/c"`},
    32  			expected: `{"a": {"b": {"c": null}}}`,
    33  		},
    34  		{
    35  			note:     "different roots",
    36  			filters:  []string{`"a/b/c"`, `"d/e/f"`},
    37  			expected: `{"a": {"b": {"c": null}}, "d": {"e": {"f": null}}}`,
    38  		},
    39  		{
    40  			note:     "shared root",
    41  			filters:  []string{`"a/b/c"`, `"a/b/d"`},
    42  			expected: `{"a": {"b": {"c": null, "d": null}}}`,
    43  		},
    44  		{
    45  			note:     "multiple shares at different points",
    46  			filters:  []string{`"a/b/c"`, `"a/b/d"`, `"a/e/f"`},
    47  			expected: `{"a": {"b": {"c": null, "d": null}, "e": {"f": null}}}`,
    48  		},
    49  		{
    50  			note:     "conflict with one ordering",
    51  			filters:  []string{`"a"`, `"a/b"`},
    52  			expected: `{"a": null}`,
    53  		},
    54  		{
    55  			note:     "conflict with reverse ordering",
    56  			filters:  []string{`"a/b"`, `"a"`},
    57  			expected: `{"a": null}`,
    58  		},
    59  		{
    60  			note:     "arrays",
    61  			filters:  []string{`"a/1/c"`, `"a/1/b"`},
    62  			expected: `{"a": {"1": {"c": null, "b": null}}}`,
    63  		},
    64  		{
    65  			note:     "non string keys",
    66  			filters:  []string{`[[1], {2}]`, `"a/1/b"`},
    67  			expected: `{"a": {"1": {"b": null}}, [1]: {{2}: null}}`,
    68  		},
    69  		{
    70  			note:     "escaped tilde",
    71  			filters:  []string{`"a/~0b~0/c~0"`},
    72  			expected: `{"a": {"~b~": {"c~": null}}}`,
    73  		},
    74  		{
    75  			note:     "escaped slash",
    76  			filters:  []string{`"a/~1b~1c/d~1"`},
    77  			expected: `{"a": {"/b/c": {"d/": null}}}`,
    78  		},
    79  		{
    80  			note:     "mixed escapes",
    81  			filters:  []string{`"a/~0b~1c/d~1~0"`},
    82  			expected: `{"a": {"~b/c": {"d/~": null}}}`,
    83  		},
    84  	}
    85  
    86  	for _, tc := range cases {
    87  		t.Run(tc.note, func(t *testing.T) {
    88  			var paths []ast.Ref
    89  			for _, path := range tc.filters {
    90  				parsedPath, err := parsePath(ast.MustParseTerm(path))
    91  				if err != nil {
    92  					t.Errorf("unexpected error parsing path %s: %s", path, err)
    93  				}
    94  				paths = append(paths, parsedPath)
    95  			}
    96  			actual := pathsToObject(paths)
    97  			expected := ast.MustParseTerm(tc.expected)
    98  			if actual.Compare(expected.Value) != 0 {
    99  				t.Errorf("Unexpected object from filters:\n\nExpected:\n\t%s\n\nActual:\n\t%s\n\n", expected.Value.String(), actual.String())
   100  			}
   101  		})
   102  	}
   103  }