Skip to content
Merged
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
45 changes: 45 additions & 0 deletions hack/verify-e2e-suites.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash

# Copyright 2021 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This script checks that all E2E test suites are sane, i.e. can be
# started without an error.

set -o errexit
set -o nounset
set -o pipefail

KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${KUBE_ROOT}/hack/lib/init.sh"
source "${KUBE_ROOT}/hack/lib/util.sh"

kube::golang::verify_go_version

cd "${KUBE_ROOT}"

kube::util::ensure-temp-dir

for suite in $(git grep -l framework.AfterReadingAllFlags | grep -v -e ^test/e2e/framework -e ^hack | xargs -n 1 dirname | sort -u); do
# Build a binary and run it in the root directory to get paths that are
# relative to that instead of the package directory.
out=""
if (cd "$suite" && go test -c -o "${KUBE_TEMP}/e2e.bin" .) && out=$("${KUBE_TEMP}/e2e.bin" --list-tests); then
echo "E2E suite $suite passed."
else
echo >&2 "ERROR: E2E test suite invocation failed for $suite."
# shellcheck disable=SC2001
echo "$out" | sed -e 's/^/ /'
fi
done
6 changes: 2 additions & 4 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,10 @@ import (
// test/e2e/lifecycle/framework.go
package lifecycle

import "github.com/onsi/ginkgo"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-cluster-lifecycle] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("cluster-lifecycle")
```
```golang
// test/e2e/lifecycle/bootstrap/bootstrap_signer.go
Expand Down
6 changes: 2 additions & 4 deletions test/e2e/apimachinery/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package apimachinery

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-api-machinery] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("api-machinery")
6 changes: 2 additions & 4 deletions test/e2e/apps/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package apps

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-apps] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("apps")
6 changes: 2 additions & 4 deletions test/e2e/architecture/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package architecture

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-architecture] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("architecture")
6 changes: 2 additions & 4 deletions test/e2e/auth/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package auth

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-auth] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("auth")
6 changes: 2 additions & 4 deletions test/e2e/autoscaling/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package autoscaling

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-autoscaling] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("autoscaling")
6 changes: 2 additions & 4 deletions test/e2e/cloud/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package cloud

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-cloud-provider] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("cloud-provider")
6 changes: 2 additions & 4 deletions test/e2e/cloud/gcp/apps/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package apps

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-apps] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("apps")
6 changes: 2 additions & 4 deletions test/e2e/cloud/gcp/auth/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package auth

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-auth] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("auth")
6 changes: 2 additions & 4 deletions test/e2e/cloud/gcp/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package gcp

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-cloud-provider-gcp] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("cloud-provider-gcp")
6 changes: 2 additions & 4 deletions test/e2e/cloud/gcp/network/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package network

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-network] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("network")
6 changes: 2 additions & 4 deletions test/e2e/cloud/gcp/node/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package node

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-node] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("node")
6 changes: 2 additions & 4 deletions test/e2e/common/network/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package network

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-network] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("network")
7 changes: 2 additions & 5 deletions test/e2e/common/node/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ limitations under the License.

package node

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-node] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("node")
6 changes: 2 additions & 4 deletions test/e2e/common/storage/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ limitations under the License.

package storage

import "github.com/onsi/ginkgo/v2"
import "k8s.io/kubernetes/test/e2e/framework"

// SIGDescribe annotates the test with the SIG label.
func SIGDescribe(text string, body func()) bool {
return ginkgo.Describe("[sig-storage] "+text, body)
}
var SIGDescribe = framework.SIGDescribe("storage")
4 changes: 4 additions & 0 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ import (
e2etestingmanifests "k8s.io/kubernetes/test/e2e/testing-manifests"
testfixtures "k8s.io/kubernetes/test/fixtures"

// define and freeze constants
_ "k8s.io/kubernetes/test/e2e/feature"
_ "k8s.io/kubernetes/test/e2e/nodefeature"

// test sources
_ "k8s.io/kubernetes/test/e2e/apimachinery"
_ "k8s.io/kubernetes/test/e2e/apps"
Expand Down
132 changes: 132 additions & 0 deletions test/e2e/feature/feature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
Copyright 2023 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package feature contains pre-defined features used by test/e2e and/or
// test/e2e_node.
Copy link
Member

Choose a reason for hiding this comment

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

how do we keep this in sync with the pkg/features?

didn't we talked about using those values directly so tests and feature gates are in sync by code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We did, and you said:

I think that we should not create this relation Feature <---> FeatureGate, those are independent things that some times be related, a FeatureGate doesn't have to be related to a Feature necessarily.

This file here is about features, not feature gates (= pkg/features), and thus intentionally not forced to be in sync.

Copy link
Member

Choose a reason for hiding this comment

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

oh, you caught me there, I missed that detail, so we call Feature something like NetworkPolicy or Ingress, sorry about that, I stand on my previous position :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, we should have that separation. But nonetheless it is confusing and we'll need very good guidance in the pending KEP and the framework about when to use FeatureGate and when Feature.

I also still wonder whether we can come up with a different name than Feature. It's just too close to FeatureGate.

Copy link
Member

Choose a reason for hiding this comment

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

@SergeyKanzhelev you will be interested on this PR, since you started the discussion here https://github.com/kubernetes/enhancements/pull/3042/files#r988729747 :)

package feature

import (
"k8s.io/kubernetes/test/e2e/framework"
)

var (
APIServerIdentity = framework.WithFeature(framework.ValidFeatures.Add("APIServerIdentity"))
AppArmor = framework.WithFeature(framework.ValidFeatures.Add("AppArmor"))
BootstrapTokens = framework.WithFeature(framework.ValidFeatures.Add("BootstrapTokens"))
BoundServiceAccountTokenVolume = framework.WithFeature(framework.ValidFeatures.Add("BoundServiceAccountTokenVolume"))
CloudProvider = framework.WithFeature(framework.ValidFeatures.Add("CloudProvider"))
ClusterAutoscalerScalability1 = framework.WithFeature(framework.ValidFeatures.Add("ClusterAutoscalerScalability1"))
ClusterAutoscalerScalability2 = framework.WithFeature(framework.ValidFeatures.Add("ClusterAutoscalerScalability2"))
ClusterAutoscalerScalability3 = framework.WithFeature(framework.ValidFeatures.Add("ClusterAutoscalerScalability3"))
ClusterAutoscalerScalability4 = framework.WithFeature(framework.ValidFeatures.Add("ClusterAutoscalerScalability4"))
ClusterAutoscalerScalability5 = framework.WithFeature(framework.ValidFeatures.Add("ClusterAutoscalerScalability5"))
ClusterAutoscalerScalability6 = framework.WithFeature(framework.ValidFeatures.Add("ClusterAutoscalerScalability6"))
ClusterDowngrade = framework.WithFeature(framework.ValidFeatures.Add("ClusterDowngrade"))
ClusterSizeAutoscalingGpu = framework.WithFeature(framework.ValidFeatures.Add("ClusterSizeAutoscalingGpu"))
ClusterSizeAutoscalingScaleDown = framework.WithFeature(framework.ValidFeatures.Add("ClusterSizeAutoscalingScaleDown"))
ClusterSizeAutoscalingScaleUp = framework.WithFeature(framework.ValidFeatures.Add("ClusterSizeAutoscalingScaleUp"))
ClusterUpgrade = framework.WithFeature(framework.ValidFeatures.Add("ClusterUpgrade"))
ComprehensiveNamespaceDraining = framework.WithFeature(framework.ValidFeatures.Add("ComprehensiveNamespaceDraining"))
CPUManager = framework.WithFeature(framework.ValidFeatures.Add("CPUManager"))
CustomMetricsAutoscaling = framework.WithFeature(framework.ValidFeatures.Add("CustomMetricsAutoscaling"))
DeviceManager = framework.WithFeature(framework.ValidFeatures.Add("DeviceManager"))
DevicePluginProbe = framework.WithFeature(framework.ValidFeatures.Add("DevicePluginProbe"))
Downgrade = framework.WithFeature(framework.ValidFeatures.Add("Downgrade"))
DynamicResourceAllocation = framework.WithFeature(framework.ValidFeatures.Add("DynamicResourceAllocation"))
EphemeralStorage = framework.WithFeature(framework.ValidFeatures.Add("EphemeralStorage"))
Example = framework.WithFeature(framework.ValidFeatures.Add("Example"))
ExperimentalResourceUsageTracking = framework.WithFeature(framework.ValidFeatures.Add("ExperimentalResourceUsageTracking"))
Flexvolumes = framework.WithFeature(framework.ValidFeatures.Add("Flexvolumes"))
GKENodePool = framework.WithFeature(framework.ValidFeatures.Add("GKENodePool"))
GPUClusterDowngrade = framework.WithFeature(framework.ValidFeatures.Add("GPUClusterDowngrade"))
GPUClusterUpgrade = framework.WithFeature(framework.ValidFeatures.Add("GPUClusterUpgrade"))
GPUDevicePlugin = framework.WithFeature(framework.ValidFeatures.Add("GPUDevicePlugin"))
GPUMasterUpgrade = framework.WithFeature(framework.ValidFeatures.Add("GPUMasterUpgrade"))
GPUUpgrade = framework.WithFeature(framework.ValidFeatures.Add("GPUUpgrade"))
HAMaster = framework.WithFeature(framework.ValidFeatures.Add("HAMaster"))
HPA = framework.WithFeature(framework.ValidFeatures.Add("HPA"))
HugePages = framework.WithFeature(framework.ValidFeatures.Add("HugePages"))
Ingress = framework.WithFeature(framework.ValidFeatures.Add("Ingress"))
IngressScale = framework.WithFeature(framework.ValidFeatures.Add("IngressScale"))
InPlacePodVerticalScaling = framework.WithFeature(framework.ValidFeatures.Add("InPlacePodVerticalScaling"))
IPv6DualStack = framework.WithFeature(framework.ValidFeatures.Add("IPv6DualStack"))
Kind = framework.WithFeature(framework.ValidFeatures.Add("Kind"))
KubeletCredentialProviders = framework.WithFeature(framework.ValidFeatures.Add("KubeletCredentialProviders"))
KubeletSecurity = framework.WithFeature(framework.ValidFeatures.Add("KubeletSecurity"))
KubeProxyDaemonSetDowngrade = framework.WithFeature(framework.ValidFeatures.Add("KubeProxyDaemonSetDowngrade"))
KubeProxyDaemonSetUpgrade = framework.WithFeature(framework.ValidFeatures.Add("KubeProxyDaemonSetUpgrade"))
KubeProxyDaemonSetMigration = framework.WithFeature(framework.ValidFeatures.Add("KubeProxyDaemonSetMigration"))
LabelSelector = framework.WithFeature(framework.ValidFeatures.Add("LabelSelector"))
LocalStorageCapacityIsolation = framework.WithFeature(framework.ValidFeatures.Add("LocalStorageCapacityIsolation"))
LocalStorageCapacityIsolationQuota = framework.WithFeature(framework.ValidFeatures.Add("LocalStorageCapacityIsolationQuota"))
MasterUpgrade = framework.WithFeature(framework.ValidFeatures.Add("MasterUpgrade"))
MemoryManager = framework.WithFeature(framework.ValidFeatures.Add("MemoryManager"))
NEG = framework.WithFeature(framework.ValidFeatures.Add("NEG"))
NetworkingDNS = framework.WithFeature(framework.ValidFeatures.Add("Networking-DNS"))
NetworkingIPv4 = framework.WithFeature(framework.ValidFeatures.Add("Networking-IPv4"))
NetworkingIPv6 = framework.WithFeature(framework.ValidFeatures.Add("Networking-IPv6"))
NetworkingPerformance = framework.WithFeature(framework.ValidFeatures.Add("Networking-Performance"))
NetworkPolicy = framework.WithFeature(framework.ValidFeatures.Add("NetworkPolicy"))
NodeAuthenticator = framework.WithFeature(framework.ValidFeatures.Add("NodeAuthenticator"))
NodeAuthorizer = framework.WithFeature(framework.ValidFeatures.Add("NodeAuthorizer"))
NodeOutOfServiceVolumeDetach = framework.WithFeature(framework.ValidFeatures.Add("NodeOutOfServiceVolumeDetach"))
NoSNAT = framework.WithFeature(framework.ValidFeatures.Add("NoSNAT"))
PerformanceDNS = framework.WithFeature(framework.ValidFeatures.Add("PerformanceDNS"))
PodGarbageCollector = framework.WithFeature(framework.ValidFeatures.Add("PodGarbageCollector"))
PodPriority = framework.WithFeature(framework.ValidFeatures.Add("PodPriority"))
PodReadyToStartContainersCondition = framework.WithFeature(framework.ValidFeatures.Add("PodReadyToStartContainersCondition"))
PodResources = framework.WithFeature(framework.ValidFeatures.Add("PodResources"))
ProbeTerminationGracePeriod = framework.WithFeature(framework.ValidFeatures.Add("ProbeTerminationGracePeriod"))
Reboot = framework.WithFeature(framework.ValidFeatures.Add("Reboot"))
ReclaimPolicy = framework.WithFeature(framework.ValidFeatures.Add("ReclaimPolicy"))
RecoverVolumeExpansionFailure = framework.WithFeature(framework.ValidFeatures.Add("RecoverVolumeExpansionFailure"))
Recreate = framework.WithFeature(framework.ValidFeatures.Add("Recreate"))
RegularResourceUsageTracking = framework.WithFeature(framework.ValidFeatures.Add("RegularResourceUsageTracking"))
ScopeSelectors = framework.WithFeature(framework.ValidFeatures.Add("ScopeSelectors"))
SCTPConnectivity = framework.WithFeature(framework.ValidFeatures.Add("SCTPConnectivity"))
SeccompDefault = framework.WithFeature(framework.ValidFeatures.Add("SeccompDefault"))
SELinux = framework.WithFeature(framework.ValidFeatures.Add("SELinux"))
SELinuxMountReadWriteOncePod = framework.WithFeature(framework.ValidFeatures.Add("SELinuxMountReadWriteOncePod"))
StackdriverAcceleratorMonitoring = framework.WithFeature(framework.ValidFeatures.Add("StackdriverAcceleratorMonitoring"))
StackdriverCustomMetrics = framework.WithFeature(framework.ValidFeatures.Add("StackdriverCustomMetrics"))
StackdriverExternalMetrics = framework.WithFeature(framework.ValidFeatures.Add("StackdriverExternalMetrics"))
StackdriverMetadataAgent = framework.WithFeature(framework.ValidFeatures.Add("StackdriverMetadataAgent"))
StackdriverMonitoring = framework.WithFeature(framework.ValidFeatures.Add("StackdriverMonitoring"))
StandaloneMode = framework.WithFeature(framework.ValidFeatures.Add("StandaloneMode"))
StatefulSet = framework.WithFeature(framework.ValidFeatures.Add("StatefulSet"))
StatefulSetStartOrdinal = framework.WithFeature(framework.ValidFeatures.Add("StatefulSetStartOrdinal"))
StatefulUpgrade = framework.WithFeature(framework.ValidFeatures.Add("StatefulUpgrade"))
StorageProvider = framework.WithFeature(framework.ValidFeatures.Add("StorageProvider"))
StorageVersionAPI = framework.WithFeature(framework.ValidFeatures.Add("StorageVersionAPI"))
TopologyHints = framework.WithFeature(framework.ValidFeatures.Add("Topology Hints"))
UDP = framework.WithFeature(framework.ValidFeatures.Add("UDP"))
Upgrade = framework.WithFeature(framework.ValidFeatures.Add("Upgrade"))
UserNamespacesStatelessPodsSupport = framework.WithFeature(framework.ValidFeatures.Add("UserNamespacesStatelessPodsSupport"))
ValidatingAdmissionPolicy = framework.WithFeature(framework.ValidFeatures.Add("ValidatingAdmissionPolicy"))
Volumes = framework.WithFeature(framework.ValidFeatures.Add("Volumes"))
VolumeSnapshotDataSource = framework.WithFeature(framework.ValidFeatures.Add("VolumeSnapshotDataSource"))
VolumeSourceXFS = framework.WithFeature(framework.ValidFeatures.Add("VolumeSourceXFS"))
Vsphere = framework.WithFeature(framework.ValidFeatures.Add("vsphere"))
WatchList = framework.WithFeature(framework.ValidFeatures.Add("WatchList"))
Windows = framework.WithFeature(framework.ValidFeatures.Add("Windows"))
WindowsHostProcessContainers = framework.WithFeature(framework.ValidFeatures.Add("WindowsHostProcessContainers"))
WindowsHyperVContainers = framework.WithFeature(framework.ValidFeatures.Add("WindowsHyperVContainers"))
)

func init() {
// This prevents adding additional ad-hoc features in tests.
Copy link
Member

Choose a reason for hiding this comment

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

didn't have time to go through the whole PR logic, do you mind explain how this prevents that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Once this package is done with registering the pre-defined features, it locks the registry. Tests that import this package then cannot add more of them.

There is a loophole: a test that doesn't import the package could define features during its own init and, depending on the order in which packages get initialized, might succeed with that. This is only a problem for init. Describe callbacks get invoked after the global init, so something like this will always fail:

_ = Describe("foo", func() {
   It("bar", framework.WithFeature("my-custom-feature"), func() { ...})
})

We can also drop this locking and rely instead on code reviews to prevent a proliferation of arbitrary feature tags. I'm open for suggestions here.

Copy link
Member

Choose a reason for hiding this comment

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

everything that is not automated is doomed to fail XD

framework.ValidFeatures.Freeze()
}
Loading