/*
* #!
* %
* Copyright (C) 2014 - 2016 Humboldt-Universität zu Berlin
* %
* 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 de.hub.cs.dbis.lrb.operators;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.stubbing.OngoingStubbing;
import org.powermock.modules.junit4.PowerMockRunner;
import backtype.storm.task.OutputCollector;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import backtype.storm.utils.Utils;
import de.hub.cs.dbis.aeolus.testUtils.TestDeclarer;
import de.hub.cs.dbis.aeolus.testUtils.TestOutputCollector;
import de.hub.cs.dbis.aeolus.utils.TimestampMerger;
import de.hub.cs.dbis.lrb.queries.utils.TopologyControl;
import de.hub.cs.dbis.lrb.types.PositionReport;
import de.hub.cs.dbis.lrb.types.internal.StoppedCarTuple;
import de.hub.cs.dbis.lrb.util.Constants;
/**
* @author mjsax
*/
@RunWith(PowerMockRunner.class)
public class StoppedCarsBoltTest {
private final static int exit = Constants.EXIT_LANE;
// @formatter:off
// position size = 528000 with pos = [0..517999]
@SuppressWarnings("boxing") private static Integer[][][] timeAndPositions = new Integer[][][] {
// vehicle 1
new Integer[][] {new Integer[] {0, 1, 50101},
new Integer[] {0, 31, 50102},
new Integer[] {0, 61, 50102},
new Integer[] {0, 91, 50102},
new Integer[] {0, 121, 50102}, // stop v1
new Integer[] {0, 151, 50103}, // move v1
new Integer[] {0, 181, 50103},
new Integer[] {0, 211, 50103},
new Integer[] {0, 241, 50103}, // stop v1 -> accident m=5
new Integer[] {0, 271, 50103}, // stop v1
new Integer[] {0, 301, 50105}, // move v1
new Integer[] {0, 331, 50105},
new Integer[] {0, 361, 50105},
new Integer[] {0, 391, 50105}, // stop v1 -> accident m=7
},
// vehicle 2
new Integer[][] {new Integer[] {0, 5, 50100},
new Integer[] {0, 35, 50101},
new Integer[] {0, 65, 50102},
new Integer[] {0, 95, 50102},
new Integer[] {0, 125, 50102},
new Integer[] {0, 155, 50102}, // stop v2
new Integer[] {0, 185, 50103}, // move v2
new Integer[] {0, 215, 50103},
new Integer[] {0, 245, 50105},
new Integer[] {0, 275, 50105},
new Integer[] {0, 305, 50105},
new Integer[] {0, 335, 50105}, // stop v2 -> accident m=6
new Integer[] {0, 365, 50105}, // stop v2 -> accident m=7
new Integer[] {0, 395, 50106}, // move v2
},
// vehicle 3
new Integer[][] {new Integer[] {0, 10, 50105},
new Integer[] {0, 40, 50105},
new Integer[] {0, 70, 50105},
new Integer[] {0, 100, 50105}, // stop v3
new Integer[] {0, 130, 50105}, // stop v3
new Integer[] {0, 160, 50105}, // stop v3
new Integer[] {0, 190, 50105}, // stop v3
new Integer[] {0, 220, 50105}, // stop v3
new Integer[] {0, 250, 50105}, // stop v3
new Integer[] {0, 280, 50105}, // stop v3
new Integer[] {0, 310, 50105}, // stop v3
new Integer[] {0, 340, 50105}, // stop v3 -> accident m=6
new Integer[] {0, 370, 50105}, // stop v3 -> accident m=7
new Integer[] {0, 400, 50106}, // move v3
},
// vehicle 4 (on exit lane -- short not trigger accident)
new Integer[][] {new Integer[] {exit, 5, 50102},
new Integer[] {exit, 35, 50102},
new Integer[] {exit, 65, 50102},
new Integer[] {exit, 95, 50102}, // stop v4
new Integer[] {exit, 125, 50102}, // stop v4
new Integer[] {exit, 155, 50103}, // move v4
new Integer[] {exit, 185, 50103},
new Integer[] {exit, 215, 50103},
new Integer[] {exit, 245, 50103}, // stop v4
new Integer[] {exit, 275, 50105}, // move v4
new Integer[] {exit, 305, 50105},
new Integer[] {exit, 335, 50105},
new Integer[] {exit, 365, 50105}, // stop v4
new Integer[] {exit, 395, 50105}, // stop v4
}
};
// @formatter:on
@SuppressWarnings("boxing")
@Test
public void testExecute() {
Tuple tuple = mock(Tuple.class);
when(tuple.getSourceStreamId()).thenReturn("streamId");
OngoingStubbing<List<Object>> tupleValueStub = when(tuple.getValues());
final int numberOfVehicles = timeAndPositions.length;
final int numberOfReporst = timeAndPositions[0].length;
for(int m = 0; m < numberOfReporst; ++m) {
for(int vid = 1; vid <= numberOfVehicles; ++vid) {
PositionReport pr = new PositionReport(timeAndPositions[vid - 1][m][1].shortValue(), vid, 0, 0,
timeAndPositions[vid - 1][m][0].shortValue(), Constants.EASTBOUND,
(short)(timeAndPositions[vid - 1][m][2].intValue() / 5280), timeAndPositions[vid - 1][m][2]);
tupleValueStub = tupleValueStub.thenReturn(pr);
}
}
tupleValueStub.thenReturn(null);
StoppedCarsBolt bolt = new StoppedCarsBolt();
TestOutputCollector collector = new TestOutputCollector();
bolt.prepare(null, null, new OutputCollector(collector));
for(int i = 0; i < numberOfReporst * numberOfVehicles; ++i) {
bolt.execute(tuple);
}
List<Values> expectedFlushs = new ArrayList<Values>();
expectedFlushs.add(new Values((short)1));
expectedFlushs.add(new Values((short)61));
expectedFlushs.add(new Values((short)121));
expectedFlushs.add(new Values((short)181));
expectedFlushs.add(new Values((short)241));
expectedFlushs.add(new Values((short)301));
expectedFlushs.add(new Values((short)361));
List<StoppedCarTuple> expectedResult = new ArrayList<StoppedCarTuple>();
expectedResult.add(new StoppedCarTuple(3, (short)100, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(1, (short)121, 0, (short)0, 50102, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)130, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(-1, (short)151, 0, (short)0, 50102, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(2, (short)155, 0, (short)0, 50102, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)160, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(-2, (short)185, 0, (short)0, 50102, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)190, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)220, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(1, (short)241, 0, (short)0, 50103, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)250, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(1, (short)271, 0, (short)0, 50103, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)280, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(-1, (short)301, 0, (short)0, 50103, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)310, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(2, (short)335, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)340, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(2, (short)365, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(3, (short)370, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(1, (short)391, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(-2, (short)395, 0, (short)0, 50105, Constants.EASTBOUND));
expectedResult.add(new StoppedCarTuple(-3, (short)400, 0, (short)0, 50105, Constants.EASTBOUND));
Assert.assertEquals(2, collector.output.size());
Assert.assertEquals(expectedFlushs, collector.output.get(TimestampMerger.FLUSH_STREAM_ID));
Assert.assertEquals(expectedResult, collector.output.get(Utils.DEFAULT_STREAM_ID));
Tuple flushTuple = mock(Tuple.class);
when(flushTuple.getSourceStreamId()).thenReturn(TimestampMerger.FLUSH_STREAM_ID);
bolt.execute(flushTuple);
Assert.assertEquals(expectedFlushs.size() + 1, collector.output.get(TimestampMerger.FLUSH_STREAM_ID).size());
Assert.assertEquals(new Values((Object)null),
collector.output.get(TimestampMerger.FLUSH_STREAM_ID).get(expectedFlushs.size()));
}
@Test
public void testDeclareOutputFields() {
AccidentDetectionBolt bolt = new AccidentDetectionBolt();
TestDeclarer declarer = new TestDeclarer();
bolt.declareOutputFields(declarer);
Assert.assertEquals(2, declarer.streamIdBuffer.size());
Assert.assertEquals(2, declarer.schemaBuffer.size());
Assert.assertEquals(2, declarer.directBuffer.size());
Assert.assertEquals(TopologyControl.ACCIDENTS_STREAM_ID, declarer.streamIdBuffer.get(0));
Assert.assertEquals(new Fields(TopologyControl.TIMESTAMP_FIELD_NAME, TopologyControl.XWAY_FIELD_NAME,
TopologyControl.SEGMENT_FIELD_NAME, TopologyControl.DIRECTION_FIELD_NAME).toList(), declarer.schemaBuffer
.get(0).toList());
Assert.assertEquals(new Boolean(false), declarer.directBuffer.get(0));
Assert.assertEquals(TimestampMerger.FLUSH_STREAM_ID, declarer.streamIdBuffer.get(1));
Assert.assertEquals(new Fields("ts").toList(), declarer.schemaBuffer.get(1).toList());
Assert.assertEquals(new Boolean(false), declarer.directBuffer.get(1));
}
}