Ray Milkey
Committed by Gerrit Code Review

Unit tests for open flow controller message handling.

Change-Id: I9cffe4f4585eaf0df48d9fcb6a9f62ddcc0f9403
...@@ -107,7 +107,7 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -107,7 +107,7 @@ public class OpenFlowControllerImpl implements OpenFlowController {
107 label = "Number of controller worker threads; default is 16") 107 label = "Number of controller worker threads; default is 16")
108 private int workerThreads = DEFAULT_WORKER_THREADS; 108 private int workerThreads = DEFAULT_WORKER_THREADS;
109 109
110 - private final ExecutorService executorMsgs = 110 + protected ExecutorService executorMsgs =
111 Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d")); 111 Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d"));
112 112
113 private final ExecutorService executorBarrier = 113 private final ExecutorService executorBarrier =
...@@ -611,10 +611,10 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -611,10 +611,10 @@ public class OpenFlowControllerImpl implements OpenFlowController {
611 } 611 }
612 } 612 }
613 613
614 - private final class OFMessageHandler implements Runnable { 614 + protected final class OFMessageHandler implements Runnable {
615 615
616 - private final OFMessage msg; 616 + protected final OFMessage msg;
617 - private final Dpid dpid; 617 + protected final Dpid dpid;
618 618
619 public OFMessageHandler(Dpid dpid, OFMessage msg) { 619 public OFMessageHandler(Dpid dpid, OFMessage msg) {
620 this.msg = msg; 620 this.msg = msg;
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.openflow;
17 +
18 +import java.util.Collection;
19 +import java.util.List;
20 +import java.util.concurrent.Callable;
21 +import java.util.concurrent.ExecutionException;
22 +import java.util.concurrent.ExecutorService;
23 +import java.util.concurrent.Future;
24 +import java.util.concurrent.TimeUnit;
25 +import java.util.concurrent.TimeoutException;
26 +
27 +/**
28 + * Test harness adapter for the ExecutorService.
29 + */
30 +public class ExecutorServiceAdapter implements ExecutorService {
31 + @Override
32 + public void shutdown() {
33 +
34 + }
35 +
36 + @Override
37 + public List<Runnable> shutdownNow() {
38 + return null;
39 + }
40 +
41 + @Override
42 + public boolean isShutdown() {
43 + return false;
44 + }
45 +
46 + @Override
47 + public boolean isTerminated() {
48 + return false;
49 + }
50 +
51 + @Override
52 + public boolean awaitTermination(long timeout, TimeUnit unit)
53 + throws InterruptedException {
54 + return false;
55 + }
56 +
57 + @Override
58 + public <T> Future<T> submit(Callable<T> task) {
59 + return null;
60 + }
61 +
62 + @Override
63 + public <T> Future<T> submit(Runnable task, T result) {
64 + return null;
65 + }
66 +
67 + @Override
68 + public Future<?> submit(Runnable task) {
69 + return null;
70 + }
71 +
72 + @Override
73 + public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
74 + throws InterruptedException {
75 + return null;
76 + }
77 +
78 + @Override
79 + public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
80 + throws InterruptedException {
81 + return null;
82 + }
83 +
84 + @Override
85 + public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
86 + return null;
87 + }
88 +
89 + @Override
90 + public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
91 + throws InterruptedException, ExecutionException, TimeoutException {
92 + return null;
93 + }
94 +
95 + @Override
96 + public void execute(Runnable command) {
97 +
98 + }
99 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.openflow;
17 +
18 +import java.util.List;
19 +import java.util.Set;
20 +
21 +import org.projectfloodlight.openflow.protocol.OFActionType;
22 +import org.projectfloodlight.openflow.protocol.OFCapabilities;
23 +import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
24 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
25 +import org.projectfloodlight.openflow.protocol.OFType;
26 +import org.projectfloodlight.openflow.types.DatapathId;
27 +import org.projectfloodlight.openflow.types.OFAuxId;
28 +
29 +/**
30 + * Mock of the Open FLow features reply message.
31 + */
32 +public class MockOfFeaturesReply extends OfMessageAdapter implements OFFeaturesReply {
33 + public MockOfFeaturesReply() {
34 + super(OFType.FEATURES_REPLY);
35 + }
36 +
37 + @Override
38 + public DatapathId getDatapathId() {
39 + return null;
40 + }
41 +
42 + @Override
43 + public long getNBuffers() {
44 + return 0;
45 + }
46 +
47 + @Override
48 + public short getNTables() {
49 + return 0;
50 + }
51 +
52 + @Override
53 + public Set<OFCapabilities> getCapabilities() {
54 + return null;
55 + }
56 +
57 + @Override
58 + public long getReserved() {
59 + return 0;
60 + }
61 +
62 + @Override
63 + public List<OFPortDesc> getPorts() {
64 + return null;
65 + }
66 +
67 + @Override
68 + public Set<OFActionType> getActions() {
69 + return null;
70 + }
71 +
72 + @Override
73 + public OFAuxId getAuxiliaryId() {
74 + return null;
75 + }
76 +
77 + @Override
78 + public OFFeaturesReply.Builder createBuilder() {
79 + return null;
80 + }
81 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.openflow;
17 +
18 +import org.projectfloodlight.openflow.protocol.OFPacketIn;
19 +import org.projectfloodlight.openflow.protocol.OFPacketInReason;
20 +import org.projectfloodlight.openflow.protocol.OFType;
21 +import org.projectfloodlight.openflow.protocol.match.Match;
22 +import org.projectfloodlight.openflow.types.OFBufferId;
23 +import org.projectfloodlight.openflow.types.OFPort;
24 +import org.projectfloodlight.openflow.types.TableId;
25 +import org.projectfloodlight.openflow.types.U64;
26 +
27 +/**
28 + * Mock of the Open Flow packet in message.
29 + */
30 +public class MockOfPacketIn extends OfMessageAdapter implements OFPacketIn {
31 + public MockOfPacketIn() {
32 + super(OFType.PACKET_IN);
33 + }
34 +
35 + @Override
36 + public OFBufferId getBufferId() {
37 + return null;
38 + }
39 +
40 + @Override
41 + public int getTotalLen() {
42 + return 0;
43 + }
44 +
45 + @Override
46 + public OFPacketInReason getReason() {
47 + return null;
48 + }
49 +
50 + @Override
51 + public TableId getTableId() {
52 + return null;
53 + }
54 +
55 + @Override
56 + public Match getMatch() {
57 + return null;
58 + }
59 +
60 + @Override
61 + public byte[] getData() {
62 + return new byte[0];
63 + }
64 +
65 + @Override
66 + public OFPort getInPort() {
67 + return null;
68 + }
69 +
70 + @Override
71 + public OFPort getInPhyPort() {
72 + return null;
73 + }
74 +
75 + @Override
76 + public U64 getCookie() {
77 + return null;
78 + }
79 +
80 + @Override
81 + public OFPacketIn.Builder createBuilder() {
82 + return null;
83 + }
84 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.openflow;
17 +
18 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
19 +import org.projectfloodlight.openflow.protocol.OFPortReason;
20 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
21 +import org.projectfloodlight.openflow.protocol.OFType;
22 +
23 +/**
24 + * Mocked open flow port status message.
25 + */
26 +public class MockOfPortStatus extends OfMessageAdapter implements OFPortStatus {
27 + public MockOfPortStatus() {
28 + super(OFType.PORT_STATUS);
29 + }
30 +
31 + @Override
32 + public OFPortReason getReason() {
33 + return null;
34 + }
35 +
36 + @Override
37 + public OFPortDesc getDesc() {
38 + return null;
39 + }
40 +
41 + @Override
42 + public OFPortStatus.Builder createBuilder() {
43 + return null;
44 + }
45 +}
...@@ -26,13 +26,21 @@ import com.google.common.hash.PrimitiveSink; ...@@ -26,13 +26,21 @@ import com.google.common.hash.PrimitiveSink;
26 * Adapter for testing against an OpenFlow message. 26 * Adapter for testing against an OpenFlow message.
27 */ 27 */
28 public class OfMessageAdapter implements OFMessage { 28 public class OfMessageAdapter implements OFMessage {
29 - @Override 29 + OFType type;
30 - public OFVersion getVersion() { 30 +
31 - return null; 31 + private OfMessageAdapter() {}
32 +
33 + public OfMessageAdapter(OFType type) {
34 + this.type = type;
32 } 35 }
33 36
34 @Override 37 @Override
35 public OFType getType() { 38 public OFType getType() {
39 + return type;
40 + }
41 +
42 + @Override
43 + public OFVersion getVersion() {
36 return null; 44 return null;
37 } 45 }
38 46
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.openflow;
17 +
18 +import java.util.ArrayList;
19 +import java.util.HashMap;
20 +import java.util.List;
21 +import java.util.Map;
22 +
23 +import org.onosproject.openflow.controller.Dpid;
24 +import org.onosproject.openflow.controller.OpenFlowSwitchListener;
25 +import org.onosproject.openflow.controller.RoleState;
26 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
27 +
28 +/**
29 + * Test harness for a switch listener.
30 + */
31 +public class OpenFlowSwitchListenerAdapter implements OpenFlowSwitchListener {
32 + final List<Dpid> removedDpids = new ArrayList<>();
33 + final List<Dpid> addedDpids = new ArrayList<>();
34 + final List<Dpid> changedDpids = new ArrayList<>();
35 + final Map<Dpid, OFPortStatus> portChangedDpids = new HashMap<>();
36 +
37 + @Override
38 + public void switchAdded(Dpid dpid) {
39 + addedDpids.add(dpid);
40 + }
41 +
42 + @Override
43 + public void switchRemoved(Dpid dpid) {
44 + removedDpids.add(dpid);
45 + }
46 +
47 + @Override
48 + public void switchChanged(Dpid dpid) {
49 + changedDpids.add(dpid);
50 + }
51 +
52 + @Override
53 + public void portChanged(Dpid dpid, OFPortStatus status) {
54 + portChangedDpids.put(dpid, status);
55 + }
56 +
57 + @Override
58 + public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
59 + // Stub
60 + }
61 +
62 + public List<Dpid> removedDpids() {
63 + return removedDpids;
64 + }
65 +
66 + public List<Dpid> addedDpids() {
67 + return addedDpids;
68 + }
69 +
70 + public List<Dpid> changedDpids() {
71 + return changedDpids;
72 + }
73 +
74 + public Map<Dpid, OFPortStatus> portChangedDpids() {
75 + return portChangedDpids;
76 + }
77 +}
...@@ -22,6 +22,7 @@ import org.jboss.netty.buffer.ChannelBuffer; ...@@ -22,6 +22,7 @@ import org.jboss.netty.buffer.ChannelBuffer;
22 import org.junit.Test; 22 import org.junit.Test;
23 import org.onosproject.openflow.OfMessageAdapter; 23 import org.onosproject.openflow.OfMessageAdapter;
24 import org.projectfloodlight.openflow.protocol.OFMessage; 24 import org.projectfloodlight.openflow.protocol.OFMessage;
25 +import org.projectfloodlight.openflow.protocol.OFType;
25 26
26 import com.google.common.collect.ImmutableList; 27 import com.google.common.collect.ImmutableList;
27 28
...@@ -39,6 +40,7 @@ public class OFMessageEncoderTest { ...@@ -39,6 +40,7 @@ public class OFMessageEncoderTest {
39 final int id; 40 final int id;
40 41
41 MockOfMessage() { 42 MockOfMessage() {
43 + super(OFType.ERROR);
42 id = nextId++; 44 id = nextId++;
43 } 45 }
44 46
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.openflow.controller.impl;
17 +
18 +import java.net.URI;
19 +import java.net.URISyntaxException;
20 +import java.util.ArrayList;
21 +import java.util.List;
22 +import java.util.concurrent.Future;
23 +
24 +import org.junit.Before;
25 +import org.junit.Test;
26 +import org.onosproject.openflow.ExecutorServiceAdapter;
27 +import org.onosproject.openflow.MockOfFeaturesReply;
28 +import org.onosproject.openflow.MockOfPacketIn;
29 +import org.onosproject.openflow.MockOfPortStatus;
30 +import org.onosproject.openflow.OfMessageAdapter;
31 +import org.onosproject.openflow.OpenFlowSwitchListenerAdapter;
32 +import org.onosproject.openflow.OpenflowSwitchDriverAdapter;
33 +import org.onosproject.openflow.controller.Dpid;
34 +import org.onosproject.openflow.controller.OpenFlowPacketContext;
35 +import org.onosproject.openflow.controller.OpenFlowSwitch;
36 +import org.onosproject.openflow.controller.PacketListener;
37 +import org.projectfloodlight.openflow.protocol.OFMessage;
38 +import org.projectfloodlight.openflow.protocol.OFType;
39 +
40 +import static junit.framework.TestCase.fail;
41 +import static org.hamcrest.MatcherAssert.assertThat;
42 +import static org.hamcrest.Matchers.equalTo;
43 +import static org.hamcrest.Matchers.hasSize;
44 +import static org.hamcrest.Matchers.is;
45 +
46 +/**
47 + * Tests for packet processing in the open flow controller impl class.
48 + */
49 +public class OpenFlowControllerImplPacketsTest {
50 + OpenFlowControllerImpl controller;
51 + OpenFlowControllerImpl.OpenFlowSwitchAgent agent;
52 + Dpid dpid1;
53 + OpenFlowSwitch switch1;
54 + OpenFlowSwitchListenerAdapter switchListener;
55 + TestPacketListener packetListener;
56 + TestExecutorService executorService;
57 +
58 + /**
59 + * Mock packet listener that accumulates packets.
60 + */
61 + class TestPacketListener implements PacketListener {
62 + List<OpenFlowPacketContext> contexts = new ArrayList<>();
63 +
64 + @Override
65 + public void handlePacket(OpenFlowPacketContext pktCtx) {
66 + contexts.add(pktCtx);
67 + }
68 +
69 + List<OpenFlowPacketContext> contexts() {
70 + return contexts;
71 + }
72 + }
73 +
74 +
75 + /**
76 + * Mock executor service that tracks submits.
77 + */
78 + static class TestExecutorService extends ExecutorServiceAdapter {
79 + private List<OFMessage> submittedMessages = new ArrayList<>();
80 +
81 + List<OFMessage> submittedMessages() {
82 + return submittedMessages;
83 + }
84 +
85 + @Override
86 + public Future<?> submit(Runnable task) {
87 + OpenFlowControllerImpl.OFMessageHandler handler =
88 + (OpenFlowControllerImpl.OFMessageHandler) task;
89 + submittedMessages.add(handler.msg);
90 + return null;
91 + }
92 + }
93 +
94 + /**
95 + * Sets up switches to use as data, mocks and launches a controller instance.
96 + */
97 + @Before
98 + public void setUp() {
99 + try {
100 + switch1 = new OpenflowSwitchDriverAdapter();
101 + dpid1 = Dpid.dpid(new URI("of:0000000000000111"));
102 + } catch (URISyntaxException ex) {
103 + // Does not happen
104 + fail();
105 + }
106 +
107 + controller = new OpenFlowControllerImpl();
108 + agent = controller.agent;
109 + switchListener = new OpenFlowSwitchListenerAdapter();
110 + controller.addListener(switchListener);
111 +
112 + packetListener = new TestPacketListener();
113 + controller.addPacketListener(100, packetListener);
114 +
115 + executorService = new TestExecutorService();
116 + controller.executorMsgs = executorService;
117 + }
118 +
119 + /**
120 + * Tests a port status operation.
121 + */
122 + @Test
123 + public void testPortStatus() {
124 + OFMessage portStatusPacket = new MockOfPortStatus();
125 + controller.processPacket(dpid1, portStatusPacket);
126 + assertThat(switchListener.portChangedDpids().size(), is(1));
127 + assertThat(switchListener.portChangedDpids().containsKey(dpid1),
128 + is(true));
129 + assertThat(switchListener.portChangedDpids().get(dpid1),
130 + equalTo(portStatusPacket));
131 + }
132 +
133 + /**
134 + * Tests a features reply operation.
135 + */
136 + @Test
137 + public void testFeaturesReply() {
138 + OFMessage ofFeaturesReplyPacket = new MockOfFeaturesReply();
139 + controller.processPacket(dpid1, ofFeaturesReplyPacket);
140 + assertThat(switchListener.changedDpids(), hasSize(1));
141 + assertThat(switchListener.changedDpids().get(0),
142 + equalTo(dpid1));
143 + }
144 +
145 + /**
146 + * Tests a packet in operation.
147 + */
148 + @Test
149 + public void testPacketIn() {
150 + agent.addConnectedSwitch(dpid1, switch1);
151 + OFMessage packetInPacket = new MockOfPacketIn();
152 + controller.processPacket(dpid1, packetInPacket);
153 + assertThat(packetListener.contexts(), hasSize(1));
154 + }
155 +
156 + /**
157 + * Tests an error operation.
158 + */
159 + @Test
160 + public void testError() {
161 + agent.addConnectedSwitch(dpid1, switch1);
162 + OfMessageAdapter errorPacket = new OfMessageAdapter(OFType.ERROR);
163 + controller.processPacket(dpid1, errorPacket);
164 + assertThat(executorService.submittedMessages(), hasSize(1));
165 + assertThat(executorService.submittedMessages().get(0), is(errorPacket));
166 + }
167 +}