From d0a2a0d22e760abe7103da4908bb86d12d7f6e13 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Fri, 17 Oct 2025 16:31:39 +0200 Subject: [PATCH] e2e: find and fix reuse of test names This reports and fixes for test/e2e: ERROR: E2E suite initialization was faulty, these errors must be fixed: ERROR: apimachinery/mutatingadmissionpolicy.go:184: full test name is not unique: "[sig-api-machinery] MutatingAdmissionPolicy [Privileged:ClusterAdmin] [Feature:MutatingAdmissionPolicy] [FeatureGate:MutatingAdmissionPolicy] [Beta] [Feature:OffByDefault] should support MutatingAdmissionPolicy API operations" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e/apimachinery/mutatingadmissionpolicy.go:184, /nvme/gopath/src/k8s.io/kubernetes/test/e2e/apimachinery/mutatingadmissionpolicy.go:606) ERROR: apimachinery/mutatingadmissionpolicy.go:412: full test name is not unique: "[sig-api-machinery] MutatingAdmissionPolicy [Privileged:ClusterAdmin] [Feature:MutatingAdmissionPolicy] [FeatureGate:MutatingAdmissionPolicy] [Beta] [Feature:OffByDefault] should support MutatingAdmissionPolicyBinding API operations" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e/apimachinery/mutatingadmissionpolicy.go:412, /nvme/gopath/src/k8s.io/kubernetes/test/e2e/apimachinery/mutatingadmissionpolicy.go:834) ERROR: common/node/pod_level_resources.go:250: full test name is not unique: "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Guaranteed QoS pod with container resources" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e/common/node/pod_level_resources.go:250 (2x)) ERROR: dra/dra.go:1899: full test name is not unique: "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAConsumableCapacity] [Alpha] [Feature:OffByDefault] [FeatureGate:DynamicResourceAllocation] must allow multiple allocations and consume capacity [KubeletMinVersion:1.34]" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e/dra/dra.go:1899 (2x)) ERROR: storage/testsuites/volume_group_snapshottable.go:173: full test name is not unique: "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e/storage/testsuites/volume_group_snapshottable.go:173 (2x)) ERROR: storage/testsuites/volume_group_snapshottable.go:173: full test name is not unique: "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e/storage/testsuites/volume_group_snapshottable.go:173 (2x)) And for test/e2e_node: ERROR: cpu_manager_test.go:1622: full test name is not unique: "[sig-node] CPU Manager [Serial] [Feature:CPUManager] when checking the CFS quota management should disable for guaranteed pod with exclusive CPUs assigned" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e_node/cpu_manager_test.go:1622, /nvme/gopath/src/k8s.io/kubernetes/test/e2e_node/cpu_manager_test.go:1642) ERROR: eviction_test.go:800: full test name is not unique: "[sig-node] LocalStorageCapacityIsolationFSQuotaMonitoring [Slow] [Serial] [Disruptive] [Feature:LocalStorageCapacityIsolationQuota] [Feature:LSCIQuotaMonitoring] [Feature:UserNamespacesSupport] when we run containers that should cause use quotas for LSCI monitoring (quotas enabled: true) should eventually evict all of the correct pods" (/nvme/gopath/src/k8s.io/kubernetes/test/e2e_node/eviction_test.go:800 (2x)) --- .../apimachinery/mutatingadmissionpolicy.go | 11 ++++--- test/e2e/common/node/pod_level_resources.go | 4 +-- test/e2e/dra/dra.go | 2 -- test/e2e/framework/ginkgowrapper.go | 31 +++++++++++++++++++ test/e2e/storage/testsuites/base.go | 5 +-- test/e2e_node/cpu_manager_test.go | 4 +-- test/e2e_node/quota_lsci_test.go | 2 +- 7 files changed, 45 insertions(+), 14 deletions(-) diff --git a/test/e2e/apimachinery/mutatingadmissionpolicy.go b/test/e2e/apimachinery/mutatingadmissionpolicy.go index e6309e12d3e..093a5c12290 100644 --- a/test/e2e/apimachinery/mutatingadmissionpolicy.go +++ b/test/e2e/apimachinery/mutatingadmissionpolicy.go @@ -19,11 +19,12 @@ package apimachinery import ( "context" "fmt" + "time" + admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1" "k8s.io/apiserver/pkg/features" "k8s.io/kubernetes/test/e2e/feature" "k8s.io/utils/ptr" - "time" "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" @@ -181,7 +182,7 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature The mutatingadmisionpolicy resource must support create, get, list, watch, update, patch, delete, and deletecollection. */ - framework.It("should support MutatingAdmissionPolicy API operations", func(ctx context.Context) { + framework.It("should support MutatingAdmissionPolicy v1alpha1 API operations", func(ctx context.Context) { mapVersion := "v1alpha1" ginkgo.By("getting /apis") { @@ -409,7 +410,7 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature The MutatingadmissionPolicyBinding resource must support create, get, list, watch, update, patch, delete, and deletecollection. */ - framework.It("should support MutatingAdmissionPolicyBinding API operations", func(ctx context.Context) { + framework.It("should support MutatingAdmissionPolicyBinding v1alpha1 API operations", func(ctx context.Context) { mapbVersion := "v1alpha1" ginkgo.By("getting /apis") { @@ -603,7 +604,7 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature The mutatingadmisionpolicy resource must support create, get, list, watch, update, patch, delete, and deletecollection. */ - framework.It("should support MutatingAdmissionPolicy API operations", func(ctx context.Context) { + framework.It("should support MutatingAdmissionPolicy v1beta1 API operations", func(ctx context.Context) { mapVersion := "v1beta1" ginkgo.By("getting /apis") { @@ -831,7 +832,7 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature The MutatingadmissionPolicyBinding resource must support create, get, list, watch, update, patch, delete, and deletecollection. */ - framework.It("should support MutatingAdmissionPolicyBinding API operations", func(ctx context.Context) { + framework.It("should support MutatingAdmissionPolicyBinding v1beta1 API operations", func(ctx context.Context) { mapbVersion := "v1beta1" ginkgo.By("getting /apis") { diff --git a/test/e2e/common/node/pod_level_resources.go b/test/e2e/common/node/pod_level_resources.go index cfb88e23186..07f91c4102a 100644 --- a/test/e2e/common/node/pod_level_resources.go +++ b/test/e2e/common/node/pod_level_resources.go @@ -185,7 +185,7 @@ func podLevelResourcesTests(f *framework.Framework) { }, }, { - name: "Guaranteed QoS pod with container resources", + name: "Guaranteed QoS pod with other container resources", podResources: &cgroups.ContainerResources{CPUReq: "100m", CPULim: "100m", MemReq: "100Mi", MemLim: "100Mi"}, containers: []containerInfo{ {Name: "c1", Resources: &cgroups.ContainerResources{CPUReq: "50m", CPULim: "100m", MemReq: "50Mi", MemLim: "100Mi"}}, @@ -221,7 +221,7 @@ func podLevelResourcesTests(f *framework.Framework) { }, }, { - name: "Burstable QoS pod with container resources", + name: "Burstable QoS pod with yet some other container resources", podResources: &cgroups.ContainerResources{CPUReq: "50m", CPULim: "100m", MemReq: "50Mi", MemLim: "100Mi"}, containers: []containerInfo{ {Name: "c1", Resources: &cgroups.ContainerResources{CPUReq: "20m", CPULim: "100m", MemReq: "20Mi", MemLim: "100Mi"}}, diff --git a/test/e2e/dra/dra.go b/test/e2e/dra/dra.go index 8bdae9ec8b4..b278a3e1cc8 100644 --- a/test/e2e/dra/dra.go +++ b/test/e2e/dra/dra.go @@ -1965,8 +1965,6 @@ var _ = framework.SIGDescribe("node")(framework.WithLabel("DRA"), func() { framework.Context("kubelet", feature.DynamicResourceAllocation, f.WithFeatureGate(features.DRAConsumableCapacity), consumableCapacityTests) - framework.Context("kubelet", feature.DynamicResourceAllocation, f.WithFeatureGate(features.DRAConsumableCapacity), consumableCapacityTests) - framework.Context("kubelet", feature.DynamicResourceAllocation, "with v1beta1 API", v1beta1Tests) framework.Context("kubelet", feature.DynamicResourceAllocation, "with v1beta2 API", v1beta2Tests) diff --git a/test/e2e/framework/ginkgowrapper.go b/test/e2e/framework/ginkgowrapper.go index 06d6974ad96..4c9ea3551e2 100644 --- a/test/e2e/framework/ginkgowrapper.go +++ b/test/e2e/framework/ginkgowrapper.go @@ -266,6 +266,9 @@ var ( func validateSpecs(specs types.SpecReports) { checked := sets.New[call]() + // Each full test name should only be used once. + specNames := make(map[string][]types.SpecReport) + for _, spec := range specs { for i, text := range spec.ContainerHierarchyTexts { c := call{ @@ -287,6 +290,34 @@ func validateSpecs(specs types.SpecReports) { validateText(spec.LeafNodeLocation, spec.LeafNodeText, spec.LeafNodeLabels) checked.Insert(c) } + + // Track what the same name is used for. The empty name is used more + // than once for special nodes (e.g. ReportAfterSuite). + fullText := spec.FullText() + if fullText != "" { + specNames[fullText] = append(specNames[fullText], spec) + } + } + + for fullText, specs := range specNames { + if len(specs) > 1 { + // The exact same It call might be made twice, in which case full + // text and location are the same in two different specs. We show + // that as " (2x)" + locationCounts := make(map[string]int) + for _, spec := range specs { + locationCounts[spec.LeafNodeLocation.String()]++ + } + var locationTexts []string + for locationText, count := range locationCounts { + text := locationText + if count > 1 { + text += fmt.Sprintf(" (%dx)", count) + } + locationTexts = append(locationTexts, text) + } + recordTextBug(specs[0].LeafNodeLocation, fmt.Sprintf("full test name is not unique: %q (%s)", fullText, strings.Join(locationTexts, ", "))) + } } } diff --git a/test/e2e/storage/testsuites/base.go b/test/e2e/storage/testsuites/base.go index 5dd2e8208c3..0208e59cf7a 100644 --- a/test/e2e/storage/testsuites/base.go +++ b/test/e2e/storage/testsuites/base.go @@ -74,13 +74,14 @@ var BaseSuites = []func() storageframework.TestSuite{ }, } -// CSISuites is a list of storage test suites that work only for CSI drivers +// CSISuites is a list of storage test suites that work only for CSI drivers. var CSISuites = append(BaseSuites, + // The following tests suites must not be already in BaseSuites, + // otherwise the same configuration gets tested multiple times. func() storageframework.TestSuite { return InitCustomEphemeralTestSuite(CSIEphemeralTestPatterns()) }, InitSnapshottableTestSuite, - InitVolumeGroupSnapshottableTestSuite, InitSnapshottableStressTestSuite, InitVolumePerformanceTestSuite, InitPvcDeletionPerformanceTestSuite, diff --git a/test/e2e_node/cpu_manager_test.go b/test/e2e_node/cpu_manager_test.go index fa593d124c4..bd704bbffae 100644 --- a/test/e2e_node/cpu_manager_test.go +++ b/test/e2e_node/cpu_manager_test.go @@ -1619,7 +1619,7 @@ var _ = SIGDescribe("CPU Manager", ginkgo.Ordered, ginkgo.ContinueOnFailure, fra gomega.Expect(pod).To(HaveContainerQuota(ctnName, "max")) }) - ginkgo.It("should disable for guaranteed pod with exclusive CPUs assigned", func(ctx context.Context) { + ginkgo.It("should disable for guaranteed pod with exclusive single CPU assigned", func(ctx context.Context) { cpuCount := 1 skipIfAllocatableCPUsLessThan(getLocalNode(ctx, f), cpuCount) @@ -1639,7 +1639,7 @@ var _ = SIGDescribe("CPU Manager", ginkgo.Ordered, ginkgo.ContinueOnFailure, fra gomega.Expect(pod).To(HaveContainerQuota(ctnName, "max")) }) - ginkgo.It("should disable for guaranteed pod with exclusive CPUs assigned", func(ctx context.Context) { + ginkgo.It("should disable for guaranteed pod with exclusive four CPUs assigned", func(ctx context.Context) { cpuCount := 4 skipIfAllocatableCPUsLessThan(getLocalNode(ctx, f), cpuCount) diff --git a/test/e2e_node/quota_lsci_test.go b/test/e2e_node/quota_lsci_test.go index 3992b4ed0b5..922fd12a005 100644 --- a/test/e2e_node/quota_lsci_test.go +++ b/test/e2e_node/quota_lsci_test.go @@ -57,7 +57,7 @@ func runOneQuotaTest(f *framework.Framework, quotasRequested bool, userNamespace if quotasRequested { priority = 1 } - ginkgo.Context(fmt.Sprintf(testContextFmt, fmt.Sprintf("use quotas for LSCI monitoring (quotas enabled: %v)", quotasRequested)), func() { + ginkgo.Context(fmt.Sprintf(testContextFmt, fmt.Sprintf("use quotas for LSCI monitoring (quotas enabled: %v, userNamespacesEnabled: %v)", quotasRequested, userNamespacesEnabled)), func() { tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) { defer withFeatureGate(LSCIQuotaFeature, quotasRequested)() // TODO: remove hardcoded kubelet volume directory path