/** * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sf.katta.tool.loadtest; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import net.sf.katta.AbstractTest; import net.sf.katta.master.DefaultDistributionPolicy; import net.sf.katta.master.Master; import net.sf.katta.master.MasterContext; import net.sf.katta.operation.master.MasterOperation; import net.sf.katta.operation.node.NodeOperation; import net.sf.katta.operation.node.OperationResult; import net.sf.katta.protocol.InteractionProtocol; import net.sf.katta.protocol.MasterQueue; import net.sf.katta.testutil.Mocks; import net.sf.katta.testutil.TestIoUtil; import net.sf.katta.tool.loadtest.query.AbstractQueryExecutor; import org.junit.Test; import org.mockito.ArgumentCaptor; public class LoadTestMasterOperationTest extends AbstractTest { private MasterQueue _queue = mock(MasterQueue.class); private InteractionProtocol _protocol = mock(InteractionProtocol.class); private Master _master = Mocks.mockMaster(); private MasterContext _context = new MasterContext(_protocol, _master, new DefaultDistributionPolicy(), _queue); private AbstractQueryExecutor _queryExecutor = mock(AbstractQueryExecutor.class); @Test public void testNodeCount() throws Exception { int nodeCount = 2; when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("n1", "n2", "n3")); LoadTestMasterOperation operation = new LoadTestMasterOperation(nodeCount, 10, 20, 2, 20000, _queryExecutor, _temporaryFolder.newFolder("result")); operation.execute(_context, Collections.EMPTY_LIST); verify(_protocol, times(nodeCount)).addNodeOperation(anyString(), any(NodeOperation.class)); } @Test(expected = IllegalStateException.class) public void testMasterChange() throws Exception { int nodeCount = 2; when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("n1", "n2", "n3")); LoadTestMasterOperation operation = new LoadTestMasterOperation(nodeCount, 10, 20, 2, 20000, _queryExecutor, _temporaryFolder.newFolder("result")); operation.execute(_context, Collections.EMPTY_LIST); _master = Mocks.mockMaster(); _context = new MasterContext(_protocol, _master, new DefaultDistributionPolicy(), _queue); operation.execute(_context, Collections.EMPTY_LIST); } @Test public void testNodeOperation() throws Exception { int nodeCount = 2; int startRate = 10; int endRate = 30; int step = 10; int runTime = 20000; when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("n1", "n2", "n3")); LoadTestMasterOperation operation = new LoadTestMasterOperation(nodeCount, startRate, endRate, step, runTime, _queryExecutor, _temporaryFolder.newFolder("result")); // iteration I operation.execute(_context, Collections.EMPTY_LIST); checkNodeOperation(0, nodeCount, startRate, step, runTime); // iteration II reset(_protocol, _queue); when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("n1", "n2", "n3")); List<OperationResult> operationResults = new ArrayList<OperationResult>(); operationResults.add(new LoadTestNodeOperationResult("n1", Arrays.asList(mock(LoadTestQueryResult.class)))); operationResults.add(new LoadTestNodeOperationResult("n2", Arrays.asList(mock(LoadTestQueryResult.class)))); operation.nodeOperationsComplete(_context, operationResults); ArgumentCaptor<MasterOperation> argumentCaptor2 = ArgumentCaptor.forClass(MasterOperation.class); verify(_queue).add(argumentCaptor2.capture()); operation = (LoadTestMasterOperation) argumentCaptor2.getValue(); operation.execute(_context, Collections.EMPTY_LIST); checkNodeOperation(1, nodeCount, startRate, step, runTime); // iteration III reset(_protocol, _queue); when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("n1", "n2", "n3")); operation.nodeOperationsComplete(_context, operationResults); argumentCaptor2 = ArgumentCaptor.forClass(MasterOperation.class); verify(_queue).add(argumentCaptor2.capture()); operation = (LoadTestMasterOperation) argumentCaptor2.getValue(); operation = (LoadTestMasterOperation) argumentCaptor2.getValue(); operation.execute(_context, Collections.EMPTY_LIST); checkNodeOperation(2, nodeCount, startRate, step, runTime); // finsih reset(_protocol, _queue); operation.nodeOperationsComplete(_context, operationResults); verify(_queue, times(0)).add((MasterOperation) any()); } private void checkNodeOperation(int iteration, int nodeCount, int startRate, int step, int runTime) { ArgumentCaptor<NodeOperation> argumentCaptor1 = ArgumentCaptor.forClass(NodeOperation.class); verify(_protocol, times(nodeCount)).addNodeOperation(anyString(), argumentCaptor1.capture()); LoadTestNodeOperation nodeOperation = (LoadTestNodeOperation) argumentCaptor1.getValue(); assertEquals((startRate + iteration * step) / nodeCount, nodeOperation._queryRate); assertEquals(runTime, nodeOperation._runTime); } @Test public void testResultFiles() throws Exception { int nodeCount = 2; int startRate = 10; int endRate = 20; int step = 10; int runTime = 20000; when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("n1", "n2", "n3")); File resultFolder = _temporaryFolder.newFolder("result"); assertEquals(0, resultFolder.list().length); LoadTestMasterOperation operation = new LoadTestMasterOperation(nodeCount, startRate, endRate, step, runTime, _queryExecutor, resultFolder); // iteration I operation.execute(_context, Collections.EMPTY_LIST); operation = (LoadTestMasterOperation) serializeDesirialize(operation); List<OperationResult> operationResults = new ArrayList<OperationResult>(); operationResults.add(new LoadTestNodeOperationResult("n1", Arrays.asList(mock(LoadTestQueryResult.class)))); operationResults.add(new LoadTestNodeOperationResult("n2", Arrays.asList(mock(LoadTestQueryResult.class)))); operation.nodeOperationsComplete(_context, operationResults); assertEquals(2, resultFolder.list().length); ArgumentCaptor<MasterOperation> argumentCaptor2 = ArgumentCaptor.forClass(MasterOperation.class); verify(_queue).add(argumentCaptor2.capture()); // iteration II operation = (LoadTestMasterOperation) argumentCaptor2.getValue(); operation = (LoadTestMasterOperation) serializeDesirialize(operation); operation.execute(_context, Collections.EMPTY_LIST); operation = (LoadTestMasterOperation) serializeDesirialize(operation); operation.nodeOperationsComplete(_context, operationResults); assertEquals(2, resultFolder.list().length); File[] listFiles = resultFolder.listFiles(); File logFile; File resultFile; if (listFiles[0].getName().contains("-results-")) { resultFile = listFiles[0]; logFile = listFiles[1]; } else { resultFile = listFiles[1]; logFile = listFiles[0]; } assertEquals(1 + 4, TestIoUtil.countLines(logFile)); assertEquals(1 + 2, TestIoUtil.countLines(resultFile)); } private Serializable serializeDesirialize(Serializable serializable) throws IOException, ClassNotFoundException { ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream(); ObjectOutputStream stream = new ObjectOutputStream(byteArrayOS); stream.writeObject(serializable); stream.close(); ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOS.toByteArray())); try { return (Serializable) inputStream.readObject(); } finally { inputStream.close(); } } }