/* * Copyright 2015 Netflix, Inc. * * Licensed 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 io.reactivex.netty.events; import io.reactivex.netty.events.ListenersHolderRule.ListenerWithSub; import io.reactivex.netty.test.util.MockEventListener; import org.junit.Rule; import org.junit.Test; import rx.Subscription; import rx.functions.Action1; import rx.functions.Action2; import rx.functions.Action3; import rx.functions.Action4; import rx.functions.Action5; import java.util.Collection; import java.util.concurrent.TimeUnit; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; public class ListenersHolderTest { @Rule public final ListenersHolderRule holderRule = new ListenersHolderRule(); @Test(timeout = 60000) public void testSubscribe() throws Exception { ListenerWithSub l = holderRule.addAListener(); holderRule.assertListenerAdded(l.listener); l.subscription.unsubscribe(); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), is(empty())); } @Test(timeout = 60000) public void testMultipleListeners() throws Exception { final MockEventListener listener1 = new MockEventListener(); final MockEventListener listener2 = new MockEventListener(); Subscription subscription1 = holderRule.getHolder().subscribe(listener1); Subscription subscription2 = holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); subscription1.unsubscribe(); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), hasSize(1)); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), not(contains(listener1))); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), contains(listener2)); subscription2.unsubscribe(); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), is(empty())); } @Test(timeout = 60000) public void testPublishingEnabled() throws Exception { assertThat("Publishing enabled with no listeners", holderRule.getHolder().publishingEnabled(), is(false)); ListenerWithSub l1 = holderRule.addAListener(); assertThat("Publishing disabled with a listener", holderRule.getHolder().publishingEnabled(), is(true)); l1.subscription.unsubscribe(); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), is(empty())); assertThat("Publishing enabled post listener unsubscribe", holderRule.getHolder().publishingEnabled(), is(false)); } @Test(timeout = 60000) public void testDispose() throws Exception { ListenerWithSub l = holderRule.addAListener(); holderRule.getHolder().dispose(); assertThat("On complete not called on dispose.", l.listener.getOnCompletedCount(), is(1)); assertThat("Listener not unsubscribed on dispose.", l.subscription.isUnsubscribed(), is(true)); assertThat("Listener not removed on dispose.", holderRule.getHolder().getAllListeners(), not(contains(l.listener))); } @Test(timeout = 60000) public void testDisposeWithExceptions() throws Exception { final MockEventListener listener1 = new MockEventListener(true); final MockEventListener listener2 = new MockEventListener(); Subscription subscription1 = holderRule.getHolder().subscribe(listener1); Subscription subscription2 = holderRule.getHolder().subscribe(listener2); assertThat("Listeners not added.", holderRule.getHolder().getAllListeners(), hasSize(2)); assertThat("Listeners not added.", holderRule.getHolder().getAllListeners(), contains(listener1, listener2)); try { holderRule.getHolder().dispose(); throw new AssertionError("Error not thrown on dispose."); } catch (Exception e) { // Expected. } assertThat("First listener not completed.", listener1.getOnCompletedCount(), is(1)); assertThat("Second listener not completed.", listener2.getOnCompletedCount(), is(1)); assertThat("First listener not unsubscribed.", subscription1.isUnsubscribed(), is(true)); assertThat("Second listener not unsubscribed.", subscription2.isUnsubscribed(), is(true)); assertThat("Listeners not removed post dispose.", holderRule.getHolder().getAllListeners(), is(empty())); } @Test(timeout = 60000) public void testInvokeListeners() throws Exception { final MockEventListener listener = new MockEventListener(); holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); holderRule.getHolder().invokeListeners(new Action1<MockEventListener>() { @Override public void call(MockEventListener mockEventListener) { mockEventListener.anEvent(); } }); assertThat("Listener not invoked.", listener.getEventInvocationCount(), is(1)); } @Test(timeout = 60000) public void testInvokeListenersMulti() throws Exception { final MockEventListener listener1 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); holderRule.getHolder().invokeListeners(new Action1<MockEventListener>() { @Override public void call(MockEventListener mockEventListener) { mockEventListener.anEvent(); } }); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked.", listener2.getEventInvocationCount(), is(1)); } @Test(timeout = 60000) public void testInvokeListenersRaiseException() throws Exception { final MockEventListener listener1 = new MockEventListener(true); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); holderRule.getHolder().subscribe(listener2); assertThat("Listeners not added.", holderRule.getHolder().getAllListeners(), hasSize(2)); assertThat("Listeners not added.", holderRule.getHolder().getAllListeners(), contains(listener1, listener2)); holderRule.getHolder().invokeListeners(new Action1<MockEventListener>() { @Override public void call(MockEventListener mockEventListener) { mockEventListener.anEvent(); } }); assertThat("First listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); } @Test(timeout = 60000) public void testInvokeListenersWithDuration() throws Exception { final MockEventListener listener = new MockEventListener(); holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); holderRule.getHolder().invokeListeners(new Action3<MockEventListener, Long, TimeUnit>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit) { mockEventListener.anEventWithDuration(duration, timeUnit); } }, 1, TimeUnit.MICROSECONDS); assertThat("Listener not invoked.", listener.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener.getTimeUnit(), is(TimeUnit.MICROSECONDS)); } @Test(timeout = 60000) public void testInvokeListenersMultiWithDuration() throws Exception { final MockEventListener listener1 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); holderRule.getHolder().invokeListeners(new Action3<MockEventListener, Long, TimeUnit>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit) { mockEventListener.anEventWithDuration(duration, timeUnit); } }, 1, TimeUnit.MICROSECONDS); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); } @Test(timeout = 60000) public void testInvokeListenersWithDurationRaiseException() throws Exception { final MockEventListener listener1 = new MockEventListener(true); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); holderRule.getHolder().invokeListeners(new Action3<MockEventListener, Long, TimeUnit>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit) { mockEventListener.anEventWithDuration(duration, timeUnit); } }, 1, TimeUnit.MICROSECONDS); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); } @Test(timeout = 60000) public void testInvokeListenersWithDurationAndError() throws Exception { final MockEventListener listener = new MockEventListener(); holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); final Throwable expected = new NullPointerException(); holderRule.getHolder().invokeListeners(new Action4<MockEventListener, Long, TimeUnit, Throwable>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, Throwable t) { mockEventListener.anEventWithDurationAndError(duration, timeUnit, t); } }, 1, TimeUnit.MICROSECONDS, expected); assertThat("Listener not invoked.", listener.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with error.", listener.getRecievedError(), is(expected)); } @Test(timeout = 60000) public void testInvokeListenersMultiWithDurationAndError() throws Exception { final MockEventListener listener1 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final Throwable expected = new NullPointerException(); holderRule.getHolder().invokeListeners(new Action4<MockEventListener, Long, TimeUnit, Throwable>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, Throwable t) { mockEventListener.anEventWithDurationAndError(duration, timeUnit, t); } }, 1, TimeUnit.MICROSECONDS, expected); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with error.", listener1.getRecievedError(), is(expected)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked with error.", listener2.getRecievedError(), is(expected)); } @Test(timeout = 60000) public void testInvokeListenersWithDurationAndErrorRaiseException() throws Exception { final MockEventListener listener1 = new MockEventListener(true); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final Throwable expected = new NullPointerException(); holderRule.getHolder().invokeListeners(new Action4<MockEventListener, Long, TimeUnit, Throwable>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, Throwable t) { mockEventListener.anEventWithDurationAndError(duration, timeUnit, t); } }, 1, TimeUnit.MICROSECONDS, expected); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with error.", listener1.getRecievedError(), is(expected)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked with error.", listener2.getRecievedError(), is(expected)); } @Test(timeout = 60000) public void testInvokeListenersWithDurationAndArg() throws Exception { final MockEventListener listener = new MockEventListener(); holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); final String arg = "doom"; holderRule.getHolder().invokeListeners(new Action4<MockEventListener, Long, TimeUnit, String>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, String arg) { mockEventListener.anEventWithDurationAndArg(duration, timeUnit, arg); } }, 1, TimeUnit.MICROSECONDS, arg); assertThat("Listener not invoked.", listener.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with argument.", listener.getArg(), is(arg)); } @Test(timeout = 60000) public void testInvokeListenersMultiWithDurationAndArg() throws Exception { final MockEventListener listener1 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final String arg = "doom"; holderRule.getHolder().invokeListeners(new Action4<MockEventListener, Long, TimeUnit, String>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, String arg) { mockEventListener.anEventWithDurationAndArg(duration, timeUnit, arg); } }, 1, TimeUnit.MICROSECONDS, arg); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with argument.", listener1.getArg(), is(arg)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked with argument.", listener2.getArg(), is(arg)); } @Test(timeout = 60000) public void testInvokeListenersMultiWithDurationErrorAndArg() throws Exception { final MockEventListener listener1 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final Object event = "doom"; final Throwable expected = new NullPointerException(); holderRule.getHolder().invokeListeners(new Action5<MockEventListener, Long, TimeUnit, Throwable, Object>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, Throwable throwable, Object event) { mockEventListener.onCustomEvent(event, duration, timeUnit, throwable); } }, 1, TimeUnit.MICROSECONDS, expected, event); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with error.", listener1.getRecievedError(), is(expected)); assertThat("Listener not invoked with argument.", listener1.getCustomEvent(), is(event)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked with error.", listener2.getRecievedError(), is(expected)); assertThat("Second listener not invoked with argument.", listener2.getCustomEvent(), is(event)); } @Test(timeout = 60000) public void testInvokeListenersWithDurationArgRaiseException() throws Exception { final MockEventListener listener1 = new MockEventListener(true); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final String arg = "doom"; holderRule.getHolder().invokeListeners(new Action4<MockEventListener, Long, TimeUnit, String>() { @Override public void call(MockEventListener mockEventListener, Long duration, TimeUnit timeUnit, String arg) { mockEventListener.anEventWithDurationAndArg(duration, timeUnit, arg); } }, 1, TimeUnit.MICROSECONDS, arg); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with duration.", listener1.getDuration(), is(1L)); assertThat("Listener not invoked with time unit.", listener1.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Listener not invoked with argument.", listener1.getArg(), is(arg)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with duration.", listener2.getDuration(), is(1L)); assertThat("Second listener not invoked with time unit.", listener2.getTimeUnit(), is(TimeUnit.MICROSECONDS)); assertThat("Second listener not invoked with argument.", listener2.getArg(), is(arg)); } @Test(timeout = 60000) public void testInvokeListenersWithArg() throws Exception { final MockEventListener listener = new MockEventListener(); holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); final String arg = "doom"; holderRule.getHolder().invokeListeners(new Action2<MockEventListener, String>() { @Override public void call(MockEventListener mockEventListener, String arg) { mockEventListener.anEventWithArg(arg); } }, arg); assertThat("Listener not invoked.", listener.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with argument.", listener.getArg(), is(arg)); } @Test(timeout = 60000) public void testInvokeListenersWithExceptionAndArg() throws Exception { final MockEventListener listener = new MockEventListener(); holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); final Object event = "doom"; final Throwable expected = new NullPointerException(); holderRule.getHolder().invokeListeners(new Action3<MockEventListener, Throwable, Object>() { @Override public void call(MockEventListener mockEventListener, Throwable throwable, Object arg) { mockEventListener.onCustomEvent(arg, throwable); } }, expected, event); assertThat("Listener not invoked.", listener.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with argument.", listener.getCustomEvent(), equalTo(event)); assertThat("Listener not invoked with exception.", listener.getRecievedError(), is(expected)); } @Test(timeout = 60000) public void testInvokeListenersMultiWithArg() throws Exception { final MockEventListener listener1 = new MockEventListener(); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final String arg = "doom"; holderRule.getHolder().invokeListeners(new Action2<MockEventListener, String>() { @Override public void call(MockEventListener mockEventListener, String arg) { mockEventListener.anEventWithArg(arg); } }, arg); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with argument.", listener1.getArg(), is(arg)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with argument.", listener2.getArg(), is(arg)); } @Test(timeout = 60000) public void testInvokeListenersWithArgAndRaiseException() throws Exception { final MockEventListener listener1 = new MockEventListener(true); holderRule.getHolder().subscribe(listener1); final MockEventListener listener2 = new MockEventListener(); holderRule.getHolder().subscribe(listener2); holderRule.assertListenerAdded(listener1, listener2); final String arg = "doom"; holderRule.getHolder().invokeListeners(new Action2<MockEventListener, String>() { @Override public void call(MockEventListener mockEventListener, String arg) { mockEventListener.anEventWithArg(arg); } }, arg); assertThat("Listener not invoked.", listener1.getEventInvocationCount(), is(1)); assertThat("Listener not invoked with argument.", listener1.getArg(), is(arg)); assertThat("Second listener not invoked.", listener2.getEventInvocationCount(), is(1)); assertThat("Second listener not invoked with argument.", listener2.getArg(), is(arg)); } @Test(timeout = 60000) public void testDuplicateListeners() throws Exception { ListenerWithSub l = holderRule.addAListener(); holderRule.assertListenerAdded(l.listener); holderRule.getHolder().subscribe(l.listener); assertThat("Duplicate listener added.", holderRule.getHolder().getActualListenersList(), hasSize(1)); l.subscription.unsubscribe(); assertThat("Listener not removed on unsubscribe.", holderRule.getHolder().getAllListeners(), is(empty())); } @Test(timeout = 60000) public void testCopy() throws Exception { final MockEventListener listener = new MockEventListener(); Subscription subscription = holderRule.getHolder().subscribe(listener); holderRule.assertListenerAdded(listener); final ListenersHolder<MockEventListener> copy = holderRule.getHolder().copy(); assertThat("Holder not copied", copy, is(not(holderRule.getHolder()))); assertThat("Listeners list not copied", copy.getActualListenersList(), not(sameInstance(holderRule.getHolder().getActualListenersList()))); final Collection<MockEventListener> allListenersCopied = copy.getAllListeners(); assertThat("Registered listeners not copied", allListenersCopied, contains(listener)); subscription.unsubscribe(); assertThat("Not removed from copy on unsubscribe.", copy.getAllListeners(), not(contains(listener))); } }