@Test public void testTimestampAndWatermarkQuerying() throws Exception { CoProcessOperator<Integer, String, String> operator = new CoProcessOperator<>(new WatermarkQueryingProcessFunction()); TwoInputStreamOperatorTestHarness<Integer, String, String> testHarness = new TwoInputStreamOperatorTestHarness<>(operator); testHarness.setup(); testHarness.open(); testHarness.processWatermark1(new Watermark(17)); testHarness.processWatermark2(new Watermark(17)); testHarness.processElement1(new StreamRecord<>(5, 12L)); testHarness.processWatermark1(new Watermark(42)); testHarness.processWatermark2(new Watermark(42)); testHarness.processElement2(new StreamRecord<>("6", 13L)); ConcurrentLinkedQueue<Object> expectedOutput = new ConcurrentLinkedQueue<>(); expectedOutput.add(new Watermark(17L)); expectedOutput.add(new StreamRecord<>("5WM:17 TS:12", 12L)); expectedOutput.add(new Watermark(42L)); expectedOutput.add(new StreamRecord<>("6WM:42 TS:13", 13L)); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); testHarness.close(); }
BasicTypeInfo.STRING_TYPE_INFO); testHarness.setup(); testHarness.open(); testHarness.processElement1(new StreamRecord<>(5, 12L)); testHarness.processElement2(new StreamRecord<>("5", 12L)); OperatorSubtaskState snapshot = testHarness.snapshot(0, 0); testHarness.close(); BasicTypeInfo.STRING_TYPE_INFO); testHarness.setup(); testHarness.initializeState(snapshot); testHarness.open(); testHarness.setProcessingTime(5); testHarness.processWatermark1(new Watermark(6)); testHarness.processWatermark2(new Watermark(6)); expectedOutput.add(new Watermark(6)); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); testHarness.close();
private static <IN1, IN2, OUT> TwoInputStreamOperatorTestHarness<IN1, IN2, OUT> getInitializedTestHarness( final BroadcastProcessFunction<IN1, IN2, OUT> function, final int maxParallelism, final int numTasks, final int taskIdx, final OperatorSubtaskState initState, final MapStateDescriptor<?, ?>... descriptors) throws Exception { TwoInputStreamOperatorTestHarness<IN1, IN2, OUT> testHarness = new TwoInputStreamOperatorTestHarness<>( new CoBroadcastWithNonKeyedOperator<>( Preconditions.checkNotNull(function), Arrays.asList(descriptors)), maxParallelism, numTasks, taskIdx ); testHarness.setup(); testHarness.initializeState(initState); testHarness.open(); return testHarness; } }
@Test public void testOpenClose() throws Exception { CoStreamFlatMap<String, Integer, String> operator = new CoStreamFlatMap<String, Integer, String>(new TestOpenCloseCoFlatMapFunction()); TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = new TwoInputStreamOperatorTestHarness<String, Integer, String>(operator); long initialTime = 0L; testHarness.open(); testHarness.processElement1(new StreamRecord<String>("Hello", initialTime)); testHarness.processElement2(new StreamRecord<Integer>(42, initialTime)); testHarness.close(); Assert.assertTrue("RichFunction methods where not called.", TestOpenCloseCoFlatMapFunction.closeCalled); Assert.assertTrue("Output contains no elements.", testHarness.getOutput().size() > 0); }
private static class IdentityKeySelector<T> implements KeySelector<T, T> { private static final long serialVersionUID = 1L; @Override public T getKey(T value) throws Exception { return value; } }
@Test public void testTimestampAndProcessingTimeQuerying() throws Exception { CoProcessOperator<Integer, String, String> operator = new CoProcessOperator<>(new ProcessingTimeQueryingProcessFunction()); TwoInputStreamOperatorTestHarness<Integer, String, String> testHarness = new TwoInputStreamOperatorTestHarness<>(operator); testHarness.setup(); testHarness.open(); testHarness.setProcessingTime(17); testHarness.processElement1(new StreamRecord<>(5)); testHarness.setProcessingTime(42); testHarness.processElement2(new StreamRecord<>("6")); ConcurrentLinkedQueue<Object> expectedOutput = new ConcurrentLinkedQueue<>(); expectedOutput.add(new StreamRecord<>("5PT:17 TS:null")); expectedOutput.add(new StreamRecord<>("6PT:42 TS:null")); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); testHarness.close(); }
testHarness = harnessFactory.create(); testHarness.open(); testHarness.processElement1(new StreamRecord<>(helloElement)); testHarness.processElement1(new StreamRecord<>(worldElement)); OperatorSubtaskState snapshot = testHarness.snapshot(0, 0); testHarness.initializeState(snapshot); testHarness.open(); testHarness.processElement2( new StreamRecord<>( new RawUnionValue( new Instant(0), firstWindow)))); testHarness.processElement2( new StreamRecord<>( new RawUnionValue( stripStreamRecordFromWindowedValue(testHarness.getOutput()), contains(helloElement, worldElement)); testHarness.close();
CoStreamMap<Double, Integer, String> operator = new CoStreamMap<Double, Integer, String>(new MyCoMap()); TwoInputStreamOperatorTestHarness<Double, Integer, String> testHarness = new TwoInputStreamOperatorTestHarness<Double, Integer, String>(operator); testHarness.open(); testHarness.processElement1(new StreamRecord<Double>(1.1d, initialTime + 1)); testHarness.processElement1(new StreamRecord<Double>(1.2d, initialTime + 2)); testHarness.processElement1(new StreamRecord<Double>(1.3d, initialTime + 3)); testHarness.processWatermark1(new Watermark(initialTime + 3)); testHarness.processElement1(new StreamRecord<Double>(1.4d, initialTime + 4)); testHarness.processElement1(new StreamRecord<Double>(1.5d, initialTime + 5)); testHarness.processElement2(new StreamRecord<Integer>(1, initialTime + 1)); testHarness.processElement2(new StreamRecord<Integer>(2, initialTime + 2)); testHarness.processWatermark2(new Watermark(initialTime + 2)); testHarness.processElement2(new StreamRecord<Integer>(3, initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(4, initialTime + 4)); testHarness.processElement2(new StreamRecord<Integer>(5, initialTime + 5)); expectedOutput.add(new StreamRecord<String>("5", initialTime + 5)); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput());
testHarness1.processElement2(new StreamRecord<>(3)); testHarness2.processElement2(new StreamRecord<>(3)); testHarness3.processElement2(new StreamRecord<>(3)); testHarness1.snapshot(0L, 0L), testHarness2.snapshot(0L, 0L), testHarness3.snapshot(0L, 0L) ); STATE_DESCRIPTOR) ) { testHarness1.processElement1(new StreamRecord<>("trigger")); testHarness2.processElement1(new StreamRecord<>("trigger")); Queue<?> output1 = testHarness1.getOutput(); Queue<?> output2 = testHarness2.getOutput();
@Test public void testBroadcastState() throws Exception { final Set<String> keysToRegister = new HashSet<>(); keysToRegister.add("test1"); keysToRegister.add("test2"); keysToRegister.add("test3"); try ( TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = getInitializedTestHarness( new TestFunction(keysToRegister), STATE_DESCRIPTOR) ) { testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement2(new StreamRecord<>(5, 12L)); testHarness.processWatermark1(new Watermark(40L)); testHarness.processWatermark2(new Watermark(40L)); testHarness.processElement1(new StreamRecord<>("6", 13L)); testHarness.processElement1(new StreamRecord<>("6", 15L)); testHarness.processWatermark1(new Watermark(50L)); testHarness.processWatermark2(new Watermark(50L)); Queue<Object> expectedOutput = new ConcurrentLinkedQueue<>(); expectedOutput.add(new Watermark(10L)); expectedOutput.add(new StreamRecord<>("5WM:10 TS:12", 12L)); expectedOutput.add(new Watermark(40L)); expectedOutput.add(new StreamRecord<>("6WM:40 TS:13", 13L)); expectedOutput.add(new StreamRecord<>("6WM:40 TS:15", 15L)); expectedOutput.add(new Watermark(50L)); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); } }
new KeyedTwoInputStreamOperatorTestHarness<>(operator, (in) -> in.f0 , null, BasicTypeInfo.INT_TYPE_INFO)) { testHarness.setup(); testHarness.open(); testHarness.processElement1(new StreamRecord<>(Tuple2.of(5, "5"), 12L)); testHarness.processElement1(new StreamRecord<>(Tuple2.of(42, "42"), 13L)); "Output was not correct.", expectedOutput, testHarness.getOutput());
@Test public void testSideOutput() throws Exception { try ( TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = getInitializedTestHarness( new FunctionWithSideOutput(), STATE_DESCRIPTOR) ) { testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement2(new StreamRecord<>(5, 12L)); testHarness.processWatermark1(new Watermark(40L)); testHarness.processWatermark2(new Watermark(40L)); testHarness.processElement1(new StreamRecord<>("6", 13L)); testHarness.processElement1(new StreamRecord<>("6", 15L)); testHarness.processWatermark1(new Watermark(50L)); testHarness.processWatermark2(new Watermark(50L)); ConcurrentLinkedQueue<StreamRecord<String>> expectedBr = new ConcurrentLinkedQueue<>(); expectedBr.add(new StreamRecord<>("BR:5 WM:10 TS:12", 12L)); ConcurrentLinkedQueue<StreamRecord<String>> expectedNonBr = new ConcurrentLinkedQueue<>(); expectedNonBr.add(new StreamRecord<>("NON-BR:6 WM:40 TS:13", 13L)); expectedNonBr.add(new StreamRecord<>("NON-BR:6 WM:40 TS:15", 15L)); ConcurrentLinkedQueue<StreamRecord<String>> brSideOutput = testHarness.getSideOutput(FunctionWithSideOutput.BROADCAST_TAG); ConcurrentLinkedQueue<StreamRecord<String>> nonBrSideOutput = testHarness.getSideOutput(FunctionWithSideOutput.NON_BROADCAST_TAG); TestHarnessUtil.assertOutputEquals("Wrong Side Output", expectedBr, brSideOutput); TestHarnessUtil.assertOutputEquals("Wrong Side Output", expectedNonBr, nonBrSideOutput); } }
@Test public void testMultiStateSupport() throws Exception { try ( TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = getInitializedTestHarness(new FunctionWithMultipleStates(), STATE_DESCRIPTOR, STATE_DESCRIPTOR_A) ) { testHarness.processElement2(new StreamRecord<>(5, 12L)); testHarness.processElement2(new StreamRecord<>(6, 13L)); testHarness.processElement1(new StreamRecord<>("9", 15L)); Queue<Object> expectedBr = new ConcurrentLinkedQueue<>(); expectedBr.add(new StreamRecord<>("9:key.6->6", 15L)); expectedBr.add(new StreamRecord<>("9:key.5->5", 15L)); expectedBr.add(new StreamRecord<>("9:5->value.5", 15L)); expectedBr.add(new StreamRecord<>("9:6->value.6", 15L)); TestHarnessUtil.assertOutputEquals("Wrong Side Output", expectedBr, testHarness.getOutput()); } }
testHarness.processElement1(new StreamRecord<>("test1", 12L)); testHarness.processElement1(new StreamRecord<>("test1", 12L)); testHarness.processElement1(new StreamRecord<>("test2", 13L)); testHarness.processElement1(new StreamRecord<>("test2", 13L)); testHarness.processElement1(new StreamRecord<>("test2", 13L)); testHarness.processElement1(new StreamRecord<>("test3", 14L)); testHarness.processElement1(new StreamRecord<>("test3", 14L)); testHarness.processElement1(new StreamRecord<>("test3", 14L)); testHarness.processElement1(new StreamRecord<>("test2", 13L)); testHarness.processElement2(new StreamRecord<>(1, 13L));
@Test public void testNoKeyedStateOnBroadcastSide() throws Exception { boolean exceptionThrown = false; try ( TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = getInitializedTestHarness( new BroadcastProcessFunction<String, Integer, String>() { private static final long serialVersionUID = -1725365436500098384L; private final ValueStateDescriptor<String> valueState = new ValueStateDescriptor<>("any", BasicTypeInfo.STRING_TYPE_INFO); @Override public void processBroadcastElement(Integer value, Context ctx, Collector<String> out) throws Exception { getRuntimeContext().getState(valueState).value(); // this should fail } @Override public void processElement(String value, ReadOnlyContext ctx, Collector<String> out) throws Exception { // do nothing } }) ) { testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement2(new StreamRecord<>(5, 12L)); } catch (NullPointerException e) { Assert.assertEquals("Keyed state can only be used on a 'keyed stream', i.e., after a 'keyBy()' operation.", e.getMessage()); exceptionThrown = true; } if (!exceptionThrown) { Assert.fail("No exception thrown"); } }
null); return new TwoInputStreamOperatorTestHarness<>(doFnOperator); });
@Test public void testNoKeyedStateOnNonBroadcastSide() throws Exception { boolean exceptionThrown = false; try ( TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = getInitializedTestHarness( new BroadcastProcessFunction<String, Integer, String>() { private static final long serialVersionUID = -1725365436500098384L; private final ValueStateDescriptor<String> valueState = new ValueStateDescriptor<>("any", BasicTypeInfo.STRING_TYPE_INFO); @Override public void processBroadcastElement(Integer value, Context ctx, Collector<String> out) throws Exception { // do nothing } @Override public void processElement(String value, ReadOnlyContext ctx, Collector<String> out) throws Exception { getRuntimeContext().getState(valueState).value(); // this should fail } }) ) { testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement1(new StreamRecord<>("5", 12L)); } catch (NullPointerException e) { Assert.assertEquals("Keyed state can only be used on a 'keyed stream', i.e., after a 'keyBy()' operation.", e.getMessage()); exceptionThrown = true; } if (!exceptionThrown) { Assert.fail("No exception thrown"); } }
@Test public void testOpenClose() throws Exception { CoStreamMap<Double, Integer, String> operator = new CoStreamMap<Double, Integer, String>(new TestOpenCloseCoMapFunction()); TwoInputStreamOperatorTestHarness<Double, Integer, String> testHarness = new TwoInputStreamOperatorTestHarness<Double, Integer, String>(operator); long initialTime = 0L; testHarness.open(); testHarness.processElement1(new StreamRecord<Double>(74d, initialTime)); testHarness.processElement2(new StreamRecord<Integer>(42, initialTime)); testHarness.close(); Assert.assertTrue("RichFunction methods where not called.", TestOpenCloseCoMapFunction.closeCalled); Assert.assertTrue("Output contains no elements.", testHarness.getOutput().size() > 0); }
@Test public void testTimestampAndProcessingTimeQuerying() throws Exception { KeyedCoProcessOperator<String, Integer, String, String> operator = new KeyedCoProcessOperator<>(new ProcessingTimeQueryingProcessFunction()); TwoInputStreamOperatorTestHarness<Integer, String, String> testHarness = new KeyedTwoInputStreamOperatorTestHarness<>( operator, new IntToStringKeySelector<>(), new IdentityKeySelector<String>(), BasicTypeInfo.STRING_TYPE_INFO); testHarness.setup(); testHarness.open(); testHarness.setProcessingTime(17); testHarness.processElement1(new StreamRecord<>(5)); testHarness.setProcessingTime(42); testHarness.processElement2(new StreamRecord<>("6")); ConcurrentLinkedQueue<Object> expectedOutput = new ConcurrentLinkedQueue<>(); expectedOutput.add(new StreamRecord<>("5PT:17 TS:null")); expectedOutput.add(new StreamRecord<>("6PT:42 TS:null")); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); testHarness.close(); }
testHarness = harnessFactory.create(); testHarness.open(); testHarness.processElement2( new StreamRecord<>( new RawUnionValue( new Instant(0), firstWindow)))); testHarness.processElement2( new StreamRecord<>( new RawUnionValue( OperatorSubtaskState snapshot = testHarness.snapshot(0, 0); testHarness.initializeState(snapshot); testHarness.open(); testHarness.processElement1(new StreamRecord<>(helloElement)); testHarness.processElement1(new StreamRecord<>(worldElement)); stripStreamRecordFromWindowedValue(testHarness.getOutput()), contains(helloElement, worldElement)); testHarness.close();