Skip to content

Commit 726ecb6

Browse files
committed
cleanup: make the featuragate test more extensible.
Signed-off-by: Lan Liang <[email protected]>
1 parent 93a245a commit 726ecb6

File tree

1 file changed

+84
-119
lines changed

1 file changed

+84
-119
lines changed

server/embed/config_test.go

+84-119
Original file line numberDiff line numberDiff line change
@@ -92,136 +92,36 @@ func TestConfigFileOtherFields(t *testing.T) {
9292
assert.Equal(t, false, cfg.SocketOpts.ReuseAddress, "ReuseAddress does not match")
9393
}
9494

95+
// TestConfigFileFeatureGates ensures that experimental flags migrate to feature gate.
9596
func TestConfigFileFeatureGates(t *testing.T) {
96-
testCases := []struct {
97-
name string
98-
serverFeatureGatesJSON string
99-
experimentalStopGRPCServiceOnDefrag string
100-
experimentalInitialCorruptCheck string
101-
expectErr bool
102-
expectedFeatures map[featuregate.Feature]bool
103-
}{
97+
testCases := []featureTestCase{
10498
{
105-
name: "default",
106-
expectedFeatures: map[featuregate.Feature]bool{
107-
features.DistributedTracing: false,
108-
features.StopGRPCServiceOnDefrag: false,
109-
features.InitialCorruptCheck: false,
110-
},
99+
name: "default",
100+
expectedFeatures: defaultFeatureGates(),
111101
},
112102
{
113-
name: "cannot set both experimental flag and feature gate flag",
114-
serverFeatureGatesJSON: "StopGRPCServiceOnDefrag=true",
115-
experimentalStopGRPCServiceOnDefrag: "false",
116-
expectErr: true,
117-
},
118-
{
119-
name: "cannot set both experimental flag and feature gate flag for InitialCorruptCheck",
120-
serverFeatureGatesJSON: "InitialCorruptCheck=true",
121-
experimentalInitialCorruptCheck: "false",
122-
expectErr: true,
123-
},
124-
{
125-
name: "ok to set different experimental flag and feature gate flag",
126-
serverFeatureGatesJSON: "DistributedTracing=true",
127-
experimentalStopGRPCServiceOnDefrag: "true",
128-
expectedFeatures: map[featuregate.Feature]bool{
129-
features.DistributedTracing: true,
130-
features.StopGRPCServiceOnDefrag: true,
131-
features.InitialCorruptCheck: false,
132-
},
133-
},
134-
{
135-
name: "can set feature gate to true from experimental flag",
136-
experimentalStopGRPCServiceOnDefrag: "true",
137-
expectedFeatures: map[featuregate.Feature]bool{
138-
features.StopGRPCServiceOnDefrag: true,
139-
features.DistributedTracing: false,
140-
features.InitialCorruptCheck: false,
141-
},
142-
},
143-
{
144-
name: "can set feature gate to false from experimental flag",
145-
experimentalStopGRPCServiceOnDefrag: "false",
146-
expectedFeatures: map[featuregate.Feature]bool{
147-
features.StopGRPCServiceOnDefrag: false,
148-
features.DistributedTracing: false,
149-
features.InitialCorruptCheck: false,
150-
},
151-
},
152-
{
153-
name: "can set feature gate experimentalInitialCorruptCheck to true from experimental flag",
154-
experimentalInitialCorruptCheck: "true",
155-
expectedFeatures: map[featuregate.Feature]bool{
156-
features.StopGRPCServiceOnDefrag: false,
157-
features.DistributedTracing: false,
158-
features.InitialCorruptCheck: true,
159-
},
160-
},
161-
{
162-
name: "can set feature gate experimentalInitialCorruptCheck to false from experimental flag",
163-
experimentalInitialCorruptCheck: "false",
164-
expectedFeatures: map[featuregate.Feature]bool{
165-
features.StopGRPCServiceOnDefrag: false,
166-
features.DistributedTracing: false,
167-
features.InitialCorruptCheck: false,
168-
},
169-
},
170-
{
171-
name: "can set feature gate StopGRPCServiceOnDefrag to true from feature gate flag",
172-
serverFeatureGatesJSON: "StopGRPCServiceOnDefrag=true",
173-
expectedFeatures: map[featuregate.Feature]bool{
174-
features.StopGRPCServiceOnDefrag: true,
175-
features.DistributedTracing: false,
176-
features.InitialCorruptCheck: false,
177-
},
178-
},
179-
{
180-
name: "can set feature gate InitialCorruptCheck to true from feature gate flag",
181-
serverFeatureGatesJSON: "InitialCorruptCheck=true",
182-
expectedFeatures: map[featuregate.Feature]bool{
183-
features.StopGRPCServiceOnDefrag: false,
184-
features.DistributedTracing: false,
185-
features.InitialCorruptCheck: true,
186-
},
187-
},
188-
{
189-
name: "can set feature gate to false from feature gate flag",
190-
serverFeatureGatesJSON: "StopGRPCServiceOnDefrag=false",
191-
expectedFeatures: map[featuregate.Feature]bool{
192-
features.StopGRPCServiceOnDefrag: false,
193-
features.DistributedTracing: false,
194-
features.InitialCorruptCheck: false,
195-
},
103+
name: "ok to set different experimental flag and feature gate flag",
104+
serverFeatureGatesJSON: "DistributedTracing=true",
105+
experimentalFlagName: "experimental-stop-grpc-service-on-defrag",
106+
experimentalValue: true,
107+
expectedFeatures: defaultFeatureGatesWithFeaturegates([]featuregate.Feature{features.StopGRPCServiceOnDefrag, features.DistributedTracing}, true),
196108
},
197109
}
110+
111+
//add a new experimental flag here when migrating a new experimental flag to feature
112+
testCases = append(testCases, testCasesForFeaturegate("experimental-stop-grpc-service-on-defrag", "StopGRPCServiceOnDefrag", features.StopGRPCServiceOnDefrag)...)
113+
testCases = append(testCases, testCasesForFeaturegate("experimental-initial-corrupt-check", "InitialCorruptCheck", features.InitialCorruptCheck)...)
114+
198115
for _, tc := range testCases {
199116
t.Run(tc.name, func(t *testing.T) {
200-
yc := struct {
201-
ExperimentalStopGRPCServiceOnDefrag *bool `json:"experimental-stop-grpc-service-on-defrag,omitempty"`
202-
ExperimentalInitialCorruptCheck *bool `json:"experimental-initial-corrupt-check,omitempty"`
203-
ServerFeatureGatesJSON string `json:"feature-gates"`
204-
}{
205-
ServerFeatureGatesJSON: tc.serverFeatureGatesJSON,
206-
}
117+
configurationMap := make(map[string]interface{})
118+
configurationMap["feature-gates"] = tc.serverFeatureGatesJSON
207119

208-
if tc.experimentalInitialCorruptCheck != "" {
209-
experimentalInitialCorruptCheck, err := strconv.ParseBool(tc.experimentalInitialCorruptCheck)
210-
if err != nil {
211-
t.Fatal(err)
212-
}
213-
yc.ExperimentalInitialCorruptCheck = &experimentalInitialCorruptCheck
120+
if tc.experimentalFlagName != "" {
121+
configurationMap[tc.experimentalFlagName] = tc.experimentalValue
214122
}
215123

216-
if tc.experimentalStopGRPCServiceOnDefrag != "" {
217-
experimentalStopGRPCServiceOnDefrag, err := strconv.ParseBool(tc.experimentalStopGRPCServiceOnDefrag)
218-
if err != nil {
219-
t.Fatal(err)
220-
}
221-
yc.ExperimentalStopGRPCServiceOnDefrag = &experimentalStopGRPCServiceOnDefrag
222-
}
223-
224-
b, err := yaml.Marshal(&yc)
124+
b, err := yaml.Marshal(configurationMap)
225125
if err != nil {
226126
t.Fatal(err)
227127
}
@@ -248,6 +148,71 @@ func TestConfigFileFeatureGates(t *testing.T) {
248148
}
249149
}
250150

151+
type featureTestCase struct {
152+
name string
153+
serverFeatureGatesJSON string
154+
expectErr bool
155+
expectedFeatures map[featuregate.Feature]bool
156+
experimentalFlagName string
157+
experimentalValue bool
158+
}
159+
160+
func testCasesForFeaturegate(experimentalFlagName, fgname string, fg featuregate.Feature) []featureTestCase {
161+
return []featureTestCase{
162+
{
163+
name: "cannot set both experimental flag and feature gate flag",
164+
serverFeatureGatesJSON: fgname + "=true",
165+
experimentalFlagName: experimentalFlagName,
166+
experimentalValue: false,
167+
expectErr: true,
168+
},
169+
{
170+
name: "can set feature gate to true from experimental flag",
171+
experimentalFlagName: experimentalFlagName,
172+
experimentalValue: true,
173+
expectedFeatures: defaultFeatureGatesWithFeaturegate(fg, true),
174+
},
175+
{
176+
name: "can set feature gate to false from experimental flag",
177+
experimentalFlagName: experimentalFlagName,
178+
experimentalValue: false,
179+
expectedFeatures: defaultFeatureGatesWithFeaturegate(fg, false),
180+
},
181+
{
182+
name: "can set feature gate " + fgname + " to true from feature gate flag",
183+
serverFeatureGatesJSON: fgname + "=true",
184+
expectedFeatures: defaultFeatureGatesWithFeaturegate(fg, true),
185+
},
186+
{
187+
name: "can set feature gate to false from feature gate flag",
188+
serverFeatureGatesJSON: fgname + "=false",
189+
expectedFeatures: defaultFeatureGatesWithFeaturegate(fg, false),
190+
},
191+
}
192+
}
193+
194+
func defaultFeatureGates() map[featuregate.Feature]bool {
195+
fgs := make(map[featuregate.Feature]bool)
196+
for fg, fgspec := range features.DefaultEtcdServerFeatureGates {
197+
fgs[fg] = fgspec.Default
198+
}
199+
return fgs
200+
}
201+
202+
func defaultFeatureGatesWithFeaturegate(fg featuregate.Feature, enabled bool) map[featuregate.Feature]bool {
203+
fgs := defaultFeatureGates()
204+
fgs[fg] = enabled
205+
return fgs
206+
}
207+
208+
func defaultFeatureGatesWithFeaturegates(fgs2 []featuregate.Feature, enabled bool) map[featuregate.Feature]bool {
209+
fgs := defaultFeatureGates()
210+
for _, f := range fgs2 {
211+
fgs[f] = enabled
212+
}
213+
return fgs
214+
}
215+
251216
// TestUpdateDefaultClusterFromName ensures that etcd can start with 'etcd --name=abc'.
252217
func TestUpdateDefaultClusterFromName(t *testing.T) {
253218
cfg := NewConfig()

0 commit comments

Comments
 (0)