Skip to content

app-policy/checker: differential tests for Evaluate against the policyscale oracle - #13896

Draft
dimitri-nicolo wants to merge 2 commits into
projectcalico:masterfrom
dimitri-nicolo:dimitri-pmreq954-differential
Draft

app-policy/checker: differential tests for Evaluate against the policyscale oracle#13896
dimitri-nicolo wants to merge 2 commits into
projectcalico:masterfrom
dimitri-nicolo:dimitri-pmreq954-differential

Conversation

@dimitri-nicolo

Copy link
Copy Markdown
Contributor

Description

Second of the stack for CORE-13316, stacked on #13895 (the policyscale generator); review the last commit only.

Adds the differential harness that gates every later change to the evaluation path:

  • TestEvaluateAgreesWithOracle runs Evaluate over a corpus drawn from each policyscale preset (baseline, baseline with missing sets, the egress allow-list, and the composite) — the denied flow, flows aimed at every 257th rule, 250 sampled flows per direction following a flow model, and replays as UDP, with an invalid protocol and with nil addresses — and requires the trace to equal the one the fixture's oracle computes from its own model of the rules, in both PolicyScopes. assertEquivalent takes two evaluators, so a second implementation of the walk (the compile-once path in Compile dikastes/collector policies once instead of interpreting per flow #13267, a verdict cache, evaluation on another goroutine) is checked against Evaluate the same way before it is switched on.
  • TestEvaluateNamedCases is the hand-built matrix for what a generated corpus cannot reach: nil addresses against positive and negated references, named and negated named ports, IP+port sets, negated and missing sets, protocols out of range / by name / by number / negated, staged policies in both scopes (including a tier that is all staged contributing nothing to the enforced verdict), HTTP criteria against an L4 flow, Log rules, Pass into the next tier and into profiles, and a policy missing from the store. runNamedCases takes an evaluator for the same reason.

No production code changes. The corpus test runs in about 5 s.

Testing

go test ./app-policy/checker/ -run 'TestEvaluateAgreesWithOracle|TestEvaluateNamedCases' -v   # PASS (5.3s)
go test ./app-policy/checker/                                                                   # ok

Release note:

None

AI assistance: Written with Claude Code (Claude Fable 5.1); the author reviewed the diff and ran the tests above.

By opening this PR you take responsibility for every line in it, and you agree to explain the change yourself during review rather than routing review comments back through an agent. See AI_POLICY.md.

🤖 Generated with Claude Code

…benchmarks

Lift the two synthetic policy sets out of the checker benchmarks into a
package that renders the same set three ways: a policystore.PolicyStore
and endpoint for engine and collector benchmarks, the ToDataplane updates
that load it through ProcessUpdate, and Calico resources (Tier,
GlobalNetworkPolicy, GlobalNetworkSet) for applying it to a cluster. A
number measured at the engine, in the collector and on a node then
describes the same policy set.

The fixture also carries an oracle: Fixture.Expect computes the trace the
engine must report for a flow from the generator's own model of each rule,
independently of the matching code, and MatchingFlow / DeniedFlow /
Sampler produce flows aimed at chosen depths of the walk or following a
flow model (miss fraction, repeat fraction). Later changes to the engine
(compiled policies, a verdict cache, evaluation off the collector's main
loop) are gated on differential tests built on these.

Composite applies both measured shapes to one endpoint: 19,992 ingress
rules, 18,662 egress rules, 7,571 IP sets. BenchmarkEvaluateComposite
measures it in the three cases that matter for the collector; the two
existing benchmarks keep their cases and their numbers.

hack/cmd/policyscale renders a preset as YAML, or prints sampled flows
with their expected verdicts, for node-level runs.

Tracking: CORE-13316.
…yscale oracle

Run Evaluate over a corpus drawn from each policyscale preset (the denied
flow, flows aimed at every 257th rule, sampled flows following a flow
model, and replays as UDP, with an invalid protocol and with nil
addresses) and require the trace to equal the one the fixture's oracle
computes from its own model of the rules, in both policy scopes. The
harness takes two evaluators, so a second implementation of the walk
(compiled policies, a verdict cache, evaluation on another goroutine) is
checked against Evaluate the same way before it is switched on.

The named cases cover what a generated corpus cannot reach: nil
addresses against positive and negated references, named and negated
named ports, IP+port sets, negated and missing sets, protocols out of
range, by name, by number and negated, staged policies in both scopes,
HTTP criteria against an L4 flow, Log rules, Pass into the next tier and
into profiles, and a policy missing from the store. runNamedCases takes
an evaluator for the same reason.

Tracking: CORE-13316.
@dimitri-nicolo dimitri-nicolo added docs-not-required Docs not required for this change release-note-not-required Change has no user-facing impact labels Sep 12, 2026
@marvin-tigera marvin-tigera added this to the Calico v3.34.0 milestone Sep 12, 2026
@github-actions

github-actions Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

CI triage — Calico

Recommendation: Dig deeper before merging

Likely caused by this PR

Test Why
Application Layer Policy: CI golangci-lint failed during static-checks (make[1]: *** [../lib.Makefile:842: golangci-lint] Error 1)
Tools (hack directory): CI golangci-lint failed during static-checks (make[1]: *** [../lib.Makefile:842: golangci-lint] Error 1)

workflow_id: 047eec87-b64f-465e-ac07-25acdb148ddb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-not-required Docs not required for this change release-note-not-required Change has no user-facing impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants