blob: 4aea22ad69dfd28ccf7807123e66f66f28a10409 [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 }
Pavlin Radoslavov613eedc2013-11-02 16:08:25 -0700259
260 /**
261 * Test if {@link LinkStorageImpl#getReverseLinks(String)} can correctly return Links connected to specific MAC address.
262 */
263 @Test
264 public void testGetReverseLinks_ByString() {
265 Link linkToVeryfy = createExistingLink();
266 String dpid = HexString.toHexString(linkToVeryfy.getDst());
267
268 List<Link> links = linkStorage.getReverseLinks(dpid);
269 assertTrue(links.contains(linkToVeryfy));
270
271 Link linkToVerifyNot = createFeasibleLink();
272 assertFalse(links.contains(linkToVerifyNot));
273 }
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800274
Naoki Shiota1b972862013-06-05 19:49:09 -0700275 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700276 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700277 */
mininet403d5892013-06-05 03:48:17 -0700278 @Test
279 public void testDeleteLink() {
280 // Deletion of existing link
281 Link linkToDelete = createExistingLink();
282 Link linkToVerify = createExistingLink();
283
284 linkStorage.deleteLink(linkToDelete);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700285 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700286 }
287
Naoki Shiota1b972862013-06-05 19:49:09 -0700288 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700289 * Test if {@link LinkStorageImpl#deleteLinks(List)} can correctly delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700290 */
mininet403d5892013-06-05 03:48:17 -0700291 @Test
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800292 public void testDeleteLinks(){
mininet403d5892013-06-05 03:48:17 -0700293 List<Link> linksToDelete = createExistingLinks();
294 List<Link> linksToVerify = createExistingLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800295
mininet403d5892013-06-05 03:48:17 -0700296 linkStorage.deleteLinks(linksToDelete);
297 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700298 doTestLinkNotExist(l);
mininet403d5892013-06-05 03:48:17 -0700299 }
300 }
mininet9d203de2013-06-05 08:40:45 -0700301
Naoki Shiota1b972862013-06-05 19:49:09 -0700302 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700303 * Test if {@link LinkStorageImpl#getActiveLinks()} can correctly return active Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700304 */
mininet9d203de2013-06-05 08:40:45 -0700305 @Test
mininet403d5892013-06-05 03:48:17 -0700306 public void testGetActiveLinks() {
307 Link existingLink = createExistingLink();
308 Link notExistingLink = createFeasibleLink();
309
310 List<Link> links = linkStorage.getActiveLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800311
mininet403d5892013-06-05 03:48:17 -0700312 assertTrue(links.contains(existingLink));
313 assertFalse(links.contains(notExistingLink));
314 }
315
Naoki Shiota1b972862013-06-05 19:49:09 -0700316 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700317 * Test if {@link LinkStorageImpl#deleteLinksOnPort(Long, short)} can delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700318 */
mininet403d5892013-06-05 03:48:17 -0700319 @Test
320 public void testDeleteLinksOnPort() {
321 Link linkToDelete = createExistingLink();
322 Link linkToVerify = createExistingLink();
323
324 linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
325
Naoki Shiotac88d9562013-06-18 15:21:56 -0700326 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700327 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700328
329 /**
330 * Test if {@link LinkStorageImpl#getLinkInfo(Link)} can delete Links.
331 */
332 @Ignore @Test
333 public void testGetLinkInfo() {
334 fail("not yet implemented");
335 }
mininet9d203de2013-06-05 08:40:45 -0700336
mininet403d5892013-06-05 03:48:17 -0700337 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700338 * Test if specific link exists
mininet9d203de2013-06-05 08:40:45 -0700339 * @param link
mininet403d5892013-06-05 03:48:17 -0700340 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700341 private void doTestLinkExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700342 int count = 0;
343 for(Link lt : links) {
344 if(lt.equals(link)) {
345 ++count;
346 }
347 }
348
349 assertTrue(count == 1);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800350 }
351
mininet403d5892013-06-05 03:48:17 -0700352 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700353 * Test if specific link doesn't exist
mininet403d5892013-06-05 03:48:17 -0700354 * @param link
355 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700356 private void doTestLinkNotExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700357 assertFalse(links.contains(link));
mininet403d5892013-06-05 03:48:17 -0700358 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700359
360 /**
361 * Test if titanGraph has specific Link with specific LinkInfo
362 * @param link
363 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700364 // TODO: Fix me
Naoki Shiotacae568a2013-06-05 17:53:41 -0700365 private void doTestLinkHasStateOf(Link link, LinkInfo info) {
Naoki Shiotacae568a2013-06-05 17:53:41 -0700366 }
Naoki Shiotac88d9562013-06-18 15:21:56 -0700367
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700368 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700369 * Class defines a function called back when {@link IPortObject#removeLink(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700370 * @author Naoki Shiota
371 *
372 */
373 private class RemoveLinkCallback implements IAnswer<Object> {
374 private long dpid;
375 private short port;
376 public RemoveLinkCallback(long dpid, short port) {
377 this.dpid = dpid; this.port = port;
378 }
379
380 @Override
381 public Object answer() throws Throwable {
382 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
383 PortInfo dst = mockToPortInfoMap.get(dstPort);
384
385 Link linkToRemove = new Link(this.dpid,this.port,dst.dpid,dst.port);
386 actions.add(new LinkEvent(linkToRemove,LinkEventType.DELETE));
387
388 return null;
389 }
390 }
391
392 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700393 * Class defines a function called back when {@link IPortObject#setLinkPort(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700394 * @author Naoki Shiota
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700395 */
396 private class SetLinkPortCallback implements IAnswer<Object> {
397 private long dpid;
398 private short port;
399 public SetLinkPortCallback(long dpid, short port) {
400 this.dpid = dpid; this.port = port;
401 }
402
403 @Override
404 public Object answer() throws Throwable {
405 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
406 PortInfo dst = mockToPortInfoMap.get(dstPort);
407
408 Link linkToAdd = new Link(this.dpid,this.port,dst.dpid,dst.port);
409 actions.add(new LinkEvent(linkToAdd,LinkEventType.ADD));
410
411 return null;
412 }
413
414 }
415
416 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700417 * Class defines a function called back when {@link IPortObject#getSwitch()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700418 * @author Naoki Shiota
419 *
420 */
421 private class GetSwitchCallback implements IAnswer<ISwitchObject> {
422 private long dpid;
423
424 public GetSwitchCallback(long dpid) {
425 this.dpid = dpid;
426 }
427
428 @Override
429 public ISwitchObject answer() throws Throwable {
430 ISwitchObject sw = createMockSwitch(dpid);
431 return sw;
432 }
433 }
434
435 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700436 * Class defines a function called back when {@link IPortObject#getLinkedPorts()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700437 * @author Naoki Shiota
438 *
439 */
440 private class GetLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
441 private long dpid;
442 private short port;
443
444 public GetLinkedPortsCallback(long dpid, short port) {
445 this.dpid = dpid;
446 this.port = port;
447 }
448
449 @Override
450 public Iterable<IPortObject> answer() throws Throwable {
451 List<IPortObject> ports = new ArrayList<IPortObject>();
452
453 for(Link lk : links) {
454 if(lk.getSrc() == dpid && lk.getSrcPort() == port) {
455 ports.add(createMockPort(lk.getDst(), lk.getDstPort()));
456 }
457 }
458
459 return ports;
460 }
461
462 }
463
464 /**
Pavlin Radoslavov613eedc2013-11-02 16:08:25 -0700465 * Class defines a function called back when {@link IPortObject#getReverseLinkedPorts()} is called.
466 * @author Naoki Shiota
467 *
468 */
469 private class GetReverseLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
470 private long dpid;
471 private short port;
472
473 public GetReverseLinkedPortsCallback(long dpid, short port) {
474 this.dpid = dpid;
475 this.port = port;
476 }
477
478 @Override
479 public Iterable<IPortObject> answer() throws Throwable {
480 List<IPortObject> ports = new ArrayList<IPortObject>();
481
482 for(Link lk : links) {
483 if(lk.getDst() == dpid && lk.getDstPort() == port) {
484 ports.add(createMockPort(lk.getSrc(), lk.getSrcPort()));
485 }
486 }
487
488 return ports;
489 }
490
491 }
492
493 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700494 * Class defines a function called back when {@link LinkStorageImplTest} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700495 * @author Naoki Shiota
496 *
497 */
498 private class GetPortsCallback implements IAnswer< Iterable <IPortObject> > {
499 private long dpid;
500
501 public GetPortsCallback(long dpid) {
502 this.dpid = dpid;
503 }
504
505 @Override
506 public Iterable<IPortObject> answer() throws Throwable {
507 List<IPortObject> ports = new ArrayList<IPortObject>();
508
509 for(Short number : getPorts(dpid)) {
510 ports.add(createMockPort(dpid, number));
511 }
512
513 return ports;
514 }
515 }
516
517 // ------------------------Creation of Mock-----------------------------
518 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700519 * Create a mock {@link GraphDBOperation} which hooks port-related methods.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700520 * @return EasyMock-wrapped GraphDBOperation object.
521 */
522 @SuppressWarnings("serial")
523 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 */
675 @SuppressWarnings("serial")
676 private List<Short> getPorts(long dpid) {
677 List<Short> ports;
678
679 if(dpid == Long.decode("0x0000000000000a01")) {
680 ports = new ArrayList<Short>() {{
681 add((short)1);
682 add((short)2);
683 add((short)3);
684 add((short)4);
685 }};
686 } else if(dpid == Long.decode("0x0000000000000a02") || dpid == Long.decode("0x0000000000000a03")) {
687 ports = new ArrayList<Short>() {{
688 add((short)1);
689 add((short)2);
690 }};
691 } else {
692 ports = new ArrayList<Short>();
693 }
694
695 return ports;
696 }
697
698 /**
699 * Returns list of DPIDs in test topology.
700 * @return List of DPIDs
701 */
702 @SuppressWarnings("serial")
703 private List<Long> getDpids() {
704 List<Long> dpids = new ArrayList<Long>() {{
705 add(Long.decode("0x0000000000000a01"));
706 add(Long.decode("0x0000000000000a02"));
707 add(Long.decode("0x0000000000000a03"));
708 }};
709
710 return dpids;
711 }
712
713 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700714 * Returns new {@link Link} object of an existing link
Naoki Shiotac88d9562013-06-18 15:21:56 -0700715 * @return new Link object
716 */
717 private Link createExistingLink() {
718 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
719 }
720
721 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700722 * Returns new {@link Link} object of a not-existing but feasible link
mininet9d203de2013-06-05 08:40:45 -0700723 * @return new Link object
724 */
mininet403d5892013-06-05 03:48:17 -0700725 private Link createFeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700726 return new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1);
mininet403d5892013-06-05 03:48:17 -0700727 }
728
mininet9d203de2013-06-05 08:40:45 -0700729 // make NO sense while test-network data doesn't define physical network (i.e. any link is feasible)
mininet403d5892013-06-05 03:48:17 -0700730 @SuppressWarnings("unused")
731 private Link createInfeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700732 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a03"), 3);
mininet403d5892013-06-05 03:48:17 -0700733 }
734
mininet9d203de2013-06-05 08:40:45 -0700735 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700736 * Returns list of existing {@link Link} objects
mininet9d203de2013-06-05 08:40:45 -0700737 * @return ArrayList of new Link objects
738 */
mininet403d5892013-06-05 03:48:17 -0700739 private List<Link> createExistingLinks() {
740 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700741 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
742 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700743 return links;
744 }
745
mininet9d203de2013-06-05 08:40:45 -0700746 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700747 * Returns list of {@link Link} objects that are all not-existing but feasible
mininet9d203de2013-06-05 08:40:45 -0700748 * @return ArrayList of new Link objects
749 */
mininet403d5892013-06-05 03:48:17 -0700750 private List<Link> createFeasibleLinks() {
751 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700752 links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a02"), 2));
753 links.add(new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1));
mininet403d5892013-06-05 03:48:17 -0700754 return links;
755 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700756
757 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700758 * Returns new {@link LinkInfo} object with convenient values.
Naoki Shiotacae568a2013-06-05 17:53:41 -0700759 * @return LinkInfo object
760 */
761 private LinkInfo createFeasibleLinkInfo(long time) {
762 long time_first = time;
763 long time_last_lldp = time + 50;
764 long time_last_bddp = time + 100;
765 int state_src = OFPhysicalPort.OFPortState.OFPPS_STP_FORWARD.getValue();
766 int state_dst = OFPhysicalPort.OFPortState.OFPPS_STP_LISTEN.getValue();
767
768 return new LinkInfo(time_first,
769 time_last_lldp,
770 time_last_bddp,
771 state_src,
772 state_dst);
773 }
mininet403d5892013-06-05 03:48:17 -0700774 //---------------------------------------------------------------
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800775}