2323import io .grpc .inprocess .InProcessServerBuilder ;
2424import io .grpc .stub .StreamObserver ;
2525import java .io .IOException ;
26+ import java .time .Clock ;
2627import java .util .LinkedHashMap ;
2728import java .util .List ;
2829import java .util .Objects ;
3738import org .hypertrace .config .service .v1 .GetAllConfigsResponse ;
3839import org .hypertrace .config .service .v1 .GetConfigRequest ;
3940import org .hypertrace .config .service .v1 .GetConfigResponse ;
41+ import org .hypertrace .config .service .v1 .UpsertAllConfigsRequest ;
42+ import org .hypertrace .config .service .v1 .UpsertAllConfigsResponse ;
43+ import org .hypertrace .config .service .v1 .UpsertAllConfigsResponse .UpsertedConfig ;
4044import org .hypertrace .config .service .v1 .UpsertConfigRequest ;
4145import org .hypertrace .config .service .v1 .UpsertConfigResponse ;
4246import org .hypertrace .core .grpcutils .context .RequestContext ;
5155public class MockGenericConfigService {
5256
5357 private Server grpcServer ;
58+ private Clock clock = Clock .systemUTC ();
5459 private final InProcessServerBuilder serverBuilder ;
5560 private final ManagedChannel configChannel ;
5661 private final RequestContext context = RequestContext .forTenantId ("default tenant" );
@@ -102,35 +107,34 @@ public void shutdown() {
102107 this .configChannel .shutdownNow ();
103108 }
104109
110+ public MockGenericConfigService withClock (Clock clock ) {
111+ this .clock = clock ;
112+ return this ;
113+ }
114+
105115 @ SuppressWarnings ("unchecked" )
106116 public MockGenericConfigService mockUpsert () {
107117 Mockito .doAnswer (
108118 invocation -> {
109119 UpsertConfigRequest request = invocation .getArgument (0 , UpsertConfigRequest .class );
110120 StreamObserver <UpsertConfigResponse > responseStreamObserver =
111121 invocation .getArgument (1 , StreamObserver .class );
112- ResourceType resourceType =
113- ResourceType .of (request .getResourceNamespace (), request .getResourceName ());
114- String configContext = configContextOrDefault (request .getContext ());
115- ContextSpecificConfig existingConfig = currentValues .get (resourceType , configContext );
116- long updateTimestamp = System .currentTimeMillis ();
117- long creationTimestamp =
118- existingConfig == null ? updateTimestamp : existingConfig .getCreationTimestamp ();
119- currentValues .put (
120- resourceType ,
121- configContext ,
122- ContextSpecificConfig .newBuilder ()
123- .setContext (configContext )
124- .setConfig (request .getConfig ())
125- .setCreationTimestamp (creationTimestamp )
126- .setUpdateTimestamp (updateTimestamp )
127- .build ());
128- responseStreamObserver .onNext (
122+ UpsertedConfig upsertedConfig =
123+ this .writeToMap (
124+ request .getResourceNamespace (),
125+ request .getResourceName (),
126+ request .getContext (),
127+ request .getConfig ());
128+ UpsertConfigResponse .Builder responseBuilder =
129129 UpsertConfigResponse .newBuilder ()
130- .setConfig (request .getConfig ())
131- .setCreationTimestamp (creationTimestamp )
132- .setUpdateTimestamp (updateTimestamp )
133- .build ());
130+ .setConfig (upsertedConfig .getConfig ())
131+ .setCreationTimestamp (upsertedConfig .getCreationTimestamp ())
132+ .setUpdateTimestamp (upsertedConfig .getUpdateTimestamp ());
133+ if (upsertedConfig .hasPrevConfig ()) {
134+ responseBuilder .setPrevConfig (upsertedConfig .getPrevConfig ());
135+ }
136+
137+ responseStreamObserver .onNext (responseBuilder .build ());
134138 responseStreamObserver .onCompleted ();
135139 return null ;
136140 })
@@ -243,6 +247,35 @@ public MockGenericConfigService mockGet() {
243247 return this ;
244248 }
245249
250+ public MockGenericConfigService mockUpsertAll () {
251+ Mockito .doAnswer (
252+ invocation -> {
253+ UpsertAllConfigsRequest request =
254+ invocation .getArgument (0 , UpsertAllConfigsRequest .class );
255+ StreamObserver <UpsertAllConfigsResponse > responseStreamObserver =
256+ invocation .getArgument (1 , StreamObserver .class );
257+
258+ List <UpsertedConfig > configs =
259+ request .getConfigsList ().stream ()
260+ .map (
261+ configToUpsert ->
262+ this .writeToMap (
263+ configToUpsert .getResourceNamespace (),
264+ configToUpsert .getResourceName (),
265+ configToUpsert .getContext (),
266+ configToUpsert .getConfig ()))
267+ .collect (Collectors .toUnmodifiableList ());
268+ responseStreamObserver .onNext (
269+ UpsertAllConfigsResponse .newBuilder ().addAllUpsertedConfigs (configs ).build ());
270+ responseStreamObserver .onCompleted ();
271+ return null ;
272+ })
273+ .when (this .mockConfigService )
274+ .upsertConfig (ArgumentMatchers .any (), ArgumentMatchers .any ());
275+
276+ return this ;
277+ }
278+
246279 private Optional <Value > mergeValues (List <Value > values ) {
247280 if (values .isEmpty ()) {
248281 return Optional .empty ();
@@ -259,6 +292,40 @@ private boolean isValidValue(Optional<Value> value) {
259292 return value .isPresent () && value .get ().getKindCase () != Value .KindCase .NULL_VALUE ;
260293 }
261294
295+ private UpsertedConfig writeToMap (String namespace , String name , String context , Value config ) {
296+ ResourceType resourceType = ResourceType .of (namespace , name );
297+ String configContext = configContextOrDefault (context );
298+ ContextSpecificConfig existingConfig = currentValues .get (resourceType , configContext );
299+ long updateTimestamp = clock .millis ();
300+ long creationTimestamp =
301+ Optional .ofNullable (existingConfig )
302+ .map (ContextSpecificConfig ::getCreationTimestamp )
303+ .orElse (updateTimestamp );
304+ Optional <Value > previousConfig =
305+ Optional .ofNullable (
306+ currentValues .put (
307+ resourceType ,
308+ configContext ,
309+ ContextSpecificConfig .newBuilder ()
310+ .setContext (configContext )
311+ .setConfig (config )
312+ .setCreationTimestamp (creationTimestamp )
313+ .setUpdateTimestamp (updateTimestamp )
314+ .build ()))
315+ .map (ContextSpecificConfig ::getConfig );
316+
317+ UpsertedConfig .Builder resultBuilder =
318+ UpsertedConfig .newBuilder ()
319+ .setConfig (config )
320+ .setContext (configContext )
321+ .setCreationTimestamp (creationTimestamp )
322+ .setUpdateTimestamp (updateTimestamp );
323+
324+ previousConfig .ifPresent (resultBuilder ::setPrevConfig );
325+
326+ return resultBuilder .build ();
327+ }
328+
262329 private class TestInterceptor implements ServerInterceptor {
263330 @ Override
264331 public <ReqT , RespT > Listener <ReqT > interceptCall (
0 commit comments