github.com/rajeev159/opa@v0.45.0/topdown/lineage/lineage_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 lineage 6 7 import ( 8 "bytes" 9 "context" 10 "strings" 11 "testing" 12 13 "github.com/open-policy-agent/opa/ast" 14 "github.com/open-policy-agent/opa/topdown" 15 ) 16 17 func TestFilter(t *testing.T) { 18 19 tests := []struct { 20 note string 21 module string 22 exp string 23 }{ 24 { 25 note: "lineage", 26 module: `package test 27 28 p { q } 29 q { r } 30 r { trace("R") }`, 31 exp: ` 32 Enter data.test.p = x 33 | Enter data.test.p 34 | | Enter data.test.q 35 | | | Enter data.test.r 36 | | | | Note "R"`, 37 }, 38 { 39 note: "conjunction", 40 module: `package test 41 42 p { trace("P1"); trace("P2") }`, 43 exp: ` 44 Enter data.test.p = x 45 | Enter data.test.p 46 | | Note "P1" 47 | | Note "P2"`, 48 }, 49 { 50 note: "conjunction (multiple enters)", 51 module: `package test 52 53 p { q; r } 54 q { trace("Q") } 55 r { trace("Q") } 56 `, 57 exp: ` 58 Enter data.test.p = x 59 | Enter data.test.p 60 | | Enter data.test.q 61 | | | Note "Q" 62 | | Enter data.test.r 63 | | | Note "Q"`, 64 }, 65 { 66 note: "disjunction", 67 module: `package test 68 69 p = x { x := true; trace("P1") } 70 p = x { x := true; false } 71 p = x { x := true; trace("P2") } 72 `, 73 exp: ` 74 Enter data.test.p = x 75 | Enter data.test.p 76 | | Note "P1" 77 Redo data.test.p = x 78 | Enter data.test.p 79 | | Note "P2"`, 80 }, 81 { 82 note: "disjunction (failure)", 83 module: `package test 84 85 p = x { x := true; trace("P1") } 86 p = x { x := true; trace("P2"); false } 87 p = x { x := true; trace("P3") } 88 `, 89 exp: ` 90 Enter data.test.p = x 91 | Enter data.test.p 92 | | Note "P1" 93 Redo data.test.p = x 94 | Enter data.test.p 95 | | Note "P2" 96 | Enter data.test.p 97 | | Note "P3"`, 98 }, 99 { 100 note: "disjunction (iteration)", 101 module: `package test 102 q[1] 103 q[2] 104 p { q[x]; trace(sprintf("x=%d", [x])) }`, 105 exp: ` 106 Enter data.test.p = x 107 | Enter data.test.p 108 | | Note "x=1" 109 `, 110 }, 111 { 112 note: "parent child", 113 module: `package test 114 115 p { trace("P"); q } 116 q { trace("Q") }`, 117 exp: ` 118 Enter data.test.p = x 119 | Enter data.test.p 120 | | Note "P" 121 | | Enter data.test.q 122 | | | Note "Q"`, 123 }, 124 { 125 note: "negation", 126 module: `package test 127 128 p { not q } 129 q = false { trace("Q") }`, 130 exp: ` 131 Enter data.test.p = x 132 | Enter data.test.p 133 | | Enter data.test.q 134 | | | Enter data.test.q 135 | | | | Note "Q"`, 136 }, 137 { 138 note: "fail", 139 module: `package test 140 141 p { not q } 142 q { trace("P"); 1 = 2 }`, 143 exp: ` 144 Enter data.test.p = x 145 | Enter data.test.p 146 | | Enter data.test.q 147 | | | Enter data.test.q 148 | | | | Note "P"`, 149 }, 150 { 151 note: "comprehensions", 152 module: `package test 153 154 p { [true | true; trace("X")] }`, 155 exp: ` 156 Enter data.test.p = x 157 | Enter data.test.p 158 | | Enter true; trace("X") 159 | | | Note "X"`, 160 }, 161 } 162 163 for _, tc := range tests { 164 t.Run(tc.note, func(t *testing.T) { 165 buf := topdown.NewBufferTracer() 166 compiler := ast.MustCompileModules(map[string]string{ 167 "test.rego": tc.module, 168 }) 169 query := topdown.NewQuery(ast.MustParseBody("data.test.p = x")).WithCompiler(compiler).WithTracer(buf) 170 rs, err := query.Run(context.TODO()) 171 if err != nil { 172 t.Fatal(err) 173 } else if len(rs) != 1 || !rs[0][ast.Var("x")].Equal(ast.BooleanTerm(true)) { 174 t.Fatalf("Unexpected result: %v", rs) 175 } 176 177 filtered := Notes(*buf) 178 179 buffer := bytes.NewBuffer(nil) 180 topdown.PrettyTrace(buffer, filtered) 181 182 if strings.TrimSpace(buffer.String()) != strings.TrimSpace(tc.exp) { 183 t.Fatalf("Expected:\n\n%v\n\nGot:\n\n%v", tc.exp, buffer.String()) 184 } 185 }) 186 } 187 188 }