Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Sources/Rego/Engine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,21 @@ extension OPA.Engine {
try await store.write(to: StoreKeyPath(["data"]), value: bundle.data)
}

let evaluator: Evaluator
if self.policies.count > 0 {
guard loadedBundles.isEmpty else {
throw RegoError.init(code: .invalidArgumentError, message: "Cannot mix direct IR policies with bundles")
}
return PreparedQuery(
query: query,
evaluator: IREvaluator(policies: self.policies),
store: self.store
)
evaluator = IREvaluator(policies: self.policies)
} else {
evaluator = try IREvaluator(bundles: loadedBundles)
}

try evaluator.ensureQueryIsSupported(query)

return PreparedQuery(
query: query,
evaluator: try IREvaluator(bundles: loadedBundles),
evaluator: evaluator,
store: self.store
)
}
Expand Down
1 change: 1 addition & 0 deletions Sources/Rego/Evaluator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import AST
import IR

protocol Evaluator {
func ensureQueryIsSupported(_ query: String) throws
func evaluate(withContext ctx: EvaluationContext) async throws -> ResultSet
}

Expand Down
41 changes: 30 additions & 11 deletions Sources/Rego/IREvaluator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,43 @@ internal struct IREvaluator {
init(policies: [IR.Policy]) {
self.policies = policies.map { IndexedIRPolicy(policy: $0) }
}

func findPlanAndPolicy(entrypoint: String) -> (IndexedIRPolicy, Plan)? {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this change warrant a dedicated test?

Copy link
Contributor Author

@dev-rice dev-rice May 9, 2025

Choose a reason for hiding this comment

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

It's still covered by IREvaluatorTests.testInvalidEvaluations because those test cases both prepare a query, then try to evaluate it. Before, the evaluation would fail, but now the query preparation step fails. I considered splitting out a distinct set of tests (for the Engine) around only query preparation to put tighter bounds around where the errors are thrown, but ultimately decided against it since it'd be duplicating most of what's covered in IREvaluatorTests.

What do you think?

// TODO: We're assuming that queries are only ever defined in a single policy... that _should_ hold true.. but who's checkin?
for policy in policies {
if let plan = policy.plans[entrypoint] {
return (policy, plan)
}
}

return nil
}

func unknownQueryError(query: String) -> RegoError {
RegoError(code: .unknownQuery, message: "query not found in plan: \(query)")
}
}

extension IREvaluator: Evaluator {
func evaluate(withContext ctx: EvaluationContext) async throws -> ResultSet {
// TODO: We're assuming that queries are only ever defined in a single policy... that _should_ hold true.. but who's checkin?
func ensureQueryIsSupported(_ query: String) throws {
let entrypoint = try queryToEntryPoint(query)

guard findPlanAndPolicy(entrypoint: entrypoint) != nil else {
throw unknownQueryError(query: query)
}
}

func evaluate(withContext ctx: EvaluationContext) async throws -> ResultSet {
let entrypoint = try queryToEntryPoint(ctx.query)

for policy in policies {
if let plan = policy.plans[entrypoint] {
let ctx = IREvaluationContext(ctx: ctx, policy: policy)
return try await evalPlan(
withContext: ctx,
plan: plan
)
}
guard let (policy, plan) = findPlanAndPolicy(entrypoint: entrypoint) else {
throw unknownQueryError(query: ctx.query)
}
throw RegoError(code: .unknownQuery, message: "query not found in plan: \(ctx.query)")

return try await evalPlan(
withContext: IREvaluationContext(ctx: ctx, policy: policy),
plan: plan
)
}
}

Expand Down