Repository: kubernetes/kubernetes
File: staging/src/k8s.io/client-go/features/testing/features.go (Go)

Code before:
	"strings"
	"sync"
	"testing"

	clientfeatures "k8s.io/client-go/features"
)

var (
	overriddenFeaturesLock sync.Mutex
	overriddenFeatures     map[clientfeatures.Feature]string
)

func init() {
	overriddenFeatures = map[clientfeatures.Feature]string{}
}

type featureGatesSetter interface {
	clientfeatures.Gates

	Set(clientfeatures.Feature, bool) error
	SetForTesting(clientfeatures.Feature, bool) error
}

// SetFeatureDuringTest sets the specified feature to the specified value for the duration of the test.
//
// Example use:
//
//	clientfeaturestesting.SetFeatureDuringTest(t, clientfeatures.WatchListClient, true)
func SetFeatureDuringTest(tb testing.TB, feature clientfeatures.Feature, featureValue bool) {
	if err := setFeatureDuringTestInternal(tb, feature, featureValue); err != nil {
		tb.Fatal(err)
	}
}

func setFeatureDuringTestInternal(tb testing.TB, feature clientfeatures.Feature, featureValue bool) error {
	overriddenFeaturesLock.Lock()
	defer overriddenFeaturesLock.Unlock()

	currentFeatureGates := clientfeatures.FeatureGates()
	featureGates, ok := currentFeatureGates.(featureGatesSetter)
	if !ok {
		panic(fmt.Errorf("clientfeatures.FeatureGates(): %T does not implement featureGatesSetter interface", currentFeatureGates))
	}

	originalFeatureValue := featureGates.Enabled(feature)
	if overridingTestName, ok := overriddenFeatures[feature]; ok {
		if !sameTestOrSubtest(tb, overridingTestName) {
			return fmt.Errorf("client-go feature %q is currently overridden by %q test and cannot be also modified by %q", feature, overridingTestName, tb.Name())
		}
	}


Review comment (refactor):
split this check into a distinct interface... we don't know which `clientfeatures.FeatureGates()` will implement and we should fallback to `Set`

Code after:
	"strings"
	"sync"
	"testing"

	clientfeatures "k8s.io/client-go/features"
)

var (
	overriddenFeaturesLock sync.Mutex
	overriddenFeatures     map[clientfeatures.Feature]string
)

func init() {
	overriddenFeatures = map[clientfeatures.Feature]string{}
}

type featureGatesSetter interface {
	clientfeatures.Gates

	Set(clientfeatures.Feature, bool) error
}

type featureGatesSetterForTesting interface {
	featureGatesSetter

	SetForTesting(clientfeatures.Feature, bool) error
}

// SetFeatureDuringTest sets the specified feature to the specified value for the duration of the test.
//
// Example use:
//
//	clientfeaturestesting.SetFeatureDuringTest(t, clientfeatures.WatchListClient, true)
func SetFeatureDuringTest(tb testing.TB, feature clientfeatures.Feature, featureValue bool) {
	if err := setFeatureDuringTestInternal(tb, feature, featureValue); err != nil {
		tb.Fatal(err)
	}
}

func setFeatureDuringTestInternal(tb testing.TB, feature clientfeatures.Feature, featureValue bool) error {
	overriddenFeaturesLock.Lock()
	defer overriddenFeaturesLock.Unlock()

	currentFeatureGates := clientfeatures.FeatureGates()
	featureGates, ok := currentFeatureGates.(featureGatesSetter)
	if !ok {
		panic(fmt.Errorf("clientfeatures.FeatureGates(): %T does not implement featureGatesSetter interface", currentFeatureGates))
	}

	originalFeatureValue := featureGates.Enabled(feature)
	if overridingTestName, ok := overriddenFeatures[feature]; ok {