From 0cb9536784b133aaf44e4ff9e4d75ec7e79775ab Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sat, 4 Apr 2026 16:06:44 +0000 Subject: [PATCH] policy/v2: remove obsolete equivalence tests Updates #3157 --- .../v2/tailscale_acl_data_compat_test.go | 121 ------------------ .../policy/v2/tailscale_grants_compat_test.go | 113 ---------------- .../v2/tailscale_routes_data_compat_test.go | 94 -------------- 3 files changed, 328 deletions(-) diff --git a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go index 03b73fe5..1c97bed3 100644 --- a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go @@ -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, - ) -} diff --git a/hscontrol/policy/v2/tailscale_grants_compat_test.go b/hscontrol/policy/v2/tailscale_grants_compat_test.go index df53f1fd..c87f1fc3 100644 --- a/hscontrol/policy/v2/tailscale_grants_compat_test.go +++ b/hscontrol/policy/v2/tailscale_grants_compat_test.go @@ -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, - ) - } - } - }) - } -} diff --git a/hscontrol/policy/v2/tailscale_routes_data_compat_test.go b/hscontrol/policy/v2/tailscale_routes_data_compat_test.go index 458bb3a1..14c677a5 100644 --- a/hscontrol/policy/v2/tailscale_routes_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_routes_data_compat_test.go @@ -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