// Copyright 2024 The OPA Authors. All rights reserved. // Use of this source code is governed by an Apache2 // license that can be found in the LICENSE file. package repl import ( "bytes" "strings" "testing" "github.com/open-policy-agent/opa/storage" "github.com/open-policy-agent/opa/storage/inmem" "github.com/open-policy-agent/opa/util" ) func TestOneShot_DefaultRegoVersion(t *testing.T) { type action struct { line string expOutput string expErrs []string } tests := []struct { note string actions []action }{ { note: "v0 rule, v1 compile-time violation", actions: []action{ { line: "b { data := 1; data == 1 }", expOutput: "Rule 'b' defined in package repl. Type 'show' to see rules.\n", }, }, }, { note: "v1 keywords used", actions: []action{ { line: "a contains 2 if { true }", expErrs: []string{ "rego_unsafe_var_error: var a is unsafe", }, }, }, }, { note: "v1 keywords not used", actions: []action{ { line: "a[2] { true }", expOutput: "Rule 'a' defined in package repl. Type 'show' to see rules.\n", }, }, }, { note: "v1 keywords imported", actions: []action{ { line: "import future.keywords", }, { line: "a contains 2 if { true }", expOutput: "Rule 'a' defined in package repl. Type 'show' to see rules.\n", }, }, }, { note: "rego.v1 imported", actions: []action{ { line: "import rego.v1", }, { line: "a contains 2 if { true }", expOutput: "Rule 'a' defined in package repl. Type 'show' to see rules.\n", }, }, }, { note: "v1 keywords", actions: []action{ { line: "a contains 2 if { true }", expErrs: []string{ "rego_unsafe_var_error: var a is unsafe", }, }, }, }, } for _, tc := range tests { t.Run(tc.note, func(t *testing.T) { ctx := t.Context() store := newTestStore() var buffer bytes.Buffer repl := newRepl(store, &buffer) for _, action := range tc.actions { err := repl.OneShot(ctx, action.line) if len(action.expErrs) != 0 { if err == nil { t.Fatalf("Expected error but got: %s", buffer.String()) } for _, e := range action.expErrs { if !strings.Contains(err.Error(), e) { t.Fatalf("Expected error to contain:\n\n%q\n\nbut got:\n\n%v", e, err) } } } else { if err != nil { t.Fatalf("Unexpected error: %v", err) } expectOutput(t, buffer.String(), action.expOutput) } } }) } } func expectOutput(t *testing.T, output string, expected string) { t.Helper() if output != expected { t.Errorf("Repl output: expected %#v but got %#v", expected, output) } } func newRepl(store storage.Store, buffer *bytes.Buffer) *REPL { repl := New(store, "", buffer, "", 0, "") return repl } func newTestStore() storage.Store { input := ` { "a": [ { "b": { "c": [true,2,false] } }, { "b": { "c": [false,true,1] } } ] } ` var data map[string]any err := util.UnmarshalJSON([]byte(input), &data) if err != nil { panic(err) } return inmem.NewFromObject(data) }