/* Copyright (c) 2012-2017 Jakub Białek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.google.code.ssm.aop.counter;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collection;
import org.hamcrest.CoreMatchers;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runners.Parameterized.Parameters;
import com.google.code.ssm.api.ParameterValueKeyProvider;
import com.google.code.ssm.api.ReturnValueKeyProvider;
import com.google.code.ssm.api.counter.ReadCounterFromCache;
import com.google.code.ssm.api.format.SerializationType;
import com.google.code.ssm.test.Point;
/**
*
* @author Jakub Białek
*
*/
public class ReadCounterFromCacheAdviceTest extends AbstractCounterTest<ReadCounterFromCacheAdvice> {
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { //
{ true, "readCounter1", new Class[] { int.class }, new Object[] { 1 }, new Integer(1), null }, //
{ true, "readCounter2", new Class[] { int.class }, new Object[] { 2 }, new Long(2), null }, //
{ true, "readCounter3", new Class[] { int.class }, new Object[] { 3 }, 3L, null }, //
{ true, "readCounter4", new Class[] { int.class }, new Object[] { 4 }, 4, null }, //
{ true, "readCounter5", new Class[] { int.class, String.class }, new Object[] { 5, "v1" }, 5, null }, //
{ true, "readCounter6", new Class[] { int.class, String.class, Point.class, String.class },
new Object[] { 6, "v1", new Point(2, 3), "test" }, 5, NS + ":v1/(2,3)/6" }, //
{ false, "readCounter20", new Class[] { int.class }, new Object[] { 20 }, "20xx", null }, //
{ false, "readCounter21", new Class[] { int.class }, new Object[] { 21 }, new Object(), null }, //
{ false, "readCounter22", new Class[] { int.class }, new Object[] { 4 }, 22, null }, //
{ false, "readCounter23", new Class[] { int.class, int.class }, new Object[] { 144, 43 }, 23, null }, //
{ false, "readCounter24", new Class[] { int.class }, new Object[] { 24 }, null, null }, //
{ false, "readCounter25", new Class[] { int.class }, new Object[] { 25 }, new Integer(25), null }, //
});
}
private static final int EXPIRATION = 100;
private final Object expectedValue;
public ReadCounterFromCacheAdviceTest(final boolean isValid, final String methodName, final Class<?>[] paramTypes,
final Object[] params, final Object expectedValue, final String cacheKey) {
super(isValid, methodName, paramTypes, params, cacheKey);
this.expectedValue = expectedValue;
}
@Before
public void setUp() {
super.setUp(new TestService());
}
@Test
public void validReadCounterCacheMiss() throws Throwable {
Assume.assumeTrue(isValid);
when(pjp.proceed()).thenReturn(expectedValue);
when(cache.getCounter(eq(cacheKey))).thenReturn(null);
assertEquals(expectedValue, advice.readCounter(pjp));
verify(cache).getCounter(eq(cacheKey));
verify(cache).incr(eq(cacheKey), eq(0), eq(((Number) expectedValue).longValue()), eq(EXPIRATION));
verify(pjp).proceed();
}
@Test
public void validReadCounterCacheHit() throws Throwable {
Assume.assumeTrue(isValid);
Long value = 100L;
when(cache.getCounter(eq(cacheKey))).thenReturn(value);
assertEquals(value.intValue(), ((Number) advice.readCounter(pjp)).intValue());
verify(cache).getCounter(eq(cacheKey));
verify(cache, never()).incr(anyString(), anyInt(), anyLong(), anyInt());
verify(pjp, never()).proceed();
}
@Test
public void invalidReadCounter() throws Throwable {
Assume.assumeThat(isValid, CoreMatchers.is(false));
when(pjp.proceed()).thenReturn(expectedValue);
assertEquals(expectedValue, advice.readCounter(pjp));
verify(cache, never()).getCounter(anyString());
verify(cache, never()).get(anyString(), any(SerializationType.class));
verify(cache, never()).incr(anyString(), anyInt(), anyLong(), anyInt());
verify(pjp).proceed();
}
@Override
protected ReadCounterFromCacheAdvice createAdvice() {
return new ReadCounterFromCacheAdvice();
}
private static class TestService {
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public Integer readCounter1(@ParameterValueKeyProvider final int id) {
return 10;
}
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public Long readCounter2(@ParameterValueKeyProvider final int id) {
return 11L;
}
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public long readCounter3(@ParameterValueKeyProvider final int id) {
return 12L;
}
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public int readCounter4(@ParameterValueKeyProvider final int id) {
return 13;
}
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public int readCounter5(@ParameterValueKeyProvider(order = 0) final int id, @ParameterValueKeyProvider(order = 1) final String id2) {
return 14;
}
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public int readCounter6(@ParameterValueKeyProvider(order = 3) final int id, @ParameterValueKeyProvider(order = 1) final String id2,
@ParameterValueKeyProvider(order = 2) final Point p, final String sth) {
return 6;
}
// wrong return type
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public String readCounter20(@ParameterValueKeyProvider final int id) {
return null;
}
// wrong return type
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public Object readCounter21(@ParameterValueKeyProvider final int id) {
return null;
}
// no @ParameterValueKeyProvider
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public int readCounter22(final int id) {
return 13;
}
// the same order in both @ParameterValueKeyProvider
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public int readCounter23(@ParameterValueKeyProvider(order = 0) final int id, @ParameterValueKeyProvider(order = 0) final int id2) {
return 14;
}
// wrong void return type
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public void readCounter24(@ParameterValueKeyProvider final int id) {
}
@ReturnValueKeyProvider
@ReadCounterFromCache(namespace = NS, expiration = EXPIRATION)
public Integer readCounter25(final int id) {
return 25;
}
}
}