1 package com.atlassian.vcache.internal.core.metrics; 2 3 import com.atlassian.vcache.CasIdentifier; 4 import com.atlassian.vcache.DirectExternalCache; 5 import com.atlassian.vcache.IdentifiedValue; 6 import org.junit.Before; 7 import org.junit.Test; 8 import org.junit.runner.RunWith; 9 import org.mockito.Mock; 10 import org.mockito.runners.MockitoJUnitRunner; 11 12 import java.util.HashMap; 13 import java.util.Map; 14 import java.util.Optional; 15 import java.util.concurrent.CompletableFuture; 16 import java.util.concurrent.CompletionStage; 17 18 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_FAILED_IDENTIFIED_GET; 19 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_FAILED_IDENTIFIED_REMOVE; 20 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_FAILED_IDENTIFIED_REPLACE; 21 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_HITS; 22 import static com.atlassian.vcache.internal.MetricLabel.NUMBER_OF_MISSES; 23 import static com.atlassian.vcache.internal.MetricLabel.TIMED_IDENTIFIED_GET_CALL; 24 import static com.atlassian.vcache.internal.MetricLabel.TIMED_IDENTIFIED_REMOVE_CALL; 25 import static com.atlassian.vcache.internal.MetricLabel.TIMED_IDENTIFIED_REPLACE_CALL; 26 import static com.atlassian.vcache.internal.core.metrics.CacheType.EXTERNAL; 27 import static java.util.Collections.singletonList; 28 import static org.hamcrest.Matchers.equalTo; 29 import static org.junit.Assert.assertThat; 30 import static org.mockito.Matchers.anyLong; 31 import static org.mockito.Matchers.eq; 32 import static org.mockito.Mockito.mock; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.verifyNoMoreInteractions; 35 import static org.mockito.Mockito.when; 36 37 @SuppressWarnings("unchecked") 38 @RunWith(MockitoJUnitRunner.class) 39 public class TimedDirectExternalCacheTest extends TimedExternalCacheTest { 40 @Mock 41 private CasIdentifier casIdentifier; 42 43 @Mock 44 private IdentifiedValue<String> identifiedValue; 45 46 @Mock 47 private DirectExternalCache<String> delegate; 48 49 private TimedDirectExternalCache<String> timed; 50 51 @Before 52 public void init() { 53 when(delegate.getName()).thenReturn(CACHE_NAME); 54 timed = new TimedDirectExternalCache<>(metricsRecorder, delegate); 55 } 56 57 @Override 58 protected DirectExternalCache<String> getDelegate() { 59 return delegate; 60 } 61 62 @Override 63 protected TimedDirectExternalCache<String> getTimed() { 64 return timed; 65 } 66 67 @Test 68 public void getIdentified_failure() throws Exception { 69 final CompletableFuture<Optional<IdentifiedValue<String>>> result = mock(CompletableFuture.class); 70 when(result.isCompletedExceptionally()).thenReturn(true); 71 when(getDelegate().getIdentified("game")).thenReturn(result); 72 73 final CompletionStage<Optional<IdentifiedValue<String>>> passedResult = getTimed().getIdentified("game"); 74 75 assertThat(passedResult, equalTo(result)); 76 77 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_FAILED_IDENTIFIED_GET), eq(1L)); 78 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_GET_CALL), anyLong()); 79 verifyNoMoreInteractions(metricsRecorder); 80 } 81 82 @Test 83 public void getIdentified_miss() throws Exception { 84 final CompletableFuture<Optional<IdentifiedValue<String>>> result = mock(CompletableFuture.class); 85 when(result.join()).thenReturn(Optional.empty()); 86 when(getDelegate().getIdentified("game")).thenReturn(result); 87 88 final CompletionStage<Optional<IdentifiedValue<String>>> passedResult = getTimed().getIdentified("game"); 89 90 assertThat(passedResult, equalTo(result)); 91 92 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_MISSES), eq(1L)); 93 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_GET_CALL), anyLong()); 94 verifyNoMoreInteractions(metricsRecorder); 95 } 96 97 @Test 98 public void getIdentified_hit() throws Exception { 99 final CompletableFuture<Optional<IdentifiedValue<String>>> result = mock(CompletableFuture.class); 100 when(result.join()).thenReturn(Optional.of(identifiedValue)); 101 when(getDelegate().getIdentified("game")).thenReturn(result); 102 103 final CompletionStage<Optional<IdentifiedValue<String>>> passedResult = getTimed().getIdentified("game"); 104 105 assertThat(passedResult, equalTo(result)); 106 107 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_HITS), eq(1L)); 108 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_GET_CALL), anyLong()); 109 verifyNoMoreInteractions(metricsRecorder); 110 } 111 112 @Test 113 public void getBulkIdentified_success() throws Exception { 114 final Map<String, Optional<IdentifiedValue<String>>> theMap = new HashMap<>(); 115 theMap.put("foo", Optional.empty()); 116 final CompletableFuture<Map<String, Optional<IdentifiedValue<String>>>> result = mock(CompletableFuture.class); 117 when(result.join()).thenReturn(theMap); 118 119 when(getDelegate().getBulkIdentified(singletonList("foo"))).thenReturn(result); 120 121 final CompletionStage<Map<String, Optional<IdentifiedValue<String>>>> passedResult = getTimed().getBulkIdentified("foo"); 122 123 assertThat(passedResult, equalTo(result)); 124 125 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_GET_CALL), anyLong()); 126 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_MISSES), eq(1L)); 127 verifyNoMoreInteractions(metricsRecorder); 128 } 129 130 @Test 131 public void getBulkIdentified_failure() throws Exception { 132 final CompletableFuture<Map<String, Optional<IdentifiedValue<String>>>> result = mock(CompletableFuture.class); 133 when(result.isCompletedExceptionally()).thenReturn(true); 134 135 when(getDelegate().getBulkIdentified(singletonList("foo"))).thenReturn(result); 136 137 final CompletionStage<Map<String, Optional<IdentifiedValue<String>>>> passedResult = getTimed().getBulkIdentified("foo"); 138 139 assertThat(passedResult, equalTo(result)); 140 141 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_GET_CALL), anyLong()); 142 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_FAILED_IDENTIFIED_GET), eq(1L)); 143 verifyNoMoreInteractions(metricsRecorder); 144 } 145 146 @Test 147 public void removeIf_okay() throws Exception { 148 final CompletableFuture<Boolean> result = mock(CompletableFuture.class); 149 when(result.join()).thenReturn(true); 150 when(getDelegate().removeIf("lock", casIdentifier)).thenReturn(result); 151 152 final CompletionStage<Boolean> passedResult = getTimed().removeIf("lock", casIdentifier); 153 154 assertThat(passedResult, equalTo(result)); 155 156 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_REMOVE_CALL), anyLong()); 157 verifyNoMoreInteractions(metricsRecorder); 158 } 159 160 @Test 161 public void removeIf_failure() throws Exception { 162 final CompletableFuture<Boolean> result = mock(CompletableFuture.class); 163 when(result.isCompletedExceptionally()).thenReturn(true); 164 when(getDelegate().removeIf("lock", casIdentifier)).thenReturn(result); 165 166 final CompletionStage<Boolean> passedResult = getTimed().removeIf("lock", casIdentifier); 167 168 assertThat(passedResult, equalTo(result)); 169 170 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_FAILED_IDENTIFIED_REMOVE), eq(1L)); 171 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_REMOVE_CALL), anyLong()); 172 verifyNoMoreInteractions(metricsRecorder); 173 } 174 175 @Test 176 public void replaceIf_okay() throws Exception { 177 final CompletableFuture<Boolean> result = mock(CompletableFuture.class); 178 when(getDelegate().replaceIf("lock", casIdentifier, "wood")).thenReturn(result); 179 180 final CompletionStage<Boolean> passedResult = getTimed().replaceIf("lock", casIdentifier, "wood"); 181 182 assertThat(passedResult, equalTo(result)); 183 184 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_REPLACE_CALL), anyLong()); 185 verifyNoMoreInteractions(metricsRecorder); 186 } 187 188 @Test 189 public void replaceIf_failure() throws Exception { 190 final CompletableFuture<Boolean> result = mock(CompletableFuture.class); 191 when(result.isCompletedExceptionally()).thenReturn(true); 192 when(getDelegate().replaceIf("lock", casIdentifier, "wood")).thenReturn(result); 193 194 final CompletionStage<Boolean> passedResult = getTimed().replaceIf("lock", casIdentifier, "wood"); 195 196 assertThat(passedResult, equalTo(result)); 197 198 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(NUMBER_OF_FAILED_IDENTIFIED_REPLACE), eq(1L)); 199 verify(metricsRecorder).record(eq(CACHE_NAME), eq(EXTERNAL), eq(TIMED_IDENTIFIED_REPLACE_CALL), anyLong()); 200 verifyNoMoreInteractions(metricsRecorder); 201 } 202 }