@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<String>("ghi", initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(1, initialTime + 1)); testHarness.processElement2(new StreamRecord<Integer>(2, initialTime + 2)); testHarness.processWatermark2(new Watermark(initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(3, initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(4, initialTime + 4)); testHarness.processElement2(new StreamRecord<Integer>(5, initialTime + 5));
testHarness.processElement2(new StreamRecord<>(1, 13L));
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));
@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()); } }
@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); }
@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 { 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(); }
@Test public void testProcessingTimeTimers() throws Exception { KeyedCoProcessOperator<String, Integer, String, String> operator = new KeyedCoProcessOperator<>(new ProcessingTimeTriggeringProcessFunction()); TwoInputStreamOperatorTestHarness<Integer, String, String> testHarness = new KeyedTwoInputStreamOperatorTestHarness<>( operator, new IntToStringKeySelector<>(), new IdentityKeySelector<String>(), BasicTypeInfo.STRING_TYPE_INFO); testHarness.setup(); testHarness.open(); testHarness.processElement1(new StreamRecord<>(17)); testHarness.processElement2(new StreamRecord<>("18")); testHarness.setProcessingTime(5); testHarness.setProcessingTime(6); ConcurrentLinkedQueue<Object> expectedOutput = new ConcurrentLinkedQueue<>(); expectedOutput.add(new StreamRecord<>("INPUT1:17")); expectedOutput.add(new StreamRecord<>("INPUT2:18")); expectedOutput.add(new StreamRecord<>("1777")); expectedOutput.add(new StreamRecord<>("1777")); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); testHarness.close(); }
@Test public void testFunctionWithTimer() throws Exception { final String expectedKey = "6"; try ( TwoInputStreamOperatorTestHarness<String, Integer, String> testHarness = getInitializedTestHarness( BasicTypeInfo.STRING_TYPE_INFO, new IdentityKeySelector<>(), new FunctionWithTimerOnKeyed(41L, expectedKey)) ) { 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<>(expectedKey, 13L)); testHarness.processElement1(new StreamRecord<>(expectedKey, 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<>("BR:5 WM:10 TS:12", 12L)); expectedOutput.add(new Watermark(40L)); expectedOutput.add(new StreamRecord<>("NON-BR:6 WM:40 TS:13", 13L)); expectedOutput.add(new StreamRecord<>("NON-BR:6 WM:40 TS:15", 15L)); expectedOutput.add(new StreamRecord<>("TIMER:41", 41L)); expectedOutput.add(new Watermark(50L)); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); } }
@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"); } }
@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(); }
@Test public void testEventTimeTimers() throws Exception { KeyedCoProcessOperator<String, Integer, String, String> operator = new KeyedCoProcessOperator<>(new EventTimeTriggeringProcessFunction()); TwoInputStreamOperatorTestHarness<Integer, String, String> testHarness = new KeyedTwoInputStreamOperatorTestHarness<>( operator, new IntToStringKeySelector<>(), new IdentityKeySelector<String>(), BasicTypeInfo.STRING_TYPE_INFO); testHarness.setup(); testHarness.open(); testHarness.processElement1(new StreamRecord<>(17, 42L)); testHarness.processElement2(new StreamRecord<>("18", 42L)); testHarness.processWatermark1(new Watermark(5)); testHarness.processWatermark2(new Watermark(5)); testHarness.processWatermark1(new Watermark(6)); testHarness.processWatermark2(new Watermark(6)); ConcurrentLinkedQueue<Object> expectedOutput = new ConcurrentLinkedQueue<>(); expectedOutput.add(new StreamRecord<>("INPUT1:17", 42L)); expectedOutput.add(new StreamRecord<>("INPUT2:18", 42L)); expectedOutput.add(new StreamRecord<>("1777", 5L)); expectedOutput.add(new Watermark(5L)); expectedOutput.add(new StreamRecord<>("1777", 6L)); expectedOutput.add(new Watermark(6L)); TestHarnessUtil.assertOutputEquals("Output was not correct.", expectedOutput, testHarness.getOutput()); testHarness.close(); }
testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement2(new StreamRecord<>(5, 12L)); } catch (NullPointerException e) { assertEquals("No key set. This method should not be called outside of a keyed context.", e.getMessage());
@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(); }
@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); } }
testHarness.processElement2(new StreamRecord<>("42")); // should set timer for 7
@Test public void testTimestampAndWatermarkQuerying() throws Exception { KeyedCoProcessOperator<String, Integer, String, String> operator = new KeyedCoProcessOperator<>(new WatermarkQueryingProcessFunction()); TwoInputStreamOperatorTestHarness<Integer, String, String> testHarness = new KeyedTwoInputStreamOperatorTestHarness<>( operator, new IntToStringKeySelector<>(), new IdentityKeySelector<String>(), BasicTypeInfo.STRING_TYPE_INFO); 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(); }
testHarness.processElement2(new StreamRecord<>(5, 12L));
testHarness.processElement2(new StreamRecord<>("5", 12L));