Skip to content

Commit adbd958

Browse files
committed
added context-based warning suppression to SetEmulationVersion to eliminate test noise
Signed-off-by: zhihao jian <zhihao.kan17@gmail.com>
1 parent fe13474 commit adbd958

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed

staging/src/k8s.io/component-base/featuregate/feature_gate.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ type MutableVersionedFeatureGate interface {
165165
// Otherwise, the emulationVersion will be the same as the binary version.
166166
// If set, the feature defaults and availability will be as if the binary is at the emulated version.
167167
SetEmulationVersion(emulationVersion *version.Version) error
168+
// SetEmulationVersionWithContext is like SetEmulationVersion but accepts a context for controlling behavior.
169+
SetEmulationVersionWithContext(ctx context.Context, emulationVersion *version.Version) error
168170
// GetAll returns a copy of the map of known feature names to versioned feature specs.
169171
GetAllVersioned() map[Feature]VersionedSpecs
170172
// AddVersioned adds versioned feature specs to the featureGate.
@@ -543,6 +545,10 @@ func (f *featureGate) GetAllVersioned() map[Feature]VersionedSpecs {
543545
}
544546

545547
func (f *featureGate) SetEmulationVersion(emulationVersion *version.Version) error {
548+
return f.SetEmulationVersionWithContext(context.Background(), emulationVersion)
549+
}
550+
551+
func (f *featureGate) SetEmulationVersionWithContext(ctx context.Context, emulationVersion *version.Version) error {
546552
if emulationVersion.EqualTo(f.EmulationVersion()) {
547553
return nil
548554
}
@@ -565,7 +571,16 @@ func (f *featureGate) SetEmulationVersion(emulationVersion *version.Version) err
565571
newVal := featureEnabled(feature, enabled, known, emulationVersion)
566572
oldVal := featureEnabled(feature, f.enabled.Load().(map[Feature]bool), known, f.EmulationVersion())
567573
if newVal != oldVal {
568-
klog.Warningf("SetEmulationVersion will change already queried feature:%s from %v to %v", feature, oldVal, newVal)
574+
// Suppress warning during test restoration to avoid noise in test output
575+
if !shouldSuppressWarning(ctx) {
576+
warningMsg := fmt.Sprintf("SetEmulationVersion will change already queried feature:%s from %v to %v", feature, oldVal, newVal)
577+
// Try to log to test output first, fallback to global klog
578+
if logger := getTestLogger(ctx); logger != nil {
579+
logger.Logf("WARNING: %s", warningMsg)
580+
} else {
581+
klog.Warningf("%s", warningMsg)
582+
}
583+
}
569584
}
570585
}
571586

@@ -669,6 +684,49 @@ func (f *featureGate) AddMetrics() {
669684
}
670685
}
671686

687+
// contextKey is used to store warning suppression flag in context
688+
type contextKey struct{}
689+
690+
// testLoggerKey is used to store test logger in context
691+
type testLoggerKey struct{}
692+
693+
// WithWarningSuppressionContext returns a context with warning suppression flag
694+
func WithWarningSuppressionContext(ctx context.Context) context.Context {
695+
return context.WithValue(ctx, contextKey{}, true)
696+
}
697+
698+
// WithTestLoggerContext returns a context with test logger for redirecting warnings to test output
699+
func WithTestLoggerContext(ctx context.Context, logger interface {
700+
Logf(format string, args ...interface{})
701+
}) context.Context {
702+
return context.WithValue(ctx, testLoggerKey{}, logger)
703+
}
704+
705+
// shouldSuppressWarning checks whether warnings should be suppressed
706+
func shouldSuppressWarning(ctx context.Context) bool {
707+
if ctx == nil {
708+
return false
709+
}
710+
suppress, ok := ctx.Value(contextKey{}).(bool)
711+
return ok && suppress
712+
}
713+
714+
// getTestLogger retrieves test logger from context if available
715+
func getTestLogger(ctx context.Context) interface {
716+
Logf(format string, args ...interface{})
717+
} {
718+
if ctx == nil {
719+
return nil
720+
}
721+
logger, ok := ctx.Value(testLoggerKey{}).(interface {
722+
Logf(format string, args ...interface{})
723+
})
724+
if ok {
725+
return logger
726+
}
727+
return nil
728+
}
729+
672730
// KnownFeatures returns a slice of strings describing the FeatureGate's known features.
673731
// preAlpha, Deprecated and GA features are hidden from the list.
674732
func (f *featureGate) KnownFeatures() []string {

staging/src/k8s.io/component-base/featuregate/feature_gate_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package featuregate
1818

1919
import (
20+
"context"
2021
"fmt"
2122
"reflect"
2223
"sort"
@@ -1905,3 +1906,55 @@ func TestAddVersioned(t *testing.T) {
19051906
})
19061907
}
19071908
}
1909+
1910+
func TestSetEmulationVersionWarningSuppression(t *testing.T) {
1911+
// Test that warnings are suppressed when using context
1912+
f := NewVersionedFeatureGate(version.MustParse("1.29"))
1913+
1914+
// Add a test feature
1915+
err := f.AddVersioned(map[Feature]VersionedSpecs{
1916+
"TestFeature": {
1917+
{Version: version.MustParse("1.28"), Default: false, PreRelease: Alpha},
1918+
{Version: version.MustParse("1.29"), Default: true, PreRelease: Beta},
1919+
},
1920+
})
1921+
require.NoError(t, err)
1922+
1923+
// Query the feature to mark it as queried
1924+
_ = f.Enabled("TestFeature")
1925+
1926+
// Test 1: Warning should be emitted in normal context
1927+
err = f.SetEmulationVersion(version.MustParse("1.28"))
1928+
require.NoError(t, err)
1929+
1930+
// Test 2: Warning should be suppressed when using context
1931+
ctx := WithWarningSuppressionContext(context.Background())
1932+
err = f.SetEmulationVersionWithContext(ctx, version.MustParse("1.29"))
1933+
require.NoError(t, err)
1934+
1935+
// Test 3: Warning should be emitted again without context
1936+
err = f.SetEmulationVersion(version.MustParse("1.28"))
1937+
require.NoError(t, err)
1938+
}
1939+
1940+
func TestSetEmulationVersionWarningRedirection(t *testing.T) {
1941+
// Test that warnings can be redirected to test output
1942+
f := NewVersionedFeatureGate(version.MustParse("1.29"))
1943+
1944+
// Add a test feature
1945+
err := f.AddVersioned(map[Feature]VersionedSpecs{
1946+
"TestFeature": {
1947+
{Version: version.MustParse("1.28"), Default: false, PreRelease: Alpha},
1948+
{Version: version.MustParse("1.29"), Default: true, PreRelease: Beta},
1949+
},
1950+
})
1951+
require.NoError(t, err)
1952+
1953+
// Query the feature to mark it as queried
1954+
_ = f.Enabled("TestFeature")
1955+
1956+
// Test: Warning should be redirected to test output instead of global klog
1957+
ctx := WithTestLoggerContext(context.Background(), t)
1958+
err = f.SetEmulationVersionWithContext(ctx, version.MustParse("1.28"))
1959+
require.NoError(t, err)
1960+
}

staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package testing
1818

1919
import (
20+
"context"
2021
"fmt"
2122
"strings"
2223
"sync"
@@ -130,7 +131,9 @@ func SetFeatureGateEmulationVersionDuringTest(tb TB, gate featuregate.FeatureGat
130131
tb.Cleanup(func() {
131132
tb.Helper()
132133
detectParallelOverrideCleanup()
133-
if err := gate.(featuregate.MutableVersionedFeatureGate).SetEmulationVersion(originalEmuVer); err != nil {
134+
// Use context to suppress warnings during test cleanup
135+
ctx := featuregate.WithWarningSuppressionContext(context.Background())
136+
if err := gate.(featuregate.MutableVersionedFeatureGate).SetEmulationVersionWithContext(ctx, originalEmuVer); err != nil {
134137
tb.Fatalf("failed to restore emulation version to %s during test", originalEmuVer.String())
135138
}
136139
})

0 commit comments

Comments
 (0)