/* * Licensed to 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 org.apache.flink.runtime.io.network.api.reader; import org.apache.flink.core.memory.DataInputView; import org.apache.flink.core.memory.DataOutputView; import org.apache.flink.runtime.event.TaskEvent; import org.apache.flink.runtime.io.network.api.EndOfPartitionEvent; import org.apache.flink.runtime.io.network.api.EndOfSuperstepEvent; import org.apache.flink.runtime.io.network.partition.consumer.InputGate; import org.apache.flink.runtime.util.event.EventListener; import org.junit.Test; import org.mockito.Matchers; import java.io.IOException; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * Tests for the event handling behaviour. */ public class AbstractReaderTest { @Test @SuppressWarnings("unchecked") public void testTaskEvent() throws Exception { final AbstractReader reader = new MockReader(createInputGate(1)); final EventListener<TaskEvent> listener1 = mock(EventListener.class); final EventListener<TaskEvent> listener2 = mock(EventListener.class); final EventListener<TaskEvent> listener3 = mock(EventListener.class); reader.registerTaskEventListener(listener1, TestTaskEvent1.class); reader.registerTaskEventListener(listener2, TestTaskEvent2.class); reader.registerTaskEventListener(listener3, TaskEvent.class); reader.handleEvent(new TestTaskEvent1()); // for listener1 only reader.handleEvent(new TestTaskEvent2()); // for listener2 only verify(listener1, times(1)).onEvent(Matchers.any(TaskEvent.class)); verify(listener2, times(1)).onEvent(Matchers.any(TaskEvent.class)); verify(listener3, times(0)).onEvent(Matchers.any(TaskEvent.class)); } @Test public void testEndOfPartitionEvent() throws Exception { final AbstractReader reader = new MockReader(createInputGate(1)); assertTrue(reader.handleEvent(EndOfPartitionEvent.INSTANCE)); } /** * Ensure that all end of superstep event related methods throw an Exception when used with a * non-iterative reader. */ @Test public void testExceptionsNonIterativeReader() throws Exception { final AbstractReader reader = new MockReader(createInputGate(4)); // Non-iterative reader cannot reach end of superstep assertFalse(reader.hasReachedEndOfSuperstep()); try { reader.startNextSuperstep(); fail("Did not throw expected exception when starting next superstep with non-iterative reader."); } catch (Throwable t) { // All good, expected exception. } try { reader.handleEvent(EndOfSuperstepEvent.INSTANCE); fail("Did not throw expected exception when handling end of superstep event with non-iterative reader."); } catch (Throwable t) { // All good, expected exception. } } @Test public void testEndOfSuperstepEventLogic() throws IOException { final int numberOfInputChannels = 4; final AbstractReader reader = new MockReader(createInputGate(numberOfInputChannels)); reader.setIterativeReader(); try { // The first superstep does not need not to be explicitly started reader.startNextSuperstep(); fail("Did not throw expected exception when starting next superstep before receiving all end of superstep events."); } catch (Throwable t) { // All good, expected exception. } EndOfSuperstepEvent eos = EndOfSuperstepEvent.INSTANCE; // One end of superstep event for each input channel. The superstep finishes with the last // received event. for (int i = 0; i < numberOfInputChannels - 1; i++) { assertFalse(reader.handleEvent(eos)); assertFalse(reader.hasReachedEndOfSuperstep()); } assertTrue(reader.handleEvent(eos)); assertTrue(reader.hasReachedEndOfSuperstep()); try { // Verify exception, when receiving too many end of superstep events. reader.handleEvent(eos); fail("Did not throw expected exception when receiving too many end of superstep events."); } catch (Throwable t) { // All good, expected exception. } // Start next superstep. reader.startNextSuperstep(); assertFalse(reader.hasReachedEndOfSuperstep()); } private InputGate createInputGate(int numberOfInputChannels) { final InputGate inputGate = mock(InputGate.class); when(inputGate.getNumberOfInputChannels()).thenReturn(numberOfInputChannels); return inputGate; } // ------------------------------------------------------------------------ private static class TestTaskEvent1 extends TaskEvent { @Override public void write(DataOutputView out) throws IOException { } @Override public void read(DataInputView in) throws IOException { } } private static class TestTaskEvent2 extends TaskEvent { @Override public void write(DataOutputView out) throws IOException { } @Override public void read(DataInputView in) throws IOException { } } private static class MockReader extends AbstractReader { protected MockReader(InputGate inputGate) { super(inputGate); } } }