tom

Added unit tests for the event abstractions.

Added Element as the notion of common ancestry between Device and Host.
...@@ -51,8 +51,13 @@ public class AbstractListenerManager<E extends Event, L extends EventListener<E> ...@@ -51,8 +51,13 @@ public class AbstractListenerManager<E extends Event, L extends EventListener<E>
51 } 51 }
52 } 52 }
53 53
54 - @Override 54 + /**
55 - public void reportProblem(E event, Throwable error) { 55 + * Reports a problem encountered while processing an event.
56 + *
57 + * @param event event being processed
58 + * @param error error encountered while processing
59 + */
60 + protected void reportProblem(E event, Throwable error) {
56 log.warn("Exception encountered while processing event " + event, error); 61 log.warn("Exception encountered while processing event " + event, error);
57 } 62 }
58 63
......
...@@ -12,7 +12,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -12,7 +12,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
12 /** 12 /**
13 * Base implementation of event sink broker. 13 * Base implementation of event sink broker.
14 */ 14 */
15 -public class AbstractEventSinkBroker implements EventSinkBroker { 15 +public class DefaultEventSinkBroker implements EventSinkBroker {
16 16
17 private final Map<Class<? extends Event>, EventSink<? extends Event>> sinks = 17 private final Map<Class<? extends Event>, EventSink<? extends Event>> sinks =
18 new ConcurrentHashMap<>(); 18 new ConcurrentHashMap<>();
...@@ -36,6 +36,7 @@ public class AbstractEventSinkBroker implements EventSinkBroker { ...@@ -36,6 +36,7 @@ public class AbstractEventSinkBroker implements EventSinkBroker {
36 @Override 36 @Override
37 @SuppressWarnings("unchecked") 37 @SuppressWarnings("unchecked")
38 public <E extends Event> EventSink<E> getSink(Class<E> eventClass) { 38 public <E extends Event> EventSink<E> getSink(Class<E> eventClass) {
39 + // TODO: add implicit registration of descendant classes
39 return (EventSink<E>) sinks.get(eventClass); 40 return (EventSink<E>) sinks.get(eventClass);
40 } 41 }
41 42
......
...@@ -12,12 +12,4 @@ public interface EventSink<E extends Event> { ...@@ -12,12 +12,4 @@ public interface EventSink<E extends Event> {
12 */ 12 */
13 void process(E event); 13 void process(E event);
14 14
15 - /**
16 - * Reports a problem encountered while processing an event.
17 - *
18 - * @param event event being processed
19 - * @param error error encountered while processing
20 - */
21 - void reportProblem(E event, Throwable error);
22 -
23 } 15 }
......
1 package org.onlab.onos.net; 1 package org.onlab.onos.net;
2 2
3 -import org.onlab.onos.net.provider.Provided;
4 -
5 /** 3 /**
6 * Representation of a network infrastructure device. 4 * Representation of a network infrastructure device.
7 */ 5 */
8 -public interface Device extends Provided { 6 +public interface Device extends Element {
9 7
10 /** 8 /**
11 * Coarse classification of the type of the infrastructure device. 9 * Coarse classification of the type of the infrastructure device.
......
1 package org.onlab.onos.net; 1 package org.onlab.onos.net;
2 2
3 import java.net.URI; 3 import java.net.URI;
4 -import java.util.Objects;
5 -
6 -import static com.google.common.base.Objects.toStringHelper;
7 4
8 /** 5 /**
9 * Immutable representation of a device identity. 6 * Immutable representation of a device identity.
10 */ 7 */
11 -public class DeviceId { 8 +public class DeviceId extends ElementId {
12 -
13 - private final URI uri;
14 -
15 - public DeviceId(URI uri) {
16 - this.uri = uri;
17 - }
18 9
19 /** 10 /**
20 - * Returns the backing URI. 11 + * Creates a device id using the supplied URI.
21 * 12 *
22 - * @return backing device URI 13 + * @param uri backing device URI
23 */ 14 */
24 - public URI uri() { 15 + public DeviceId(URI uri) {
25 - return uri; 16 + super(uri);
26 - }
27 -
28 - @Override
29 - public int hashCode() {
30 - return Objects.hash(uri);
31 - }
32 -
33 - @Override
34 - public boolean equals(Object obj) {
35 - if (this == obj) {
36 - return true;
37 - }
38 - if (obj == null || getClass() != obj.getClass()) {
39 - return false;
40 - }
41 - final DeviceId other = (DeviceId) obj;
42 - return Objects.equals(this.uri, other.uri);
43 - }
44 - @Override
45 - public String toString() {
46 - return toStringHelper(this).add("uri", uri).toString();
47 } 17 }
48 18
49 } 19 }
......
1 +package org.onlab.onos.net;
2 +
3 +import org.onlab.onos.net.provider.Provided;
4 +
5 +/**
6 + * Base abstraction of a network element, i.e. an infrastructure device or an end-station host.
7 + */
8 +public interface Element extends Provided {
9 +
10 + /**
11 + * Returns the network element identifier.
12 + *
13 + * @return element identifier
14 + */
15 + ElementId id();
16 +
17 +}
1 +package org.onlab.onos.net;
2 +
3 +import java.net.URI;
4 +import java.util.Objects;
5 +
6 +import static com.google.common.base.Objects.toStringHelper;
7 +
8 +/**
9 + * Immutable representation of a network element identity.
10 + */
11 +public class ElementId {
12 +
13 + private final URI uri;
14 +
15 + /**
16 + * Creates an element identifier using the supplied URI.
17 + *
18 + * @param uri backing URI
19 + */
20 + public ElementId(URI uri) {
21 + this.uri = uri;
22 + }
23 +
24 + /**
25 + * Returns the backing URI.
26 + *
27 + * @return backing URI
28 + */
29 + public URI uri() {
30 + return uri;
31 + }
32 +
33 + @Override
34 + public int hashCode() {
35 + return Objects.hash(uri);
36 + }
37 +
38 + @Override
39 + public boolean equals(Object obj) {
40 + if (this == obj) {
41 + return true;
42 + }
43 + if (obj == null || getClass() != obj.getClass()) {
44 + return false;
45 + }
46 + final ElementId other = (ElementId) obj;
47 + return Objects.equals(this.uri, other.uri);
48 + }
49 +
50 + @Override
51 + public String toString() {
52 + return toStringHelper(this).add("uri", uri).toString();
53 + }
54 +
55 +}
1 package org.onlab.onos.net; 1 package org.onlab.onos.net;
2 2
3 -import org.onlab.onos.net.provider.Provided;
4 -
5 /** 3 /**
6 * Abstraction of an end-station host on the network, essentially a NIC. 4 * Abstraction of an end-station host on the network, essentially a NIC.
7 */ 5 */
8 -public interface Host extends Provided { 6 +public interface Host extends Element {
9 7
10 // MAC, IP(s), optional VLAN ID 8 // MAC, IP(s), optional VLAN ID
11 9
12 - // Location (current, recent locations? 10 +
11 + /**
12 + * Returns the most recent host location where the host attaches to the
13 + * network edge.
14 + *
15 + * @return host location
16 + */
17 + HostLocation location();
18 +
19 + // list of recent locations?
13 20
14 } 21 }
......
1 +package org.onlab.onos.net;
2 +
3 +/**
4 + * Representation of a network edge location where an end-station host is
5 + * connected.
6 + */
7 +public interface HostLocation extends ConnectPoint {
8 +
9 + /**
10 + * Returns the timestamp when the location was established, given in
11 + * milliseconds since start of epoch.
12 + *
13 + * @return timestamp in milliseconds since start of epoch
14 + */
15 + long timestamp();
16 +
17 +}
1 +package org.onlab.onos.net;
2 +
3 +/**
4 + * Abstraction of a network port.
5 + */
6 +public interface Port {
7 +
8 + // Notion of port state: enabled, disabled, blocked
9 +
10 + /**
11 + * Returns the port number.
12 + *
13 + * @return port number
14 + */
15 + PortNumber number();
16 +
17 + /**
18 + * Returns the identifier of the network element to which this port belongs.
19 + *
20 + * @return parent network element
21 + */
22 + Element parent();
23 +
24 + // set of port attributes
25 +
26 +}
...@@ -3,6 +3,10 @@ package org.onlab.onos.net.device; ...@@ -3,6 +3,10 @@ package org.onlab.onos.net.device;
3 import org.onlab.onos.net.Device; 3 import org.onlab.onos.net.Device;
4 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
5 import org.onlab.onos.net.MastershipRole; 5 import org.onlab.onos.net.MastershipRole;
6 +import org.onlab.onos.net.Port;
7 +import org.onlab.onos.net.PortNumber;
8 +
9 +import java.util.List;
6 10
7 /** 11 /**
8 * Service for interacting with the inventory of infrastructure devices. 12 * Service for interacting with the inventory of infrastructure devices.
...@@ -34,7 +38,21 @@ public interface DeviceService { ...@@ -34,7 +38,21 @@ public interface DeviceService {
34 Device getDevice(DeviceId deviceId); 38 Device getDevice(DeviceId deviceId);
35 39
36 40
37 -// List<Port> getPorts(DeviceId deviceId); 41 + /**
42 + * Returns the list of ports associated with the device.
43 + *
44 + * @param deviceId device identifier
45 + * @return list of ports
46 + */
47 + List<Port> getPorts(DeviceId deviceId);
48 +
49 + /**
50 + * Returns the port with the specified number and hosted by the given device.
51 + * @param deviceId device identifier
52 + * @param portNumber port number
53 + * @return device port
54 + */
55 + Port getPort(DeviceId deviceId, PortNumber portNumber);
38 56
39 /** 57 /**
40 * Adds the specified device listener. 58 * Adds the specified device listener.
...@@ -49,4 +67,5 @@ public interface DeviceService { ...@@ -49,4 +67,5 @@ public interface DeviceService {
49 * @param listener device listener 67 * @param listener device listener
50 */ 68 */
51 void removeListener(DeviceListener listener); 69 void removeListener(DeviceListener listener);
70 +
52 } 71 }
......
1 +package org.onlab.onos.event;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.junit.Assert.assertEquals;
6 +import static org.junit.Assert.assertTrue;
7 +import static org.onlab.onos.event.TestEvent.Type.FOO;
8 +
9 +/**
10 + * Tests of the base event abstraction.
11 + */
12 +public class AbstractEventTest {
13 +
14 + @Test
15 + public void withTime() {
16 + TestEvent event = new TestEvent(FOO, "foo", 123L);
17 + assertEquals("incorrect type", FOO, event.type());
18 + assertEquals("incorrect subject", "foo", event.subject());
19 + assertEquals("incorrect time", 123L, event.time());
20 + }
21 +
22 + @Test
23 + public void withoutTime() {
24 + long before = System.currentTimeMillis();
25 + TestEvent event = new TestEvent(FOO, "foo");
26 + long after = System.currentTimeMillis();
27 + assertEquals("incorrect type", FOO, event.type());
28 + assertEquals("incorrect subject", "foo", event.subject());
29 + assertTrue("incorrect time", before <= event.time() && event.time() <= after);
30 + }
31 +}
1 +package org.onlab.onos.event;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.junit.Assert.assertFalse;
6 +import static org.junit.Assert.assertTrue;
7 +
8 +/**
9 + * Tests of the base listener manager.
10 + */
11 +public class AbstractListenerManagerTest {
12 +
13 + @Test
14 + public void basics() {
15 + TestListener listener = new TestListener();
16 + TestListener secondListener = new TestListener();
17 + TestListenerManager manager = new TestListenerManager();
18 + manager.addListener(listener);
19 + manager.addListener(secondListener);
20 +
21 + TestEvent event = new TestEvent(TestEvent.Type.BAR, "bar");
22 + manager.process(event);
23 + assertTrue("event not processed", listener.events.contains(event));
24 + assertTrue("event not processed", secondListener.events.contains(event));
25 +
26 + manager.removeListener(listener);
27 +
28 + TestEvent another = new TestEvent(TestEvent.Type.FOO, "foo");
29 + manager.process(another);
30 + assertFalse("event processed", listener.events.contains(another));
31 + assertTrue("event not processed", secondListener.events.contains(event));
32 + }
33 +
34 + @Test
35 + public void badListener() {
36 + TestListener listener = new BrokenListener();
37 + TestListener secondListener = new TestListener();
38 + TestListenerManager manager = new TestListenerManager();
39 + manager.addListener(listener);
40 + manager.addListener(secondListener);
41 +
42 + TestEvent event = new TestEvent(TestEvent.Type.BAR, "bar");
43 + manager.process(event);
44 + assertFalse("event processed", listener.events.contains(event));
45 + assertFalse("error not reported", manager.errors.isEmpty());
46 + assertTrue("event not processed", secondListener.events.contains(event));
47 + }
48 +
49 +}
1 +package org.onlab.onos.event;
2 +
3 +/**
4 + * Test event listener fixture.
5 + */
6 +public class BrokenListener extends TestListener {
7 +
8 + public void event(TestEvent event) {
9 + throw new IllegalStateException("boom");
10 + }
11 +
12 +}
13 +
1 +package org.onlab.onos.event;
2 +
3 +import org.junit.Before;
4 +import org.junit.Test;
5 +
6 +import static org.junit.Assert.*;
7 +
8 +/**
9 + * Tests of the default event sink broker.
10 + */
11 +public class DefaultEventSinkBrokerTest {
12 +
13 + private DefaultEventSinkBroker broker;
14 +
15 + private static class FooEvent extends TestEvent {
16 + public FooEvent(String subject) { super(Type.FOO, subject); }
17 + }
18 +
19 + private static class BarEvent extends TestEvent {
20 + public BarEvent(String subject) { super(Type.BAR, subject); }
21 + }
22 +
23 + private static class FooSink implements EventSink<FooEvent> {
24 + @Override public void process(FooEvent event) {}
25 + }
26 +
27 + private static class BarSink implements EventSink<BarEvent> {
28 + @Override public void process(BarEvent event) {}
29 + }
30 +
31 + @Before
32 + public void setUp() {
33 + broker = new DefaultEventSinkBroker();
34 + }
35 +
36 + @Test
37 + public void basics() {
38 + FooSink fooSink = new FooSink();
39 + BarSink barSink = new BarSink();
40 + broker.addSink(FooEvent.class, fooSink);
41 + broker.addSink(BarEvent.class, barSink);
42 +
43 + assertEquals("incorrect sink count", 2, broker.getSinks().size());
44 + assertEquals("incorrect sink", fooSink, broker.getSink(FooEvent.class));
45 + assertEquals("incorrect sink", barSink, broker.getSink(BarEvent.class));
46 +
47 + broker.removeSink(FooEvent.class);
48 + assertNull("incorrect sink", broker.getSink(FooEvent.class));
49 + assertEquals("incorrect sink", barSink, broker.getSink(BarEvent.class));
50 +
51 + }
52 +}
1 +package org.onlab.onos.event;
2 +
3 +/**
4 + * Test event fixture.
5 + */
6 +public class TestEvent extends AbstractEvent<TestEvent.Type, String> {
7 +
8 + public enum Type { FOO, BAR };
9 +
10 + public TestEvent(Type type, String subject) {
11 + super(type, subject);
12 + }
13 +
14 + public TestEvent(Type type, String subject, long timestamp) {
15 + super(type, subject, timestamp);
16 + }
17 +
18 +}
19 +
1 +package org.onlab.onos.event;
2 +
3 +import java.util.ArrayList;
4 +import java.util.List;
5 +
6 +/**
7 + * Test event listener fixture.
8 + */
9 +public class TestListener implements EventListener<TestEvent> {
10 +
11 + public final List<TestEvent> events = new ArrayList<>();
12 +
13 + @Override
14 + public void event(TestEvent event) {
15 + events.add(event);
16 + }
17 +
18 +}
19 +
1 +package org.onlab.onos.event;
2 +
3 +import java.util.ArrayList;
4 +import java.util.List;
5 +
6 +/**
7 + * Test event listener manager fixture.
8 + */
9 +public class TestListenerManager
10 + extends AbstractListenerManager<TestEvent, TestListener> {
11 +
12 + public final List<Throwable> errors = new ArrayList<>();
13 +
14 + @Override
15 + protected void reportProblem(TestEvent event, Throwable error) {
16 + super.reportProblem(event, error);
17 + errors.add(error);
18 + }
19 +
20 +}
21 +
...@@ -19,7 +19,7 @@ import org.slf4j.LoggerFactory; ...@@ -19,7 +19,7 @@ import org.slf4j.LoggerFactory;
19 import java.util.List; 19 import java.util.List;
20 20
21 /** 21 /**
22 - * Provides basic implementation of the device SB & NB APIs. 22 + * Provides basic implementation of the device SB &amp; NB APIs.
23 */ 23 */
24 @Component(immediate = true) 24 @Component(immediate = true)
25 @Service 25 @Service
......