Added unit tests for the event abstractions.
Added Element as the notion of common ancestry between Device and Host.
Showing
19 changed files
with
366 additions
and
55 deletions
... | @@ -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 | +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 & NB APIs. |
23 | */ | 23 | */ |
24 | @Component(immediate = true) | 24 | @Component(immediate = true) |
25 | @Service | 25 | @Service | ... | ... |
-
Please register or login to post a comment