blob: abb88094f841f684c8d619e47e72592d470b3b02 [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})
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080040public class LinkStorageImplTest {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070041 protected final static Logger log = LoggerFactory.getLogger(LinkStorageImplTest.class);
Naoki Shiotac88d9562013-06-18 15:21:56 -070042
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080043 private static ILinkStorage linkStorage;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080044
Naoki Shiotac88d9562013-06-18 15:21:56 -070045 // Mock GraphDBConnection (do nothing)
46 private static GraphDBConnection conn;
47
48 // Mock GraphDBOperation (mocks port-related methods only)
Naoki Shiota5f9197a2013-06-20 17:36:29 -070049 private static GraphDBOperation ope;
50
51 // Uncommitted actions executed in LinkStorageImpl
52 private static ArrayList<LinkEvent> actions;
53
54 // Dictionary of mock IPortObject to information of port
55 // -> Used to refer DPID from IPortObject
56 private static Map<IPortObject,PortInfo> mockToPortInfoMap;
57
58
59 // Links existing in virtual graph
60 private List<Link> links;
61
62 //================ Utility classes for logging actions in LinkStorageImpl ===========
63 private enum LinkEventType {
64 ADD, DELETE
65 }
66
67 private class LinkEvent {
68 private Long src_dpid = null;
69 private Long dst_dpid = null;
70 private Short src_port = null;
71 private Short dst_port = null;
72
73 public LinkEventType type;
74
75 public LinkEvent(Link link, LinkEventType type) {
76 this.src_dpid = link.getSrc();
77 this.src_port = link.getSrcPort();
78 this.dst_dpid = link.getDst();
79 this.dst_port = link.getDstPort();
80
81 this.type = type;
82 }
83
84 public Long getSrcDpid() { return src_dpid; }
85 public Short getSrcPort() { return src_port; }
86 public Long getDstDpid() { return dst_dpid; }
87 public Short getDstPort() { return dst_port; }
88 public LinkEventType getType() { return type; }
89 }
90
91 private class PortInfo {
92 public Long dpid = null;
93 public Short port = null;
94
95 public PortInfo(Long dpid, Short port) { this.dpid = dpid; this.port = port; }
96 }
mininet37dc5892013-06-04 10:58:44 -070097
mininet9d203de2013-06-05 08:40:45 -070098 /**
99 * Setup code called before each tests.
100 * Read test graph data and replace DB access by test graph data.
101 * @throws Exception
102 */
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800103 @Before
Jonathan Hart627f10c2013-01-16 14:20:03 -0800104 public void setUp() throws Exception{
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700105 // Create mock GraphDBConnection (replace Singleton object to mock one)
Naoki Shiotac88d9562013-06-18 15:21:56 -0700106 PowerMock.mockStatic(GraphDBConnection.class);
107 PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700108 conn = PowerMock.createMock(GraphDBConnection.class);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700109 EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(conn).anyTimes();
110 PowerMock.replay(GraphDBConnection.class);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800111
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700112 // Create mock GraphDBOperation
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700113 ope = createMockGraphDBOperation();
114 PowerMock.expectNew(GraphDBOperation.class, new Class<?>[] {GraphDBConnection.class}, EasyMock.anyObject(GraphDBConnection.class)).andReturn(ope).anyTimes();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700115 PowerMock.replay(GraphDBOperation.class);
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700116
117 actions = new ArrayList<LinkEvent>();
118 mockToPortInfoMap = new HashMap<IPortObject,PortInfo>();
119
mininet403d5892013-06-05 03:48:17 -0700120 linkStorage = new LinkStorageImpl();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700121 linkStorage.init("/dummy/path/to/conf");
mininet403d5892013-06-05 03:48:17 -0700122
Naoki Shiotac88d9562013-06-18 15:21:56 -0700123 initLinks();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800124 }
125
mininet9d203de2013-06-05 08:40:45 -0700126 /**
127 * Closing code called after each tests.
mininet9d203de2013-06-05 08:40:45 -0700128 * @throws Exception
129 */
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800130 @After
mininet403d5892013-06-05 03:48:17 -0700131 public void tearDown() throws Exception {
mininet403d5892013-06-05 03:48:17 -0700132 linkStorage.close();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800133 }
134
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700135
136 /**
137 * Test if {@link LinkStorageImpl#addLink(Link)} can correctly creates a Link.
138 */
139 @Test
140 public void testAddLink() {
141 Link linkToCreate = createFeasibleLink();
142 Link linkToVerify = createFeasibleLink();
143
144 //Use the link storage API to add the link
145 linkStorage.addLink(linkToCreate);
146 doTestLinkExist(linkToVerify);
147 }
148
149 /**
150 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly creates multiple Links.
151 */
152 @Test
153 public void testAddLinks() {
154 List<Link> linksToCreate = createFeasibleLinks();
155 List<Link> linksToVerify = createFeasibleLinks();
156
157 // Test creation of new links
158 linkStorage.addLinks(linksToCreate);
159 for(Link l : linksToVerify) {
160 doTestLinkExist(l);
161 }
162 }
163
Naoki Shiotacae568a2013-06-05 17:53:41 -0700164 // TODO: remove @Ignore after UPDATE method is implemented
Naoki Shiota1b972862013-06-05 19:49:09 -0700165 /**
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700166 * Test if {@link LinkStorageImpl#updateLinkInfo(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700167 */
mininet403d5892013-06-05 03:48:17 -0700168 @Ignore @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700169 public void testUpdate_Update() {
mininet403d5892013-06-05 03:48:17 -0700170 Link linkToUpdate= createExistingLink();
Naoki Shiotacae568a2013-06-05 17:53:41 -0700171 long currentTime = System.currentTimeMillis();
172 LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
173 LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
mininet403d5892013-06-05 03:48:17 -0700174
175 linkStorage.update(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
176
Naoki Shiotacae568a2013-06-05 17:53:41 -0700177 doTestLinkHasStateOf(linkToUpdate, infoToVerify);
mininet403d5892013-06-05 03:48:17 -0700178 }
179
Naoki Shiota1b972862013-06-05 19:49:09 -0700180 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700181 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly creates a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700182 */
mininet403d5892013-06-05 03:48:17 -0700183 @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700184 public void testUpdate_Create() {
mininet403d5892013-06-05 03:48:17 -0700185 Link linkToCreate = createFeasibleLink();
186 Link linkToVerify = createFeasibleLink();
187
188 //Use the link storage API to add the link
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700189 linkStorage.update(linkToCreate, null, ILinkStorage.DM_OPERATION.CREATE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700190 doTestLinkExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700191 }
192
Naoki Shiota1b972862013-06-05 19:49:09 -0700193 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700194 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)}can correctly inserts a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700195 */
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800196 @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700197 public void testUpdate_Insert(){
mininet403d5892013-06-05 03:48:17 -0700198 Link linkToInsert = createFeasibleLink();
199 Link linkToVerify = createFeasibleLink();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800200
201 //Use the link storage API to add the link
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700202 linkStorage.update(linkToInsert, null, ILinkStorage.DM_OPERATION.INSERT);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700203 doTestLinkExist(linkToVerify);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800204 }
205
Naoki Shiota1b972862013-06-05 19:49:09 -0700206 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700207 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly deletes a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700208 */
mininet403d5892013-06-05 03:48:17 -0700209 @Test
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700210 public void testUpdate_Delete(){
mininet403d5892013-06-05 03:48:17 -0700211 Link linkToDelete = createExistingLink();
212 Link linkToVerify = createExistingLink();
213
214 // Test deletion of existing link
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700215 linkStorage.update(linkToDelete, null, DM_OPERATION.DELETE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700216 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700217 }
Naoki Shiota1b972862013-06-05 19:49:09 -0700218
219 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700220 * Test if {@link LinkStorageImpl#getLinks(Long, short)} can correctly return Links connected to specific DPID and port.
Naoki Shiota1b972862013-06-05 19:49:09 -0700221 */
mininet9d203de2013-06-05 08:40:45 -0700222 @Test
223 public void testGetLinks_ByDpidPort(){
224 Link linkToVerify = createExistingLink();
225 Long dpid = linkToVerify.getSrc();
226 short port = (short)linkToVerify.getSrcPort();
227
228 List<Link> list = linkStorage.getLinks(dpid, port);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800229
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700230 assertEquals(1, list.size());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800231
232 Link l = list.get(0);
mininet403d5892013-06-05 03:48:17 -0700233 assertEquals(l.getSrc(), linkToVerify.getSrc());
234 assertEquals(l.getSrcPort(), linkToVerify.getSrcPort());
235 assertEquals(l.getDst(), linkToVerify.getDst());
236 assertEquals(l.getDstPort(), linkToVerify.getDstPort());
237
238 Link linkToVerifyNot = createFeasibleLink();
239
240 List<Link> list2 = linkStorage.getLinks(linkToVerifyNot.getSrc(), (short)linkToVerifyNot.getSrcPort());
241
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700242 assertEquals(0, list2.size());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800243 }
244
Naoki Shiota1b972862013-06-05 19:49:09 -0700245 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700246 * Test if {@link LinkStorageImpl#getLinks(String)} can correctly return Links connected to specific MAC address.
Naoki Shiota1b972862013-06-05 19:49:09 -0700247 */
mininet403d5892013-06-05 03:48:17 -0700248 @Test
mininet9d203de2013-06-05 08:40:45 -0700249 public void testGetLinks_ByString() {
mininet403d5892013-06-05 03:48:17 -0700250 Link linkToVeryfy = createExistingLink();
mininet9d203de2013-06-05 08:40:45 -0700251 String dpid = HexString.toHexString(linkToVeryfy.getSrc());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800252
mininet9d203de2013-06-05 08:40:45 -0700253 List<Link> links = linkStorage.getLinks(dpid);
mininet403d5892013-06-05 03:48:17 -0700254 assertTrue(links.contains(linkToVeryfy));
255
256 Link linkToVerifyNot = createFeasibleLink();
257 assertFalse(links.contains(linkToVerifyNot));
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800258 }
259
Naoki Shiota1b972862013-06-05 19:49:09 -0700260 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700261 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700262 */
mininet403d5892013-06-05 03:48:17 -0700263 @Test
264 public void testDeleteLink() {
265 // Deletion of existing link
266 Link linkToDelete = createExistingLink();
267 Link linkToVerify = createExistingLink();
268
269 linkStorage.deleteLink(linkToDelete);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700270 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700271 }
272
Naoki Shiota1b972862013-06-05 19:49:09 -0700273 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700274 * Test if {@link LinkStorageImpl#deleteLinks(List)} can correctly delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700275 */
mininet403d5892013-06-05 03:48:17 -0700276 @Test
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800277 public void testDeleteLinks(){
mininet403d5892013-06-05 03:48:17 -0700278 List<Link> linksToDelete = createExistingLinks();
279 List<Link> linksToVerify = createExistingLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800280
mininet403d5892013-06-05 03:48:17 -0700281 linkStorage.deleteLinks(linksToDelete);
282 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700283 doTestLinkNotExist(l);
mininet403d5892013-06-05 03:48:17 -0700284 }
285 }
mininet9d203de2013-06-05 08:40:45 -0700286
Naoki Shiota1b972862013-06-05 19:49:09 -0700287 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700288 * Test if {@link LinkStorageImpl#getActiveLinks()} can correctly return active Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700289 */
mininet9d203de2013-06-05 08:40:45 -0700290 @Test
mininet403d5892013-06-05 03:48:17 -0700291 public void testGetActiveLinks() {
292 Link existingLink = createExistingLink();
293 Link notExistingLink = createFeasibleLink();
294
295 List<Link> links = linkStorage.getActiveLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800296
mininet403d5892013-06-05 03:48:17 -0700297 assertTrue(links.contains(existingLink));
298 assertFalse(links.contains(notExistingLink));
299 }
300
Naoki Shiota1b972862013-06-05 19:49:09 -0700301 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700302 * Test if {@link LinkStorageImpl#deleteLinksOnPort(Long, short)} can delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700303 */
mininet403d5892013-06-05 03:48:17 -0700304 @Test
305 public void testDeleteLinksOnPort() {
306 Link linkToDelete = createExistingLink();
307 Link linkToVerify = createExistingLink();
308
309 linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
310
Naoki Shiotac88d9562013-06-18 15:21:56 -0700311 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700312 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700313
314 /**
315 * Test if {@link LinkStorageImpl#getLinkInfo(Link)} can delete Links.
316 */
317 @Ignore @Test
318 public void testGetLinkInfo() {
319 fail("not yet implemented");
320 }
mininet9d203de2013-06-05 08:40:45 -0700321
mininet403d5892013-06-05 03:48:17 -0700322 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700323 * Test if specific link exists
mininet9d203de2013-06-05 08:40:45 -0700324 * @param link
mininet403d5892013-06-05 03:48:17 -0700325 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700326 private void doTestLinkExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700327 int count = 0;
328 for(Link lt : links) {
329 if(lt.equals(link)) {
330 ++count;
331 }
332 }
333
334 assertTrue(count == 1);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800335 }
336
mininet403d5892013-06-05 03:48:17 -0700337 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700338 * Test if specific link doesn't exist
mininet403d5892013-06-05 03:48:17 -0700339 * @param link
340 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700341 private void doTestLinkNotExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700342 assertFalse(links.contains(link));
mininet403d5892013-06-05 03:48:17 -0700343 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700344
345 /**
346 * Test if titanGraph has specific Link with specific LinkInfo
347 * @param link
348 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700349 // TODO: Fix me
Naoki Shiotacae568a2013-06-05 17:53:41 -0700350 private void doTestLinkHasStateOf(Link link, LinkInfo info) {
Naoki Shiotacae568a2013-06-05 17:53:41 -0700351 }
Naoki Shiotac88d9562013-06-18 15:21:56 -0700352
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700353 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700354 * Class defines a function called back when {@link IPortObject#removeLink(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700355 * @author Naoki Shiota
356 *
357 */
358 private class RemoveLinkCallback implements IAnswer<Object> {
359 private long dpid;
360 private short port;
361 public RemoveLinkCallback(long dpid, short port) {
362 this.dpid = dpid; this.port = port;
363 }
364
365 @Override
366 public Object answer() throws Throwable {
367 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
368 PortInfo dst = mockToPortInfoMap.get(dstPort);
369
370 Link linkToRemove = new Link(this.dpid,this.port,dst.dpid,dst.port);
371 actions.add(new LinkEvent(linkToRemove,LinkEventType.DELETE));
372
373 return null;
374 }
375 }
376
377 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700378 * Class defines a function called back when {@link IPortObject#setLinkPort(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700379 * @author Naoki Shiota
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700380 */
381 private class SetLinkPortCallback implements IAnswer<Object> {
382 private long dpid;
383 private short port;
384 public SetLinkPortCallback(long dpid, short port) {
385 this.dpid = dpid; this.port = port;
386 }
387
388 @Override
389 public Object answer() throws Throwable {
390 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
391 PortInfo dst = mockToPortInfoMap.get(dstPort);
392
393 Link linkToAdd = new Link(this.dpid,this.port,dst.dpid,dst.port);
394 actions.add(new LinkEvent(linkToAdd,LinkEventType.ADD));
395
396 return null;
397 }
398
399 }
400
401 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700402 * Class defines a function called back when {@link IPortObject#getSwitch()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700403 * @author Naoki Shiota
404 *
405 */
406 private class GetSwitchCallback implements IAnswer<ISwitchObject> {
407 private long dpid;
408
409 public GetSwitchCallback(long dpid) {
410 this.dpid = dpid;
411 }
412
413 @Override
414 public ISwitchObject answer() throws Throwable {
415 ISwitchObject sw = createMockSwitch(dpid);
416 return sw;
417 }
418 }
419
420 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700421 * Class defines a function called back when {@link IPortObject#getLinkedPorts()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700422 * @author Naoki Shiota
423 *
424 */
425 private class GetLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
426 private long dpid;
427 private short port;
428
429 public GetLinkedPortsCallback(long dpid, short port) {
430 this.dpid = dpid;
431 this.port = port;
432 }
433
434 @Override
435 public Iterable<IPortObject> answer() throws Throwable {
436 List<IPortObject> ports = new ArrayList<IPortObject>();
437
438 for(Link lk : links) {
439 if(lk.getSrc() == dpid && lk.getSrcPort() == port) {
440 ports.add(createMockPort(lk.getDst(), lk.getDstPort()));
441 }
442 }
443
444 return ports;
445 }
446
447 }
448
449 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700450 * Class defines a function called back when {@link LinkStorageImplTest} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700451 * @author Naoki Shiota
452 *
453 */
454 private class GetPortsCallback implements IAnswer< Iterable <IPortObject> > {
455 private long dpid;
456
457 public GetPortsCallback(long dpid) {
458 this.dpid = dpid;
459 }
460
461 @Override
462 public Iterable<IPortObject> answer() throws Throwable {
463 List<IPortObject> ports = new ArrayList<IPortObject>();
464
465 for(Short number : getPorts(dpid)) {
466 ports.add(createMockPort(dpid, number));
467 }
468
469 return ports;
470 }
471 }
472
473 // ------------------------Creation of Mock-----------------------------
474 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700475 * Create a mock {@link GraphDBOperation} which hooks port-related methods.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700476 * @return EasyMock-wrapped GraphDBOperation object.
477 */
478 @SuppressWarnings("serial")
479 private GraphDBOperation createMockGraphDBOperation() {
480 GraphDBOperation mockDBOpe = EasyMock.createNiceMock(GraphDBOperation.class);
481
482 // Mock searchPort() method to create new mock IPortObject.
483 EasyMock.expect(mockDBOpe.searchPort((String)EasyMock.anyObject(), EasyMock.anyShort())).
484 andAnswer(new IAnswer<IPortObject>() {
485 @Override
486 public IPortObject answer() throws Throwable {
487 long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
488 short port = (Short) EasyMock.getCurrentArguments()[1];
489 IPortObject ret = createMockPort(dpid,port);
490
491 return ret;
492 }
493 }).anyTimes();
494
495 // Mock searchSwitch() method to create new mock ISwitchObject.
496 EasyMock.expect(mockDBOpe.searchSwitch((String)EasyMock.anyObject())).
497 andAnswer(new IAnswer<ISwitchObject>() {
498 @Override
499 public ISwitchObject answer() throws Throwable {
500 long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
501 ISwitchObject ret = createMockSwitch(dpid);
502
503 return ret;
504 }
505 }).anyTimes();
506
507 // Mock getActiveSwitches() method to create list of mock ISwitchObject.
508 EasyMock.expect(mockDBOpe.getActiveSwitches()).andReturn(new ArrayList<ISwitchObject> () {{
509 for(Long dpid : getDpids()) {
510 add(createMockSwitch(dpid));
511 }
512 }}).anyTimes();
513
514 // Mock commit() method to commit change of link information
515 mockDBOpe.commit();
516 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
517 @Override
518 public Object answer() throws Throwable {
519 for(LinkEvent action : actions) {
520 if(action.getType().equals(LinkEventType.ADD)) {
521 Link linkToAdd = new Link(
522 action.getSrcDpid(),
523 action.getSrcPort(),
524 action.getDstDpid(),
525 action.getDstPort());
526 links.add(linkToAdd);
527 } else if(action.getType().equals(LinkEventType.DELETE)) {
528 Link linkToRemove = new Link(
529 action.getSrcDpid(),
530 action.getSrcPort(),
531 action.getDstDpid(),
532 action.getDstPort());
533 links.remove(linkToRemove);
534 } else {
535 log.error("mock commit(): unexpected action {}", new Object[]{action.getType()});
536 }
537 }
538 actions.clear();
539 return null;
540 }
541 }).atLeastOnce();
542
543 EasyMock.replay(mockDBOpe);
544 return mockDBOpe;
545 }
546
547 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700548 * Create a mock {@link IPortObject} using given DPID and port number.
549 * {@link IPortObject} can't store DPID, so DPID is stored to mockToPortInfoMap for later use.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700550 * Duplication is not checked.
551 * @param dpid DPID of a port
552 * @param number Port Number
553 * @return EasyMock-wrapped IPortObject
554 */
555 private IPortObject createMockPort(long dpid, short number) {
556 IPortObject mockPort = EasyMock.createNiceMock(IPortObject.class);
557
558 EasyMock.expect(mockPort.getNumber()).andReturn(number);
559
560 // Mock removeLink() method
561 mockPort.removeLink((IPortObject) EasyMock.anyObject());
562 EasyMock.expectLastCall().andAnswer(new RemoveLinkCallback(dpid, number)).anyTimes();
563
564 // Mock setLinkPort() method
565 mockPort.setLinkPort((IPortObject) EasyMock.anyObject());
566 EasyMock.expectLastCall().andAnswer(new SetLinkPortCallback(dpid, number)).anyTimes();
567
568 // Mock getLinkPorts() method
569 EasyMock.expect(mockPort.getLinkedPorts()).andAnswer(new GetLinkedPortsCallback(dpid, number)).anyTimes();
570
571 // Mock getSwitch() method
572 EasyMock.expect(mockPort.getSwitch()).andAnswer(new GetSwitchCallback(dpid)).anyTimes();
573
574 mockToPortInfoMap.put(mockPort, new PortInfo(dpid,number));
575 EasyMock.replay(mockPort);
576
577 return mockPort;
578 }
579
580 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700581 * Create a mock {@link ISwitchObject} using given DPID number.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700582 * Duplication is not checked.
583 * @param dpid DPID of a switch
584 * @return EasyMock-wrapped ISwitchObject
585 */
586 private ISwitchObject createMockSwitch(long dpid) {
587 ISwitchObject mockSw = EasyMock.createNiceMock(ISwitchObject.class);
588
589 EasyMock.expect(mockSw.getPorts()).andAnswer(new GetPortsCallback(dpid)).anyTimes();
590 EasyMock.expect(mockSw.getDPID()).andReturn(HexString.toHexString(dpid)).anyTimes();
591 EasyMock.expect(mockSw.getState()).andReturn("ACTIVE").anyTimes();
592
593 EasyMock.replay(mockSw);
594 return mockSw;
595 }
596
597
mininet403d5892013-06-05 03:48:17 -0700598 //----------------- Creation of test data -----------------------
Naoki Shiotac88d9562013-06-18 15:21:56 -0700599 // Assume a network shown below.
600 //
601 // [dpid1]--+--[port:1]----[port:1]--+--[dpid2]
602 // | |
603 // +--[port:2] [port:2]--+
604 // |
605 // +--[port:3] [port:1]--+--[dpid3]
606 // | |
607 // +--[port:4]----[port:2]--+
608 //
609 // dpid1 : 00:00:00:00:0a:01
610 // dpid2 : 00:00:00:00:0a:02
611 // dpid3 : 00:00:00:00:0a:03
612
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700613 /**
614 * Initialize links member to represent test topology above.
615 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700616 private void initLinks() {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700617 links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700618
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700619 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
620 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700621 }
622
mininet9d203de2013-06-05 08:40:45 -0700623 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700624 * Returns list of port number attached to the switch specified by given DPID.
625 * @param dpid DPID of the switch
626 * @return List of port number
627 */
628 @SuppressWarnings("serial")
629 private List<Short> getPorts(long dpid) {
630 List<Short> ports;
631
632 if(dpid == Long.decode("0x0000000000000a01")) {
633 ports = new ArrayList<Short>() {{
634 add((short)1);
635 add((short)2);
636 add((short)3);
637 add((short)4);
638 }};
639 } else if(dpid == Long.decode("0x0000000000000a02") || dpid == Long.decode("0x0000000000000a03")) {
640 ports = new ArrayList<Short>() {{
641 add((short)1);
642 add((short)2);
643 }};
644 } else {
645 ports = new ArrayList<Short>();
646 }
647
648 return ports;
649 }
650
651 /**
652 * Returns list of DPIDs in test topology.
653 * @return List of DPIDs
654 */
655 @SuppressWarnings("serial")
656 private List<Long> getDpids() {
657 List<Long> dpids = new ArrayList<Long>() {{
658 add(Long.decode("0x0000000000000a01"));
659 add(Long.decode("0x0000000000000a02"));
660 add(Long.decode("0x0000000000000a03"));
661 }};
662
663 return dpids;
664 }
665
666 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700667 * Returns new {@link Link} object of an existing link
Naoki Shiotac88d9562013-06-18 15:21:56 -0700668 * @return new Link object
669 */
670 private Link createExistingLink() {
671 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
672 }
673
674 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700675 * Returns new {@link Link} object of a not-existing but feasible link
mininet9d203de2013-06-05 08:40:45 -0700676 * @return new Link object
677 */
mininet403d5892013-06-05 03:48:17 -0700678 private Link createFeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700679 return new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1);
mininet403d5892013-06-05 03:48:17 -0700680 }
681
mininet9d203de2013-06-05 08:40:45 -0700682 // make NO sense while test-network data doesn't define physical network (i.e. any link is feasible)
mininet403d5892013-06-05 03:48:17 -0700683 @SuppressWarnings("unused")
684 private Link createInfeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700685 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a03"), 3);
mininet403d5892013-06-05 03:48:17 -0700686 }
687
mininet9d203de2013-06-05 08:40:45 -0700688 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700689 * Returns list of existing {@link Link} objects
mininet9d203de2013-06-05 08:40:45 -0700690 * @return ArrayList of new Link objects
691 */
mininet403d5892013-06-05 03:48:17 -0700692 private List<Link> createExistingLinks() {
693 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700694 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
695 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700696 return links;
697 }
698
mininet9d203de2013-06-05 08:40:45 -0700699 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700700 * Returns list of {@link Link} objects that are all not-existing but feasible
mininet9d203de2013-06-05 08:40:45 -0700701 * @return ArrayList of new Link objects
702 */
mininet403d5892013-06-05 03:48:17 -0700703 private List<Link> createFeasibleLinks() {
704 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700705 links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a02"), 2));
706 links.add(new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1));
mininet403d5892013-06-05 03:48:17 -0700707 return links;
708 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700709
710 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700711 * Returns new {@link LinkInfo} object with convenient values.
Naoki Shiotacae568a2013-06-05 17:53:41 -0700712 * @return LinkInfo object
713 */
714 private LinkInfo createFeasibleLinkInfo(long time) {
715 long time_first = time;
716 long time_last_lldp = time + 50;
717 long time_last_bddp = time + 100;
718 int state_src = OFPhysicalPort.OFPortState.OFPPS_STP_FORWARD.getValue();
719 int state_dst = OFPhysicalPort.OFPortState.OFPPS_STP_LISTEN.getValue();
720
721 return new LinkInfo(time_first,
722 time_last_lldp,
723 time_last_bddp,
724 state_src,
725 state_dst);
726 }
mininet403d5892013-06-05 03:48:17 -0700727 //---------------------------------------------------------------
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800728}