func TestEventEqual(t *testing.T) { a := ast.NewValueMap() a.Put(ast.String("foo"), ast.Number("1")) b := ast.NewValueMap() b.Put(ast.String("foo"), ast.Number("2")) tests := []struct { a *Event b *Event equal bool }{ {&Event{}, &Event{}, true}, {&Event{Op: EvalOp}, &Event{Op: EnterOp}, false}, {&Event{QueryID: 1}, &Event{QueryID: 2}, false}, {&Event{ParentID: 1}, &Event{ParentID: 2}, false}, {&Event{Node: ast.MustParseBody("true")}, &Event{Node: ast.MustParseBody("false")}, false}, {&Event{Node: ast.MustParseBody("true")[0]}, &Event{Node: ast.MustParseBody("false")[0]}, false}, {&Event{Node: ast.MustParseRule("p :- true")}, &Event{Node: ast.MustParseRule("p :- false")}, false}, {&Event{Node: "foo"}, &Event{Node: "foo"}, false}, // test some unsupported node type } for _, tc := range tests { if tc.a.Equal(tc.b) != tc.equal { var s string if tc.equal { s = "==" } else { s = "!=" } t.Errorf("Expected %v %v %v", tc.a, s, tc.b) } } }
func ExampleEval() { // Initialize context for the example. Normally the caller would obtain the // context from an input parameter or instantiate their own. ctx := context.Background() compiler := ast.NewCompiler() // Define a dummy query and some data that the query will execute against. query, err := compiler.QueryCompiler().Compile(ast.MustParseBody("data.a[_] = x, x >= 2")) if err != nil { // Handle error. } var data map[string]interface{} // OPA uses Go's standard JSON library but assumes that numbers have been // decoded as json.Number instead of float64. You MUST decode with UseNumber // enabled. decoder := json.NewDecoder(bytes.NewBufferString(`{"a": [1,2,3,4]}`)) decoder.UseNumber() if err := decoder.Decode(&data); err != nil { // Handle error. } // Instantiate the policy engine's storage layer. store := storage.New(storage.InMemoryWithJSONConfig(data)) // Create a new transaction. Transactions allow the policy engine to // evaluate the query over a consistent snapshot fo the storage layer. txn, err := store.NewTransaction(ctx) if err != nil { // Handle error. } defer store.Close(ctx, txn) // Prepare the evaluation parameters. Evaluation executes against the policy // engine's storage. In this case, we seed the storage with a single array // of number. Other parameters such as the request, tracing configuration, // etc. can be set on the Topdown object. t := topdown.New(ctx, query, compiler, store, txn) result := []interface{}{} // Execute the query and provide a callbakc function to accumulate the results. err = topdown.Eval(t, func(t *topdown.Topdown) error { // Each variable in the query will have an associated "binding" in the context. x := t.Binding(ast.Var("x")) // The bindings are ast.Value types so we will convert to a native Go value here. v, err := topdown.ValueToInterface(x, t) if err != nil { return err } result = append(result, v) return nil }) // Inspect the query result. fmt.Println("result:", result) fmt.Println("err:", err) // Output: // result: [2 3 4] // err: <nil> }