@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 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 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 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(); }
testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement2(new StreamRecord<>(5, 12L)); testHarness.processWatermark2(new Watermark(40L)); testHarness.processElement1(new StreamRecord<>("6", 13L)); testHarness.processElement1(new StreamRecord<>("6", 15L)); testHarness.processWatermark2(new Watermark(50L));
) { testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processWatermark2(new Watermark(50L));
testHarness.processWatermark2(new Watermark(1)); testHarness.processElement1(new StreamRecord<>(17, 0L)); // should set timer for 6 testHarness.processElement1(new StreamRecord<>(13, 0L)); // should set timer for 6 testHarness.processWatermark2(new Watermark(2)); testHarness.processElement1(new StreamRecord<>(13, 1L)); // should delete timer testHarness.processElement2(new StreamRecord<>("42", 1L)); // should set timer for 7 testHarness.processWatermark2(new Watermark(6)); testHarness.processWatermark2(new Watermark(7));
testHarness.processWatermark2(new Watermark(initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(3, initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(4, initialTime + 4));
@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(); }
@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.processWatermark2(new Watermark(initialTime + 2)); testHarness.processElement2(new StreamRecord<Integer>(3, initialTime + 3)); testHarness.processElement2(new StreamRecord<Integer>(4, initialTime + 4));
@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 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"); } }
) { testHarness.processWatermark1(new Watermark(10L)); testHarness.processWatermark2(new Watermark(10L)); testHarness.processElement2(new StreamRecord<>(5, 12L)); } catch (NullPointerException e) {
testHarness.processWatermark2(new Watermark(6));