### Question:
RateLimiterClient { private static Counter increment(Counter current) { return Counter.newBuilder(current).clearValue().setValue(current.getValue() + 1).build(); } @Inject  RateLimiterClient(
      @com.google.firebase.inappmessaging.internal.injection.qualifiers.RateLimit
          ProtoStorageClient storageClient,
      Clock clock); Completable increment(RateLimit limit); Single<Boolean> isRateLimited(RateLimit limit);  }### Answer:
@Test public void increment_noErrors_writesToStorage() { rateLimiterClient.increment(rateLimit).subscribe(); assertThat(wasWritten).isTrue(); }
@Test public void increment_noExistingCounter_writesToStorage() { when(storageClient.read(any(RateLimitParser.class))).thenReturn(Maybe.empty()); rateLimiterClient.increment(rateLimit).subscribe(); assertThat(wasWritten).isTrue(); }
@Test public void increment_noErrors_incrementsCounter() { ArgumentCaptor<RateLimitProto.RateLimit> rateLimitCaptor = ArgumentCaptor.forClass(RateLimitProto.RateLimit.class); rateLimiterClient.increment(rateLimit).subscribe(); verify(storageClient).write(rateLimitCaptor.capture()); assertThat(rateLimitCaptor.getValue().getLimitsOrThrow(LIMITER_KEY).getValue()).isEqualTo(2); }
@Test public void increment_noExistingLimits_initializesLimits() { when(storageClient.read(any(RateLimitParser.class))).thenReturn(Maybe.empty()); ArgumentCaptor<RateLimitProto.RateLimit> rateLimitCaptor = ArgumentCaptor.forClass(RateLimitProto.RateLimit.class); rateLimiterClient.increment(rateLimit).subscribe(); verify(storageClient).write(rateLimitCaptor.capture()); assertThat(rateLimitCaptor.getValue().getLimitsOrThrow(LIMITER_KEY).getValue()).isEqualTo(1); }
@Test public void increment_expiredLimit_resetsLimit() { RateLimit noTTLLimit = RateLimit.builder() .setLimit(LIMIT_TWO) .setLimiterKey(LIMITER_KEY) .setTimeToLiveMillis(1000L) .build(); ArgumentCaptor<RateLimitProto.RateLimit> rateLimitCaptor = ArgumentCaptor.forClass(RateLimitProto.RateLimit.class); rateLimiterClient = new RateLimiterClient(storageClient, new FakeClock(NOW + 1001)); rateLimiterClient.increment(noTTLLimit).subscribe(); verify(storageClient).write(rateLimitCaptor.capture()); assertThat(rateLimitCaptor.getValue().getLimitsOrThrow(LIMITER_KEY).getValue()).isEqualTo(1); assertThat(rateLimitCaptor.getValue().getLimitsOrThrow(LIMITER_KEY).getStartTimeEpoch()) .isEqualTo(NOW + 1001); }
@Test public void increment_noCounterForLimit_initializesCounter() { RateLimit otherLimit = RateLimit.builder() .setLimit(LIMIT_TWO) .setLimiterKey("OTHER_KEY") .setTimeToLiveMillis(TTL) .build(); ArgumentCaptor<RateLimitProto.RateLimit> rateLimitCaptor = ArgumentCaptor.forClass(RateLimitProto.RateLimit.class); rateLimiterClient.increment(otherLimit).subscribe(); verify(storageClient).write(rateLimitCaptor.capture()); assertThat(rateLimitCaptor.getValue().getLimitsOrThrow(LIMITER_KEY).getValue()).isEqualTo(1); assertThat(rateLimitCaptor.getValue().getLimitsOrThrow("OTHER_KEY").getValue()).isEqualTo(1); }
@Test public void increment_writeErrors_notifiesError() { when(storageClient.write(any(RateLimitProto.RateLimit.class))) .thenReturn(Completable.error(new IOException())); TestObserver<Void> testObserver = rateLimiterClient.increment(rateLimit).test(); testObserver.assertError(IOException.class); }