Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

topdown/eval: Fix key construction for NDBCache. #5097

Merged
merged 3 commits into from Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions rego/rego.go
Expand Up @@ -320,7 +320,6 @@ func (pq preparedQuery) newEvalContext(ctx context.Context, options []EvalOption
compiledQuery: compiledQuery{},
indexing: true,
earlyExit: true,
ndBuiltinCache: builtins.NDBCache{},
resolvers: pq.r.resolvers,
printHook: pq.r.printHook,
capabilities: pq.r.capabilities,
Expand Down Expand Up @@ -1112,7 +1111,6 @@ func New(options ...func(r *Rego)) *Rego {
builtinDecls: map[string]*ast.Builtin{},
builtinFuncs: map[string]*topdown.Builtin{},
bundles: map[string]*bundle.Bundle{},
ndBuiltinCache: builtins.NDBCache{},
}

for _, option := range options {
Expand Down
42 changes: 41 additions & 1 deletion rego/rego_test.go
Expand Up @@ -2105,7 +2105,47 @@ p {
}
_, ok := ndBC["http.send"]
if !ok {
t.Errorf("expected http.send cache entry")
t.Fatalf("expected http.send cache entry")
}
}

// Catches issues around iteration with ND builtins.
func TestNDBCacheWithRuleBodyAndIteration(t *testing.T) {
ctx := context.Background()
ndBC := builtins.NDBCache{}
query := "data.foo.results = x"
_, err := New(
Query(query),
NDBuiltinCache(ndBC),
Module("test.rego", `package foo

import future.keywords

urls := [
"https://httpbin.org/headers",
"https://httpbin.org/ip",
"https://httpbin.org/user-agent"
]

results[response] {
some url in urls
response := http.send({
"method": "GET",
"url": url
})
}`),
Comment on lines +2124 to +2136
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're likely to run into test flakes w/ this because it has to reach out to the internet. We would be better off registering a mock built-in function that sets the Nondeterministic bit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...or use rand.int_n with a key from a variable...? But agreed let's find a way to do this without the internet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s keep using http.send here, although with a mock server. The impact of breaking http.send vs. rand.int_n makes it valuable, even if the bug affects both in this case.

).Eval(ctx)
if err != nil {
t.Fatal(err)
}

// Ensure that the cache exists, and has exactly 3 entries.
entries, ok := ndBC["http.send"]
if !ok {
t.Fatalf("expected http.send cache entry")
}
if entries.Len() != 3 {
t.Fatalf("expected 3 http.send cache entries, received:\n%v", ndBC)
}
}

Expand Down
4 changes: 2 additions & 2 deletions topdown/eval.go
Expand Up @@ -1707,7 +1707,7 @@ func (e evalBuiltin) eval(iter unifyIterator) error {
e.e.instr.stopTimer(evalOpBuiltinCall)

// Unify against the NDBCache result if present.
if v, ok := e.bctx.NDBuiltinCache.Get(e.bi.Name, ast.NewArray(e.terms[:endIndex]...)); ok {
if v, ok := e.bctx.NDBuiltinCache.Get(e.bi.Name, ast.NewArray(operands[:endIndex]...)); ok {
switch {
case e.bi.Decl.Result() == nil:
err = iter()
Expand Down Expand Up @@ -1753,7 +1753,7 @@ func (e evalBuiltin) eval(iter unifyIterator) error {
// call was not cached earlier.
if e.canUseNDBCache(e.bi) {
// Populate the NDBCache from the output term.
e.bctx.NDBuiltinCache.Put(e.bi.Name, ast.NewArray(e.terms[:endIndex]...), output.Value)
e.bctx.NDBuiltinCache.Put(e.bi.Name, ast.NewArray(operands[:endIndex]...), output.Value)
}

if err != nil {
Expand Down