2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.registry.flow;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.mockito.Matchers.any;
14 import static org.mockito.Mockito.inOrder;
15 import static org.mockito.Mockito.times;
16 import static org.mockito.Mockito.verify;
17 import static org.mockito.Mockito.when;
19 import com.google.common.base.Optional;
20 import com.google.common.util.concurrent.Futures;
21 import java.math.BigInteger;
22 import java.util.Collections;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import org.junit.Assert;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.mockito.InOrder;
31 import org.mockito.Mock;
32 import org.mockito.runners.MockitoJUnitRunner;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.openflowplugin.api.OFConstants;
37 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
38 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
56 * Test for {@link DeviceFlowRegistryImpl}.
58 @RunWith(MockitoJUnitRunner.class)
59 public class DeviceFlowRegistryImplTest {
60 private static final String NODE_ID = "openflow:1";
61 private static final Pattern INDEX_PATTERN = Pattern.compile("^#UF\\$TABLE\\*1-([0-9]+)$");
62 private static final Short DUMMY_TABLE_ID = 1;
64 private DeviceFlowRegistryImpl deviceFlowRegistry;
65 private FlowRegistryKey key;
66 private FlowDescriptor descriptor;
67 private KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
69 private DataBroker dataBroker;
71 private ReadOnlyTransaction readOnlyTransaction;
74 public void setUp() throws Exception {
75 nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(NODE_ID)));
76 when(dataBroker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
77 deviceFlowRegistry = new DeviceFlowRegistryImpl(OFConstants.OFP_VERSION_1_3, dataBroker, nodeInstanceIdentifier);
78 final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(1).build();
79 key = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, flowStats);
80 descriptor = FlowDescriptorFactory.create(key.getTableId(), new FlowId("ut:1"));
82 Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
83 deviceFlowRegistry.storeDescriptor(key, descriptor);
84 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
88 public void testFill() throws Exception {
89 final InstanceIdentifier<FlowCapableNode> path = nodeInstanceIdentifier.augmentation(FlowCapableNode.class);
91 final Flow flow = new FlowBuilder()
94 .setCookie(new FlowCookie(BigInteger.TEN))
95 .setId(new FlowId("HELLO"))
98 final Table table = new TableBuilder()
99 .setFlow(Collections.singletonList(flow))
102 final FlowCapableNode flowCapableNode = new FlowCapableNodeBuilder()
103 .setTable(Collections.singletonList(table))
106 final Map<FlowRegistryKey, FlowDescriptor> allFlowDescriptors = testFill(path, flowCapableNode);
107 final FlowRegistryKey key = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, flow);
109 InOrder order = inOrder(dataBroker, readOnlyTransaction);
110 order.verify(dataBroker).newReadOnlyTransaction();
111 order.verify(readOnlyTransaction).read(LogicalDatastoreType.CONFIGURATION, path);
112 order.verify(dataBroker).newReadOnlyTransaction();
113 order.verify(readOnlyTransaction).read(LogicalDatastoreType.OPERATIONAL, path);
114 assertTrue(allFlowDescriptors.containsKey(key));
116 deviceFlowRegistry.addMark(key);
120 public void testFailedFill() throws Exception {
121 final InstanceIdentifier<FlowCapableNode> path = nodeInstanceIdentifier.augmentation(FlowCapableNode.class);
123 testFill(path, null);
125 testFill(path, new FlowCapableNodeBuilder()
129 testFill(path, new FlowCapableNodeBuilder()
130 .setTable(Collections.singletonList(null))
133 testFill(path, new FlowCapableNodeBuilder()
134 .setTable(Collections.singletonList(new TableBuilder()
139 testFill(path, new FlowCapableNodeBuilder()
140 .setTable(Collections.singletonList(new TableBuilder()
141 .setFlow(Collections.singletonList(null))
145 testFill(path, new FlowCapableNodeBuilder()
146 .setTable(Collections.singletonList(new TableBuilder()
147 .setFlow(Collections.singletonList(new FlowBuilder()
153 verify(dataBroker, times(12)).newReadOnlyTransaction();
154 verify(readOnlyTransaction, times(6)).read(LogicalDatastoreType.CONFIGURATION, path);
155 verify(readOnlyTransaction, times(6)).read(LogicalDatastoreType.OPERATIONAL, path);
157 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
160 private Map<FlowRegistryKey, FlowDescriptor> testFill(final InstanceIdentifier<FlowCapableNode> path,
161 final FlowCapableNode flowCapableNode) throws Exception {
162 when(readOnlyTransaction.read(any(), any())).thenReturn(Futures.immediateCheckedFuture(Optional.fromNullable(flowCapableNode)));
163 deviceFlowRegistry.fill().get();
164 return deviceFlowRegistry.getAllFlowDescriptors();
168 public void testRetrieveIdForFlow() throws Exception {
169 Assert.assertEquals(descriptor, deviceFlowRegistry.retrieveDescriptor(key));
173 public void testStore() throws Exception {
174 //store the same key with different value
175 final FlowDescriptor descriptor2 = FlowDescriptorFactory.create(key.getTableId(), new FlowId("ut:2"));
176 deviceFlowRegistry.storeDescriptor(key, descriptor2);
177 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
178 Assert.assertEquals("ut:2", deviceFlowRegistry.retrieveDescriptor(key).getFlowId().getValue());
180 // store new key with old value
181 final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build();
182 final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, flowStats);
183 deviceFlowRegistry.storeDescriptor(key2, descriptor);
184 Assert.assertEquals(2, deviceFlowRegistry.getAllFlowDescriptors().size());
185 Assert.assertEquals("ut:1", deviceFlowRegistry.retrieveDescriptor(key2).getFlowId().getValue());
189 public void testStoreIfNecessary() throws Exception {
193 deviceFlowRegistry.store(key);
194 newFlowId = deviceFlowRegistry.retrieveDescriptor(key).getFlowId();
196 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
197 Assert.assertEquals(descriptor, deviceFlowRegistry.retrieveDescriptor(key));
198 Assert.assertEquals(descriptor.getFlowId(), newFlowId);
201 final String alienPrefix = "#UF$TABLE*2-";
202 final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build());
203 deviceFlowRegistry.store(key2);
204 newFlowId = deviceFlowRegistry.retrieveDescriptor(key2).getFlowId();
206 Assert.assertTrue(newFlowId.getValue().startsWith(alienPrefix));
207 Assert.assertTrue(deviceFlowRegistry.retrieveDescriptor(key2).getFlowId().getValue().startsWith(alienPrefix));
208 Assert.assertEquals(2, deviceFlowRegistry.getAllFlowDescriptors().size());
212 public void testRemoveDescriptor() throws Exception {
213 deviceFlowRegistry.addMark(key);
214 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
218 public void testClose() throws Exception {
219 deviceFlowRegistry.close();
220 Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
224 public void createAlienFlowIdTest() throws Exception {
225 final String alienFlowId1 = DeviceFlowRegistryImpl.createAlienFlowId(DUMMY_TABLE_ID).getValue();
226 final Integer index1 = parseIndex(alienFlowId1);
227 final String alienFlowId2 = DeviceFlowRegistryImpl.createAlienFlowId(DUMMY_TABLE_ID).getValue();
228 final Integer index2 = parseIndex(alienFlowId2);
230 assertNotNull("index1 parsing failed: " + alienFlowId1, index1);
231 assertNotNull("index2 parsing failed: " + alienFlowId2, index2);
232 assertTrue(index1 < index2);
235 private static Integer parseIndex(String alienFlowIdValue) {
236 final Matcher mach = INDEX_PATTERN.matcher(alienFlowIdValue);
239 return Integer.valueOf(mach.group(1));