Skip to content

Commit 4086bd9

Browse files
test(GOFeatureFlag): Address flaky test (#472)
Signed-off-by: Kyle Julian <[email protected]>
1 parent 211e3a3 commit 4086bd9

File tree

2 files changed

+161
-48
lines changed

2 files changed

+161
-48
lines changed

test/OpenFeature.Providers.GOFeatureFlag.Test/GoFeatureFlagProviderTest.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,11 @@ public async Task ShouldUseBooleanDefaultValueIfTheFlagIsDisabled()
339339
public async Task ShouldEmitConfigurationChangeEventIfConfigHasChanged()
340340
{
341341
var mockHttp = new RelayProxyMock();
342+
var changeConfigMock = mockHttp.GetRelayProxyMock("CHANGE_CONFIG");
342343
var provider = new GOFeatureFlagProvider(
343344
new GOFeatureFlagProviderOptions
344345
{
345-
HttpMessageHandler = mockHttp.GetRelayProxyMock("CHANGE_CONFIG"),
346+
HttpMessageHandler = changeConfigMock,
346347
Endpoint = RelayProxyMock.baseUrl,
347348
EvaluationType = EvaluationType.InProcess,
348349
FlagChangePollingIntervalMs = TimeSpan.FromMilliseconds(50)
@@ -357,6 +358,8 @@ public async Task ShouldEmitConfigurationChangeEventIfConfigHasChanged()
357358
handlerCalled = true;
358359
});
359360

361+
// Change the config returned by the mock, wait for handler to detect this
362+
mockHttp.UpdateConfigurationMock(changeConfigMock, "CHANGE_CONFIG");
360363

361364
var maxRetry = 10;
362365
while (!handlerCalled && maxRetry > 0)
@@ -372,10 +375,11 @@ public async Task ShouldEmitConfigurationChangeEventIfConfigHasChanged()
372375
public async Task ShouldChangeEvaluationDetailsIfConfigHasChanged()
373376
{
374377
var mockHttp = new RelayProxyMock();
378+
var changeConfigMock = mockHttp.GetRelayProxyMock("CHANGE_CONFIG");
375379
var provider = new GOFeatureFlagProvider(
376380
new GOFeatureFlagProviderOptions
377381
{
378-
HttpMessageHandler = mockHttp.GetRelayProxyMock("CHANGE_CONFIG"),
382+
HttpMessageHandler = changeConfigMock,
379383
Endpoint = RelayProxyMock.baseUrl,
380384
EvaluationType = EvaluationType.InProcess,
381385
FlagChangePollingIntervalMs = TimeSpan.FromMilliseconds(50)
@@ -389,6 +393,9 @@ public async Task ShouldChangeEvaluationDetailsIfConfigHasChanged()
389393
handlerCalled = true;
390394
});
391395
var v1 = await client.GetBooleanDetailsAsync("TEST", false, DefaultEvaluationContext);
396+
397+
// Change the config returned by the mock, wait for handler to detect this
398+
mockHttp.UpdateConfigurationMock(changeConfigMock, "CHANGE_CONFIG");
392399
while (!handlerCalled)
393400
{
394401
await Task.Delay(TimeSpan.FromMilliseconds(100));
@@ -474,10 +481,11 @@ public async Task ShouldErrorIfFlagConfigurationEndpointReturnA401()
474481
public async Task ShouldIgnoreConfigurationIfEtagIsDifferentByLastModifiedIsOlder()
475482
{
476483
var mockHttp = new RelayProxyMock();
484+
var changeConfigMock = mockHttp.GetRelayProxyMock("CHANGE_CONFIG_LAST_MODIFIED_OLDER");
477485
var provider = new GOFeatureFlagProvider(
478486
new GOFeatureFlagProviderOptions
479487
{
480-
HttpMessageHandler = mockHttp.GetRelayProxyMock("CHANGE_CONFIG_LAST_MODIFIED_OLDER"),
488+
HttpMessageHandler = changeConfigMock,
481489
Endpoint = RelayProxyMock.baseUrl,
482490
EvaluationType = EvaluationType.InProcess,
483491
FlagChangePollingIntervalMs = TimeSpan.FromMilliseconds(50)
@@ -491,6 +499,10 @@ public async Task ShouldIgnoreConfigurationIfEtagIsDifferentByLastModifiedIsOlde
491499
{
492500
handlerCalled = true;
493501
});
502+
503+
// Change the config returned by the mock, wait for handler to not detect this
504+
mockHttp.UpdateConfigurationMock(changeConfigMock, "CHANGE_CONFIG_LAST_MODIFIED_OLDER");
505+
494506
var maxRetry = 10;
495507
while (!handlerCalled && maxRetry > 0)
496508
{

test/OpenFeature.Providers.GOFeatureFlag.Test/Mocks/RelayProxyMock.cs

Lines changed: 146 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -146,52 +146,11 @@ private void AddConfigurationMock(MockHttpMessageHandler mockHttp, string mode)
146146
"{\"error\": \"Internal Server Error\"}");
147147
break;
148148
case "CHANGE_CONFIG":
149-
var callCount = 0;
150-
mockHttp.When(path).With(this.RecordRequest).Respond(request =>
151-
{
152-
callCount++;
153-
var response = new HttpResponseMessage(HttpStatusCode.OK)
154-
{
155-
Content = new StringContent(
156-
callCount == 1
157-
? "{\n \"flags\": {\n \"TEST\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"off\"\n }\n },\n \"TEST2\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"on\"\n }\n }\n },\n \"evaluationContextEnrichment\": {\n \"env\": \"production\"\n }\n}\n"
158-
: "{\n \"flags\": {\n \"TEST123\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"off\"\n }\n },\n \"TEST2\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"on\"\n }\n }\n },\n \"evaluationContextEnrichment\": {\n \"env\": \"production\"\n }\n}\n",
159-
Encoding.UTF8,
160-
mediaType
161-
)
162-
};
163-
response.Content.Headers.LastModified =
164-
callCount == 1
165-
? new DateTimeOffset(2015, 10, 21, 7, 20, 0, TimeSpan.Zero).ToUniversalTime()
166-
: new DateTimeOffset(2015, 10, 21, 7, 28, 0, TimeSpan.Zero).ToUniversalTime();
167-
response.Headers.ETag =
168-
new EntityTagHeaderValue(callCount == 1 ? "\"123456789\"" : "\"1234567891011\"");
169-
return response;
170-
});
171-
break;
172149
case "CHANGE_CONFIG_LAST_MODIFIED_OLDER":
173-
var callCountLastModified = 0;
174-
mockHttp.When(path).With(this.RecordRequest).Respond(request =>
175-
{
176-
callCountLastModified++;
177-
var response = new HttpResponseMessage(HttpStatusCode.OK)
178-
{
179-
Content = new StringContent(
180-
callCountLastModified == 1
181-
? "{\n \"flags\": {\n \"TEST\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"off\"\n }\n },\n \"TEST2\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"on\"\n }\n }\n },\n \"evaluationContextEnrichment\": {\n \"env\": \"production\"\n }\n}\n"
182-
: "{\n \"flags\": {\n \"TEST123\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"off\"\n }\n },\n \"TEST2\": {\n \"variations\": {\n \"off\": false,\n \"on\": true\n },\n \"defaultRule\": {\n \"variation\": \"on\"\n }\n }\n },\n \"evaluationContextEnrichment\": {\n \"env\": \"production\"\n }\n}\n",
183-
Encoding.UTF8,
184-
mediaType
185-
)
186-
};
187-
response.Content.Headers.LastModified =
188-
callCountLastModified == 1
189-
? new DateTimeOffset(2015, 10, 21, 7, 20, 0, TimeSpan.Zero).ToUniversalTime()
190-
: new DateTimeOffset(2015, 10, 21, 7, 18, 0, TimeSpan.Zero).ToUniversalTime();
191-
response.Headers.ETag =
192-
new EntityTagHeaderValue(callCountLastModified == 1 ? "\"123456789\"" : "\"1234567891011\"");
193-
return response;
194-
});
150+
mockHttp
151+
.When(path)
152+
.With(this.RecordRequest)
153+
.Respond(request => GetFirstChangeConfigMessage());
195154
break;
196155
case "SIMPLE_FLAG_CONFIG":
197156
mockHttp.When(path).With(this.RecordRequest).Respond(request =>
@@ -249,4 +208,146 @@ private void AddConfigurationMock(MockHttpMessageHandler mockHttp, string mode)
249208
break;
250209
}
251210
}
211+
212+
public void UpdateConfigurationMock(MockHttpMessageHandler mockHttp, string mode)
213+
{
214+
var path = $"{baseUrl}/v1/flag/configuration";
215+
mockHttp.Clear();
216+
217+
switch (mode)
218+
{
219+
case "CHANGE_CONFIG":
220+
mockHttp
221+
.When(path)
222+
.With(this.RecordRequest)
223+
.Respond(request => GetSecondChangeConfigMessage());
224+
break;
225+
case "CHANGE_CONFIG_LAST_MODIFIED_OLDER":
226+
mockHttp
227+
.When(path)
228+
.With(this.RecordRequest)
229+
.Respond(request => GetOlderChangeConfigMessage());
230+
break;
231+
}
232+
}
233+
234+
private static HttpResponseMessage GetFirstChangeConfigMessage()
235+
{
236+
var response = new HttpResponseMessage(HttpStatusCode.OK)
237+
{
238+
Content = new StringContent(
239+
"""
240+
{
241+
"flags": {
242+
"TEST": {
243+
"variations": {
244+
"off": false,
245+
"on": true
246+
},
247+
"defaultRule": {
248+
"variation": "off"
249+
}
250+
},
251+
"TEST2": {
252+
"variations": {
253+
"off": false,
254+
"on": true
255+
},
256+
"defaultRule": {
257+
"variation": "on"
258+
}
259+
}
260+
},
261+
"evaluationContextEnrichment": {
262+
"env": "production"
263+
}
264+
}
265+
""",
266+
Encoding.UTF8,
267+
mediaType)
268+
};
269+
response.Content.Headers.LastModified = new DateTimeOffset(2015, 10, 21, 7, 20, 0, TimeSpan.Zero).ToUniversalTime();
270+
response.Headers.ETag = new EntityTagHeaderValue("\"123456789\"");
271+
return response;
272+
}
273+
274+
private static HttpResponseMessage GetSecondChangeConfigMessage()
275+
{
276+
var response = new HttpResponseMessage(HttpStatusCode.OK)
277+
{
278+
Content = new StringContent(
279+
"""
280+
{
281+
"flags": {
282+
"TEST123": {
283+
"variations": {
284+
"off": false,
285+
"on": true
286+
},
287+
"defaultRule": {
288+
"variation": "off"
289+
}
290+
},
291+
"TEST2": {
292+
"variations": {
293+
"off": false,
294+
"on": true
295+
},
296+
"defaultRule": {
297+
"variation": "on"
298+
}
299+
}
300+
},
301+
"evaluationContextEnrichment": {
302+
"env": "production"
303+
}
304+
}
305+
""",
306+
Encoding.UTF8,
307+
mediaType)
308+
};
309+
response.Content.Headers.LastModified = new DateTimeOffset(2015, 10, 21, 7, 28, 0, TimeSpan.Zero).ToUniversalTime();
310+
response.Headers.ETag = new EntityTagHeaderValue("\"1234567891011\"");
311+
return response;
312+
}
313+
314+
private static HttpResponseMessage GetOlderChangeConfigMessage()
315+
{
316+
var response = new HttpResponseMessage(HttpStatusCode.OK)
317+
{
318+
Content = new StringContent(
319+
"""
320+
{
321+
"flags": {
322+
"TEST123": {
323+
"variations": {
324+
"off": false,
325+
"on": true
326+
},
327+
"defaultRule": {
328+
"variation": "off"
329+
}
330+
},
331+
"TEST2": {
332+
"variations": {
333+
"off": false,
334+
"on": true
335+
},
336+
"defaultRule": {
337+
"variation": "on"
338+
}
339+
}
340+
},
341+
"evaluationContextEnrichment": {
342+
"env": "production"
343+
}
344+
}
345+
""",
346+
Encoding.UTF8,
347+
mediaType)
348+
};
349+
response.Content.Headers.LastModified = new DateTimeOffset(2015, 10, 21, 7, 18, 0, TimeSpan.Zero).ToUniversalTime();
350+
response.Headers.ETag = new EntityTagHeaderValue("\"1234567891011\"");
351+
return response;
352+
}
252353
}

0 commit comments

Comments
 (0)