package uk.co.acuminous.julez.event.handler;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.UUID;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import uk.co.acuminous.julez.runner.ScenarioRunnerEvent;
import uk.co.acuminous.julez.runner.ScenarioRunnerEventFactory;
import uk.co.acuminous.julez.scenario.ScenarioEvent;
import uk.co.acuminous.julez.scenario.ScenarioEventFactory;
import uk.co.acuminous.julez.util.ConcurrencyUtils;
public class ThroughputMonitorTest {
private ScenarioEventFactory scenarioEventFactory;
private ScenarioRunnerEventFactory scenarioRunnerEventFactory;
private ThroughputMonitor monitor;
private DateTime timestamp;
@Before
public void init() {
scenarioEventFactory = new ScenarioEventFactory();
scenarioRunnerEventFactory = new ScenarioRunnerEventFactory();
monitor = new ThroughputMonitor();
timestamp = new DateTime();
}
@Test
public void tolleratesThroughputEnquiriesBeforeTheScenarioRunnerHasStarted() {
assertTrue(0 == new ThroughputMonitor().getThroughput());
}
public void disregardsScenarioEventsBeforeArrivalOfScenarioRunnerBeginEvent() {
scenario();
assertTrue(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingAfterScenarioRunnerBeginEventWithIdenticalTimestamps() {
scenarioRunnerBegin(timestamp);
scenario(timestamp);
assertFalse(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingAfterScenarioRunnerBeginEventWithAscendingTimestamps() {
scenarioRunnerBegin(timestamp);
scenario(timestamp.plusMillis(1));
assertFalse(wasDisregarded());
}
@Test
public void disregardsScenarioEventsArrivingAfterScenarioRunnerBeginEventWithDescendingTimestamps() {
scenarioRunnerBegin(timestamp);
scenario(timestamp.minusMillis(1));
assertTrue(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingBetweenScenarioRunnerBeginAndEndEventsWithIdenticalTimestamps() {
scenarioRunnerBegin(timestamp);
scenario(timestamp);
scenarioRunnerEnd(timestamp);
assertFalse(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingBetweenScenarioRunnerBeginAndEndEventsWithAscendingTimestamps() {
scenarioRunnerBegin(timestamp);
scenario(timestamp.plusMillis(1));
scenarioRunnerEnd(timestamp.plusMillis(2));
assertFalse(wasDisregarded());
}
@Test
public void disregardsScenarioEventsArrivingAfterBothScenarioRunnerBeginAndEndEventsWithAscendingTimestamps() {
scenarioRunnerBegin(timestamp);
scenarioRunnerEnd(timestamp.plusMillis(1));
scenario(timestamp.plusMillis(2));
assertTrue(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingAfterBothScenarioRunnerBeginAndEndEventsWithTimestampIdenticalToScenarioRunnerBeginEvent() {
scenarioRunnerBegin(timestamp);
scenarioRunnerEnd(timestamp.plusMillis(1));
scenario(timestamp);
assertFalse(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingAfterBothScenarioRunnerBeginAndEndEventsWithTimestampIdenticalToScenarioRunnerEndEvent() {
scenarioRunnerBegin(timestamp);
scenarioRunnerEnd(timestamp.plusMillis(1));
scenario(timestamp.plusMillis(1));
assertFalse(wasDisregarded());
}
@Test
public void regardsScenarioEventsArrivingAfterBothScenarioRunnerBeginAndEndEventsWithTimestampBetweenScenarioRunnerEvents() {
scenarioRunnerBegin(timestamp);
scenarioRunnerEnd(timestamp.plusMillis(2));
scenario(timestamp.plusMillis(1));
assertFalse(wasDisregarded());
}
@Test
public void disregardsScenarioEventsArrivingAfterScenarioRunnerBeginButButStampedAsBefore() {
ThroughputMonitor monitor = new ThroughputMonitor();
DateTime now = new DateTime();
monitor.onEvent(new ScenarioEvent("id", now.getMillis(), ScenarioRunnerEvent.BEGIN));
monitor.onEvent(new ScenarioEvent("id", now.minusMillis(1).getMillis(), ScenarioEvent.END));
assertEquals(0, monitor.getThroughput());
}
@Test
public void calculatesThroughputWhileScenarioRunnerIsRunning() {
scenarioRunnerBegin();
for (int i = 0; i < 10; i++) {
scenario();
}
ConcurrencyUtils.sleep(500, MILLISECONDS);
assertEquals(20, monitor.getThroughput());
ConcurrencyUtils.sleep(500, MILLISECONDS);
assertEquals(10, monitor.getThroughput());
scenarioRunnerEnd();
}
@Test
public void regurgitatesThroughputAfterScenarioRunnerIsFinished() {
ThroughputMonitor monitor = new ThroughputMonitor();
scenarioRunnerBegin();
for (int i = 0; i < 10; i++) {
scenario();
}
int throughput = monitor.getThroughput();
scenarioRunnerEnd();
ConcurrencyUtils.sleep(100, MILLISECONDS);
assertEquals(throughput, monitor.getThroughput());
}
@Test
public void calculatesThroughputForVeryQuickScenarios() {
ThroughputMonitor monitor = new ThroughputMonitor();
monitor.onEvent(scenarioRunnerEventFactory.begin());
monitor.onEvent(scenarioEventFactory.begin());
monitor.onEvent(scenarioEventFactory.pass());
monitor.onEvent(scenarioEventFactory.end());
monitor.onEvent(scenarioRunnerEventFactory.end());
assertFalse("Throughput was not calculated for extremely quick scenario", 0 == monitor.getThroughput());
}
public void scenario() {
scenario(new DateTime());
}
public void scenario(DateTime timestamp) {
monitor.onEvent(new ScenarioEvent(UUID.randomUUID().toString(), timestamp.getMillis(), ScenarioEvent.BEGIN));
monitor.onEvent(new ScenarioEvent(UUID.randomUUID().toString(), timestamp.getMillis(), ScenarioEvent.END));
}
public void scenarioRunnerBegin() {
scenarioRunnerBegin(new DateTime());
}
private void scenarioRunnerBegin(DateTime timestamp) {
monitor.onEvent(new ScenarioRunnerEvent(UUID.randomUUID().toString(), timestamp.getMillis(), ScenarioRunnerEvent.BEGIN));
}
public void scenarioRunnerEnd() {
scenarioRunnerEnd(new DateTime());
}
private void scenarioRunnerEnd(DateTime timestamp) {
monitor.onEvent(new ScenarioRunnerEvent(UUID.randomUUID().toString(), timestamp.getMillis(), ScenarioRunnerEvent.END));
}
private boolean wasDisregarded() {
return (0 == monitor.getThroughput());
}
}