blob: 8034d4468a00ffac2b7cf3d6db4194972ff2658f [file] [log] [blame]
HIGUCHI Yuta08137932013-06-17 14:11:50 -07001package net.onrc.onos.ofcontroller.core.internal;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -08002
Naoki Shiotab2d17e82013-10-18 18:08:16 -07003import static org.junit.Assert.*;
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -08004
mininet403d5892013-06-05 03:48:17 -07005import java.util.ArrayList;
Naoki Shiota5f9197a2013-06-20 17:36:29 -07006import java.util.HashMap;
Jonathan Hartc86a2ea2013-01-15 22:39:42 -08007import java.util.List;
Naoki Shiota5f9197a2013-06-20 17:36:29 -07008import java.util.Map;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -08009
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080010import net.floodlightcontroller.routing.Link;
Pankaj Berde38646d62013-06-21 11:34:04 -070011import net.onrc.onos.graph.GraphDBConnection;
12import net.onrc.onos.graph.GraphDBOperation;
HIGUCHI Yuta2d011582013-06-15 01:47:11 -070013import net.onrc.onos.ofcontroller.core.ILinkStorage;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070014import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
Naoki Shiota5f9197a2013-06-20 17:36:29 -070015import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
16import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
17import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080018
Naoki Shiota5f9197a2013-06-20 17:36:29 -070019import org.easymock.*;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080020import org.junit.After;
21import org.junit.Before;
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080022import org.junit.Ignore;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080023import org.junit.Test;
mininet37dc5892013-06-04 10:58:44 -070024import org.junit.runner.RunWith;
Naoki Shiotacae568a2013-06-05 17:53:41 -070025import org.openflow.protocol.OFPhysicalPort;
mininet403d5892013-06-05 03:48:17 -070026import org.openflow.util.HexString;
mininet37dc5892013-06-04 10:58:44 -070027import org.powermock.api.easymock.PowerMock;
28import org.powermock.core.classloader.annotations.PrepareForTest;
29import org.powermock.modules.junit4.PowerMockRunner;
Naoki Shiotac88d9562013-06-18 15:21:56 -070030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080032
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070033/**
34 * Unit test for {@link LinkStorageImpl}.
35 * @author Naoki Shiota
36 *
37 */
mininet37dc5892013-06-04 10:58:44 -070038@RunWith(PowerMockRunner.class)
Naoki Shiotac88d9562013-06-18 15:21:56 -070039@PrepareForTest({LinkStorageImpl.class, GraphDBConnection.class, GraphDBOperation.class})
Naoki Shiota991093a2013-12-10 14:47:18 -080040@SuppressWarnings("serial")
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080041public class LinkStorageImplTest {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070042 protected final static Logger log = LoggerFactory.getLogger(LinkStorageImplTest.class);
Naoki Shiotac88d9562013-06-18 15:21:56 -070043
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080044 private static ILinkStorage linkStorage;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080045
Naoki Shiotac88d9562013-06-18 15:21:56 -070046 // Mock GraphDBConnection (do nothing)
47 private static GraphDBConnection conn;
48
49 // Mock GraphDBOperation (mocks port-related methods only)
Naoki Shiota5f9197a2013-06-20 17:36:29 -070050 private static GraphDBOperation ope;
51
52 // Uncommitted actions executed in LinkStorageImpl
53 private static ArrayList<LinkEvent> actions;
54
55 // Dictionary of mock IPortObject to information of port
56 // -> Used to refer DPID from IPortObject
57 private static Map<IPortObject,PortInfo> mockToPortInfoMap;
58
59
60 // Links existing in virtual graph
61 private List<Link> links;
62
63 //================ Utility classes for logging actions in LinkStorageImpl ===========
64 private enum LinkEventType {
65 ADD, DELETE
66 }
67
68 private class LinkEvent {
69 private Long src_dpid = null;
70 private Long dst_dpid = null;
71 private Short src_port = null;
72 private Short dst_port = null;
73
74 public LinkEventType type;
75
76 public LinkEvent(Link link, LinkEventType type) {
77 this.src_dpid = link.getSrc();
78 this.src_port = link.getSrcPort();
79 this.dst_dpid = link.getDst();
80 this.dst_port = link.getDstPort();
81
82 this.type = type;
83 }
84
85 public Long getSrcDpid() { return src_dpid; }
86 public Short getSrcPort() { return src_port; }
87 public Long getDstDpid() { return dst_dpid; }
88 public Short getDstPort() { return dst_port; }
89 public LinkEventType getType() { return type; }
90 }
91
92 private class PortInfo {
93 public Long dpid = null;
94 public Short port = null;
95
96 public PortInfo(Long dpid, Short port) { this.dpid = dpid; this.port = port; }
97 }
mininet37dc5892013-06-04 10:58:44 -070098
mininet9d203de2013-06-05 08:40:45 -070099 /**
100 * Setup code called before each tests.
101 * Read test graph data and replace DB access by test graph data.
102 * @throws Exception
103 */
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800104 @Before
Jonathan Hart627f10c2013-01-16 14:20:03 -0800105 public void setUp() throws Exception{
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700106 // Create mock GraphDBConnection (replace Singleton object to mock one)
Naoki Shiotac88d9562013-06-18 15:21:56 -0700107 PowerMock.mockStatic(GraphDBConnection.class);
108 PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700109 conn = PowerMock.createMock(GraphDBConnection.class);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700110 EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(conn).anyTimes();
111 PowerMock.replay(GraphDBConnection.class);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800112
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700113 // Create mock GraphDBOperation
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700114 ope = createMockGraphDBOperation();
115 PowerMock.expectNew(GraphDBOperation.class, new Class<?>[] {GraphDBConnection.class}, EasyMock.anyObject(GraphDBConnection.class)).andReturn(ope).anyTimes();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700116 PowerMock.replay(GraphDBOperation.class);
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700117
118 actions = new ArrayList<LinkEvent>();
119 mockToPortInfoMap = new HashMap<IPortObject,PortInfo>();
120
mininet403d5892013-06-05 03:48:17 -0700121 linkStorage = new LinkStorageImpl();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700122 linkStorage.init("/dummy/path/to/conf");
mininet403d5892013-06-05 03:48:17 -0700123
Naoki Shiotac88d9562013-06-18 15:21:56 -0700124 initLinks();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800125 }
126
mininet9d203de2013-06-05 08:40:45 -0700127 /**
128 * Closing code called after each tests.
mininet9d203de2013-06-05 08:40:45 -0700129 * @throws Exception
130 */
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800131 @After
mininet403d5892013-06-05 03:48:17 -0700132 public void tearDown() throws Exception {
mininet403d5892013-06-05 03:48:17 -0700133 linkStorage.close();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800134 }
135
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700136
137 /**
138 * Test if {@link LinkStorageImpl#addLink(Link)} can correctly creates a Link.
139 */
140 @Test
141 public void testAddLink() {
142 Link linkToCreate = createFeasibleLink();
143 Link linkToVerify = createFeasibleLink();
144
145 //Use the link storage API to add the link
146 linkStorage.addLink(linkToCreate);
147 doTestLinkExist(linkToVerify);
148 }
149
150 /**
151 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly creates multiple Links.
152 */
153 @Test
154 public void testAddLinks() {
155 List<Link> linksToCreate = createFeasibleLinks();
156 List<Link> linksToVerify = createFeasibleLinks();
157
158 // Test creation of new links
159 linkStorage.addLinks(linksToCreate);
160 for(Link l : linksToVerify) {
161 doTestLinkExist(l);
162 }
163 }
164
Naoki Shiotacae568a2013-06-05 17:53:41 -0700165 // TODO: remove @Ignore after UPDATE method is implemented
Naoki Shiota1b972862013-06-05 19:49:09 -0700166 /**
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700167 * Test if {@link LinkStorageImpl#updateLinkInfo(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700168 */
mininet403d5892013-06-05 03:48:17 -0700169 @Ignore @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700170 public void testUpdate_Update() {
mininet403d5892013-06-05 03:48:17 -0700171 Link linkToUpdate= createExistingLink();
Naoki Shiotacae568a2013-06-05 17:53:41 -0700172 long currentTime = System.currentTimeMillis();
173 LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
174 LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
mininet403d5892013-06-05 03:48:17 -0700175
176 linkStorage.update(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
177
Naoki Shiotacae568a2013-06-05 17:53:41 -0700178 doTestLinkHasStateOf(linkToUpdate, infoToVerify);
mininet403d5892013-06-05 03:48:17 -0700179 }
180
Naoki Shiota1b972862013-06-05 19:49:09 -0700181 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700182 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly creates a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700183 */
mininet403d5892013-06-05 03:48:17 -0700184 @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700185 public void testUpdate_Create() {
mininet403d5892013-06-05 03:48:17 -0700186 Link linkToCreate = createFeasibleLink();
187 Link linkToVerify = createFeasibleLink();
188
189 //Use the link storage API to add the link
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700190 linkStorage.update(linkToCreate, null, ILinkStorage.DM_OPERATION.CREATE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700191 doTestLinkExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700192 }
193
Naoki Shiota1b972862013-06-05 19:49:09 -0700194 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700195 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)}can correctly inserts a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700196 */
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800197 @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700198 public void testUpdate_Insert(){
mininet403d5892013-06-05 03:48:17 -0700199 Link linkToInsert = createFeasibleLink();
200 Link linkToVerify = createFeasibleLink();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800201
202 //Use the link storage API to add the link
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700203 linkStorage.update(linkToInsert, null, ILinkStorage.DM_OPERATION.INSERT);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700204 doTestLinkExist(linkToVerify);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800205 }
206
Naoki Shiota1b972862013-06-05 19:49:09 -0700207 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700208 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly deletes a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700209 */
mininet403d5892013-06-05 03:48:17 -0700210 @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700211 public void testUpdate_Delete(){
mininet403d5892013-06-05 03:48:17 -0700212 Link linkToDelete = createExistingLink();
213 Link linkToVerify = createExistingLink();
214
215 // Test deletion of existing link
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700216 linkStorage.update(linkToDelete, null, DM_OPERATION.DELETE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700217 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700218 }
Naoki Shiota1b972862013-06-05 19:49:09 -0700219
220 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700221 * Test if {@link LinkStorageImpl#getLinks(Long, short)} can correctly return Links connected to specific DPID and port.
Naoki Shiota1b972862013-06-05 19:49:09 -0700222 */
mininet9d203de2013-06-05 08:40:45 -0700223 @Test
224 public void testGetLinks_ByDpidPort(){
225 Link linkToVerify = createExistingLink();
226 Long dpid = linkToVerify.getSrc();
227 short port = (short)linkToVerify.getSrcPort();
228
229 List<Link> list = linkStorage.getLinks(dpid, port);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800230
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700231 assertEquals(1, list.size());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800232
233 Link l = list.get(0);
mininet403d5892013-06-05 03:48:17 -0700234 assertEquals(l.getSrc(), linkToVerify.getSrc());
235 assertEquals(l.getSrcPort(), linkToVerify.getSrcPort());
236 assertEquals(l.getDst(), linkToVerify.getDst());
237 assertEquals(l.getDstPort(), linkToVerify.getDstPort());
238
239 Link linkToVerifyNot = createFeasibleLink();
240
241 List<Link> list2 = linkStorage.getLinks(linkToVerifyNot.getSrc(), (short)linkToVerifyNot.getSrcPort());
242
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700243 assertEquals(0, list2.size());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800244 }
245
Naoki Shiota1b972862013-06-05 19:49:09 -0700246 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700247 * Test if {@link LinkStorageImpl#getLinks(String)} can correctly return Links connected to specific MAC address.
Naoki Shiota1b972862013-06-05 19:49:09 -0700248 */
mininet403d5892013-06-05 03:48:17 -0700249 @Test
mininet9d203de2013-06-05 08:40:45 -0700250 public void testGetLinks_ByString() {
mininet403d5892013-06-05 03:48:17 -0700251 Link linkToVeryfy = createExistingLink();
mininet9d203de2013-06-05 08:40:45 -0700252 String dpid = HexString.toHexString(linkToVeryfy.getSrc());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800253
mininet9d203de2013-06-05 08:40:45 -0700254 List<Link> links = linkStorage.getLinks(dpid);
mininet403d5892013-06-05 03:48:17 -0700255 assertTrue(links.contains(linkToVeryfy));
256
257 Link linkToVerifyNot = createFeasibleLink();
258 assertFalse(links.contains(linkToVerifyNot));
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800259 }
Pavlin Radoslavov613eedc2013-11-02 16:08:25 -0700260
261 /**
262 * Test if {@link LinkStorageImpl#getReverseLinks(String)} can correctly return Links connected to specific MAC address.
263 */
264 @Test
265 public void testGetReverseLinks_ByString() {
266 Link linkToVeryfy = createExistingLink();
267 String dpid = HexString.toHexString(linkToVeryfy.getDst());
268
269 List<Link> links = linkStorage.getReverseLinks(dpid);
270 assertTrue(links.contains(linkToVeryfy));
271
272 Link linkToVerifyNot = createFeasibleLink();
273 assertFalse(links.contains(linkToVerifyNot));
274 }
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800275
Naoki Shiota1b972862013-06-05 19:49:09 -0700276 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700277 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700278 */
mininet403d5892013-06-05 03:48:17 -0700279 @Test
280 public void testDeleteLink() {
281 // Deletion of existing link
282 Link linkToDelete = createExistingLink();
283 Link linkToVerify = createExistingLink();
284
285 linkStorage.deleteLink(linkToDelete);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700286 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700287 }
288
Naoki Shiota1b972862013-06-05 19:49:09 -0700289 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700290 * Test if {@link LinkStorageImpl#deleteLinks(List)} can correctly delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700291 */
mininet403d5892013-06-05 03:48:17 -0700292 @Test
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800293 public void testDeleteLinks(){
mininet403d5892013-06-05 03:48:17 -0700294 List<Link> linksToDelete = createExistingLinks();
295 List<Link> linksToVerify = createExistingLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800296
mininet403d5892013-06-05 03:48:17 -0700297 linkStorage.deleteLinks(linksToDelete);
298 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700299 doTestLinkNotExist(l);
mininet403d5892013-06-05 03:48:17 -0700300 }
301 }
mininet9d203de2013-06-05 08:40:45 -0700302
Naoki Shiota1b972862013-06-05 19:49:09 -0700303 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700304 * Test if {@link LinkStorageImpl#getActiveLinks()} can correctly return active Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700305 */
mininet9d203de2013-06-05 08:40:45 -0700306 @Test
mininet403d5892013-06-05 03:48:17 -0700307 public void testGetActiveLinks() {
308 Link existingLink = createExistingLink();
309 Link notExistingLink = createFeasibleLink();
310
311 List<Link> links = linkStorage.getActiveLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800312
mininet403d5892013-06-05 03:48:17 -0700313 assertTrue(links.contains(existingLink));
314 assertFalse(links.contains(notExistingLink));
315 }
316
Naoki Shiota1b972862013-06-05 19:49:09 -0700317 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700318 * Test if {@link LinkStorageImpl#deleteLinksOnPort(Long, short)} can delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700319 */
mininet403d5892013-06-05 03:48:17 -0700320 @Test
321 public void testDeleteLinksOnPort() {
322 Link linkToDelete = createExistingLink();
323 Link linkToVerify = createExistingLink();
324
325 linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
326
Naoki Shiotac88d9562013-06-18 15:21:56 -0700327 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700328 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700329
330 /**
331 * Test if {@link LinkStorageImpl#getLinkInfo(Link)} can delete Links.
332 */
333 @Ignore @Test
334 public void testGetLinkInfo() {
335 fail("not yet implemented");
336 }
mininet9d203de2013-06-05 08:40:45 -0700337
mininet403d5892013-06-05 03:48:17 -0700338 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700339 * Test if specific link exists
mininet9d203de2013-06-05 08:40:45 -0700340 * @param link
mininet403d5892013-06-05 03:48:17 -0700341 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700342 private void doTestLinkExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700343 int count = 0;
344 for(Link lt : links) {
345 if(lt.equals(link)) {
346 ++count;
347 }
348 }
349
350 assertTrue(count == 1);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800351 }
352
mininet403d5892013-06-05 03:48:17 -0700353 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700354 * Test if specific link doesn't exist
mininet403d5892013-06-05 03:48:17 -0700355 * @param link
356 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700357 private void doTestLinkNotExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700358 assertFalse(links.contains(link));
mininet403d5892013-06-05 03:48:17 -0700359 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700360
361 /**
362 * Test if titanGraph has specific Link with specific LinkInfo
363 * @param link
364 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700365 // TODO: Fix me
Naoki Shiotacae568a2013-06-05 17:53:41 -0700366 private void doTestLinkHasStateOf(Link link, LinkInfo info) {
Naoki Shiotacae568a2013-06-05 17:53:41 -0700367 }
Naoki Shiotac88d9562013-06-18 15:21:56 -0700368
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700369 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700370 * Class defines a function called back when {@link IPortObject#removeLink(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700371 * @author Naoki Shiota
372 *
373 */
374 private class RemoveLinkCallback implements IAnswer<Object> {
375 private long dpid;
376 private short port;
377 public RemoveLinkCallback(long dpid, short port) {
378 this.dpid = dpid; this.port = port;
379 }
380
381 @Override
382 public Object answer() throws Throwable {
383 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
384 PortInfo dst = mockToPortInfoMap.get(dstPort);
385
386 Link linkToRemove = new Link(this.dpid,this.port,dst.dpid,dst.port);
387 actions.add(new LinkEvent(linkToRemove,LinkEventType.DELETE));
388
389 return null;
390 }
391 }
392
393 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700394 * Class defines a function called back when {@link IPortObject#setLinkPort(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700395 * @author Naoki Shiota
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700396 */
397 private class SetLinkPortCallback implements IAnswer<Object> {
398 private long dpid;
399 private short port;
400 public SetLinkPortCallback(long dpid, short port) {
401 this.dpid = dpid; this.port = port;
402 }
403
404 @Override
405 public Object answer() throws Throwable {
406 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
407 PortInfo dst = mockToPortInfoMap.get(dstPort);
408
409 Link linkToAdd = new Link(this.dpid,this.port,dst.dpid,dst.port);
410 actions.add(new LinkEvent(linkToAdd,LinkEventType.ADD));
411
412 return null;
413 }
414
415 }
416
417 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700418 * Class defines a function called back when {@link IPortObject#getSwitch()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700419 * @author Naoki Shiota
420 *
421 */
422 private class GetSwitchCallback implements IAnswer<ISwitchObject> {
423 private long dpid;
424
425 public GetSwitchCallback(long dpid) {
426 this.dpid = dpid;
427 }
428
429 @Override
430 public ISwitchObject answer() throws Throwable {
431 ISwitchObject sw = createMockSwitch(dpid);
432 return sw;
433 }
434 }
435
436 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700437 * Class defines a function called back when {@link IPortObject#getLinkedPorts()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700438 * @author Naoki Shiota
439 *
440 */
441 private class GetLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
442 private long dpid;
443 private short port;
444
445 public GetLinkedPortsCallback(long dpid, short port) {
446 this.dpid = dpid;
447 this.port = port;
448 }
449
450 @Override
451 public Iterable<IPortObject> answer() throws Throwable {
452 List<IPortObject> ports = new ArrayList<IPortObject>();
453
454 for(Link lk : links) {
455 if(lk.getSrc() == dpid && lk.getSrcPort() == port) {
456 ports.add(createMockPort(lk.getDst(), lk.getDstPort()));
457 }
458 }
459
460 return ports;
461 }
462
463 }
464
465 /**
Pavlin Radoslavov613eedc2013-11-02 16:08:25 -0700466 * Class defines a function called back when {@link IPortObject#getReverseLinkedPorts()} is called.
467 * @author Naoki Shiota
468 *
469 */
470 private class GetReverseLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
471 private long dpid;
472 private short port;
473
474 public GetReverseLinkedPortsCallback(long dpid, short port) {
475 this.dpid = dpid;
476 this.port = port;
477 }
478
479 @Override
480 public Iterable<IPortObject> answer() throws Throwable {
481 List<IPortObject> ports = new ArrayList<IPortObject>();
482
483 for(Link lk : links) {
484 if(lk.getDst() == dpid && lk.getDstPort() == port) {
485 ports.add(createMockPort(lk.getSrc(), lk.getSrcPort()));
486 }
487 }
488
489 return ports;
490 }
491
492 }
493
494 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700495 * Class defines a function called back when {@link LinkStorageImplTest} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700496 * @author Naoki Shiota
497 *
498 */
499 private class GetPortsCallback implements IAnswer< Iterable <IPortObject> > {
500 private long dpid;
501
502 public GetPortsCallback(long dpid) {
503 this.dpid = dpid;
504 }
505
506 @Override
507 public Iterable<IPortObject> answer() throws Throwable {
508 List<IPortObject> ports = new ArrayList<IPortObject>();
509
510 for(Short number : getPorts(dpid)) {
511 ports.add(createMockPort(dpid, number));
512 }
513
514 return ports;
515 }
516 }
517
518 // ------------------------Creation of Mock-----------------------------
519 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700520 * Create a mock {@link GraphDBOperation} which hooks port-related methods.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700521 * @return EasyMock-wrapped GraphDBOperation object.
522 */
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700523 private GraphDBOperation createMockGraphDBOperation() {
524 GraphDBOperation mockDBOpe = EasyMock.createNiceMock(GraphDBOperation.class);
525
526 // Mock searchPort() method to create new mock IPortObject.
527 EasyMock.expect(mockDBOpe.searchPort((String)EasyMock.anyObject(), EasyMock.anyShort())).
528 andAnswer(new IAnswer<IPortObject>() {
529 @Override
530 public IPortObject answer() throws Throwable {
531 long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
532 short port = (Short) EasyMock.getCurrentArguments()[1];
533 IPortObject ret = createMockPort(dpid,port);
534
535 return ret;
536 }
537 }).anyTimes();
538
539 // Mock searchSwitch() method to create new mock ISwitchObject.
540 EasyMock.expect(mockDBOpe.searchSwitch((String)EasyMock.anyObject())).
541 andAnswer(new IAnswer<ISwitchObject>() {
542 @Override
543 public ISwitchObject answer() throws Throwable {
544 long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
545 ISwitchObject ret = createMockSwitch(dpid);
546
547 return ret;
548 }
549 }).anyTimes();
550
551 // Mock getActiveSwitches() method to create list of mock ISwitchObject.
552 EasyMock.expect(mockDBOpe.getActiveSwitches()).andReturn(new ArrayList<ISwitchObject> () {{
553 for(Long dpid : getDpids()) {
554 add(createMockSwitch(dpid));
555 }
556 }}).anyTimes();
557
558 // Mock commit() method to commit change of link information
559 mockDBOpe.commit();
560 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
561 @Override
562 public Object answer() throws Throwable {
563 for(LinkEvent action : actions) {
564 if(action.getType().equals(LinkEventType.ADD)) {
565 Link linkToAdd = new Link(
566 action.getSrcDpid(),
567 action.getSrcPort(),
568 action.getDstDpid(),
569 action.getDstPort());
570 links.add(linkToAdd);
571 } else if(action.getType().equals(LinkEventType.DELETE)) {
572 Link linkToRemove = new Link(
573 action.getSrcDpid(),
574 action.getSrcPort(),
575 action.getDstDpid(),
576 action.getDstPort());
577 links.remove(linkToRemove);
578 } else {
579 log.error("mock commit(): unexpected action {}", new Object[]{action.getType()});
580 }
581 }
582 actions.clear();
583 return null;
584 }
585 }).atLeastOnce();
586
587 EasyMock.replay(mockDBOpe);
588 return mockDBOpe;
589 }
590
591 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700592 * Create a mock {@link IPortObject} using given DPID and port number.
593 * {@link IPortObject} can't store DPID, so DPID is stored to mockToPortInfoMap for later use.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700594 * Duplication is not checked.
595 * @param dpid DPID of a port
596 * @param number Port Number
597 * @return EasyMock-wrapped IPortObject
598 */
599 private IPortObject createMockPort(long dpid, short number) {
600 IPortObject mockPort = EasyMock.createNiceMock(IPortObject.class);
601
602 EasyMock.expect(mockPort.getNumber()).andReturn(number);
603
604 // Mock removeLink() method
605 mockPort.removeLink((IPortObject) EasyMock.anyObject());
606 EasyMock.expectLastCall().andAnswer(new RemoveLinkCallback(dpid, number)).anyTimes();
607
608 // Mock setLinkPort() method
609 mockPort.setLinkPort((IPortObject) EasyMock.anyObject());
610 EasyMock.expectLastCall().andAnswer(new SetLinkPortCallback(dpid, number)).anyTimes();
611
612 // Mock getLinkPorts() method
613 EasyMock.expect(mockPort.getLinkedPorts()).andAnswer(new GetLinkedPortsCallback(dpid, number)).anyTimes();
Pavlin Radoslavov613eedc2013-11-02 16:08:25 -0700614
615 // Mock getReverseLinkPorts() method
616 EasyMock.expect(mockPort.getReverseLinkedPorts()).andAnswer(new GetReverseLinkedPortsCallback(dpid, number)).anyTimes();
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700617
618 // Mock getSwitch() method
619 EasyMock.expect(mockPort.getSwitch()).andAnswer(new GetSwitchCallback(dpid)).anyTimes();
620
621 mockToPortInfoMap.put(mockPort, new PortInfo(dpid,number));
622 EasyMock.replay(mockPort);
623
624 return mockPort;
625 }
626
627 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700628 * Create a mock {@link ISwitchObject} using given DPID number.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700629 * Duplication is not checked.
630 * @param dpid DPID of a switch
631 * @return EasyMock-wrapped ISwitchObject
632 */
633 private ISwitchObject createMockSwitch(long dpid) {
634 ISwitchObject mockSw = EasyMock.createNiceMock(ISwitchObject.class);
635
636 EasyMock.expect(mockSw.getPorts()).andAnswer(new GetPortsCallback(dpid)).anyTimes();
637 EasyMock.expect(mockSw.getDPID()).andReturn(HexString.toHexString(dpid)).anyTimes();
638 EasyMock.expect(mockSw.getState()).andReturn("ACTIVE").anyTimes();
639
640 EasyMock.replay(mockSw);
641 return mockSw;
642 }
643
644
mininet403d5892013-06-05 03:48:17 -0700645 //----------------- Creation of test data -----------------------
Naoki Shiotac88d9562013-06-18 15:21:56 -0700646 // Assume a network shown below.
647 //
648 // [dpid1]--+--[port:1]----[port:1]--+--[dpid2]
649 // | |
650 // +--[port:2] [port:2]--+
651 // |
652 // +--[port:3] [port:1]--+--[dpid3]
653 // | |
654 // +--[port:4]----[port:2]--+
655 //
656 // dpid1 : 00:00:00:00:0a:01
657 // dpid2 : 00:00:00:00:0a:02
658 // dpid3 : 00:00:00:00:0a:03
659
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700660 /**
661 * Initialize links member to represent test topology above.
662 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700663 private void initLinks() {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700664 links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700665
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700666 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
667 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700668 }
669
mininet9d203de2013-06-05 08:40:45 -0700670 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700671 * Returns list of port number attached to the switch specified by given DPID.
672 * @param dpid DPID of the switch
673 * @return List of port number
674 */
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700675 private List<Short> getPorts(long dpid) {
676 List<Short> ports;
677
678 if(dpid == Long.decode("0x0000000000000a01")) {
679 ports = new ArrayList<Short>() {{
680 add((short)1);
681 add((short)2);
682 add((short)3);
683 add((short)4);
684 }};
685 } else if(dpid == Long.decode("0x0000000000000a02") || dpid == Long.decode("0x0000000000000a03")) {
686 ports = new ArrayList<Short>() {{
687 add((short)1);
688 add((short)2);
689 }};
690 } else {
691 ports = new ArrayList<Short>();
692 }
693
694 return ports;
695 }
696
697 /**
698 * Returns list of DPIDs in test topology.
699 * @return List of DPIDs
700 */
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700701 private List<Long> getDpids() {
702 List<Long> dpids = new ArrayList<Long>() {{
703 add(Long.decode("0x0000000000000a01"));
704 add(Long.decode("0x0000000000000a02"));
705 add(Long.decode("0x0000000000000a03"));
706 }};
707
708 return dpids;
709 }
710
711 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700712 * Returns new {@link Link} object of an existing link
Naoki Shiotac88d9562013-06-18 15:21:56 -0700713 * @return new Link object
714 */
715 private Link createExistingLink() {
716 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
717 }
718
719 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700720 * Returns new {@link Link} object of a not-existing but feasible link
mininet9d203de2013-06-05 08:40:45 -0700721 * @return new Link object
722 */
mininet403d5892013-06-05 03:48:17 -0700723 private Link createFeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700724 return new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1);
mininet403d5892013-06-05 03:48:17 -0700725 }
726
mininet9d203de2013-06-05 08:40:45 -0700727 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700728 * Returns list of existing {@link Link} objects
mininet9d203de2013-06-05 08:40:45 -0700729 * @return ArrayList of new Link objects
730 */
mininet403d5892013-06-05 03:48:17 -0700731 private List<Link> createExistingLinks() {
732 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700733 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
734 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700735 return links;
736 }
737
mininet9d203de2013-06-05 08:40:45 -0700738 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700739 * Returns list of {@link Link} objects that are all not-existing but feasible
mininet9d203de2013-06-05 08:40:45 -0700740 * @return ArrayList of new Link objects
741 */
mininet403d5892013-06-05 03:48:17 -0700742 private List<Link> createFeasibleLinks() {
743 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700744 links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a02"), 2));
745 links.add(new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1));
mininet403d5892013-06-05 03:48:17 -0700746 return links;
747 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700748
749 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700750 * Returns new {@link LinkInfo} object with convenient values.
Naoki Shiotacae568a2013-06-05 17:53:41 -0700751 * @return LinkInfo object
752 */
753 private LinkInfo createFeasibleLinkInfo(long time) {
754 long time_first = time;
755 long time_last_lldp = time + 50;
756 long time_last_bddp = time + 100;
757 int state_src = OFPhysicalPort.OFPortState.OFPPS_STP_FORWARD.getValue();
758 int state_dst = OFPhysicalPort.OFPortState.OFPPS_STP_LISTEN.getValue();
759
760 return new LinkInfo(time_first,
761 time_last_lldp,
762 time_last_bddp,
763 state_src,
764 state_dst);
765 }
mininet403d5892013-06-05 03:48:17 -0700766 //---------------------------------------------------------------
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800767}