11
11
import static org .junit .Assert .fail ;
12
12
import static org .mockito .ArgumentMatchers .any ;
13
13
import static org .mockito .ArgumentMatchers .anyString ;
14
- import static org .mockito .Mockito .atLeast ;
15
14
import static org .mockito .Mockito .doThrow ;
16
15
import static org .mockito .Mockito .mock ;
17
16
import static org .mockito .Mockito .spy ;
54
53
import java .util .Locale ;
55
54
import java .util .Map ;
56
55
import java .util .concurrent .CompletableFuture ;
56
+ import java .util .concurrent .CountDownLatch ;
57
57
import java .util .concurrent .ExecutionException ;
58
58
import java .util .concurrent .TimeUnit ;
59
59
import java .util .concurrent .TimeoutException ;
@@ -354,14 +354,27 @@ private void testLoadConfigurationHelper(boolean loadAsync)
354
354
355
355
@ Test
356
356
public void testPollingClient () throws ExecutionException , InterruptedException {
357
- // Set up a changing response from the "server"
358
357
EppoHttpClient mockHttpClient = mock (EppoHttpClient .class );
359
358
360
- // Mock sync get
361
- when (mockHttpClient .get (anyString ())).thenReturn (EMPTY_CONFIG );
359
+ CountDownLatch pollLatch = new CountDownLatch (1 );
360
+
361
+ // The poller fetches synchronously so let's return the boolean flag config
362
+ when (mockHttpClient .get (anyString ()))
363
+ .thenAnswer (
364
+ invocation -> {
365
+ pollLatch .countDown (); // Signal that polling occurred
366
+ Log .d ("TEST" , "Polling has occurred" );
367
+ return BOOL_FLAG_CONFIG ;
368
+ });
369
+
370
+ // Async get is used for initialization, so we'll return an empty response.
371
+ CompletableFuture <byte []> emptyResponse =
372
+ CompletableFuture .supplyAsync (
373
+ () -> {
374
+ Log .d ("TEST" , "empty config supplied" );
375
+ return EMPTY_CONFIG ;
376
+ });
362
377
363
- // Mock async get
364
- CompletableFuture <byte []> emptyResponse = CompletableFuture .completedFuture (EMPTY_CONFIG );
365
378
when (mockHttpClient .getAsync (anyString ())).thenReturn (emptyResponse );
366
379
367
380
setBaseClientHttpClientOverrideField (mockHttpClient );
@@ -375,18 +388,21 @@ public void testPollingClient() throws ExecutionException, InterruptedException
375
388
.pollingIntervalMs (pollingIntervalMs )
376
389
.isGracefulMode (false );
377
390
378
- // Initialize and no exception should be thrown.
379
391
EppoClient eppoClient = clientBuilder .buildAndInitAsync ().get ();
380
392
393
+ // Empty config on initialization
381
394
verify (mockHttpClient , times (1 )).getAsync (anyString ());
382
395
assertFalse (eppoClient .getBooleanAssignment ("bool_flag" , "subject1" , false ));
383
396
384
- // Now, return the boolean flag config (bool_flag = true)
385
- when (mockHttpClient .get (anyString ())).thenReturn (BOOL_FLAG_CONFIG );
386
- // Wait the polling interval
387
- Thread .sleep (pollingIntervalMs * 2 );
397
+ // Wait for the client to send the "fetch"
398
+ assertTrue ("Polling did not occur within timeout" , pollLatch .await (5 , TimeUnit .SECONDS ));
388
399
389
- verify (mockHttpClient , atLeast (1 )).get (anyString ());
400
+ // Sleep a short period to allow the polling mechanism to complete writing the config.
401
+ // The above latch releases immediately after the config is "fetched", not necessarily before
402
+ // the config is applied.
403
+ Thread .sleep (150 );
404
+
405
+ // Assignment is now true.
390
406
assertTrue (eppoClient .getBooleanAssignment ("bool_flag" , "subject1" , false ));
391
407
392
408
eppoClient .stopPolling ();
@@ -1048,7 +1064,7 @@ public static <T> void setBaseClientOverrideField(String fieldName, T override)
1048
1064
private static final byte [] BOOL_FLAG_CONFIG =
1049
1065
("{\n "
1050
1066
+ " \" createdAt\" : \" 2024-04-17T19:40:53.716Z\" ,\n "
1051
- + " \" format\" : \" SERVER \" ,\n "
1067
+ + " \" format\" : \" CLIENT \" ,\n "
1052
1068
+ " \" environment\" : {\n "
1053
1069
+ " \" name\" : \" Test\" \n "
1054
1070
+ " },\n "
0 commit comments