package com.ldbc.driver; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.ldbc.driver.control.ConsoleAndFileDriverConfiguration; import com.ldbc.driver.control.DriverConfigurationException; import com.ldbc.driver.control.Log4jLoggingServiceFactory; import com.ldbc.driver.control.LoggingServiceFactory; import com.ldbc.driver.generator.GeneratorFactory; import com.ldbc.driver.generator.RandomDataGeneratorFactory; import com.ldbc.driver.util.Tuple3; import com.ldbc.driver.workloads.WorkloadFactory; import com.ldbc.driver.workloads.dummy.NothingOperation; import com.ldbc.driver.workloads.dummy.TimedNamedOperation1; import com.ldbc.driver.workloads.dummy.TimedNamedOperation1Factory; import com.ldbc.driver.workloads.dummy.TimedNamedOperation2; import com.ldbc.driver.workloads.dummy.TimedNamedOperation2Factory; import com.ldbc.driver.workloads.dummy.TimedNamedOperation3; import com.ldbc.driver.workloads.dummy.TimedNamedOperation3Factory; import org.junit.Test; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; public class WorkloadStreamsTest { @Test public void shouldReturnSameWorkloadStreamsAsCreatedWith() { WorkloadStreams workloadStreamsBefore = getWorkloadStreams(); Operation firstAsyncDependencyOperation = workloadStreamsBefore.asynchronousStream().dependencyOperations().next(); Operation secondAsyncDependencyOperation = workloadStreamsBefore.asynchronousStream().dependencyOperations().next(); assertThat( firstAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 0l ) ); assertThat( firstAsyncDependencyOperation.timeStamp(), is( 0l ) ); assertThat( firstAsyncDependencyOperation.dependencyTimeStamp(), is( 0l ) ); assertThat( secondAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 10l ) ); assertThat( secondAsyncDependencyOperation.timeStamp(), is( 10l ) ); assertThat( secondAsyncDependencyOperation.dependencyTimeStamp(), is( 10l ) ); Operation firstAsyncNonDependencyOperation = workloadStreamsBefore.asynchronousStream().nonDependencyOperations().next(); Operation secondAsyncNonDependencyOperation = workloadStreamsBefore.asynchronousStream().nonDependencyOperations().next(); assertThat( firstAsyncNonDependencyOperation.scheduledStartTimeAsMilli(), is( 2l ) ); assertThat( firstAsyncNonDependencyOperation.timeStamp(), is( 2l ) ); assertThat( firstAsyncNonDependencyOperation.dependencyTimeStamp(), is( 2l ) ); assertThat( secondAsyncNonDependencyOperation.scheduledStartTimeAsMilli(), is( 102l ) ); assertThat( secondAsyncNonDependencyOperation.timeStamp(), is( 102l ) ); assertThat( secondAsyncNonDependencyOperation.dependencyTimeStamp(), is( 102l ) ); Operation firstBlocking1DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).dependencyOperations().next(); Operation secondBlocking1DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).dependencyOperations().next(); assertThat( firstBlocking1DependencyOperation.scheduledStartTimeAsMilli(), is( 4l ) ); assertThat( firstBlocking1DependencyOperation.timeStamp(), is( 4l ) ); assertThat( firstBlocking1DependencyOperation.dependencyTimeStamp(), is( 4l ) ); assertThat( secondBlocking1DependencyOperation.scheduledStartTimeAsMilli(), is( 1004l ) ); assertThat( secondBlocking1DependencyOperation.timeStamp(), is( 1004l ) ); assertThat( secondBlocking1DependencyOperation.dependencyTimeStamp(), is( 1004l ) ); Operation firstBlocking1NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).nonDependencyOperations().next(); Operation secondBlocking1NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).nonDependencyOperations().next(); assertThat( firstBlocking1NonDependencyOperation.scheduledStartTimeAsMilli(), is( 6l ) ); assertThat( firstBlocking1NonDependencyOperation.timeStamp(), is( 6l ) ); assertThat( firstBlocking1NonDependencyOperation.dependencyTimeStamp(), is( 6l ) ); assertThat( secondBlocking1NonDependencyOperation.scheduledStartTimeAsMilli(), is( 10006l ) ); assertThat( secondBlocking1NonDependencyOperation.timeStamp(), is( 10006l ) ); assertThat( secondBlocking1NonDependencyOperation.dependencyTimeStamp(), is( 10006l ) ); Operation firstBlocking2DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).dependencyOperations().next(); Operation secondBlocking2DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).dependencyOperations().next(); assertThat( firstBlocking2DependencyOperation.scheduledStartTimeAsMilli(), is( 8l ) ); assertThat( firstBlocking2DependencyOperation.timeStamp(), is( 8l ) ); assertThat( firstBlocking2DependencyOperation.dependencyTimeStamp(), is( 8l ) ); assertThat( secondBlocking2DependencyOperation.scheduledStartTimeAsMilli(), is( 10008l ) ); assertThat( secondBlocking2DependencyOperation.timeStamp(), is( 10008l ) ); assertThat( secondBlocking2DependencyOperation.dependencyTimeStamp(), is( 10008l ) ); Operation firstBlocking2NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).nonDependencyOperations().next(); Operation secondBlocking2NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).nonDependencyOperations().next(); assertThat( firstBlocking2NonDependencyOperation.scheduledStartTimeAsMilli(), is( 10l ) ); assertThat( firstBlocking2NonDependencyOperation.timeStamp(), is( 10l ) ); assertThat( firstBlocking2NonDependencyOperation.dependencyTimeStamp(), is( 10l ) ); assertThat( secondBlocking2NonDependencyOperation.scheduledStartTimeAsMilli(), is( 100010l ) ); assertThat( secondBlocking2NonDependencyOperation.timeStamp(), is( 100010l ) ); assertThat( secondBlocking2NonDependencyOperation.dependencyTimeStamp(), is( 100010l ) ); } @Test public void shouldPerformTimeOffsetCorrectly() throws WorkloadException { long offset = TimeUnit.SECONDS.toMillis( 100 ); WorkloadStreams workloadStreamsBefore = WorkloadStreams.timeOffsetAndCompressWorkloadStreams( getWorkloadStreams(), 0l + offset, 1.0, new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ) ); Operation firstAsyncDependencyOperation = workloadStreamsBefore.asynchronousStream().dependencyOperations().next(); Operation secondAsyncDependencyOperation = workloadStreamsBefore.asynchronousStream().dependencyOperations().next(); assertThat( firstAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 0l + offset ) ); assertThat( firstAsyncDependencyOperation.timeStamp(), is( 0l ) ); assertThat( firstAsyncDependencyOperation.dependencyTimeStamp(), is( 0l ) ); assertThat( secondAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 10l + offset ) ); assertThat( secondAsyncDependencyOperation.timeStamp(), is( 10l ) ); assertThat( secondAsyncDependencyOperation.dependencyTimeStamp(), is( 10l ) ); Operation firstAsyncNonDependencyOperation = workloadStreamsBefore.asynchronousStream().nonDependencyOperations().next(); Operation secondAsyncNonDependencyOperation = workloadStreamsBefore.asynchronousStream().nonDependencyOperations().next(); assertThat( firstAsyncNonDependencyOperation.scheduledStartTimeAsMilli(), is( 2l + offset ) ); assertThat( firstAsyncNonDependencyOperation.timeStamp(), is( 2l ) ); assertThat( firstAsyncNonDependencyOperation.dependencyTimeStamp(), is( 2l ) ); assertThat( secondAsyncNonDependencyOperation.scheduledStartTimeAsMilli(), is( 102l + offset ) ); assertThat( secondAsyncNonDependencyOperation.timeStamp(), is( 102l ) ); assertThat( secondAsyncNonDependencyOperation.dependencyTimeStamp(), is( 102l ) ); Operation firstBlocking1DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).dependencyOperations().next(); Operation secondBlocking1DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).dependencyOperations().next(); assertThat( firstBlocking1DependencyOperation.scheduledStartTimeAsMilli(), is( 4l + offset ) ); assertThat( firstBlocking1DependencyOperation.timeStamp(), is( 4l ) ); assertThat( firstBlocking1DependencyOperation.dependencyTimeStamp(), is( 4l ) ); assertThat( secondBlocking1DependencyOperation.scheduledStartTimeAsMilli(), is( 1004l + offset ) ); assertThat( secondBlocking1DependencyOperation.timeStamp(), is( 1004l ) ); assertThat( secondBlocking1DependencyOperation.dependencyTimeStamp(), is( 1004l ) ); Operation firstBlocking1NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).nonDependencyOperations().next(); Operation secondBlocking1NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).nonDependencyOperations().next(); assertThat( firstBlocking1NonDependencyOperation.scheduledStartTimeAsMilli(), is( 6l + offset ) ); assertThat( firstBlocking1NonDependencyOperation.timeStamp(), is( 6l ) ); assertThat( firstBlocking1NonDependencyOperation.dependencyTimeStamp(), is( 6l ) ); assertThat( secondBlocking1NonDependencyOperation.scheduledStartTimeAsMilli(), is( 10006l + offset ) ); assertThat( secondBlocking1NonDependencyOperation.timeStamp(), is( 10006l ) ); assertThat( secondBlocking1NonDependencyOperation.dependencyTimeStamp(), is( 10006l ) ); Operation firstBlocking2DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).dependencyOperations().next(); Operation secondBlocking2DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).dependencyOperations().next(); assertThat( firstBlocking2DependencyOperation.scheduledStartTimeAsMilli(), is( 8l + offset ) ); assertThat( firstBlocking2DependencyOperation.timeStamp(), is( 8l ) ); assertThat( firstBlocking2DependencyOperation.dependencyTimeStamp(), is( 8l ) ); assertThat( secondBlocking2DependencyOperation.scheduledStartTimeAsMilli(), is( 10008l + offset ) ); assertThat( secondBlocking2DependencyOperation.timeStamp(), is( 10008l ) ); assertThat( secondBlocking2DependencyOperation.dependencyTimeStamp(), is( 10008l ) ); Operation firstBlocking2NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).nonDependencyOperations().next(); Operation secondBlocking2NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).nonDependencyOperations().next(); assertThat( firstBlocking2NonDependencyOperation.scheduledStartTimeAsMilli(), is( 10l + offset ) ); assertThat( firstBlocking2NonDependencyOperation.timeStamp(), is( 10l ) ); assertThat( firstBlocking2NonDependencyOperation.dependencyTimeStamp(), is( 10l ) ); assertThat( secondBlocking2NonDependencyOperation.scheduledStartTimeAsMilli(), is( 100010l + offset ) ); assertThat( secondBlocking2NonDependencyOperation.timeStamp(), is( 100010l ) ); assertThat( secondBlocking2NonDependencyOperation.dependencyTimeStamp(), is( 100010l ) ); } @Test public void shouldPerformTimeOffsetAndCompressionCorrectly() throws WorkloadException { long offset = TimeUnit.SECONDS.toMillis( 100 ); WorkloadStreams workloadStreamsBefore = WorkloadStreams.timeOffsetAndCompressWorkloadStreams( getWorkloadStreams(), 0l + offset, 0.5, new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ) ); Operation firstAsyncDependencyOperation = workloadStreamsBefore.asynchronousStream().dependencyOperations().next(); Operation secondAsyncDependencyOperation = workloadStreamsBefore.asynchronousStream().dependencyOperations().next(); assertThat( firstAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 0l + offset ) ); assertThat( firstAsyncDependencyOperation.timeStamp(), is( 0l ) ); assertThat( secondAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 5l + offset ) ); assertThat( secondAsyncDependencyOperation.timeStamp(), is( 10l ) ); assertThat( secondAsyncDependencyOperation.scheduledStartTimeAsMilli() - firstAsyncDependencyOperation.scheduledStartTimeAsMilli(), is( 5l ) ); assertThat( secondAsyncDependencyOperation.timeStamp() - firstAsyncDependencyOperation.timeStamp(), is( 10l ) ); assertThat( secondAsyncDependencyOperation.dependencyTimeStamp() - firstAsyncDependencyOperation.dependencyTimeStamp(), is( 10l ) ); Operation firstAsyncNonDependencyOperation = workloadStreamsBefore.asynchronousStream().nonDependencyOperations().next(); Operation secondAsyncNonDependencyOperation = workloadStreamsBefore.asynchronousStream().nonDependencyOperations().next(); assertThat( firstAsyncNonDependencyOperation.scheduledStartTimeAsMilli(), is( 1l + offset ) ); assertThat( firstAsyncNonDependencyOperation.timeStamp(), is( 2l ) ); assertThat( firstAsyncNonDependencyOperation.dependencyTimeStamp(), is( 2l ) ); assertThat( secondAsyncNonDependencyOperation.scheduledStartTimeAsMilli(), is( 51l + offset ) ); assertThat( secondAsyncNonDependencyOperation.timeStamp(), is( 102l ) ); assertThat( secondAsyncNonDependencyOperation.dependencyTimeStamp(), is( 102l ) ); Operation firstBlocking1DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).dependencyOperations().next(); Operation secondBlocking1DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).dependencyOperations().next(); assertThat( firstBlocking1DependencyOperation.scheduledStartTimeAsMilli(), is( 2l + offset ) ); assertThat( firstBlocking1DependencyOperation.timeStamp(), is( 4l ) ); assertThat( firstBlocking1DependencyOperation.dependencyTimeStamp(), is( 4l ) ); assertThat( secondBlocking1DependencyOperation.scheduledStartTimeAsMilli(), is( 502l + offset ) ); assertThat( secondBlocking1DependencyOperation.timeStamp(), is( 1004l ) ); assertThat( secondBlocking1DependencyOperation.dependencyTimeStamp(), is( 1004l ) ); Operation firstBlocking1NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).nonDependencyOperations().next(); Operation secondBlocking1NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 0 ).nonDependencyOperations().next(); assertThat( firstBlocking1NonDependencyOperation.scheduledStartTimeAsMilli(), is( 3l + offset ) ); assertThat( firstBlocking1NonDependencyOperation.timeStamp(), is( 6l ) ); assertThat( firstBlocking1NonDependencyOperation.dependencyTimeStamp(), is( 6l ) ); assertThat( secondBlocking1NonDependencyOperation.scheduledStartTimeAsMilli(), is( 5003l + offset ) ); assertThat( secondBlocking1NonDependencyOperation.timeStamp(), is( 10006l ) ); assertThat( secondBlocking1NonDependencyOperation.dependencyTimeStamp(), is( 10006l ) ); Operation firstBlocking2DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).dependencyOperations().next(); Operation secondBlocking2DependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).dependencyOperations().next(); assertThat( firstBlocking2DependencyOperation.scheduledStartTimeAsMilli(), is( 4l + offset ) ); assertThat( firstBlocking2DependencyOperation.timeStamp(), is( 8l ) ); assertThat( firstBlocking2DependencyOperation.dependencyTimeStamp(), is( 8l ) ); assertThat( secondBlocking2DependencyOperation.scheduledStartTimeAsMilli(), is( 5004l + offset ) ); assertThat( secondBlocking2DependencyOperation.timeStamp(), is( 10008l ) ); assertThat( secondBlocking2DependencyOperation.dependencyTimeStamp(), is( 10008l ) ); Operation firstBlocking2NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).nonDependencyOperations().next(); Operation secondBlocking2NonDependencyOperation = workloadStreamsBefore.blockingStreamDefinitions().get( 1 ).nonDependencyOperations().next(); assertThat( firstBlocking2NonDependencyOperation.scheduledStartTimeAsMilli(), is( 5l + offset ) ); assertThat( firstBlocking2NonDependencyOperation.timeStamp(), is( 10l ) ); assertThat( firstBlocking2NonDependencyOperation.dependencyTimeStamp(), is( 10l ) ); assertThat( secondBlocking2NonDependencyOperation.scheduledStartTimeAsMilli(), is( 50005l + offset ) ); assertThat( secondBlocking2NonDependencyOperation.timeStamp(), is( 100010l ) ); assertThat( secondBlocking2NonDependencyOperation.dependencyTimeStamp(), is( 100010l ) ); } @Test public void shouldLimitWorkloadCorrectly() throws WorkloadException, DriverConfigurationException, IOException { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); WorkloadFactory workloadFactory = new WorkloadFactory() { @Override public Workload createWorkload() throws WorkloadException { return new TestWorkload(); } }; ConsoleAndFileDriverConfiguration configuration = ConsoleAndFileDriverConfiguration.fromDefaults( null, null, 100 ); boolean returnStreamsWithDbConnector = false; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<WorkloadStreams,Workload,Long> limitedWorkloadStreamsAndWorkload = WorkloadStreams.createNewWorkloadWithOffsetAndLimitedWorkloadStreams( workloadFactory, configuration, gf, returnStreamsWithDbConnector, 0, configuration.operationCount(), loggingServiceFactory ); WorkloadStreams workloadStreams = limitedWorkloadStreamsAndWorkload._1(); Workload workload = limitedWorkloadStreamsAndWorkload._2(); assertThat( Iterators .size( WorkloadStreams .mergeSortedByStartTimeExcludingChildOperationGenerators( gf, workloadStreams ) ), is( 100 ) ); workload.close(); } @Test public void shouldLimitWorkloadCorrectly_WITH_OFFSET() throws WorkloadException, DriverConfigurationException, IOException { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); WorkloadFactory workloadFactory = new WorkloadFactory() { @Override public Workload createWorkload() throws WorkloadException { return new TestWorkload(); } }; ConsoleAndFileDriverConfiguration configuration = ConsoleAndFileDriverConfiguration.fromDefaults( null, null, 100 ); configuration = (ConsoleAndFileDriverConfiguration) configuration .applyArg( ConsoleAndFileDriverConfiguration.WARMUP_COUNT_ARG, Long.toString( 10 ) ); boolean returnStreamsWithDbConnector = false; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<WorkloadStreams,Workload,Long> limitedWorkloadStreamsAndWorkload = WorkloadStreams.createNewWorkloadWithOffsetAndLimitedWorkloadStreams( workloadFactory, configuration, gf, returnStreamsWithDbConnector, configuration.warmupCount(), configuration.operationCount(), loggingServiceFactory ); WorkloadStreams workloadStreams = limitedWorkloadStreamsAndWorkload._1(); Workload workload = limitedWorkloadStreamsAndWorkload._2(); assertThat( Iterators .size( WorkloadStreams .mergeSortedByStartTimeExcludingChildOperationGenerators( gf, workloadStreams ) ), is( 100 ) ); workload.close(); } @Test public void shouldLimitStreamsCorrectly() throws WorkloadException { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); List<Operation> stream0 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "0-1" ), new TimedNamedOperation1( 1l, 1l, 0l, "0-2" ), new TimedNamedOperation1( 2l, 2l, 0l, "0-3" ), new TimedNamedOperation1( 6l, 6l, 0l, "0-4" ), new TimedNamedOperation1( 7l, 7l, 0l, "0-5" ) ); List<Operation> stream1 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "1-1" ), new TimedNamedOperation1( 3l, 3l, 0l, "1-2" ), new TimedNamedOperation1( 4l, 4l, 0l, "1-3" ), new TimedNamedOperation1( 9l, 9l, 0l, "1-4" ) ); List<Operation> stream2 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 1l, 1l, 0l, "2-1" ), new TimedNamedOperation1( 3l, 3l, 0l, "2-2" ), new TimedNamedOperation1( 4l, 4l, 0l, "2-3" ), new TimedNamedOperation1( 8l, 8l, 0l, "2-4" ), new TimedNamedOperation1( 8l, 8l, 0l, "2-5" ), new TimedNamedOperation1( 9l, 9l, 0l, "2-6" ) ); List<Operation> stream3 = Lists.newArrayList( ); List<Operation> stream4 = Lists.newArrayList( gf.limit( new TimedNamedOperation1Factory( gf.incrementing( 10l, 1l ), gf.constant( 0l ), gf.constant( "4-x" ) ), 1000000 ) ); List<Iterator<Operation>> streams = Lists.newArrayList( stream0.iterator(), stream1.iterator(), stream2.iterator(), stream3.iterator(), stream4.iterator() ); List<ChildOperationGenerator> childOperationGenerators = Lists.newArrayList( null, null, null, null, null ); long offset = 0; long count = 10; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<long[],long[],Long> kForIteratorAndMinimums = WorkloadStreams.fromAmongAllRetrieveTopCountFromOffset( streams, offset, count, childOperationGenerators, loggingServiceFactory ); long[] startForIterator = kForIteratorAndMinimums._1(); long[] countForIterator = kForIteratorAndMinimums._2(); long minimumTimeStamp = kForIteratorAndMinimums._3(); List<Operation> topK = Lists.newArrayList( gf.mergeSortOperationsByTimeStamp( gf.limit( stream0.iterator(), countForIterator[0] ), gf.limit( stream1.iterator(), countForIterator[1] ), gf.limit( stream2.iterator(), countForIterator[2] ), gf.limit( stream3.iterator(), countForIterator[3] ), gf.limit( stream4.iterator(), countForIterator[4] ) ) ); assertThat( (long) topK.size(), is( count ) ); assertThat( minimumTimeStamp, is( 0l ) ); assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), anyOf( equalTo( "0-1" ), equalTo( "1-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 1 )).name(), anyOf( equalTo( "0-1" ), equalTo( "1-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 1 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), anyOf( equalTo( "0-2" ), equalTo( "2-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 3 )).name(), anyOf( equalTo( "0-2" ), equalTo( "2-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 3 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 4 )).name(), anyOf( equalTo( "0-3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 5 )).name(), anyOf( equalTo( "1-2" ), equalTo( "2-2" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 6 )).name(), anyOf( equalTo( "1-2" ), equalTo( "2-2" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 5 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 6 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 7 )).name(), anyOf( equalTo( "1-3" ), equalTo( "2-3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 8 )).name(), anyOf( equalTo( "1-3" ), equalTo( "2-3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 7 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 8 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 9 )).name(), anyOf( equalTo( "0-4" ) ) ); } @Test public void shouldLimitStreamsCorrectlyWhenLimitIsHigherThanActualStreamsLength() throws WorkloadException { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); List<Operation> stream0 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "0-1" ), new TimedNamedOperation1( 1l, 1l, 0l, "0-2" ), new TimedNamedOperation1( 2l, 2l, 0l, "0-3" ), new TimedNamedOperation1( 6l, 6l, 0l, "0-4" ) ); List<Operation> stream1 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "1-1" ), new TimedNamedOperation1( 3l, 3l, 0l, "1-2" ), new TimedNamedOperation1( 4l, 4l, 0l, "1-3" ) ); List<Operation> stream2 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 1l, 1l, 0l, "2-1" ), new TimedNamedOperation1( 3l, 3l, 0l, "2-2" ), new TimedNamedOperation1( 4l, 4l, 0l, "2-3" ) ); List<Operation> stream3 = Lists.newArrayList( ); List<Operation> stream4 = Lists.newArrayList( gf.limit( new TimedNamedOperation1Factory( gf.incrementing( 10l, 1l ), gf.constant( 0l ), gf.constant( "4-x" ) ), 1000000 ) ); List<Iterator<Operation>> streams = Lists.newArrayList( stream0.iterator(), stream1.iterator(), stream2.iterator(), stream3.iterator(), stream4.iterator() ); List<ChildOperationGenerator> childOperationGenerators = Lists.newArrayList( null, null, null, null, null ); long offset = 0; long count = 10000; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<long[],long[],Long> kForIteratorAndMinimums = WorkloadStreams.fromAmongAllRetrieveTopCountFromOffset( streams, offset, count, childOperationGenerators, loggingServiceFactory ); long[] startForIterator = kForIteratorAndMinimums._1(); long[] countForIterator = kForIteratorAndMinimums._2(); long minimumTimeStamp = kForIteratorAndMinimums._3(); List<Operation> topK = Lists.newArrayList( gf.mergeSortOperationsByTimeStamp( gf.limit( stream0.iterator(), countForIterator[0] ), gf.limit( stream1.iterator(), countForIterator[1] ), gf.limit( stream2.iterator(), countForIterator[2] ), gf.limit( stream3.iterator(), countForIterator[3] ), gf.limit( stream4.iterator(), countForIterator[4] ) ) ); assertThat( (long) topK.size(), is( count ) ); assertThat( minimumTimeStamp, is( 0l ) ); assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), anyOf( equalTo( "0-1" ), equalTo( "1-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 1 )).name(), anyOf( equalTo( "0-1" ), equalTo( "1-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 1 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), anyOf( equalTo( "0-2" ), equalTo( "2-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 3 )).name(), anyOf( equalTo( "0-2" ), equalTo( "2-1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 3 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 4 )).name(), anyOf( equalTo( "0-3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 5 )).name(), anyOf( equalTo( "1-2" ), equalTo( "2-2" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 6 )).name(), anyOf( equalTo( "1-2" ), equalTo( "2-2" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 5 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 6 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 7 )).name(), anyOf( equalTo( "1-3" ), equalTo( "2-3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 8 )).name(), anyOf( equalTo( "1-3" ), equalTo( "2-3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 7 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 8 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 9 )).name(), anyOf( equalTo( "0-4" ) ) ); } @Test public void shouldStartAtOffsetAndLimitStreamsCorrectlyWhenLimitIsLowerThanStreamsLength() throws WorkloadException { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); List<Operation> stream0 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "0-1--0" ), new TimedNamedOperation1( 1l, 1l, 0l, "0-2--1" ), new TimedNamedOperation1( 2l, 2l, 0l, "0-3--2" ), new TimedNamedOperation1( 6l, 6l, 0l, "0-4--6" ), new TimedNamedOperation1( 7l, 7l, 0l, "0-5--7" ) ); List<Operation> stream1 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "1-1--0" ), new TimedNamedOperation1( 3l, 3l, 0l, "1-2--3" ), new TimedNamedOperation1( 4l, 4l, 0l, "1-3--4" ), new TimedNamedOperation1( 9l, 9l, 0l, "1-4--9" ) ); List<Operation> stream2 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 1l, 1l, 0l, "2-1--1" ), new TimedNamedOperation1( 3l, 3l, 0l, "2-2--3" ), new TimedNamedOperation1( 4l, 4l, 0l, "2-3--4" ), new TimedNamedOperation1( 8l, 8l, 0l, "2-4--8" ), new TimedNamedOperation1( 8l, 8l, 0l, "2-5--8" ), new TimedNamedOperation1( 9l, 9l, 0l, "2-6--9" ) ); List<Operation> stream3 = Lists.newArrayList( ); List<Operation> stream4 = Lists.newArrayList( gf.limit( new TimedNamedOperation1Factory( gf.incrementing( 10l, 1l ), gf.constant( 0l ), gf.constant( "4-x--y" ) ), 1000000 ) ); List<Iterator<Operation>> streams = Lists.newArrayList( stream0.iterator(), stream1.iterator(), stream2.iterator(), stream3.iterator(), stream4.iterator() ); List<ChildOperationGenerator> childOperationGenerators = Lists.newArrayList( null, null, null, null, null ); long offset = 5; long count = 6; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<long[],long[],Long> kForIteratorAndMinimums = WorkloadStreams.fromAmongAllRetrieveTopCountFromOffset( streams, offset, count, childOperationGenerators, loggingServiceFactory ); long[] startForIterator = kForIteratorAndMinimums._1(); long[] countForIterator = kForIteratorAndMinimums._2(); long minimumTimeStamp = kForIteratorAndMinimums._3(); List<Iterator<Operation>> offsetStreams = Lists.newArrayList( stream0.iterator(), stream1.iterator(), stream2.iterator(), stream3.iterator(), stream4.iterator() ); for ( int i = 0; i < offsetStreams.size(); i++ ) { Iterator<Operation> offsetStream = offsetStreams.get( i ); gf.consume( offsetStream, startForIterator[i] ); } List<Operation> topK = Lists.newArrayList( gf.mergeSortOperationsByTimeStamp( gf.limit( offsetStreams.get( 0 ), countForIterator[0] ), gf.limit( offsetStreams.get( 1 ), countForIterator[1] ), gf.limit( offsetStreams.get( 2 ), countForIterator[2] ), gf.limit( offsetStreams.get( 3 ), countForIterator[3] ), gf.limit( offsetStreams.get( 4 ), countForIterator[4] ) ) ); /* offset = 5 count = 6 TimeStamp Operation 0 0-1--0, 1-1--0 1 0-2--1, 2-1--1 2 0-3--2 ----- 5 ----- 3 1-2--3, 2-2--3 4 1-3--4, 2-3--4 6 0-4--6 ----- 10 ---- 7 0-5--7 8 2-4--8, 2-5--8 9 1-4--9, 2-6--9 ----- 15 ---- 10 4-x--y 11 4-x--y ... 1000000 4-x--y */ assertThat( (long) topK.size(), is( count ) ); assertThat( minimumTimeStamp, is( 3l ) ); assertThat( startForIterator.length, is( 5 ) ); assertThat( countForIterator.length, is( 5 ) ); assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), anyOf( equalTo( "1-2--3" ), equalTo( "2-2--3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 1 )).name(), anyOf( equalTo( "1-2--3" ), equalTo( "2-2--3" ) ) ); // does not return the same operation twice, when their time stamps are equal assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 1 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), anyOf( equalTo( "1-3--4" ), equalTo( "2-3--4" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 3 )).name(), anyOf( equalTo( "1-3--4" ), equalTo( "2-3--4" ) ) ); // does not return the same operation twice, when their time stamps are equal assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 3 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 4 )).name(), anyOf( equalTo( "0-4--6" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 5 )).name(), anyOf( equalTo( "0-5--7" ) ) ); } @Test public void shouldStartAtOffsetAndLimitStreamsCorrectlyWhenLimitIsHigherThanStreamsLength() throws WorkloadException { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); List<Operation> stream0 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "0-1--0" ), new TimedNamedOperation1( 1l, 1l, 0l, "0-2--1" ), new TimedNamedOperation1( 2l, 2l, 0l, "0-3--2" ), new TimedNamedOperation1( 6l, 6l, 0l, "0-4--6" ), new TimedNamedOperation1( 7l, 7l, 0l, "0-5--7" ) ); List<Operation> stream1 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 0l, 0l, 0l, "1-1--0" ), new TimedNamedOperation1( 3l, 3l, 0l, "1-2--3" ), new TimedNamedOperation1( 4l, 4l, 0l, "1-3--4" ), new TimedNamedOperation1( 9l, 9l, 0l, "1-4--9" ) ); List<Operation> stream2 = Lists.<Operation>newArrayList( new TimedNamedOperation1( 1l, 1l, 0l, "2-1--1" ), new TimedNamedOperation1( 3l, 3l, 0l, "2-2--3" ), new TimedNamedOperation1( 4l, 4l, 0l, "2-3--4" ), new TimedNamedOperation1( 8l, 8l, 0l, "2-4--8" ), new TimedNamedOperation1( 8l, 8l, 0l, "2-5--8" ), new TimedNamedOperation1( 9l, 9l, 0l, "2-6--9" ) ); List<Operation> stream3 = Lists.newArrayList( ); List<Iterator<Operation>> streams = Lists.newArrayList( stream0.iterator(), stream1.iterator(), stream2.iterator(), stream3.iterator() ); List<ChildOperationGenerator> childOperationGenerators = Lists.newArrayList( null, null, null, null, null ); long offset = 3; long count = 100; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<long[],long[],Long> kForIteratorAndMinimums = WorkloadStreams.fromAmongAllRetrieveTopCountFromOffset( streams, offset, count, childOperationGenerators, loggingServiceFactory ); long[] startForIterator = kForIteratorAndMinimums._1(); long[] countForIterator = kForIteratorAndMinimums._2(); long minimumTimeStamp = kForIteratorAndMinimums._3(); List<Iterator<Operation>> offsetStreams = Lists.newArrayList( stream0.iterator(), stream1.iterator(), stream2.iterator(), stream3.iterator() ); for ( int i = 0; i < offsetStreams.size(); i++ ) { Iterator<Operation> offsetStream = offsetStreams.get( i ); gf.consume( offsetStream, startForIterator[i] ); } List<Operation> topK = Lists.newArrayList( gf.mergeSortOperationsByTimeStamp( gf.limit( offsetStreams.get( 0 ), countForIterator[0] ), gf.limit( offsetStreams.get( 1 ), countForIterator[1] ), gf.limit( offsetStreams.get( 2 ), countForIterator[2] ), gf.limit( offsetStreams.get( 3 ), countForIterator[3] ) ) ); /* offset = 3 count = 100 TimeStamp Operation 0 0-1--0, 1-1--0 ----- 2 ----- 1 0-2--1, 2-1--1 ----- 4 ----- 2 0-3--2 3 1-2--3, 2-2--3 4 1-3--4, 2-3--4 6 0-4--6 7 0-5--7 8 2-4--8, 2-5--8 9 1-4--9, 2-6--9 */ assertThat( (long) topK.size(), is( 12l ) ); assertThat( minimumTimeStamp, is( 1l ) ); assertThat( startForIterator.length, is( 4 ) ); assertThat( countForIterator.length, is( 4 ) ); assertThat( ((TimedNamedOperation1) topK.get( 0 )).name(), anyOf( equalTo( "0-2--1" ), equalTo( "2-1--1" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 1 )).name(), anyOf( equalTo( "0-3--2" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), anyOf( equalTo( "1-2--3" ), equalTo( "2-2--3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 3 )).name(), anyOf( equalTo( "1-2--3" ), equalTo( "2-2--3" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 2 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 3 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 4 )).name(), anyOf( equalTo( "1-3--4" ), equalTo( "2-3--4" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 5 )).name(), anyOf( equalTo( "1-3--4" ), equalTo( "2-3--4" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 4 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 5 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 6 )).name(), anyOf( equalTo( "0-4--6" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 7 )).name(), anyOf( equalTo( "0-5--7" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 8 )).name(), anyOf( equalTo( "2-4--8" ), equalTo( "2-5--8" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 9 )).name(), anyOf( equalTo( "2-4--8" ), equalTo( "2-5--8" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 8 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 9 )).name() ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 10 )).name(), anyOf( equalTo( "1-4--9" ), equalTo( "2-6--9" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 11 )).name(), anyOf( equalTo( "1-4--9" ), equalTo( "2-6--9" ) ) ); assertThat( ((TimedNamedOperation1) topK.get( 10 )).name(), not( equalTo( ((TimedNamedOperation1) topK.get( 11 )).name() ) ) ); } private class TestWorkload extends Workload { @Override public Map<Integer,Class<? extends Operation>> operationTypeToClassMapping() { Map<Integer,Class<? extends Operation>> operationTypeToClassMapping = new HashMap<>(); operationTypeToClassMapping.put( NothingOperation.TYPE, NothingOperation.class ); operationTypeToClassMapping.put( TimedNamedOperation1.TYPE, TimedNamedOperation1.class ); operationTypeToClassMapping.put( TimedNamedOperation2.TYPE, TimedNamedOperation2.class ); operationTypeToClassMapping.put( TimedNamedOperation3.TYPE, TimedNamedOperation3.class ); return operationTypeToClassMapping; } @Override public void onInit( Map<String,String> params ) throws WorkloadException { } @Override protected void onClose() throws IOException { } @Override protected WorkloadStreams getStreams( GeneratorFactory generators, boolean hasDbConnected ) throws WorkloadException { return getWorkloadStreams(); } @Override public String serializeOperation( Operation operation ) throws SerializingMarshallingException { return null; } @Override public Operation marshalOperation( String serializedOperation ) throws SerializingMarshallingException { return null; } @Override public boolean resultsEqual( Operation operation, Object result1, Object result2 ) throws WorkloadException { if ( null == result1 || null == result2 ) { return false; } else { return result1.equals( result2 ); } } } private WorkloadStreams getWorkloadStreams() { GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42l ) ); Iterator<Operation> asyncDependencyStream = new TimedNamedOperation1Factory( gf.incrementing( 0l, 10l ), gf.incrementing( 0l, 10l ), gf.constant( "ad" ) ); Iterator<Operation> asyncNonDependencyStream = new TimedNamedOperation1Factory( gf.incrementing( 2l, 100l ), gf.incrementing( 2l, 100l ), gf.constant( "an" ) ); Iterator<Operation> blockingDependencyStream1 = new TimedNamedOperation2Factory( gf.incrementing( 4l, 1000l ), gf.incrementing( 4l, 1000l ), gf.constant( "bd1" ) ); Iterator<Operation> blockingNonDependencyStream1 = new TimedNamedOperation2Factory( gf.incrementing( 6l, 10000l ), gf.incrementing( 6l, 10000l ), gf.constant( "bn1" ) ); Iterator<Operation> blockingDependencyStream2 = new TimedNamedOperation3Factory( gf.incrementing( 8l, 10000l ), gf.incrementing( 8l, 10000l ), gf.constant( "bd2" ) ); Iterator<Operation> blockingNonDependencyStream2 = new TimedNamedOperation3Factory( gf.incrementing( 10l, 100000l ), gf.incrementing( 10l, 100000l ), gf.constant( "bn2" ) ); WorkloadStreams workloadStreams = new WorkloadStreams(); workloadStreams.setAsynchronousStream( new HashSet<Class<? extends Operation>>(), Sets.<Class<? extends Operation>>newHashSet( TimedNamedOperation1.class ), asyncDependencyStream, asyncNonDependencyStream, null ); workloadStreams.addBlockingStream( new HashSet<Class<? extends Operation>>(), Sets.<Class<? extends Operation>>newHashSet( TimedNamedOperation2.class ), blockingDependencyStream1, blockingNonDependencyStream1, null ); workloadStreams.addBlockingStream( new HashSet<Class<? extends Operation>>(), Sets.<Class<? extends Operation>>newHashSet( TimedNamedOperation3.class ), blockingDependencyStream2, blockingNonDependencyStream2, null ); return workloadStreams; } }