/* * #! * % * 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.aeolus.batching.api; import static org.mockito.Matchers.any; import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; import java.util.Random; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import backtype.storm.Config; import backtype.storm.generated.Grouping; import backtype.storm.spout.SpoutOutputCollector; import backtype.storm.task.TopologyContext; import backtype.storm.topology.IRichSpout; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.tuple.Fields; import backtype.storm.utils.Utils; import de.hub.cs.dbis.aeolus.batching.Batch; import de.hub.cs.dbis.aeolus.batching.BatchColumn; import de.hub.cs.dbis.aeolus.batching.BatchSpoutOutputCollector; import de.hub.cs.dbis.aeolus.batching.BatchingOutputFieldsDeclarer; import de.hub.cs.dbis.aeolus.testUtils.IncSpout; import de.hub.cs.dbis.aeolus.testUtils.RandomSpout; import de.hub.cs.dbis.aeolus.testUtils.TestSpoutOutputCollector; /** * @author mjsax */ @RunWith(PowerMockRunner.class) @PrepareForTest(SpoutOutputBatcher.class) public class SpoutOutputBatcherTest { private IRichSpout spoutMock; private final HashMap<String, Integer> noBatching = new HashMap<String, Integer>(); 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); this.spoutMock = mock(IRichSpout.class); } @Test public void testOpen() { SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); @SuppressWarnings("rawtypes") Map conf = new HashMap(); TopologyContext context = mock(TopologyContext.class); spout.open(conf, context, null); verify(this.spoutMock).open(same(conf), same(context), any(BatchSpoutOutputCollector.class)); } @Test public void testClose() throws Exception { BatchSpoutOutputCollector collectorMock = mock(BatchSpoutOutputCollector.class); PowerMockito.whenNew(BatchSpoutOutputCollector.class).withAnyArguments().thenReturn(collectorMock); SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); spout.open(null, null, null); spout.close(); verify(this.spoutMock).close(); verify(collectorMock).flush(); } @Test public void testActivate() { SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); spout.activate(); verify(this.spoutMock).activate(); } @Test public void testDeactivate() throws Exception { BatchSpoutOutputCollector collectorMock = mock(BatchSpoutOutputCollector.class); PowerMockito.whenNew(BatchSpoutOutputCollector.class).withAnyArguments().thenReturn(collectorMock); SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); spout.open(null, null, null); spout.deactivate(); verify(this.spoutMock).deactivate(); verify(collectorMock).flush(); } @Test public void testAck() { SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); Object messageId = mock(Object.class); spout.ack(messageId); verify(this.spoutMock).ack(messageId); } @Test public void testFail() { SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); Object messageId = mock(Object.class); spout.fail(messageId); verify(this.spoutMock).fail(messageId); } @Test public void testDeclareOutputFields() { SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); OutputFieldsDeclarer declarer = mock(OutputFieldsDeclarer.class); spout.declareOutputFields(declarer); verify(this.spoutMock).declareOutputFields(any(BatchingOutputFieldsDeclarer.class)); } @Test public void testGetComponentConfiguration() { SpoutOutputBatcher spout = new SpoutOutputBatcher(this.spoutMock, this.noBatching); final Map<String, Object> conf = new HashMap<String, Object>(); when(spout.getComponentConfiguration()).thenReturn(conf); Map<String, Object> result = spout.getComponentConfiguration(); verify(this.spoutMock).getComponentConfiguration(); Assert.assertSame(result, conf); } @Test(timeout = 1000) public void testNextTuple() { final int batchSize = 2 + this.r.nextInt(9); final String streamId = Utils.DEFAULT_STREAM_ID; final String sourceId = "sourceId"; Grouping groupingMock = mock(Grouping.class); HashMap<String, Map<String, Grouping>> targets = new HashMap<String, Map<String, Grouping>>(); Map<String, Grouping> receiver = new HashMap<String, Grouping>(); receiver.put("receiverId", groupingMock); targets.put(streamId, receiver); TopologyContext context = mock(TopologyContext.class); when(context.getThisComponentId()).thenReturn(sourceId); when(context.getThisTargets()).thenReturn(targets); when(context.getComponentOutputFields(sourceId, streamId)).thenReturn(new Fields("dummy")); RandomSpout userSpout = new RandomSpout(1, 1000, new String[] {Utils.DEFAULT_STREAM_ID}, this.seed); SpoutOutputBatcher batcher = new SpoutOutputBatcher(userSpout, batchSize); TestSpoutOutputCollector collector = new TestSpoutOutputCollector(); batcher.open(null, context, new SpoutOutputCollector(collector)); batcher.nextTuple(); Assert.assertEquals(1, collector.output.get(Utils.DEFAULT_STREAM_ID).size()); } @Test(timeout = 1000) public void testNextTupleNoEmit() { final int batchSize = 6 + this.r.nextInt(5); final int skipInterval = 2 + this.r.nextInt(4); final String streamId = Utils.DEFAULT_STREAM_ID; final String sourceId = "sourceId"; Map<String, Grouping> receiver = new HashMap<String, Grouping>(); receiver.put("receiverId", mock(Grouping.class)); HashMap<String, Map<String, Grouping>> targets = new HashMap<String, Map<String, Grouping>>(); targets.put(streamId, receiver); TopologyContext context = mock(TopologyContext.class); when(context.getThisComponentId()).thenReturn(sourceId); when(context.getThisTargets()).thenReturn(targets); when(context.getComponentOutputFields(sourceId, streamId)).thenReturn(new Fields("dummy")); IncSpout userSpout = new IncSpout(skipInterval); SpoutOutputBatcher batcher = new SpoutOutputBatcher(userSpout, batchSize); TestSpoutOutputCollector collector = new TestSpoutOutputCollector(); batcher.open(null, context, new SpoutOutputCollector(collector)); int iterations = (int)Math.ceil(batchSize / (skipInterval - 1.)); for(int i = 1; i < iterations; ++i) { batcher.nextTuple(); Assert.assertNull(collector.output.get(Utils.DEFAULT_STREAM_ID)); } batcher.nextTuple(); Assert.assertEquals(1, collector.output.get(Utils.DEFAULT_STREAM_ID).size()); } @Test public void testKryoRegistrations() { Config stormConfig = mock(Config.class); SpoutOutputBatcher.registerKryoClasses(stormConfig); verify(stormConfig).registerSerialization(Batch.class); verify(stormConfig).registerSerialization(BatchColumn.class); } }