package org.radargun.stages.cache.background;
import org.mockito.Mockito;
import org.radargun.config.Cluster;
import org.radargun.logging.Log;
import org.radargun.stages.helpers.Range;
import org.radargun.state.SlaveState;
import org.radargun.traits.BasicOperations;
import org.radargun.util.CacheTestUtils;
import org.radargun.util.CacheTraitRepository;
import org.radargun.util.ReflectionUtils;
import org.testng.annotations.Test;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
import static org.mockito.Mockito.*;
import static org.testng.Assert.*;
/**
* @author Matej Cimbora
*/
@Test
public class AbstractLogLogicTest {
public void testInit() throws NoSuchFieldException, IllegalAccessException {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), new LogLogicConfiguration(), cache);
cache.put(LogChecker.lastOperationKey(logic.stressor.id), new LogChecker.LastOperation(10, 123));
logic.init();
assertEquals(logic.operationId, 11);
assertNotNull(logic.keySelectorRandom);
}
public void testInvoke() throws NoSuchFieldException, IllegalAccessException, InterruptedException {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), new LogLogicConfiguration(), cache);
logic.keySelectorRandom = mock(Random.class);
doReturn(true).when(logic).invokeOn(anyLong());
assertEquals(logic.operationId, 0);
logic.invoke();
assertEquals(logic.operationId, 1);
doReturn(true).when(logic).invokeOn(anyLong());
logic.invoke();
assertEquals(logic.operationId, 2);
assertNull(getFailureManager(logic).getError(true));
}
public void testInvokeOperationFailures() throws NoSuchFieldException, IllegalAccessException, InterruptedException {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), new LogLogicConfiguration(), cache);
logic.keySelectorRandom = mock(Random.class);
doReturn(false).doReturn(false).doReturn(true).when(logic).invokeOn(anyLong());
assertEquals(logic.operationId, 0);
logic.invoke();
assertEquals(logic.operationId, 1);
assertNull(getFailureManager(logic).getError(true));
}
public void testInvokeTxFailures() throws NoSuchFieldException, IllegalAccessException, InterruptedException {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
LogLogicConfiguration llc = new LogLogicConfiguration();
llc.maxTransactionAttempts = 2;
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), llc, cache);
logic.keySelectorRandom = mock(Random.class);
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "txRolledBack", true);
doReturn(true).when(logic).invokeOn(anyLong());
logic.invoke();
assertEquals(getFailureManager(logic).getFailedTransactionAttempts(), 0);
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "txRolledBack", true);
logic.invoke();
assertEquals(getFailureManager(logic).getFailedTransactionAttempts(), 0);
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "txRolledBack", true);
logic.invoke();
assertEquals(getFailureManager(logic).getFailedTransactionAttempts(), 1);
}
public void testWriteStressorLastOperation() throws NoSuchFieldException, IllegalAccessException {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), new LogLogicConfiguration(), cache);
logic.keySelectorRandom = mock(Random.class);
ReflectionUtils.setClassProperty(Random.class, logic.keySelectorRandom, "seed", new AtomicLong(123));
assertNull(cache.get(LogChecker.lastOperationKey(logic.stressor.id)));
assertEquals(logic.operationId, 0);
logic.writeStressorLastOperation();
LogChecker.LastOperation lastOperation = (LogChecker.LastOperation) cache.get(LogChecker.lastOperationKey(logic.stressor.id));
assertNotNull(lastOperation);
assertEquals(lastOperation.getOperationId(), 0);
}
public void testAfterCommitFailures() throws Exception {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
LogLogicConfiguration llc = new LogLogicConfiguration();
llc.maxDelayedRemoveAttempts = 2;
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), llc, cache);
Map<Long, AbstractLogLogic.DelayedRemove> delayedRemoves = new HashMap<>(1);
delayedRemoves.put(0l, logic.new DelayedRemove(0, new PrivateLogValue(0, 1)));
logic.delayedRemoves = delayedRemoves;
doNothing().when(logic).startTransaction();
Mockito.doThrow(CacheTestUtils.TestException.class).when(logic).checkedRemoveValue(anyLong(), anyObject());
logic.afterCommit();
assertEquals(getFailureManager(logic).getDelayedRemovesErrors(), 1);
}
public void testGetCheckedOperationPresentInCache() throws NoSuchFieldException, IllegalAccessException, StressorException, BreakTxRequest {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), new LogLogicConfiguration(), cache);
Cluster cluster = new Cluster();
cluster.addGroup("group", 2);
logic.manager.getSlaveState().setCluster(cluster);
cache.put(LogChecker.checkerKey(0, logic.stressor.id), new LogChecker.LastOperation(10, 123));
cache.put(LogChecker.checkerKey(1, logic.stressor.id), new LogChecker.LastOperation(15, 123));
assertEquals(logic.getCheckedOperation(logic.stressor.id, 20), 10);
}
public void testGetCheckedOperationNotPresentInCache() throws NoSuchFieldException, IllegalAccessException, StressorException, BreakTxRequest {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
AbstractLogLogic logic = createLogic(new GeneralConfiguration(), new BackgroundStressorLogicConfiguration(), new LogLogicConfiguration(), cache);
Cluster cluster = new Cluster();
cluster.addGroup("group", 2);
logic.manager.getSlaveState().setCluster(cluster);
assertEquals(logic.getCheckedOperation(logic.stressor.id, 20), Long.MIN_VALUE);
}
public void testGetCheckedOperationIgnoreDeadCheckers() throws NoSuchFieldException, IllegalAccessException, StressorException, BreakTxRequest {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
LogLogicConfiguration llc = new LogLogicConfiguration();
llc.ignoreDeadCheckers = true;
GeneralConfiguration gc = new GeneralConfiguration();
gc.transactionSize = 10;
AbstractLogLogic logic = createLogic(gc, new BackgroundStressorLogicConfiguration(), llc, cache);
Cluster cluster = new Cluster();
cluster.addGroup("group", 2);
logic.manager.getSlaveState().setCluster(cluster);
cache.put(LogChecker.checkerKey(0, logic.stressor.id), new LogChecker.LastOperation(10, 123));
cache.put(LogChecker.checkerKey(1, logic.stressor.id), new LogChecker.LastOperation(15, 123));
BreakTxRequest expectedException = null;
try {
logic.getCheckedOperation(logic.stressor.id, 20);
} catch (BreakTxRequest ex) {
expectedException = ex;
}
assertEquals(cache.get(LogChecker.ignoredKey(0, logic.stressor.id)), 20l);
assertNotNull(expectedException);
}
public void testGetCheckedOperationIgnoreDeadCheckersInitial1() throws NoSuchFieldException, IllegalAccessException, StressorException, BreakTxRequest {
BasicOperations.Cache cache = new CacheTraitRepository.BasicOperationsCache<>();
LogLogicConfiguration llc = new LogLogicConfiguration();
llc.ignoreDeadCheckers = true;
GeneralConfiguration gc = new GeneralConfiguration();
gc.transactionSize = 10;
AbstractLogLogic logic = createLogic(gc, new BackgroundStressorLogicConfiguration(), llc, cache);
Cluster cluster = new Cluster();
cluster.addGroup("group", 2);
logic.manager.getSlaveState().setCluster(cluster);
cache.put(LogChecker.checkerKey(0, logic.stressor.id), new LogChecker.LastOperation(10, 123));
cache.put(LogChecker.checkerKey(1, logic.stressor.id), new LogChecker.LastOperation(15, 123));
assertEquals(logic.getCheckedOperation(logic.stressor.id, 5l), 10l);
}
private AbstractLogLogic createLogic(GeneralConfiguration gc, BackgroundStressorLogicConfiguration lc, LogLogicConfiguration llc, BasicOperations.Cache cache) throws NoSuchFieldException, IllegalAccessException {
if (gc == null || lc == null || llc == null || cache == null) {
throw new IllegalArgumentException("All configuration parameters need to be specified");
}
llc.enabled = true;
BackgroundOpsManager manager = BackgroundOpsManager.getOrCreateInstance(new SlaveState(), "test");
manager.getSlaveState().setSlaveIndex(0);
ReflectionUtils.setClassProperty(BackgroundOpsManager.class, manager, "generalConfiguration", gc);
ReflectionUtils.setClassProperty(BackgroundOpsManager.class, manager, "backgroundStressorLogicConfiguration", lc);
ReflectionUtils.setClassProperty(BackgroundOpsManager.class, manager, "logLogicConfiguration", llc);
ReflectionUtils.setClassProperty(BackgroundOpsManager.class, manager, "basicCache", cache);
AbstractLogLogic logic = Mockito.mock(AbstractLogLogic.class, CALLS_REAL_METHODS);
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "nonTxBasicCache", cache);
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "basicCache", cache);
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "keySelectorRandom", mock(Random.class));
ReflectionUtils.setClassProperty(AbstractLogLogic.class, logic, "keyRange", new Range(0, 1));
ReflectionUtils.setClassProperty(AbstractLogic.class, logic, "manager", manager);
ReflectionUtils.setClassProperty(AbstractLogic.class, logic, "log", mock(Log.class));
ReflectionUtils.setClassProperty(AbstractLogic.class, logic, "keyGenerator", new CacheTestUtils.SimpleStringKeyGenerator());
ReflectionUtils.setClassProperty(AbstractLogic.class, logic, "transactionSize", gc.transactionSize);
new Stressor(manager, logic, 0);
return logic;
}
private FailureManager getFailureManager(AbstractLogic logic) throws NoSuchFieldException, IllegalAccessException {
BackgroundOpsManager manager = ReflectionUtils.getClassProperty(AbstractLogic.class, logic, "manager", BackgroundOpsManager.class);
return manager.getFailureManager();
}
}