|
8 | 8 | import static org.mockito.ArgumentMatchers.any;
|
9 | 9 | import static org.mockito.ArgumentMatchers.anyLong;
|
10 | 10 | import static org.mockito.ArgumentMatchers.argThat;
|
| 11 | +import static org.mockito.Mockito.doAnswer; |
11 | 12 | import static org.mockito.Mockito.mock;
|
12 | 13 | import static org.mockito.Mockito.mockStatic;
|
13 | 14 | import static org.mockito.Mockito.times;
|
|
16 | 17 |
|
17 | 18 | import java.lang.reflect.Field;
|
18 | 19 | import java.util.ArrayList;
|
| 20 | +import java.util.Arrays; |
19 | 21 | import java.util.HashMap;
|
20 | 22 | import java.util.List;
|
21 | 23 | import java.util.Map;
|
22 | 24 | import java.util.concurrent.TimeUnit;
|
23 | 25 | import java.util.function.Supplier;
|
| 26 | +import java.util.concurrent.LinkedBlockingQueue; |
24 | 27 |
|
25 | 28 | import org.junit.jupiter.api.BeforeAll;
|
26 | 29 | import org.junit.jupiter.api.Test;
|
27 | 30 | import org.mockito.MockedStatic;
|
| 31 | +import org.mockito.Mockito; |
28 | 32 |
|
29 | 33 | import com.google.protobuf.Struct;
|
30 | 34 |
|
31 | 35 | import dev.openfeature.contrib.providers.flagd.resolver.Resolver;
|
32 | 36 | import dev.openfeature.contrib.providers.flagd.resolver.grpc.GrpcConnector;
|
33 | 37 | import dev.openfeature.contrib.providers.flagd.resolver.grpc.GrpcResolver;
|
34 | 38 | import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.Cache;
|
| 39 | +import dev.openfeature.contrib.providers.flagd.resolver.process.InProcessResolver; |
| 40 | +import dev.openfeature.contrib.providers.flagd.resolver.process.MockStorage; |
| 41 | +import dev.openfeature.contrib.providers.flagd.resolver.process.model.FeatureFlag; |
| 42 | +import dev.openfeature.contrib.providers.flagd.resolver.process.storage.StorageState; |
35 | 43 | import dev.openfeature.flagd.grpc.evaluation.ServiceGrpc;
|
36 | 44 | import dev.openfeature.flagd.grpc.evaluation.Evaluation.ResolveBooleanRequest;
|
37 | 45 | import dev.openfeature.flagd.grpc.evaluation.Evaluation.ResolveBooleanResponse;
|
@@ -824,6 +832,43 @@ void initializationAndShutdown() throws Exception{
|
824 | 832 | verify(resolverMock, times(1)).shutdown();
|
825 | 833 | }
|
826 | 834 |
|
| 835 | + @Test |
| 836 | + void test_state_on_grpc_resolver_shutdown() throws Exception { |
| 837 | + // setup mock provider |
| 838 | + final FlagdProvider grpcProvider = Mockito.spy(FlagdProvider.class); |
| 839 | + try { |
| 840 | + doAnswer(invocation -> { |
| 841 | + final Field stateField = FlagdProvider.class.getDeclaredField("state"); |
| 842 | + stateField.setAccessible(true); |
| 843 | + stateField.set(grpcProvider, ProviderState.READY); |
| 844 | + |
| 845 | + final Field intializedField = FlagdProvider.class.getDeclaredField("initialized"); |
| 846 | + intializedField.setAccessible(true); |
| 847 | + intializedField.set(grpcProvider, true); |
| 848 | + |
| 849 | + return null; |
| 850 | + }).when(grpcProvider).initialize(any()); |
| 851 | + } catch (Exception e) { |
| 852 | + throw new RuntimeException(e); |
| 853 | + } |
| 854 | + |
| 855 | + grpcProvider.initialize(new ImmutableContext()); |
| 856 | + assertEquals(ProviderState.READY, grpcProvider.getState()); |
| 857 | + grpcProvider.shutdown(); |
| 858 | + assertEquals(ProviderState.NOT_READY, grpcProvider.getState()); |
| 859 | + } |
| 860 | + |
| 861 | + @Test |
| 862 | + void test_state_on_in_process_resolver_shutdown() throws Exception { |
| 863 | + // setup mock in-process provider |
| 864 | + FlagdProvider inProcessProvider = createInProcessProvider(); |
| 865 | + |
| 866 | + inProcessProvider.initialize(new ImmutableContext()); |
| 867 | + assertEquals(ProviderState.READY, inProcessProvider.getState()); |
| 868 | + inProcessProvider.shutdown(); |
| 869 | + assertEquals(ProviderState.NOT_READY, inProcessProvider.getState()); |
| 870 | + } |
| 871 | + |
827 | 872 |
|
828 | 873 | // test helper
|
829 | 874 |
|
@@ -863,4 +908,29 @@ private FlagdProvider createProvider(GrpcConnector grpc, Cache cache, Supplier<P
|
863 | 908 | return provider;
|
864 | 909 | }
|
865 | 910 |
|
| 911 | + // Create an in process provider |
| 912 | + private FlagdProvider createInProcessProvider() { |
| 913 | + |
| 914 | + final FlagdOptions flagdOptions = FlagdOptions.builder() |
| 915 | + .resolverType(Config.Resolver.IN_PROCESS) |
| 916 | + .deadline(1000) |
| 917 | + .build(); |
| 918 | + final FlagdProvider provider = new FlagdProvider(flagdOptions); |
| 919 | + final MockStorage mockStorage = new MockStorage(new HashMap<String, FeatureFlag>(), new LinkedBlockingQueue<StorageState>(Arrays.asList(StorageState.OK))); |
| 920 | + |
| 921 | + try { |
| 922 | + final Field flagResolver = FlagdProvider.class.getDeclaredField("flagResolver"); |
| 923 | + flagResolver.setAccessible(true); |
| 924 | + final Resolver resolver = (Resolver) flagResolver.get(provider); |
| 925 | + |
| 926 | + final Field flagStore = InProcessResolver.class.getDeclaredField("flagStore"); |
| 927 | + flagStore.setAccessible(true); |
| 928 | + flagStore.set(resolver, mockStorage); |
| 929 | + } catch (NoSuchFieldException | IllegalAccessException e) { |
| 930 | + throw new RuntimeException(e); |
| 931 | + } |
| 932 | + |
| 933 | + return provider; |
| 934 | + } |
| 935 | + |
866 | 936 | }
|
0 commit comments