1 package com.atlassian.vcache.internal.core.metrics; 2 3 import com.atlassian.vcache.ExternalCache; 4 import org.junit.Test; 5 import org.mockito.Mock; 6 7 import java.util.HashMap; 8 import java.util.Map; 9 import java.util.Optional; 10 import java.util.concurrent.CompletableFuture; 11 import java.util.concurrent.CompletionStage; 12 13 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_FAILED_GET; 14 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_HITS; 15 import static com.atlassian.vcache.internal.MetricLabel.TIMED_GET_CALL; 16 import static com.atlassian.vcache.internal.core.metrics.CacheType.EXTERNAL; 17 import static java.util.Collections.singletonList; 18 import static org.hamcrest.Matchers.equalTo; 19 import static org.junit.Assert.assertThat; 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Matchers.anyLong; 22 import static org.mockito.Matchers.eq; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.verifyNoMoreInteractions; 26 import static org.mockito.Mockito.when; 27 28 @SuppressWarnings("unchecked") 29 public abstract class TimedExternalCacheTest { 30 protected static final String CACHE_NAME = "cashew"; 31 32 @Mock 33 protected MetricsRecorder metricsRecorder; 34 35 protected abstract ExternalCache<String> getDelegate(); 36 37 protected abstract TimedExternalCache<String> getTimed(); 38 39 @Test 40 public void get_hit() { 41 final CompletableFuture<Optional<String>> result = mock(CompletableFuture.class); 42 when(result.join()).thenReturn(Optional.of("politics of dancing")); 43 when(getDelegate().get("foo")).thenReturn(result); 44 45 final CompletionStage<Optional<String>> passedResult = getTimed().get("foo"); 46 47 assertThat(passedResult, equalTo(result)); 48 49 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_GET_CALL), anyLong()); 50 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_HITS), eq(1L)); 51 verifyNoMoreInteractions(metricsRecorder); 52 } 53 54 @Test 55 public void get_miss() throws Exception { 56 final CompletableFuture<Optional<String>> result = mock(CompletableFuture.class); 57 when(result.join()).thenReturn(Optional.of("politics of dancing")); 58 when(getDelegate().get("foo")).thenReturn(result); 59 60 final CompletionStage<Optional<String>> passedResult = getTimed().get("foo"); 61 62 assertThat(passedResult, equalTo(result)); 63 64 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_GET_CALL), anyLong()); 65 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_HITS), eq(1L)); 66 verifyNoMoreInteractions(metricsRecorder); 67 } 68 69 @Test 70 public void getSupplier_hit() { 71 final CompletableFuture<String> result = mock(CompletableFuture.class); 72 when(result.join()).thenReturn("politics of dancing"); 73 74 when(getDelegate().get(eq("foo"), any())).thenReturn(result); 75 76 final CompletionStage<String> passedResult = getTimed().get("foo", () -> ""); 77 78 assertThat(passedResult, equalTo(result)); 79 80 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_GET_CALL), anyLong()); 81 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_HITS), eq(1L)); 82 verifyNoMoreInteractions(metricsRecorder); 83 } 84 85 @Test 86 public void getBulk_success() { 87 final Map<String, Optional<String>> theMap = new HashMap<>(); 88 theMap.put("foo", Optional.of("moving")); 89 final CompletableFuture<Map<String, Optional<String>>> result = mock(CompletableFuture.class); 90 when(result.join()).thenReturn(theMap); 91 92 when(getDelegate().getBulk(singletonList("foo"))).thenReturn(result); 93 94 final CompletionStage<Map<String, Optional<String>>> passedResult = getTimed().getBulk("foo"); 95 96 assertThat(passedResult, equalTo(result)); 97 98 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_GET_CALL), anyLong()); 99 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_HITS), eq(1L)); 100 verifyNoMoreInteractions(metricsRecorder); 101 } 102 103 @Test 104 public void getBulk_fail() { 105 final CompletableFuture<Map<String, Optional<String>>> result = mock(CompletableFuture.class); 106 when(result.isCompletedExceptionally()).thenReturn(true); 107 when(getDelegate().getBulk(singletonList("foo"))).thenReturn(result); 108 109 final CompletionStage<Map<String, Optional<String>>> passedResult = getTimed().getBulk("foo"); 110 111 assertThat(passedResult, equalTo(result)); 112 113 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_GET_CALL), anyLong()); 114 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_FAILED_GET), eq(1L)); 115 verifyNoMoreInteractions(metricsRecorder); 116 } 117 118 @Test 119 public void getBulkFactory_success() { 120 final Map<String, String> theMap = new HashMap<>(); 121 theMap.put("foo", "moving"); 122 final CompletableFuture<Map<String, String>> result = mock(CompletableFuture.class); 123 when(result.join()).thenReturn(theMap); 124 125 when(getDelegate().getBulk(any(), eq(singletonList("foo")))).thenReturn(result); 126 127 final CompletionStage<Map<String, String>> passedResult = getTimed().getBulk(keys -> new HashMap(), "foo"); 128 129 assertThat(passedResult, equalTo(result)); 130 131 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_GET_CALL), anyLong()); 132 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_HITS), eq(1L)); 133 verifyNoMoreInteractions(metricsRecorder); 134 } 135 }