blob: 9b1c4d62fac12138ddb07b341509f277985465fb [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
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -08003import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertFalse;
5import static org.junit.Assert.assertTrue;
6
mininet403d5892013-06-05 03:48:17 -07007import java.util.ArrayList;
Naoki Shiota5f9197a2013-06-20 17:36:29 -07008import java.util.HashMap;
Jonathan Hartc86a2ea2013-01-15 22:39:42 -08009import java.util.List;
Naoki Shiota5f9197a2013-06-20 17:36:29 -070010import java.util.Map;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080011
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080012import net.floodlightcontroller.routing.Link;
Pankaj Berde38646d62013-06-21 11:34:04 -070013import net.onrc.onos.graph.GraphDBConnection;
14import net.onrc.onos.graph.GraphDBOperation;
HIGUCHI Yuta2d011582013-06-15 01:47:11 -070015import net.onrc.onos.ofcontroller.core.ILinkStorage;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070016import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
Naoki Shiota5f9197a2013-06-20 17:36:29 -070017import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
18import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
19import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080020
Naoki Shiota5f9197a2013-06-20 17:36:29 -070021import org.easymock.*;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080022import org.junit.After;
23import org.junit.Before;
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080024import org.junit.Ignore;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080025import org.junit.Test;
mininet37dc5892013-06-04 10:58:44 -070026import org.junit.runner.RunWith;
Naoki Shiotacae568a2013-06-05 17:53:41 -070027import org.openflow.protocol.OFPhysicalPort;
mininet403d5892013-06-05 03:48:17 -070028import org.openflow.util.HexString;
mininet37dc5892013-06-04 10:58:44 -070029import org.powermock.api.easymock.PowerMock;
30import org.powermock.core.classloader.annotations.PrepareForTest;
31import org.powermock.modules.junit4.PowerMockRunner;
Naoki Shiotac88d9562013-06-18 15:21:56 -070032import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080034
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070035/**
36 * Unit test for {@link LinkStorageImpl}.
37 * @author Naoki Shiota
38 *
39 */
mininet37dc5892013-06-04 10:58:44 -070040@RunWith(PowerMockRunner.class)
Naoki Shiotac88d9562013-06-18 15:21:56 -070041@PrepareForTest({LinkStorageImpl.class, GraphDBConnection.class, GraphDBOperation.class})
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080042public class LinkStorageImplTest {
Naoki Shiotac88d9562013-06-18 15:21:56 -070043 protected static Logger log = LoggerFactory.getLogger(LinkStorageImplTest.class);
44
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080045 private static ILinkStorage linkStorage;
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -080046
Naoki Shiotac88d9562013-06-18 15:21:56 -070047 // Mock GraphDBConnection (do nothing)
48 private static GraphDBConnection conn;
49
50 // Mock GraphDBOperation (mocks port-related methods only)
Naoki Shiota5f9197a2013-06-20 17:36:29 -070051 private static GraphDBOperation ope;
52
53 // Uncommitted actions executed in LinkStorageImpl
54 private static ArrayList<LinkEvent> actions;
55
56 // Dictionary of mock IPortObject to information of port
57 // -> Used to refer DPID from IPortObject
58 private static Map<IPortObject,PortInfo> mockToPortInfoMap;
59
60
61 // Links existing in virtual graph
62 private List<Link> links;
63
64 //================ Utility classes for logging actions in LinkStorageImpl ===========
65 private enum LinkEventType {
66 ADD, DELETE
67 }
68
69 private class LinkEvent {
70 private Long src_dpid = null;
71 private Long dst_dpid = null;
72 private Short src_port = null;
73 private Short dst_port = null;
74
75 public LinkEventType type;
76
77 public LinkEvent(Link link, LinkEventType type) {
78 this.src_dpid = link.getSrc();
79 this.src_port = link.getSrcPort();
80 this.dst_dpid = link.getDst();
81 this.dst_port = link.getDstPort();
82
83 this.type = type;
84 }
85
86 public Long getSrcDpid() { return src_dpid; }
87 public Short getSrcPort() { return src_port; }
88 public Long getDstDpid() { return dst_dpid; }
89 public Short getDstPort() { return dst_port; }
90 public LinkEventType getType() { return type; }
91 }
92
93 private class PortInfo {
94 public Long dpid = null;
95 public Short port = null;
96
97 public PortInfo(Long dpid, Short port) { this.dpid = dpid; this.port = port; }
98 }
mininet37dc5892013-06-04 10:58:44 -070099
mininet9d203de2013-06-05 08:40:45 -0700100 /**
101 * Setup code called before each tests.
102 * Read test graph data and replace DB access by test graph data.
103 * @throws Exception
104 */
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800105 @Before
Jonathan Hart627f10c2013-01-16 14:20:03 -0800106 public void setUp() throws Exception{
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700107 // Create mock GraphDBConnection (replace Singleton object to mock one)
Naoki Shiotac88d9562013-06-18 15:21:56 -0700108 PowerMock.mockStatic(GraphDBConnection.class);
109 PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700110 conn = PowerMock.createMock(GraphDBConnection.class);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700111 EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(conn).anyTimes();
112 PowerMock.replay(GraphDBConnection.class);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800113
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700114 // Create mock GraphDBOperation
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700115 ope = createMockGraphDBOperation();
116 PowerMock.expectNew(GraphDBOperation.class, new Class<?>[] {GraphDBConnection.class}, EasyMock.anyObject(GraphDBConnection.class)).andReturn(ope).anyTimes();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700117 PowerMock.replay(GraphDBOperation.class);
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700118
119 actions = new ArrayList<LinkEvent>();
120 mockToPortInfoMap = new HashMap<IPortObject,PortInfo>();
121
mininet403d5892013-06-05 03:48:17 -0700122 linkStorage = new LinkStorageImpl();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700123 linkStorage.init("/dummy/path/to/conf");
mininet403d5892013-06-05 03:48:17 -0700124
Naoki Shiotac88d9562013-06-18 15:21:56 -0700125 initLinks();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800126 }
127
mininet9d203de2013-06-05 08:40:45 -0700128 /**
129 * Closing code called after each tests.
mininet9d203de2013-06-05 08:40:45 -0700130 * @throws Exception
131 */
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800132 @After
mininet403d5892013-06-05 03:48:17 -0700133 public void tearDown() throws Exception {
mininet403d5892013-06-05 03:48:17 -0700134 linkStorage.close();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800135 }
136
Naoki Shiotacae568a2013-06-05 17:53:41 -0700137 // TODO: remove @Ignore after UPDATE method is implemented
Naoki Shiota1b972862013-06-05 19:49:09 -0700138 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700139 * Test if {@link LinkStorageImpl#update(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700140 */
mininet403d5892013-06-05 03:48:17 -0700141 @Ignore @Test
142 public void testUpdate_UpdateSingleLink() {
143 Link linkToUpdate= createExistingLink();
Naoki Shiotacae568a2013-06-05 17:53:41 -0700144 long currentTime = System.currentTimeMillis();
145 LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
146 LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
mininet403d5892013-06-05 03:48:17 -0700147
148 linkStorage.update(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
149
Naoki Shiotacae568a2013-06-05 17:53:41 -0700150 doTestLinkHasStateOf(linkToUpdate, infoToVerify);
mininet403d5892013-06-05 03:48:17 -0700151 }
152
Naoki Shiota1b972862013-06-05 19:49:09 -0700153 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700154 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly creates a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700155 */
mininet403d5892013-06-05 03:48:17 -0700156 @Test
157 public void testUpdate_CreateSingleLink() {
158 Link linkToCreate = createFeasibleLink();
159 Link linkToVerify = createFeasibleLink();
160
161 //Use the link storage API to add the link
162 linkStorage.update(linkToCreate, ILinkStorage.DM_OPERATION.CREATE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700163 doTestLinkExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700164 }
165
Naoki Shiota1b972862013-06-05 19:49:09 -0700166 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700167 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)}can correctly inserts a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700168 */
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800169 @Test
mininet403d5892013-06-05 03:48:17 -0700170 public void testUpdate_InsertSingleLink(){
171 Link linkToInsert = createFeasibleLink();
172 Link linkToVerify = createFeasibleLink();
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800173
174 //Use the link storage API to add the link
mininet403d5892013-06-05 03:48:17 -0700175 linkStorage.update(linkToInsert, ILinkStorage.DM_OPERATION.INSERT);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700176 doTestLinkExist(linkToVerify);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800177 }
178
Naoki Shiota1b972862013-06-05 19:49:09 -0700179 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700180 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly deletes a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700181 */
mininet403d5892013-06-05 03:48:17 -0700182 @Test
183 public void testUpdate_DeleteSingleLink(){
184 Link linkToDelete = createExistingLink();
185 Link linkToVerify = createExistingLink();
186
187 // Test deletion of existing link
188 linkStorage.update(linkToDelete, DM_OPERATION.DELETE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700189 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700190 }
Naoki Shiota1b972862013-06-05 19:49:09 -0700191
192 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700193 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly creates multiple Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700194 */
mininet403d5892013-06-05 03:48:17 -0700195 @Test
196 public void testUpdate_CreateLinks(){
197 List<Link> linksToCreate = createFeasibleLinks();
198 List<Link> linksToVerify = createFeasibleLinks();
199
200 // Test creation of new links
201 linkStorage.update(linksToCreate, ILinkStorage.DM_OPERATION.CREATE);
202 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700203 doTestLinkExist(l);
mininet403d5892013-06-05 03:48:17 -0700204 }
mininet403d5892013-06-05 03:48:17 -0700205 }
206
Naoki Shiota1b972862013-06-05 19:49:09 -0700207 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700208 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly inserts multiple Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700209 */
mininet403d5892013-06-05 03:48:17 -0700210 @Test
211 public void testUpdate_InsertLinks(){
212 List<Link> linksToInsert = createFeasibleLinks();
213 List<Link> linksToVerify = createFeasibleLinks();
214
215 // Test insertion of new links
216 linkStorage.update(linksToInsert, ILinkStorage.DM_OPERATION.INSERT);
217 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700218 doTestLinkExist(l);
mininet403d5892013-06-05 03:48:17 -0700219 }
220 }
221
Naoki Shiota1b972862013-06-05 19:49:09 -0700222 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700223 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly deletes multiple Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700224 */
mininet403d5892013-06-05 03:48:17 -0700225 @Test
226 public void testUpdate_DeleteLinks(){
227 List<Link> linksToDelete = createExistingLinks();
228 List<Link> linksToVerify = createExistingLinks();
229
230 // Test deletion of existing links
231 linkStorage.update(linksToDelete, ILinkStorage.DM_OPERATION.DELETE);
232 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700233 doTestLinkNotExist(l);
mininet403d5892013-06-05 03:48:17 -0700234 }
235 }
236
Naoki Shiotacae568a2013-06-05 17:53:41 -0700237 // TODO: remove @Ignore after UPDATE method is implemented
Naoki Shiota1b972862013-06-05 19:49:09 -0700238 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700239 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700240 */
mininet9d203de2013-06-05 08:40:45 -0700241 @Ignore @Test
Naoki Shiota1b972862013-06-05 19:49:09 -0700242 public void testUpdateLink_Update() {
mininet9d203de2013-06-05 08:40:45 -0700243 Link linkToUpdate= createExistingLink();
Naoki Shiotacae568a2013-06-05 17:53:41 -0700244 long currentTime = System.currentTimeMillis();
245 LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
246 LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
mininet9d203de2013-06-05 08:40:45 -0700247
Naoki Shiota1b972862013-06-05 19:49:09 -0700248 linkStorage.updateLink(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
mininet9d203de2013-06-05 08:40:45 -0700249
Naoki Shiotacae568a2013-06-05 17:53:41 -0700250 doTestLinkHasStateOf(linkToUpdate, infoToVerify);
mininet403d5892013-06-05 03:48:17 -0700251 }
252
Naoki Shiota1b972862013-06-05 19:49:09 -0700253 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700254 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly creates a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700255 */
mininet403d5892013-06-05 03:48:17 -0700256 @Test
Naoki Shiota1b972862013-06-05 19:49:09 -0700257 public void testUpdateLink_Create() {
mininet9d203de2013-06-05 08:40:45 -0700258 Link linkToCreate = createFeasibleLink();
259 Link linkToVerify = createFeasibleLink();
mininet403d5892013-06-05 03:48:17 -0700260
mininet9d203de2013-06-05 08:40:45 -0700261 //Use the link storage API to add the link
Naoki Shiota1b972862013-06-05 19:49:09 -0700262 linkStorage.updateLink(linkToCreate, null, ILinkStorage.DM_OPERATION.CREATE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700263 doTestLinkExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700264 }
265
Naoki Shiota1b972862013-06-05 19:49:09 -0700266 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700267 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly inserts a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700268 */
mininet403d5892013-06-05 03:48:17 -0700269 @Test
Naoki Shiota1b972862013-06-05 19:49:09 -0700270 public void testUpdateLink_Insert() {
mininet9d203de2013-06-05 08:40:45 -0700271 Link linkToInsert = createFeasibleLink();
272 Link linkToVerify = createFeasibleLink();
mininet403d5892013-06-05 03:48:17 -0700273
mininet9d203de2013-06-05 08:40:45 -0700274 //Use the link storage API to add the link
Naoki Shiota1b972862013-06-05 19:49:09 -0700275 linkStorage.updateLink(linkToInsert, null, ILinkStorage.DM_OPERATION.INSERT);
mininet9d203de2013-06-05 08:40:45 -0700276
Naoki Shiotac88d9562013-06-18 15:21:56 -0700277 doTestLinkExist(linkToVerify);
mininet9d203de2013-06-05 08:40:45 -0700278 }
279
280 // TODO: Check if addOrUpdateLink() should accept DELETE operation. If not, remove this test.
Naoki Shiota1b972862013-06-05 19:49:09 -0700281 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700282 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly deletes a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700283 */
mininet9d203de2013-06-05 08:40:45 -0700284 @Ignore @Test
Naoki Shiota1b972862013-06-05 19:49:09 -0700285 public void testUpdateLink_Delete() {
mininet9d203de2013-06-05 08:40:45 -0700286 Link linkToDelete = createExistingLink();
287 Link linkToVerify = createExistingLink();
288
289 // Test deletion of existing link
Naoki Shiota1b972862013-06-05 19:49:09 -0700290 linkStorage.updateLink(linkToDelete, null, DM_OPERATION.DELETE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700291 doTestLinkNotExist(linkToVerify);
mininet9d203de2013-06-05 08:40:45 -0700292
293 linkToDelete = createFeasibleLink();
294 linkToVerify = createFeasibleLink();
295
296 // Test deletion of not-existing link
Naoki Shiota1b972862013-06-05 19:49:09 -0700297 linkStorage.updateLink(linkToDelete, null, DM_OPERATION.DELETE);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700298 doTestLinkNotExist(linkToVerify);
mininet9d203de2013-06-05 08:40:45 -0700299 }
300
Naoki Shiota1b972862013-06-05 19:49:09 -0700301 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700302 * Test if {@link LinkStorageImpl#getLinks(Long, short)} can correctly return Links connected to specific DPID and port.
Naoki Shiota1b972862013-06-05 19:49:09 -0700303 */
mininet9d203de2013-06-05 08:40:45 -0700304 @Test
305 public void testGetLinks_ByDpidPort(){
306 Link linkToVerify = createExistingLink();
307 Long dpid = linkToVerify.getSrc();
308 short port = (short)linkToVerify.getSrcPort();
309
310 List<Link> list = linkStorage.getLinks(dpid, port);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800311
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700312 assertEquals(1, list.size());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800313
314 Link l = list.get(0);
mininet403d5892013-06-05 03:48:17 -0700315 assertEquals(l.getSrc(), linkToVerify.getSrc());
316 assertEquals(l.getSrcPort(), linkToVerify.getSrcPort());
317 assertEquals(l.getDst(), linkToVerify.getDst());
318 assertEquals(l.getDstPort(), linkToVerify.getDstPort());
319
320 Link linkToVerifyNot = createFeasibleLink();
321
322 List<Link> list2 = linkStorage.getLinks(linkToVerifyNot.getSrc(), (short)linkToVerifyNot.getSrcPort());
323
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700324 assertEquals(0, list2.size());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800325 }
326
Naoki Shiota1b972862013-06-05 19:49:09 -0700327 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700328 * Test if {@link LinkStorageImpl#getLinks(String)} can correctly return Links connected to specific MAC address.
Naoki Shiota1b972862013-06-05 19:49:09 -0700329 */
mininet403d5892013-06-05 03:48:17 -0700330 @Test
mininet9d203de2013-06-05 08:40:45 -0700331 public void testGetLinks_ByString() {
mininet403d5892013-06-05 03:48:17 -0700332 Link linkToVeryfy = createExistingLink();
mininet9d203de2013-06-05 08:40:45 -0700333 String dpid = HexString.toHexString(linkToVeryfy.getSrc());
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800334
mininet9d203de2013-06-05 08:40:45 -0700335 List<Link> links = linkStorage.getLinks(dpid);
mininet403d5892013-06-05 03:48:17 -0700336 assertTrue(links.contains(linkToVeryfy));
337
338 Link linkToVerifyNot = createFeasibleLink();
339 assertFalse(links.contains(linkToVerifyNot));
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800340 }
341
Naoki Shiota1b972862013-06-05 19:49:09 -0700342 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700343 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
Naoki Shiota1b972862013-06-05 19:49:09 -0700344 */
mininet403d5892013-06-05 03:48:17 -0700345 @Test
346 public void testDeleteLink() {
347 // Deletion of existing link
348 Link linkToDelete = createExistingLink();
349 Link linkToVerify = createExistingLink();
350
351 linkStorage.deleteLink(linkToDelete);
Naoki Shiotac88d9562013-06-18 15:21:56 -0700352 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700353 }
354
Naoki Shiota1b972862013-06-05 19:49:09 -0700355 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700356 * Test if {@link LinkStorageImpl#deleteLinks(List)} can correctly delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700357 */
mininet403d5892013-06-05 03:48:17 -0700358 @Test
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800359 public void testDeleteLinks(){
mininet403d5892013-06-05 03:48:17 -0700360 List<Link> linksToDelete = createExistingLinks();
361 List<Link> linksToVerify = createExistingLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800362
mininet403d5892013-06-05 03:48:17 -0700363 linkStorage.deleteLinks(linksToDelete);
364 for(Link l : linksToVerify) {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700365 doTestLinkNotExist(l);
mininet403d5892013-06-05 03:48:17 -0700366 }
367 }
mininet9d203de2013-06-05 08:40:45 -0700368
Naoki Shiota1b972862013-06-05 19:49:09 -0700369 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700370 * Test if {@link LinkStorageImpl#getActiveLinks()} can correctly return active Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700371 */
mininet9d203de2013-06-05 08:40:45 -0700372 @Test
mininet403d5892013-06-05 03:48:17 -0700373 public void testGetActiveLinks() {
374 Link existingLink = createExistingLink();
375 Link notExistingLink = createFeasibleLink();
376
377 List<Link> links = linkStorage.getActiveLinks();
Jonathan Hartc86a2ea2013-01-15 22:39:42 -0800378
mininet403d5892013-06-05 03:48:17 -0700379 assertTrue(links.contains(existingLink));
380 assertFalse(links.contains(notExistingLink));
381 }
382
Naoki Shiota1b972862013-06-05 19:49:09 -0700383 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700384 * Test if {@link LinkStorageImpl#deleteLinksOnPort(Long, short)} can delete Links.
Naoki Shiota1b972862013-06-05 19:49:09 -0700385 */
mininet403d5892013-06-05 03:48:17 -0700386 @Test
387 public void testDeleteLinksOnPort() {
388 Link linkToDelete = createExistingLink();
389 Link linkToVerify = createExistingLink();
390
391 linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
392
Naoki Shiotac88d9562013-06-18 15:21:56 -0700393 doTestLinkNotExist(linkToVerify);
mininet403d5892013-06-05 03:48:17 -0700394 }
mininet9d203de2013-06-05 08:40:45 -0700395
mininet403d5892013-06-05 03:48:17 -0700396 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700397 * Test if specific link exists
mininet9d203de2013-06-05 08:40:45 -0700398 * @param link
mininet403d5892013-06-05 03:48:17 -0700399 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700400 private void doTestLinkExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700401 int count = 0;
402 for(Link lt : links) {
403 if(lt.equals(link)) {
404 ++count;
405 }
406 }
407
408 assertTrue(count == 1);
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800409 }
410
mininet403d5892013-06-05 03:48:17 -0700411 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700412 * Test if specific link doesn't exist
mininet403d5892013-06-05 03:48:17 -0700413 * @param link
414 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700415 private void doTestLinkNotExist(Link link) {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700416 assertFalse(links.contains(link));
mininet403d5892013-06-05 03:48:17 -0700417 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700418
419 /**
420 * Test if titanGraph has specific Link with specific LinkInfo
421 * @param link
422 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700423 // TODO: Fix me
Naoki Shiotacae568a2013-06-05 17:53:41 -0700424 private void doTestLinkHasStateOf(Link link, LinkInfo info) {
Naoki Shiotacae568a2013-06-05 17:53:41 -0700425 }
Naoki Shiotac88d9562013-06-18 15:21:56 -0700426
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700427 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700428 * Class defines a function called back when {@link IPortObject#removeLink(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700429 * @author Naoki Shiota
430 *
431 */
432 private class RemoveLinkCallback implements IAnswer<Object> {
433 private long dpid;
434 private short port;
435 public RemoveLinkCallback(long dpid, short port) {
436 this.dpid = dpid; this.port = port;
437 }
438
439 @Override
440 public Object answer() throws Throwable {
441 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
442 PortInfo dst = mockToPortInfoMap.get(dstPort);
443
444 Link linkToRemove = new Link(this.dpid,this.port,dst.dpid,dst.port);
445 actions.add(new LinkEvent(linkToRemove,LinkEventType.DELETE));
446
447 return null;
448 }
449 }
450
451 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700452 * Class defines a function called back when {@link IPortObject#setLinkPort(IPortObject)} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700453 * @author Naoki Shiota
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700454 */
455 private class SetLinkPortCallback implements IAnswer<Object> {
456 private long dpid;
457 private short port;
458 public SetLinkPortCallback(long dpid, short port) {
459 this.dpid = dpid; this.port = port;
460 }
461
462 @Override
463 public Object answer() throws Throwable {
464 IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
465 PortInfo dst = mockToPortInfoMap.get(dstPort);
466
467 Link linkToAdd = new Link(this.dpid,this.port,dst.dpid,dst.port);
468 actions.add(new LinkEvent(linkToAdd,LinkEventType.ADD));
469
470 return null;
471 }
472
473 }
474
475 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700476 * Class defines a function called back when {@link IPortObject#getSwitch()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700477 * @author Naoki Shiota
478 *
479 */
480 private class GetSwitchCallback implements IAnswer<ISwitchObject> {
481 private long dpid;
482
483 public GetSwitchCallback(long dpid) {
484 this.dpid = dpid;
485 }
486
487 @Override
488 public ISwitchObject answer() throws Throwable {
489 ISwitchObject sw = createMockSwitch(dpid);
490 return sw;
491 }
492 }
493
494 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700495 * Class defines a function called back when {@link IPortObject#getLinkedPorts()} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700496 * @author Naoki Shiota
497 *
498 */
499 private class GetLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
500 private long dpid;
501 private short port;
502
503 public GetLinkedPortsCallback(long dpid, short port) {
504 this.dpid = dpid;
505 this.port = port;
506 }
507
508 @Override
509 public Iterable<IPortObject> answer() throws Throwable {
510 List<IPortObject> ports = new ArrayList<IPortObject>();
511
512 for(Link lk : links) {
513 if(lk.getSrc() == dpid && lk.getSrcPort() == port) {
514 ports.add(createMockPort(lk.getDst(), lk.getDstPort()));
515 }
516 }
517
518 return ports;
519 }
520
521 }
522
523 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700524 * Class defines a function called back when {@link LinkStorageImplTest} is called.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700525 * @author Naoki Shiota
526 *
527 */
528 private class GetPortsCallback implements IAnswer< Iterable <IPortObject> > {
529 private long dpid;
530
531 public GetPortsCallback(long dpid) {
532 this.dpid = dpid;
533 }
534
535 @Override
536 public Iterable<IPortObject> answer() throws Throwable {
537 List<IPortObject> ports = new ArrayList<IPortObject>();
538
539 for(Short number : getPorts(dpid)) {
540 ports.add(createMockPort(dpid, number));
541 }
542
543 return ports;
544 }
545 }
546
547 // ------------------------Creation of Mock-----------------------------
548 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700549 * Create a mock {@link GraphDBOperation} which hooks port-related methods.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700550 * @return EasyMock-wrapped GraphDBOperation object.
551 */
552 @SuppressWarnings("serial")
553 private GraphDBOperation createMockGraphDBOperation() {
554 GraphDBOperation mockDBOpe = EasyMock.createNiceMock(GraphDBOperation.class);
555
556 // Mock searchPort() method to create new mock IPortObject.
557 EasyMock.expect(mockDBOpe.searchPort((String)EasyMock.anyObject(), EasyMock.anyShort())).
558 andAnswer(new IAnswer<IPortObject>() {
559 @Override
560 public IPortObject answer() throws Throwable {
561 long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
562 short port = (Short) EasyMock.getCurrentArguments()[1];
563 IPortObject ret = createMockPort(dpid,port);
564
565 return ret;
566 }
567 }).anyTimes();
568
569 // Mock searchSwitch() method to create new mock ISwitchObject.
570 EasyMock.expect(mockDBOpe.searchSwitch((String)EasyMock.anyObject())).
571 andAnswer(new IAnswer<ISwitchObject>() {
572 @Override
573 public ISwitchObject answer() throws Throwable {
574 long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
575 ISwitchObject ret = createMockSwitch(dpid);
576
577 return ret;
578 }
579 }).anyTimes();
580
581 // Mock getActiveSwitches() method to create list of mock ISwitchObject.
582 EasyMock.expect(mockDBOpe.getActiveSwitches()).andReturn(new ArrayList<ISwitchObject> () {{
583 for(Long dpid : getDpids()) {
584 add(createMockSwitch(dpid));
585 }
586 }}).anyTimes();
587
588 // Mock commit() method to commit change of link information
589 mockDBOpe.commit();
590 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
591 @Override
592 public Object answer() throws Throwable {
593 for(LinkEvent action : actions) {
594 if(action.getType().equals(LinkEventType.ADD)) {
595 Link linkToAdd = new Link(
596 action.getSrcDpid(),
597 action.getSrcPort(),
598 action.getDstDpid(),
599 action.getDstPort());
600 links.add(linkToAdd);
601 } else if(action.getType().equals(LinkEventType.DELETE)) {
602 Link linkToRemove = new Link(
603 action.getSrcDpid(),
604 action.getSrcPort(),
605 action.getDstDpid(),
606 action.getDstPort());
607 links.remove(linkToRemove);
608 } else {
609 log.error("mock commit(): unexpected action {}", new Object[]{action.getType()});
610 }
611 }
612 actions.clear();
613 return null;
614 }
615 }).atLeastOnce();
616
617 EasyMock.replay(mockDBOpe);
618 return mockDBOpe;
619 }
620
621 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700622 * Create a mock {@link IPortObject} using given DPID and port number.
623 * {@link IPortObject} can't store DPID, so DPID is stored to mockToPortInfoMap for later use.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700624 * Duplication is not checked.
625 * @param dpid DPID of a port
626 * @param number Port Number
627 * @return EasyMock-wrapped IPortObject
628 */
629 private IPortObject createMockPort(long dpid, short number) {
630 IPortObject mockPort = EasyMock.createNiceMock(IPortObject.class);
631
632 EasyMock.expect(mockPort.getNumber()).andReturn(number);
633
634 // Mock removeLink() method
635 mockPort.removeLink((IPortObject) EasyMock.anyObject());
636 EasyMock.expectLastCall().andAnswer(new RemoveLinkCallback(dpid, number)).anyTimes();
637
638 // Mock setLinkPort() method
639 mockPort.setLinkPort((IPortObject) EasyMock.anyObject());
640 EasyMock.expectLastCall().andAnswer(new SetLinkPortCallback(dpid, number)).anyTimes();
641
642 // Mock getLinkPorts() method
643 EasyMock.expect(mockPort.getLinkedPorts()).andAnswer(new GetLinkedPortsCallback(dpid, number)).anyTimes();
644
645 // Mock getSwitch() method
646 EasyMock.expect(mockPort.getSwitch()).andAnswer(new GetSwitchCallback(dpid)).anyTimes();
647
648 mockToPortInfoMap.put(mockPort, new PortInfo(dpid,number));
649 EasyMock.replay(mockPort);
650
651 return mockPort;
652 }
653
654 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700655 * Create a mock {@link ISwitchObject} using given DPID number.
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700656 * Duplication is not checked.
657 * @param dpid DPID of a switch
658 * @return EasyMock-wrapped ISwitchObject
659 */
660 private ISwitchObject createMockSwitch(long dpid) {
661 ISwitchObject mockSw = EasyMock.createNiceMock(ISwitchObject.class);
662
663 EasyMock.expect(mockSw.getPorts()).andAnswer(new GetPortsCallback(dpid)).anyTimes();
664 EasyMock.expect(mockSw.getDPID()).andReturn(HexString.toHexString(dpid)).anyTimes();
665 EasyMock.expect(mockSw.getState()).andReturn("ACTIVE").anyTimes();
666
667 EasyMock.replay(mockSw);
668 return mockSw;
669 }
670
671
mininet403d5892013-06-05 03:48:17 -0700672 //----------------- Creation of test data -----------------------
Naoki Shiotac88d9562013-06-18 15:21:56 -0700673 // Assume a network shown below.
674 //
675 // [dpid1]--+--[port:1]----[port:1]--+--[dpid2]
676 // | |
677 // +--[port:2] [port:2]--+
678 // |
679 // +--[port:3] [port:1]--+--[dpid3]
680 // | |
681 // +--[port:4]----[port:2]--+
682 //
683 // dpid1 : 00:00:00:00:0a:01
684 // dpid2 : 00:00:00:00:0a:02
685 // dpid3 : 00:00:00:00:0a:03
686
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700687 /**
688 * Initialize links member to represent test topology above.
689 */
Naoki Shiotac88d9562013-06-18 15:21:56 -0700690 private void initLinks() {
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700691 links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700692
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700693 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
694 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700695 }
696
mininet9d203de2013-06-05 08:40:45 -0700697 /**
Naoki Shiota5f9197a2013-06-20 17:36:29 -0700698 * Returns list of port number attached to the switch specified by given DPID.
699 * @param dpid DPID of the switch
700 * @return List of port number
701 */
702 @SuppressWarnings("serial")
703 private List<Short> getPorts(long dpid) {
704 List<Short> ports;
705
706 if(dpid == Long.decode("0x0000000000000a01")) {
707 ports = new ArrayList<Short>() {{
708 add((short)1);
709 add((short)2);
710 add((short)3);
711 add((short)4);
712 }};
713 } else if(dpid == Long.decode("0x0000000000000a02") || dpid == Long.decode("0x0000000000000a03")) {
714 ports = new ArrayList<Short>() {{
715 add((short)1);
716 add((short)2);
717 }};
718 } else {
719 ports = new ArrayList<Short>();
720 }
721
722 return ports;
723 }
724
725 /**
726 * Returns list of DPIDs in test topology.
727 * @return List of DPIDs
728 */
729 @SuppressWarnings("serial")
730 private List<Long> getDpids() {
731 List<Long> dpids = new ArrayList<Long>() {{
732 add(Long.decode("0x0000000000000a01"));
733 add(Long.decode("0x0000000000000a02"));
734 add(Long.decode("0x0000000000000a03"));
735 }};
736
737 return dpids;
738 }
739
740 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700741 * Returns new {@link Link} object of an existing link
Naoki Shiotac88d9562013-06-18 15:21:56 -0700742 * @return new Link object
743 */
744 private Link createExistingLink() {
745 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
746 }
747
748 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700749 * Returns new {@link Link} object of a not-existing but feasible link
mininet9d203de2013-06-05 08:40:45 -0700750 * @return new Link object
751 */
mininet403d5892013-06-05 03:48:17 -0700752 private Link createFeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700753 return new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1);
mininet403d5892013-06-05 03:48:17 -0700754 }
755
mininet9d203de2013-06-05 08:40:45 -0700756 // make NO sense while test-network data doesn't define physical network (i.e. any link is feasible)
mininet403d5892013-06-05 03:48:17 -0700757 @SuppressWarnings("unused")
758 private Link createInfeasibleLink() {
Naoki Shiotac88d9562013-06-18 15:21:56 -0700759 return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a03"), 3);
mininet403d5892013-06-05 03:48:17 -0700760 }
761
mininet9d203de2013-06-05 08:40:45 -0700762 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700763 * Returns list of existing {@link Link} objects
mininet9d203de2013-06-05 08:40:45 -0700764 * @return ArrayList of new Link objects
765 */
mininet403d5892013-06-05 03:48:17 -0700766 private List<Link> createExistingLinks() {
767 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700768 links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
769 links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
mininet403d5892013-06-05 03:48:17 -0700770 return links;
771 }
772
mininet9d203de2013-06-05 08:40:45 -0700773 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700774 * Returns list of {@link Link} objects that are all not-existing but feasible
mininet9d203de2013-06-05 08:40:45 -0700775 * @return ArrayList of new Link objects
776 */
mininet403d5892013-06-05 03:48:17 -0700777 private List<Link> createFeasibleLinks() {
778 List<Link> links = new ArrayList<Link>();
Naoki Shiotac88d9562013-06-18 15:21:56 -0700779 links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a02"), 2));
780 links.add(new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1));
mininet403d5892013-06-05 03:48:17 -0700781 return links;
782 }
Naoki Shiotacae568a2013-06-05 17:53:41 -0700783
784 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700785 * Returns new {@link LinkInfo} object with convenient values.
Naoki Shiotacae568a2013-06-05 17:53:41 -0700786 * @return LinkInfo object
787 */
788 private LinkInfo createFeasibleLinkInfo(long time) {
789 long time_first = time;
790 long time_last_lldp = time + 50;
791 long time_last_bddp = time + 100;
792 int state_src = OFPhysicalPort.OFPortState.OFPPS_STP_FORWARD.getValue();
793 int state_dst = OFPhysicalPort.OFPortState.OFPPS_STP_LISTEN.getValue();
794
795 return new LinkInfo(time_first,
796 time_last_lldp,
797 time_last_bddp,
798 state_src,
799 state_dst);
800 }
mininet403d5892013-06-05 03:48:17 -0700801 //---------------------------------------------------------------
Jonathan Hartb7e3d2c2013-01-15 18:45:19 -0800802}