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  }