/** * Copyright 2015 StreamSets Inc. * * Licensed under the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 com.streamsets.datacollector.runner; import com.google.common.collect.ImmutableList; import com.streamsets.datacollector.config.PipelineConfiguration; import com.streamsets.datacollector.creation.PipelineBean; import com.streamsets.datacollector.creation.PipelineBeanCreator; import com.streamsets.datacollector.creation.StageBean; import com.streamsets.datacollector.record.RecordImpl; import com.streamsets.datacollector.stagelibrary.StageLibraryTask; import com.streamsets.datacollector.validation.Issue; import com.streamsets.pipeline.api.Batch; import com.streamsets.pipeline.api.Record; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; public class TestPipeBatch { private PipelineBean getPipelineBean() { List<Issue> errors = new ArrayList<>(); StageLibraryTask library = MockStages.createStageLibrary(); PipelineConfiguration pipelineConf = MockStages.createPipelineConfigurationSourceTarget(); PipelineBean pipelineBean = PipelineBeanCreator.get().create(false, library, pipelineConf, errors); if (pipelineBean == null) { Assert.fail(errors.toString()); } return pipelineBean; } @Test @SuppressWarnings("unchecked") public void testStageMethodsNoSnapshot() throws Exception { PipeBatch pipeBatch = new FullPipeBatch(null,null, -1, false); PipelineBean pipelineBean = getPipelineBean(); StageRuntime[] stages = { new StageRuntime(pipelineBean, pipelineBean.getOrigin()), new StageRuntime(pipelineBean, pipelineBean.getPipelineStageBeans().getStages().get(0)) }; StageContext context = Mockito.mock(StageContext.class); Mockito.when(context.isPreview()).thenReturn(false); stages[0].setContext(context); stages[1].setContext(context); List<String> stageOutputLanes = stages[0].getConfiguration().getOutputLanes(); StagePipe pipe = new StagePipe(stages[0], Collections.EMPTY_LIST, LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST); // starting source BatchMakerImpl batchMaker = pipeBatch.startStage(pipe); Assert.assertEquals(new ArrayList<String>(stageOutputLanes), batchMaker.getLanes()); Record origRecord = new RecordImpl("i", "source", null, null); origRecord.getHeader().setAttribute("a", "A"); batchMaker.addRecord(origRecord, stageOutputLanes.get(0)); // completing source pipeBatch.completeStage(batchMaker); pipe = new StagePipe(stages[1], LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST, Collections.EMPTY_LIST); // starting target batchMaker = pipeBatch.startStage(pipe); BatchImpl batch = pipeBatch.getBatch(pipe); // completing target pipeBatch.completeStage(batchMaker); Iterator<Record> records = batch.getRecords(); Record recordFromBatch = records.next(); Assert.assertNotSame(origRecord, recordFromBatch); Assert.assertEquals(origRecord.getHeader().getAttributeNames(), recordFromBatch.getHeader().getAttributeNames()); Assert.assertEquals(origRecord.getHeader().getStageCreator(), recordFromBatch.getHeader().getStageCreator()); Assert.assertEquals(origRecord.getHeader().getSourceId(), recordFromBatch.getHeader().getSourceId()); Assert.assertEquals("s", recordFromBatch.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getStagesPath(), recordFromBatch.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getTrackingId(), recordFromBatch.getHeader().getTrackingId()); Assert.assertFalse(records.hasNext()); Assert.assertNull(pipeBatch.getSnapshotsOfAllStagesOutput()); try { pipeBatch.startStage(pipe); Assert.fail(); } catch (IllegalStateException ex) { //expected } } @Test @SuppressWarnings("unchecked") public void testStageMethodsWithSnapshot() throws Exception { PipeBatch pipeBatch = new FullPipeBatch(null,null, -1, true); PipelineBean pipelineBean = getPipelineBean(); StageRuntime[] stages = { new StageRuntime(pipelineBean, pipelineBean.getOrigin()), new StageRuntime(pipelineBean, pipelineBean.getPipelineStageBeans().getStages().get(0)) }; StageContext context = Mockito.mock(StageContext.class); Mockito.when(context.isPreview()).thenReturn(false); stages[0].setContext(context); stages[1].setContext(context); List<String> stageOutputLanes = stages[0].getConfiguration().getOutputLanes(); StagePipe sourcePipe = new StagePipe(stages[0], Collections.EMPTY_LIST, LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST); // starting source BatchMakerImpl batchMaker = pipeBatch.startStage(sourcePipe); Assert.assertEquals(new ArrayList<String>(stageOutputLanes), batchMaker.getLanes()); Record origRecord = new RecordImpl("i", "source", null, null); origRecord.getHeader().setAttribute("a", "A"); batchMaker.addRecord(origRecord, stageOutputLanes.get(0)); // completing source pipeBatch.completeStage(batchMaker); StagePipe targetPipe = new StagePipe(stages[1], LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST, Collections.EMPTY_LIST); // starting target batchMaker = pipeBatch.startStage(targetPipe); BatchImpl batch = pipeBatch.getBatch(targetPipe); // completing target pipeBatch.completeStage(batchMaker); Iterator<Record> records = batch.getRecords(); Record recordFromBatch = records.next(); Assert.assertNotSame(origRecord, recordFromBatch); Assert.assertEquals(origRecord.getHeader().getAttributeNames(), recordFromBatch.getHeader().getAttributeNames()); Assert.assertEquals(origRecord.getHeader().getStageCreator(), recordFromBatch.getHeader().getStageCreator()); Assert.assertEquals(origRecord.getHeader().getSourceId(), recordFromBatch.getHeader().getSourceId()); Assert.assertEquals("s", recordFromBatch.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getStagesPath(), recordFromBatch.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getTrackingId(), recordFromBatch.getHeader().getTrackingId()); Assert.assertEquals(origRecord.get(), recordFromBatch.get()); Assert.assertEquals(origRecord.get(), recordFromBatch.get()); Assert.assertEquals(origRecord.get(), recordFromBatch.get()); Assert.assertEquals(origRecord.get(), recordFromBatch.get()); Assert.assertTrue(recordFromBatch.getHeader().getStagesPath(). endsWith(sourcePipe.getStage().getInfo().getInstanceName())); Assert.assertFalse(records.hasNext()); List<StageOutput> stageOutputs = pipeBatch.getSnapshotsOfAllStagesOutput(); Assert.assertNotNull(stageOutputs); Assert.assertEquals(2, stageOutputs.size()); Assert.assertEquals("s", stageOutputs.get(0).getInstanceName()); Assert.assertEquals(1, stageOutputs.get(0).getOutput().size()); Record recordFromSnapshot = stageOutputs.get(0).getOutput().get(stageOutputLanes.get(0)).get(0); Assert.assertNotSame(origRecord, recordFromBatch); Assert.assertNotSame(origRecord, recordFromBatch); Assert.assertEquals(origRecord.getHeader().getAttributeNames(), recordFromBatch.getHeader().getAttributeNames()); Assert.assertEquals(origRecord.getHeader().getStageCreator(), recordFromBatch.getHeader().getStageCreator()); Assert.assertEquals(origRecord.getHeader().getSourceId(), recordFromBatch.getHeader().getSourceId()); Assert.assertEquals("s", recordFromBatch.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getStagesPath(), recordFromBatch.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getTrackingId(), recordFromBatch.getHeader().getTrackingId()); Assert.assertNotSame(origRecord, recordFromSnapshot); Assert.assertEquals(origRecord.getHeader().getAttributeNames(), recordFromSnapshot.getHeader().getAttributeNames()); Assert.assertEquals(origRecord.getHeader().getStageCreator(), recordFromSnapshot.getHeader().getStageCreator()); Assert.assertEquals(origRecord.getHeader().getSourceId(), recordFromSnapshot.getHeader().getSourceId()); Assert.assertEquals("s", recordFromSnapshot.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getStagesPath(), recordFromSnapshot.getHeader().getStagesPath()); Assert.assertNotEquals(origRecord.getHeader().getTrackingId(), recordFromSnapshot.getHeader().getTrackingId()); Assert.assertEquals(recordFromBatch, recordFromSnapshot); Assert.assertNotSame(recordFromBatch, recordFromSnapshot); Assert.assertEquals("t", stageOutputs.get(1).getInstanceName()); Assert.assertEquals(0, stageOutputs.get(1).getOutput().size()); } @Test @SuppressWarnings("unchecked") public void testMoveLane() throws Exception { FullPipeBatch pipeBatch = new FullPipeBatch(null, null, -1, true); PipelineBean pipelineBean = getPipelineBean(); StageRuntime[] stages = { new StageRuntime(pipelineBean, pipelineBean.getOrigin()), new StageRuntime(pipelineBean, pipelineBean.getPipelineStageBeans().getStages().get(0)) }; StageContext context = Mockito.mock(StageContext.class); Mockito.when(context.isPreview()).thenReturn(false); stages[0].setContext(context); List<String> stageOutputLanes = stages[0].getConfiguration().getOutputLanes(); StagePipe pipe = new StagePipe(stages[0], Collections.EMPTY_LIST, LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST); // starting source BatchMakerImpl batchMaker = pipeBatch.startStage(pipe); Assert.assertEquals(new ArrayList<String>(stageOutputLanes), batchMaker.getLanes()); Record record = new RecordImpl("i", "source", null, null); record.getHeader().setAttribute("a", "A"); batchMaker.addRecord(record, stageOutputLanes.get(0)); // completing source pipeBatch.completeStage(batchMaker); Record origRecord = pipeBatch.getFullPayload().get(pipe.getOutputLanes().get(0)).get(0); pipeBatch.moveLane(pipe.getOutputLanes().get(0), "x"); Record movedRecord = pipeBatch.getFullPayload().get("x").get(0); Assert.assertSame(origRecord, movedRecord); Map<String, List<Record>> snapshot = pipeBatch.getLaneOutputRecords(ImmutableList.of("x")); Assert.assertEquals(1, snapshot.size()); Assert.assertEquals(1, snapshot.get("x").size()); Assert.assertEquals("A", snapshot.get("x").get(0).getHeader().getAttribute("a")); } @Test @SuppressWarnings("unchecked") public void testMoveLaneCopying() throws Exception { FullPipeBatch pipeBatch = new FullPipeBatch(null, null, -1, true); PipelineBean pipelineBean = getPipelineBean(); StageRuntime[] stages = { new StageRuntime(pipelineBean, pipelineBean.getOrigin()), new StageRuntime(pipelineBean, pipelineBean.getPipelineStageBeans().getStages().get(0)) }; StageContext context = Mockito.mock(StageContext.class); Mockito.when(context.isPreview()).thenReturn(false); stages[0].setContext(context); List<String> stageOutputLanes = stages[0].getConfiguration().getOutputLanes(); StagePipe pipe = new StagePipe(stages[0], Collections.EMPTY_LIST, LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST); // starting source BatchMakerImpl batchMaker = pipeBatch.startStage(pipe); Assert.assertEquals(new ArrayList<String>(stageOutputLanes), batchMaker.getLanes()); Record record = new RecordImpl("i", "source", null, null); record.getHeader().setAttribute("a", "A"); batchMaker.addRecord(record, stageOutputLanes.get(0)); // completing source pipeBatch.completeStage(batchMaker); List<String> list = ImmutableList.of("x", "y"); Record origRecord = pipeBatch.getFullPayload().get(pipe.getOutputLanes().get(0)).get(0); pipeBatch.moveLaneCopying(pipe.getOutputLanes().get(0), list); Record copiedRecordX = pipeBatch.getFullPayload().get("x").get(0); Record copiedRecordY = pipeBatch.getFullPayload().get("y").get(0); Assert.assertEquals(origRecord, copiedRecordX); Assert.assertNotSame(origRecord, copiedRecordX); Assert.assertEquals(origRecord, copiedRecordY); Assert.assertNotSame(origRecord, copiedRecordY); Map<String, List<Record>> snapshot = pipeBatch.getLaneOutputRecords(list); Assert.assertEquals(2, snapshot.size()); Assert.assertEquals(1, snapshot.get("x").size()); Assert.assertEquals(1, snapshot.get("y").size()); Assert.assertEquals("A", snapshot.get("x").get(0).getHeader().getAttribute("a")); Assert.assertEquals("A", snapshot.get("y").get(0).getHeader().getAttribute("a")); } @Test @SuppressWarnings("unchecked") public void testCombineLanes() throws Exception { FullPipeBatch pipeBatch = new FullPipeBatch(null, null, -1, true); PipelineBean pipelineBean = getPipelineBean(); StageRuntime[] stages = { new StageRuntime(pipelineBean, pipelineBean.getOrigin()), new StageRuntime(pipelineBean, pipelineBean.getPipelineStageBeans().getStages().get(0)) }; StageContext context = Mockito.mock(StageContext.class); Mockito.when(context.isPreview()).thenReturn(false); stages[0].setContext(context); List<String> stageOutputLanes = stages[0].getConfiguration().getOutputLanes(); StagePipe pipe = new StagePipe(stages[0], Collections.EMPTY_LIST, LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST); // starting source BatchMakerImpl batchMaker = pipeBatch.startStage(pipe); Assert.assertEquals(new ArrayList<String>(stageOutputLanes), batchMaker.getLanes()); Record record = new RecordImpl("i", "source", null, null); record.getHeader().setAttribute("a", "A"); batchMaker.addRecord(record, stageOutputLanes.get(0)); // completing source pipeBatch.completeStage(batchMaker); List<String> list = ImmutableList.of("x", "y"); pipeBatch.moveLaneCopying(pipe.getOutputLanes().get(0), list); Record copiedRecordX = pipeBatch.getFullPayload().get("x").get(0); Record copiedRecordY = pipeBatch.getFullPayload().get("y").get(0); pipeBatch.combineLanes(list, "z"); Map<String, List<Record>> snapshot = pipeBatch.getLaneOutputRecords(ImmutableList.of("z")); Assert.assertEquals(1, snapshot.size()); Assert.assertEquals(2, snapshot.get("z").size()); Assert.assertSame(copiedRecordX, pipeBatch.getFullPayload().get("z").get(0)); Assert.assertSame(copiedRecordY, pipeBatch.getFullPayload().get("z").get(1)); } @Test @SuppressWarnings("unchecked") public void testOverride() throws Exception { PipeBatch pipeBatch = new FullPipeBatch(null, null, -1, true); PipelineBean pipelineBean = getPipelineBean(); StageRuntime[] stages = { new StageRuntime(pipelineBean, pipelineBean.getOrigin()), new StageRuntime(pipelineBean, pipelineBean.getPipelineStageBeans().getStages().get(0)) }; StageContext context = Mockito.mock(StageContext.class); Mockito.when(context.isPreview()).thenReturn(false); stages[0].setContext(context); stages[1].setContext(context); List<String> stageOutputLanes = stages[0].getConfiguration().getOutputLanes(); StagePipe sourcePipe = new StagePipe(stages[0], Collections.EMPTY_LIST, LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST); // starting source BatchMakerImpl batchMaker = pipeBatch.startStage(sourcePipe); Assert.assertEquals(new ArrayList<String>(stageOutputLanes), batchMaker.getLanes()); Record origRecord = new RecordImpl("i", "source", null, null); origRecord.getHeader().setAttribute("a", "A"); batchMaker.addRecord(origRecord, stageOutputLanes.get(0)); // completing source pipeBatch.completeStage(batchMaker); StagePipe targetPipe = new StagePipe(stages[1], LaneResolver.getPostFixed(stageOutputLanes, LaneResolver.STAGE_OUT), Collections.EMPTY_LIST, Collections.EMPTY_LIST); // starting target batchMaker = pipeBatch.startStage(targetPipe); BatchImpl batch = pipeBatch.getBatch(targetPipe); // completing target pipeBatch.completeStage(batchMaker); // getting stages ouptut List<StageOutput> stageOutputs = pipeBatch.getSnapshotsOfAllStagesOutput(); StageOutput sourceOutput = stageOutputs.get(0); Assert.assertEquals("s", sourceOutput.getInstanceName()); Record modRecord = new RecordImpl("i", "source", null, null); modRecord.getHeader().setAttribute("a", "B"); //modifying the source output sourceOutput.getOutput().get(stages[0].getConfiguration().getOutputLanes().get(0)).set(0, modRecord); //starting a new pipe batch pipeBatch = new FullPipeBatch(null, null, -1, true); //instead running source, we inject its previous-modified output, it implicitly starts the pipe pipeBatch.overrideStageOutput(sourcePipe, sourceOutput); // starting target pipeBatch.startStage(targetPipe); batch = pipeBatch.getBatch(targetPipe); Iterator<Record> it = batch.getRecords(); Record tRecord = it.next(); //check that we get the injected record. Assert.assertEquals("B", tRecord.getHeader().getAttribute("a")); Assert.assertFalse(it.hasNext()); // completing target pipeBatch.completeStage(batchMaker); } }