/**
* 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.google.common.collect.ImmutableMap;
import com.streamsets.datacollector.config.StageConfiguration;
import com.streamsets.datacollector.config.StageDefinition;
import com.streamsets.datacollector.config.StageType;
import com.streamsets.datacollector.record.RecordImpl;
import com.streamsets.datacollector.runner.preview.StageConfigurationBuilder;
import com.streamsets.pipeline.api.Record;
import com.streamsets.pipeline.api.Source;
import com.streamsets.pipeline.api.Stage;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestBatchMakerImpl {
@SuppressWarnings("unchecked")
private StagePipe createStagePipe(List<String> outputs) {
StageConfiguration stageConfiguration = new StageConfigurationBuilder("i", "n")
.withOutputLanes("i")
.withOutputLanes(outputs)
.build();
StageDefinition stageDef = Mockito.mock(StageDefinition.class);
Mockito.when(stageDef.getType()).thenReturn(StageType.SOURCE);
StageRuntime stageRuntime = Mockito.mock(StageRuntime.class);
Stage.Info stageInfo = Mockito.mock(Stage.Info.class);
Mockito.when(stageInfo.getInstanceName()).thenReturn("i");
Mockito.when(stageInfo.getName()).thenReturn("n");
Mockito.when(stageInfo.getVersion()).thenReturn(1);
Mockito.when(stageRuntime.getInfo()).thenReturn(stageInfo);
Mockito.when(stageRuntime.getConfiguration()).thenReturn(stageConfiguration);
Mockito.when(stageRuntime.getDefinition()).thenReturn(stageDef);
List<String> pipeInput = LaneResolver.getPostFixed(ImmutableList.of("a"), LaneResolver.COMBINER_OUT);
List<String> pipeOutputs = new ArrayList<String>();
for (String output : outputs) {
pipeOutputs.add(LaneResolver.createLane(output, "x"));
}
List<String> pipeOutput = LaneResolver.getPostFixed(pipeOutputs, LaneResolver.STAGE_OUT);
StageContext context = Mockito.mock(StageContext.class);
Mockito.when(context.isPreview()).thenReturn(false);
Mockito.when(stageRuntime.getContext()).thenReturn(context);
return new StagePipe(stageRuntime, pipeInput, pipeOutput, Collections.<String>emptyList());
}
@Test
@SuppressWarnings("unchecked")
public void testBatchMakerSingleOutputNoSnapshot() {
StagePipe pipe = createStagePipe(ImmutableList.of("o"));
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, false);
Assert.assertEquals(pipe, batchMaker.getStagePipe());
Assert.assertEquals(1, batchMaker.getStageOutput().size());
Assert.assertEquals(ImmutableMap.of("o", Collections.EMPTY_LIST), batchMaker.getStageOutput());
Assert.assertNull(batchMaker.getStageOutputSnapshot());
Assert.assertEquals(ImmutableList.of("o"), batchMaker.getLanes());
Record record1 = new RecordImpl("i", "source", null, null);
record1.getHeader().setAttribute("r", "1");
batchMaker.addRecord(record1);
Record record2 = new RecordImpl("i", "source", null, null);
record2.getHeader().setAttribute("r", "2");
batchMaker.addRecord(record2, "o");
Record record3 = new RecordImpl("i", "source", null, null);
record3.getHeader().setAttribute("r", "3");
try {
batchMaker.addRecord(record3, "x");
Assert.fail();
} catch (IllegalArgumentException ex) {
//expected
}
try {
batchMaker.addRecord(record3, "o", "o");
Assert.fail();
} catch (IllegalArgumentException ex) {
//expected
}
List<Record> records = batchMaker.getStageOutput().get("o");
Assert.assertEquals(2, records.size());
Assert.assertEquals("1", records.get(0).getHeader().getAttribute("r"));
Assert.assertEquals("2", records.get(1).getHeader().getAttribute("r"));
}
@Test
@SuppressWarnings("unchecked")
public void testBatchMakerSingleOutputWithSnapshot() {
StagePipe pipe = createStagePipe(ImmutableList.of("o"));
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, true);
Assert.assertNotNull(batchMaker.getStageOutputSnapshot());
Record record1 = new RecordImpl("i", "source", null, null);
record1.getHeader().setAttribute("r", "1");
batchMaker.addRecord(record1);
Record record2 = new RecordImpl("i", "source", null, null);
record2.getHeader().setAttribute("r", "2");
batchMaker.addRecord(record2, "o");
List<Record> records = batchMaker.getStageOutputSnapshot().get("o");
Assert.assertEquals(2, records.size());
Assert.assertEquals("1", records.get(0).getHeader().getAttribute("r"));
Assert.assertEquals("2", records.get(1).getHeader().getAttribute("r"));
}
@Test
@SuppressWarnings("unchecked")
public void testBatchMakerMultipleOutputNoSnapshot() {
StagePipe pipe = createStagePipe(ImmutableList.of("o1", "o2"));
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, false);
Assert.assertEquals(pipe, batchMaker.getStagePipe());
Assert.assertEquals(2, batchMaker.getStageOutput().size());
Assert.assertEquals(ImmutableMap.of("o1", Collections.EMPTY_LIST, "o2", Collections.EMPTY_LIST),
batchMaker.getStageOutput());
Assert.assertNull(batchMaker.getStageOutputSnapshot());
Assert.assertEquals(ImmutableList.of("o1", "o2"), batchMaker.getLanes());
Record record1 = new RecordImpl("i", "source", null, null);
record1.getHeader().setAttribute("r", "1");
batchMaker.addRecord(record1, "o1");
Record record2 = new RecordImpl("i", "source", null, null);
record2.getHeader().setAttribute("r", "2");
batchMaker.addRecord(record2, "o2");
Record record3 = new RecordImpl("i", "source", null, null);
record3.getHeader().setAttribute("r", "3");
try {
batchMaker.addRecord(record3, "o1", "o1");
Assert.fail();
} catch (IllegalArgumentException ex) {
//expected
}
try {
batchMaker.addRecord(record3, "x");
Assert.fail();
} catch (IllegalArgumentException ex) {
//expected
}
try {
batchMaker.addRecord(record3);
Assert.fail();
} catch (IllegalArgumentException ex) {
//expected
}
batchMaker.addRecord(record3, "o1", "o2");
List<Record> records = batchMaker.getStageOutput().get("o1");
Assert.assertEquals(2, records.size());
Assert.assertEquals("1", records.get(0).getHeader().getAttribute("r"));
Assert.assertEquals("3", records.get(1).getHeader().getAttribute("r"));
records = batchMaker.getStageOutput().get("o2");
Assert.assertEquals(2, records.size());
Assert.assertEquals("2", records.get(0).getHeader().getAttribute("r"));
Assert.assertEquals("3", records.get(1).getHeader().getAttribute("r"));
}
@Test
@SuppressWarnings("unchecked")
public void testBatchMakerMultipleOutputWithSnapshot() {
StagePipe pipe = createStagePipe(ImmutableList.of("o1", "o2"));
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, true);
Assert.assertNotNull(batchMaker.getStageOutputSnapshot());
Record record1 = new RecordImpl("i", "source", null, null);
record1.getHeader().setAttribute("r", "1");
batchMaker.addRecord(record1, "o1");
Record record2 = new RecordImpl("i", "source", null, null);
record2.getHeader().setAttribute("r", "2");
batchMaker.addRecord(record2, "o2");
List<Record> records = batchMaker.getStageOutputSnapshot().get("o1");
Assert.assertEquals(1, records.size());
Assert.assertEquals("1", records.get(0).getHeader().getAttribute("r"));
records = batchMaker.getStageOutputSnapshot().get("o2");
Assert.assertEquals(1, records.size());
Assert.assertEquals("2", records.get(0).getHeader().getAttribute("r"));
}
@Test
@SuppressWarnings("unchecked")
public void testMaxRecordsWithInLimit() {
StagePipe pipe = createStagePipe(ImmutableList.of("o"));
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, false, 1);
Record record = new RecordImpl("i", "source", null, null);
batchMaker.addRecord(record);
}
@Test()
@SuppressWarnings("unchecked")
public void testMaxRecordsBeyondLimit() {
StagePipe pipe = createStagePipe(ImmutableList.of("o"));
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, false, 1);
Record record = new RecordImpl("i", "source", null, null);
batchMaker.addRecord(record);
batchMaker.addRecord(record);
//This is changed to log warning and not throw IllegalArgumentException.
//Some sources could translate one event to multiple records and my go over the batch size.
}
@Test
public void testRecordByRef() {
StageConfiguration stageConfiguration = new StageConfigurationBuilder("i","n")
.withOutputLanes("o")
.build();
StageDefinition stageDef = Mockito.mock(StageDefinition.class);
Mockito.when(stageDef.getType()).thenReturn(StageType.SOURCE);
Source.Context context = Mockito.mock(Source.Context.class);
Mockito.when(stageDef.getType()).thenReturn(StageType.SOURCE);
Stage.Info stageInfo = Mockito.mock(Stage.Info.class);
Mockito.when(stageInfo.getInstanceName()).thenReturn("i");
StageRuntime stageRuntime = Mockito.mock(StageRuntime.class);
Mockito.when(stageRuntime.getInfo()).thenReturn(stageInfo);
Mockito.when(stageRuntime.getConfiguration()).thenReturn(stageConfiguration);
Mockito.when(stageRuntime.getDefinition()).thenReturn(stageDef);
Mockito.when(stageRuntime.getContext()).thenReturn(context);
StagePipe pipe = new StagePipe(stageRuntime, Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList());
Record record = new RecordImpl("s", "s", null, null);
// preview by value
Mockito.when(context.isPreview()).thenReturn(true);
Mockito.when(stageDef.getRecordsByRef()).thenReturn(false);
BatchMakerImpl batchMaker = new BatchMakerImpl(pipe, false);
Assert.assertFalse(batchMaker.isRecordByRef());
Assert.assertNotSame(record, batchMaker.getRecordForBatchMaker(record));
// preview by ref
Mockito.when(context.isPreview()).thenReturn(true);
Mockito.when(stageDef.getRecordsByRef()).thenReturn(true);
batchMaker = new BatchMakerImpl(pipe, false);
Assert.assertFalse(batchMaker.isRecordByRef());
Assert.assertNotSame(record, batchMaker.getRecordForBatchMaker(record));
// prod by value
Mockito.when(stageDef.getRecordsByRef()).thenReturn(false);
Mockito.when(context.isPreview()).thenReturn(false);
batchMaker = new BatchMakerImpl(pipe, false);
Assert.assertFalse(batchMaker.isRecordByRef());
Assert.assertNotSame(record, batchMaker.getRecordForBatchMaker(record));
// prod by ref
Mockito.when(stageDef.getRecordsByRef()).thenReturn(true);
Mockito.when(context.isPreview()).thenReturn(false);
batchMaker = new BatchMakerImpl(pipe, false);
Assert.assertTrue(batchMaker.isRecordByRef());
Assert.assertSame(record, batchMaker.getRecordForBatchMaker(record));
}
}