/**
* 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.preview;
import com.streamsets.datacollector.config.PipelineConfiguration;
import com.streamsets.datacollector.json.ObjectMapperFactory;
import com.streamsets.datacollector.main.RuntimeInfo;
import com.streamsets.datacollector.record.RecordImpl;
import com.streamsets.datacollector.restapi.bean.BeanHelper;
import com.streamsets.datacollector.restapi.bean.StageOutputJson;
import com.streamsets.datacollector.runner.MockStages;
import com.streamsets.datacollector.runner.Pipeline;
import com.streamsets.datacollector.runner.PipelineRunner;
import com.streamsets.datacollector.runner.SourceOffsetTracker;
import com.streamsets.datacollector.runner.StageOutput;
import com.streamsets.datacollector.util.Configuration;
import com.streamsets.datacollector.util.ContainerError;
import com.streamsets.pipeline.api.Batch;
import com.streamsets.pipeline.api.BatchMaker;
import com.streamsets.pipeline.api.Field;
import com.streamsets.pipeline.api.Record;
import com.streamsets.pipeline.api.Source;
import com.streamsets.pipeline.api.StageException;
import com.streamsets.pipeline.api.base.BaseSource;
import com.streamsets.pipeline.api.base.BaseTarget;
import com.streamsets.pipeline.api.base.SingleLaneRecordProcessor;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.Arrays;
import java.util.List;
public class TestPreviewRun {
private Configuration configuration;
private RuntimeInfo runtimeInfo;
@Before
public void setUp() {
MockStages.resetStageCaptures();
configuration = new Configuration();
runtimeInfo = Mockito.mock(RuntimeInfo.class);
}
@Test
public void testPreviewRun() throws Exception {
MockStages.setSourceCapture(new BaseSource() {
@Override
public String produce(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
Record record = getContext().createRecord("x");
record.set(Field.create(1));
batchMaker.addRecord(record);
return "1";
}
});
MockStages.setProcessorCapture(new SingleLaneRecordProcessor() {
@Override
protected void process(Record record, SingleLaneBatchMaker batchMaker) throws StageException {
record.set(Field.create(2));
batchMaker.addRecord(record);
}
});
MockStages.setTargetCapture(new BaseTarget() {
@Override
public void write(Batch batch) throws StageException {
}
});
SourceOffsetTracker tracker = Mockito.mock(SourceOffsetTracker.class);
PipelineRunner runner = new PreviewPipelineRunner( "name", "0", runtimeInfo, tracker, -1, 1, true);
Pipeline pipeline = new Pipeline.Builder(MockStages.createStageLibrary(), configuration, "name", "name", "0", MockStages.userContext(),
MockStages.createPipelineConfigurationSourceProcessorTarget()).build(runner);
pipeline.init();
pipeline.run();
pipeline.destroy();
List<StageOutput> output = runner.getBatchesOutput().get(0);
Assert.assertEquals(1, output.get(0).getOutput().get("s").get(0).get().getValue());
Assert.assertEquals(2, output.get(1).getOutput().get("p").get(0).get().getValue());
// Test serializing to json and json to bean
List<StageOutputJson> stageOutputJsonList = BeanHelper.wrapStageOutput(output);
String outputStr = ObjectMapperFactory.get().writeValueAsString(stageOutputJsonList.get(0));
StageOutputJson stageOutputJson = ObjectMapperFactory.get().readValue(outputStr, StageOutputJson.class);
Assert.assertNotNull(stageOutputJson);
}
@Test
public void testPreviewPipelineBuilder() throws Exception {
MockStages.setSourceCapture(new BaseSource() {
@Override
public String produce(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
Record record = getContext().createRecord("x");
record.set(Field.create(1));
batchMaker.addRecord(record);
return "1";
}
});
MockStages.setProcessorCapture(new SingleLaneRecordProcessor() {
@Override
protected void process(Record record, SingleLaneBatchMaker batchMaker) throws StageException {
record.set(Field.create(2));
batchMaker.addRecord(record);
}
});
SourceOffsetTracker tracker = Mockito.mock(SourceOffsetTracker.class);
PreviewPipelineRunner runner = new PreviewPipelineRunner( "name", "0", runtimeInfo, tracker, -1, 1, true);
PipelineConfiguration pipelineConfiguration = MockStages.createPipelineConfigurationSourceProcessorTarget();
pipelineConfiguration.getStages().remove(2);
PreviewPipeline pipeline = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name", "0",
pipelineConfiguration, null).build(MockStages.userContext(), runner);
PreviewPipelineOutput previewOutput = pipeline.run();
List<StageOutput> output = previewOutput.getBatchesOutput().get(0);
Assert.assertEquals(2, output.size());
Assert.assertEquals(1, output.get(0).getOutput().get("s").get(0).get().getValue());
Assert.assertEquals(2, output.get(1).getOutput().get("p").get(0).get().getValue());
}
@Test
public void testPreviewPipelineBuilderWithLastStage() throws Exception {
MockStages.setSourceCapture(new BaseSource() {
@Override
public String produce(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
Record record = getContext().createRecord("x");
record.set(Field.create(1));
batchMaker.addRecord(record);
return "1";
}
});
MockStages.setProcessorCapture(new SingleLaneRecordProcessor() {
@Override
protected void process(Record record, SingleLaneBatchMaker batchMaker) throws StageException {
record.set(Field.create(2));
//batchMaker.addRecord(record);
}
});
SourceOffsetTracker tracker = Mockito.mock(SourceOffsetTracker.class);
PreviewPipelineRunner runner = new PreviewPipelineRunner( "name", "0",runtimeInfo, tracker, -1, 1, true);
PipelineConfiguration pipelineConfiguration = MockStages.createPipelineConfigurationSourceProcessorTarget();
PreviewPipeline pipeline = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name", "0",
pipelineConfiguration, "p").build(MockStages.userContext(), runner);
PreviewPipelineOutput previewOutput = pipeline.run();
List<StageOutput> output = previewOutput.getBatchesOutput().get(0);
Assert.assertEquals(1, output.size());
//Complex graph
runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
pipelineConfiguration = MockStages.createPipelineConfigurationComplexSourceProcessorTarget();
pipeline = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name", "0",
pipelineConfiguration, "p1").build(MockStages.userContext(), runner);
previewOutput = pipeline.run();
output = previewOutput.getBatchesOutput().get(0);
Assert.assertEquals(1, output.size());
Assert.assertEquals(1, output.get(0).getOutput().get("s").get(0).get().getValue());
runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
pipelineConfiguration = MockStages.createPipelineConfigurationComplexSourceProcessorTarget();
pipeline = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name", "0",
pipelineConfiguration, "p5").build(MockStages.userContext(), runner);
previewOutput = pipeline.run();
output = previewOutput.getBatchesOutput().get(0);
Assert.assertEquals(2, output.size());
Assert.assertEquals(1, output.get(0).getOutput().get("s").get(0).get().getValue());
runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
pipelineConfiguration = MockStages.createPipelineConfigurationComplexSourceProcessorTarget();
pipeline = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name1", "0",
pipelineConfiguration, "p6").build(MockStages.userContext(), runner);
previewOutput = pipeline.run();
output = previewOutput.getBatchesOutput().get(0);
Assert.assertEquals(3, output.size());
runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
pipelineConfiguration = MockStages.createPipelineConfigurationComplexSourceProcessorTarget();
pipeline = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name1", "0",
pipelineConfiguration, "t").build(MockStages.userContext(), runner);
previewOutput = pipeline.run();
output = previewOutput.getBatchesOutput().get(0);
Assert.assertEquals(7, output.size());
}
@Test
public void testIsPreview() throws Exception {
MockStages.setSourceCapture(new BaseSource() {
@Override
protected List<ConfigIssue> init() {
List<ConfigIssue> issues = super.init();
Assert.assertTrue(getContext().isPreview());
return issues;
}
@Override
public String produce(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
return "X";
}
});
SourceOffsetTracker tracker = Mockito.mock(SourceOffsetTracker.class);
PreviewPipelineRunner runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
PipelineConfiguration pipelineConfiguration = MockStages.createPipelineConfigurationSourceProcessorTarget();
pipelineConfiguration.getStages().remove(2);
PreviewPipeline pipeline = new PreviewPipelineBuilder(
MockStages.createStageLibrary(),
configuration,
"name",
"0",
pipelineConfiguration,
null)
.build(MockStages.userContext(), runner);
PreviewPipelineOutput previewOutput = pipeline.run();
}
@Test
public void testPreviewRunFailValidationConfigs() throws Exception {
MockStages.setSourceCapture(new BaseSource() {
@Override
public List<ConfigIssue> init(Info info, Source.Context context) {
return Arrays.asList(context.createConfigIssue(null, null, ContainerError.CONTAINER_0000));
}
@Override
public String produce(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
return "1";
}
});
MockStages.setProcessorCapture(new SingleLaneRecordProcessor() {
@Override
protected void process(Record record, SingleLaneBatchMaker batchMaker) throws StageException {
record.set(Field.create(2));
batchMaker.addRecord(record);
}
});
MockStages.setTargetCapture(new BaseTarget() {
@Override
public void write(Batch batch) throws StageException {
}
});
SourceOffsetTracker tracker = Mockito.mock(SourceOffsetTracker.class);
PipelineRunner runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
PreviewPipeline pp = new PreviewPipelineBuilder(MockStages.createStageLibrary(), configuration, "name", "0",
MockStages.createPipelineConfigurationSourceProcessorTarget(), null).build(MockStages.userContext(), runner);
Assert.assertFalse(pp.validateConfigs().isEmpty());
}
@Test
public void testPreviewRunOverride() throws Exception {
MockStages.setSourceCapture(new BaseSource() {
@Override
public String produce(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
Record record = getContext().createRecord("x");
record.set(Field.create(1));
batchMaker.addRecord(record);
return "1";
}
});
MockStages.setProcessorCapture(new SingleLaneRecordProcessor() {
@Override
protected void process(Record record, SingleLaneBatchMaker batchMaker) throws StageException {
int currentValue = record.get().getValueAsInteger();
record.set(Field.create(currentValue * 2));
batchMaker.addRecord(record);
}
});
MockStages.setTargetCapture(new BaseTarget() {
@Override
public void write(Batch batch) throws StageException {
}
});
PipelineConfiguration pipelineConf = MockStages.createPipelineConfigurationSourceProcessorTarget();
SourceOffsetTracker tracker = Mockito.mock(SourceOffsetTracker.class);
PipelineRunner runner = new PreviewPipelineRunner("name", "0", runtimeInfo, tracker, -1, 1, true);
Pipeline pipeline = new Pipeline.Builder(MockStages.createStageLibrary(), configuration, "name", "name", "0", MockStages.userContext(), pipelineConf).build(runner);
pipeline.init();
pipeline.run();
pipeline.destroy();
List<StageOutput> output = runner.getBatchesOutput().get(0);
Assert.assertEquals(1, output.get(0).getOutput().get("s").get(0).get().getValue());
Assert.assertEquals(2, output.get(1).getOutput().get("p").get(0).get().getValue());
StageOutput sourceOutput = output.get(0);
Assert.assertEquals("s", sourceOutput.getInstanceName());
Record modRecord = new RecordImpl("i", "source", null, null);
modRecord.set(Field.create(10));
//modifying the source output
sourceOutput.getOutput().get(pipelineConf.getStages().get(0).getOutputLanes().get(0)).set(0, modRecord);
runner = new PreviewPipelineRunner("name", "0",runtimeInfo, tracker, -1, 1, true);
pipeline = new Pipeline.Builder(MockStages.createStageLibrary(), configuration, "name", "name", "0", MockStages.userContext(),
MockStages.createPipelineConfigurationSourceProcessorTarget()).build(runner);
pipeline.init();
pipeline.run(Arrays.asList(sourceOutput));
pipeline.destroy();
output = runner.getBatchesOutput().get(0);
Assert.assertEquals(10, output.get(0).getOutput().get("s").get(0).get().getValue());
Assert.assertEquals(20, output.get(1).getOutput().get("p").get(0).get().getValue());
}
}