/* * Copyright 2014-present Open Networking Laboratory * * 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 org.onosproject.event.impl; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.onosproject.event.AbstractEvent; import org.onosproject.event.EventSink; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * Test of the event dispatcher mechanism. */ public class CoreEventDispatcherTest { private final CoreEventDispatcher dispatcher = new CoreEventDispatcher(); private final PrickleSink prickleSink = new PrickleSink(); private final GooSink gooSink = new GooSink(); @Before public void setUp() { dispatcher.activate(); dispatcher.addSink(Prickle.class, prickleSink); dispatcher.addSink(Goo.class, gooSink); } @After public void tearDown() { dispatcher.removeSink(Goo.class); dispatcher.removeSink(Prickle.class); dispatcher.deactivate(); } @Test public void post() throws Exception { prickleSink.latch = new CountDownLatch(1); dispatcher.post(new Prickle("yo")); prickleSink.latch.await(100, TimeUnit.MILLISECONDS); validate(prickleSink, "yo"); validate(gooSink); } @Test public void postEventWithBadSink() throws Exception { gooSink.latch = new CountDownLatch(1); dispatcher.post(new Goo("boom")); gooSink.latch.await(100, TimeUnit.MILLISECONDS); validate(gooSink, "boom"); validate(prickleSink); } @Test public void postEventWithNoSink() throws Exception { dispatcher.post(new Thing("boom")); validate(gooSink); validate(prickleSink); } @Test public void postEventSinkTakesTooLong() throws Exception { SinkProcessTakesTooLong takesTooLong = new SinkProcessTakesTooLong(); dispatcher.setDispatchTimeLimit(250); dispatcher.addSink(TooLongEvent.class, takesTooLong); takesTooLong.latch = new CountDownLatch(1); dispatcher.post(new TooLongEvent("XYZZY")); takesTooLong.latch.await(1000, TimeUnit.MILLISECONDS); assertTrue(takesTooLong.interrupted); } private void validate(Sink sink, String... strings) { int i = 0; assertEquals("incorrect event count", strings.length, sink.subjects.size()); for (String string : strings) { assertEquals("incorrect event", string, sink.subjects.get(i++)); } } private enum Type { FOO } private static class Thing extends AbstractEvent<Type, String> { protected Thing(String subject) { super(Type.FOO, subject); } } private static class Prickle extends Thing { protected Prickle(String subject) { super(subject); } } private static class Goo extends Thing { protected Goo(String subject) { super(subject); } } private static class Sink { final List<String> subjects = new ArrayList<>(); CountDownLatch latch; protected void process(String subject) { subjects.add(subject); latch.countDown(); } } private static class PrickleSink extends Sink implements EventSink<Prickle> { @Override public void process(Prickle event) { process(event.subject()); } } private static class GooSink extends Sink implements EventSink<Goo> { @Override public void process(Goo event) { process(event.subject()); throw new IllegalStateException("BOOM!"); } } private static class TooLongEvent extends AbstractEvent<Type, String> { protected TooLongEvent(String subject) { super(Type.FOO, subject); } } private static class SinkProcessTakesTooLong implements EventSink<TooLongEvent> { boolean interrupted = false; CountDownLatch latch; public void process(TooLongEvent event) { try { Thread.sleep(5 * 1000); } catch (InterruptedException ie) { interrupted = true; } latch.countDown(); } } }