/* * #! * % * 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.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Random; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import storm.lrb.tools.EntityHelper; 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.AvgVehicleSpeedTuple; import de.hub.cs.dbis.lrb.types.util.SegmentIdentifier; import de.hub.cs.dbis.lrb.util.Constants; import de.hub.cs.dbis.lrb.util.Time; /** * @author richter * @author mjsax */ public class AverageVehicleSpeedBoltTest { private long seed; private Random r; @Before public void prepare() { this.seed = System.currentTimeMillis(); this.r = new Random(this.seed); System.out.println("Test seed: " + this.seed); } @Test public void testExecute() { AverageVehicleSpeedBolt bolt = new AverageVehicleSpeedBolt(); TestOutputCollector collector = new TestOutputCollector(); bolt.prepare(null, null, new OutputCollector(collector)); final Tuple tuple = mock(Tuple.class); int vehicleID0, vehicleID1, vehicleID2; vehicleID0 = (int)(this.r.nextDouble() * Constants.NUMBER_OF_VIDS); do { vehicleID1 = (int)(this.r.nextDouble() * Constants.NUMBER_OF_VIDS); } while(vehicleID1 == vehicleID0); do { vehicleID2 = (int)(this.r.nextDouble() * Constants.NUMBER_OF_VIDS); } while(vehicleID2 == vehicleID1 || vehicleID2 == vehicleID0); short segment = (short)(this.r.nextDouble() * Constants.NUMBER_OF_SEGMENT); short time0 = (short)this.r.nextInt(60); PositionReport posReport0Stopped = EntityHelper.createPosReport(new Short(time0), new Short(segment), this.r, new Integer(vehicleID0), 0, // minSpeed 0 // maxSpeed ); when(tuple.getValues()).thenReturn(posReport0Stopped); when(tuple.getSourceStreamId()).thenReturn("streamId"); bolt.execute(tuple); assertEquals(1, collector.acked.size()); assertEquals(0, collector.output.size()); // one tuple doesn't trigger emission short time1 = (short)(time0 + 60); // step to next minute PositionReport posReport1Stopped = EntityHelper.createPosReport(new Short(time1), new Short(segment), this.r, new Integer(vehicleID0), 0, // minSpeed 0 // maxSpeed ); when(tuple.getValues()).thenReturn(posReport1Stopped); when(tuple.getSourceStreamId()).thenReturn("streamId"); bolt.execute(tuple); assertEquals(2, collector.acked.size()); // second tuple with another time should have triggered emission after one minute assertEquals(1, collector.output.get(Utils.DEFAULT_STREAM_ID).size()); AvgVehicleSpeedTuple result = (AvgVehicleSpeedTuple)collector.output.get(Utils.DEFAULT_STREAM_ID).get(0); assertEquals(new SegmentIdentifier(posReport1Stopped), new SegmentIdentifier(result)); assertEquals(time1 / 60, result.getMinute().shortValue()); assertEquals(0.0, result.getAvgSpeed().doubleValue(), 0.0); assertEquals(1, collector.output.get(TimestampMerger.FLUSH_STREAM_ID).size()); assertEquals(new Values(new Short(Time.getMinute(time1))), collector.output .get(TimestampMerger.FLUSH_STREAM_ID).get(0)); // three cars int speed2 = this.r.nextInt(Constants.NUMBER_OF_SPEEDS); int speed3 = this.r.nextInt(Constants.NUMBER_OF_SPEEDS); int speed4 = this.r.nextInt(Constants.NUMBER_OF_SPEEDS); PositionReport posReport2Running = EntityHelper.createPosReport(new Short(time1), new Short(segment), this.r, new Integer(vehicleID1), speed2, // minSpeed speed2 // maxSpeed ); when(tuple.getValues()).thenReturn(posReport2Running); when(tuple.getSourceStreamId()).thenReturn("streamId"); bolt.execute(tuple); assertEquals(3, collector.acked.size()); assertEquals(1, collector.output.get(Utils.DEFAULT_STREAM_ID).size()); assertEquals(1, collector.output.get(TimestampMerger.FLUSH_STREAM_ID).size()); PositionReport posReport3Running = EntityHelper.createPosReport(new Short(time1), new Short(segment), this.r, new Integer(vehicleID1), speed3, // minSpeed speed3 // maxSpeed ); when(tuple.getValues()).thenReturn(posReport3Running); when(tuple.getSourceStreamId()).thenReturn("streamId"); bolt.execute(tuple); assertEquals(4, collector.acked.size()); assertEquals(1, collector.output.get(Utils.DEFAULT_STREAM_ID).size()); assertEquals(1, collector.output.get(TimestampMerger.FLUSH_STREAM_ID).size()); short time2 = (short)(time1 + 60); // step to next minute PositionReport posReport4Running = EntityHelper.createPosReport(new Short(time2), new Short(segment), this.r, new Integer(vehicleID2), speed4, // minSpeed speed4 // maxSpeed ); when(tuple.getValues()).thenReturn(posReport4Running); when(tuple.getSourceStreamId()).thenReturn("streamId"); bolt.execute(tuple); assertEquals(5, collector.acked.size()); assertEquals(3, collector.output.get(Utils.DEFAULT_STREAM_ID).size()); assertEquals(2, collector.output.get(TimestampMerger.FLUSH_STREAM_ID).size()); assertEquals(new Values(new Short(Time.getMinute(time2))), collector.output .get(TimestampMerger.FLUSH_STREAM_ID).get(1)); for(int i = 1; i < 3; ++i) { result = (AvgVehicleSpeedTuple)collector.output.get(Utils.DEFAULT_STREAM_ID).get(i); assertEquals(new SegmentIdentifier(posReport1Stopped), new SegmentIdentifier(result)); // average update only occurs after emission if(result.getVid().intValue() == vehicleID0) { assertEquals(0.0, result.getAvgSpeed().doubleValue(), 0.0); } else { assertEquals(result.getVid().intValue(), vehicleID1); assertEquals((speed2 + speed3) / 2.0, result.getAvgSpeed().doubleValue(), 0.0); } assertEquals(time2 / 60, result.getMinute().shortValue()); } Tuple flushTuple = mock(Tuple.class); when(flushTuple.getSourceStreamId()).thenReturn(TimestampMerger.FLUSH_STREAM_ID); bolt.execute(flushTuple); result = (AvgVehicleSpeedTuple)collector.output.get(Utils.DEFAULT_STREAM_ID).get(3); assertEquals(new SegmentIdentifier(posReport1Stopped), new SegmentIdentifier(result)); assertEquals(result.getVid().intValue(), vehicleID2); assertEquals(speed4, result.getAvgSpeed().doubleValue(), 0.0); assertEquals((time2 + 60) / 60, result.getMinute().shortValue()); assertEquals(3, collector.output.get(TimestampMerger.FLUSH_STREAM_ID).size()); assertEquals(new Values((Object)null), collector.output.get(TimestampMerger.FLUSH_STREAM_ID).get(2)); assertEquals(2, collector.output.size()); } @Test public void testDeclareOutputFields() { AverageVehicleSpeedBolt bolt = new AverageVehicleSpeedBolt(); 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.assertNull(declarer.streamIdBuffer.get(0)); Assert.assertEquals(new Fields(TopologyControl.VEHICLE_ID_FIELD_NAME, TopologyControl.MINUTE_FIELD_NAME, TopologyControl.XWAY_FIELD_NAME, TopologyControl.SEGMENT_FIELD_NAME, TopologyControl.DIRECTION_FIELD_NAME, TopologyControl.AVERAGE_VEHICLE_SPEED_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)); } }