policy/v2: remove obsolete global vs per-node equivalence tests

With the unified compiledGrant infrastructure, there is only one
filter compilation path. The equivalence tests that compared the
old global path against the old per-node path no longer serve a
purpose since both callers now go through the same compileGrants
resolution.

Remove TestACLCompatGlobalEquivalence, TestGrantsCompatGlobalEquivalence,
and TestRoutesCompatGlobalEquivalence.

Updates #3157
This commit is contained in:
Kristoffer Dalby
2026-04-04 16:06:44 +00:00
parent 3065b45310
commit 2469c3eb80
3 changed files with 0 additions and 328 deletions
@@ -514,124 +514,3 @@ func testACLSuccess(
})
}
}
// TestACLCompatGlobalEquivalence verifies that the global filter
// compilation path (PolicyManager.FilterForNode) produces the same
// output as the per-node path (compileFilterRulesForNode +
// ReduceFilterRules) for all ACL golden files that use ACL-only
// policies (no autogroup:self, no via grants).
//
// Files using autogroup:self are skipped because they correctly
// require per-node compilation (needsPerNodeFilter=true), where
// the global path intentionally diverges.
func TestACLCompatGlobalEquivalence(t *testing.T) {
t.Parallel()
files, err := filepath.Glob(
filepath.Join("testdata", "acl_results", "ACL-*.hujson"),
)
require.NoError(t, err)
require.NotEmpty(t, files)
users := setupACLCompatUsers()
nodes := setupACLCompatNodes(users)
tested := 0
skippedSelf := 0
skippedErr := 0
for _, file := range files {
tf := loadACLTestFile(t, file)
t.Run(tf.TestID, func(t *testing.T) {
t.Parallel()
if reason, ok := aclSkipReasons[tf.TestID]; ok {
t.Skipf("TODO: %s", reason)
return
}
if tf.Error {
skippedErr++
t.Skip("error case, not applicable")
return
}
policyJSON := convertPolicyUserEmails(
tf.Input.FullPolicy,
)
// Check if policy uses autogroup:self — if so, the
// global and per-node paths intentionally diverge.
if strings.Contains(string(policyJSON), "autogroup:self") {
skippedSelf++
t.Skip(
"uses autogroup:self, global path " +
"intentionally diverges",
)
return
}
// Per-node path.
pol, err := unmarshalPolicy(policyJSON)
require.NoError(t, err)
err = pol.validate()
require.NoError(t, err)
// Global path.
pm, err := NewPolicyManager(
policyJSON, users, nodes.ViewSlice(),
)
require.NoError(t, err)
for _, node := range nodes {
nv := node.View()
perNodeRules, err := pol.compileFilterRulesForNode(
users, nv, nodes.ViewSlice(),
)
require.NoError(t, err)
perNodeReduced := policyutil.ReduceFilterRules(
nv, perNodeRules,
)
globalReduced, err := pm.FilterForNode(nv)
require.NoError(t, err)
opts := append(
cmpOptions(),
cmpopts.EquateEmpty(),
)
if diff := cmp.Diff(
perNodeReduced,
globalReduced,
opts...,
); diff != "" {
t.Errorf(
"%s/%s: global vs per-node "+
"filter mismatch "+
"(-perNode +global):\n%s",
tf.TestID,
node.GivenName,
diff,
)
}
}
tested++
})
}
t.Logf(
"ACL global equivalence: tested=%d, "+
"skippedSelf=%d, skippedErr=%d",
tested, skippedSelf, skippedErr,
)
}
@@ -618,116 +618,3 @@ func testGrantSuccess(
})
}
}
// TestGrantsCompatGlobalEquivalence verifies that the global filter
// compilation path (PolicyManager.FilterForNode) produces the same
// output as the per-node path (compileFilterRulesForNode +
// ReduceFilterRules) for all GRANT golden files that don't require
// per-node compilation.
//
// Files using via grants or autogroup:self are skipped because they
// correctly require per-node compilation (needsPerNodeFilter=true).
func TestGrantsCompatGlobalEquivalence(t *testing.T) {
t.Parallel()
files, err := filepath.Glob(
filepath.Join("testdata", "grant_results", "GRANT-*.hujson"),
)
require.NoError(t, err)
require.NotEmpty(t, files)
users := setupGrantsCompatUsers()
allNodes := setupGrantsCompatNodes(users)
for _, file := range files {
tf := loadGrantTestFile(t, file)
t.Run(tf.TestID, func(t *testing.T) {
t.Parallel()
if reason, ok := grantSkipReasons[tf.TestID]; ok {
t.Skipf("TODO: %s", reason)
return
}
if tf.Error {
t.Skip("error case")
return
}
policyJSON := convertPolicyUserEmails(
tf.Input.FullPolicy,
)
policyStr := string(policyJSON)
// Skip files that require per-node compilation.
if strings.Contains(policyStr, "autogroup:self") {
t.Skip("uses autogroup:self")
return
}
if strings.Contains(policyStr, "\"via\"") {
t.Skip("uses via grants")
return
}
// Select nodes based on topology size.
nodes := allNodes
if _, hasNewNodes := tf.Captures["exit-a"]; !hasNewNodes {
nodes = allNodes[:8]
}
// Per-node path.
pol, err := unmarshalPolicy(policyJSON)
require.NoError(t, err)
err = pol.validate()
require.NoError(t, err)
// Global path.
pm, err := NewPolicyManager(
policyJSON, users, nodes.ViewSlice(),
)
require.NoError(t, err)
for _, node := range nodes {
nv := node.View()
perNodeRules, err := pol.compileFilterRulesForNode(
users, nv, nodes.ViewSlice(),
)
require.NoError(t, err)
perNodeReduced := policyutil.ReduceFilterRules(
nv, perNodeRules,
)
globalReduced, err := pm.FilterForNode(nv)
require.NoError(t, err)
opts := append(
cmpOptions(),
cmpopts.EquateEmpty(),
)
if diff := cmp.Diff(
perNodeReduced,
globalReduced,
opts...,
); diff != "" {
t.Errorf(
"%s/%s: global vs per-node "+
"filter mismatch "+
"(-perNode +global):\n%s",
tf.TestID,
node.GivenName,
diff,
)
}
}
})
}
}
@@ -1092,100 +1092,6 @@ func TestRoutesCompatReduceRoutes(t *testing.T) {
}
}
// TestRoutesCompatGlobalEquivalence verifies that the global filter
// compilation path (compileFilterRules + ReduceFilterRules, used in
// production for ACL-only policies) produces the same output as the
// per-node path (compileFilterRulesForNode + ReduceFilterRules, used
// by TestRoutesCompat).
//
// All 98 ROUTES golden files use ACL-only policies (no autogroup:self,
// no via grants), so production code takes the global path. The
// TestRoutesCompat test always uses the per-node path. If these two
// paths ever diverge, this test will detect it.
func TestRoutesCompatGlobalEquivalence(t *testing.T) {
t.Parallel()
files, err := filepath.Glob(
filepath.Join("testdata", "routes_results", "ROUTES-*.hujson"),
)
require.NoError(t, err, "failed to glob test files")
require.NotEmpty(
t,
files,
"no ROUTES-*.hujson test files found",
)
for _, file := range files {
tf := loadRoutesTestFile(t, file)
t.Run(tf.TestID, func(t *testing.T) {
t.Parallel()
if reason, ok := routesSkipReasons[tf.TestID]; ok {
t.Skipf("TODO: %s", reason)
return
}
users, nodes := buildRoutesUsersAndNodes(t, tf.Topology)
policyJSON := convertPolicyUserEmails(tf.Input.FullPolicy)
// Per-node path: compile per-node, then reduce.
pol, err := unmarshalPolicy(policyJSON)
require.NoError(t, err)
err = pol.validate()
require.NoError(t, err)
// Global path: create PolicyManager (compiles global
// filter internally).
pm, err := NewPolicyManager(
policyJSON, users, nodes.ViewSlice(),
)
require.NoError(t, err,
"%s: failed to create PolicyManager", tf.TestID,
)
for _, node := range nodes {
nv := node.View()
// Per-node path (what TestRoutesCompat uses).
perNodeRules, err := pol.compileFilterRulesForNode(
users, nv, nodes.ViewSlice(),
)
require.NoError(t, err)
perNodeReduced := policyutil.ReduceFilterRules(
nv, perNodeRules,
)
// Global path (what production FilterForNode
// uses for ACL-only policies).
globalReduced, err := pm.FilterForNode(nv)
require.NoError(t, err)
opts := append(
cmpOptions(),
cmpopts.EquateEmpty(),
)
if diff := cmp.Diff(
perNodeReduced,
globalReduced,
opts...,
); diff != "" {
t.Errorf(
"%s/%s: global vs per-node filter "+
"mismatch (-perNode +global):\n%s",
tf.TestID,
node.GivenName,
diff,
)
}
}
})
}
}
// TestRoutesCompatExitNodePeerVisibility validates that CanAccess
// correctly handles exit node peer visibility for the b-series golden
// files. These files exercise exit route behaviors (b1-b10) which