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.openflow.registry.flow.FlowDescriptor;
37 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
55 * Test for {@link DeviceFlowRegistryImpl}.
57 @RunWith(MockitoJUnitRunner.class)
58 public class DeviceFlowRegistryImplTest {
59 private static final String NODE_ID = "openflow:1";
60 private static final Pattern INDEX_PATTERN = Pattern.compile("^#UF\\$TABLE\\*1-([0-9]+)$");
61 private static final Short DUMMY_TABLE_ID = 1;
63 private DeviceFlowRegistryImpl deviceFlowRegistry;
64 private FlowRegistryKey key;
65 private FlowDescriptor descriptor;
66 private KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
68 private DataBroker dataBroker;
70 private ReadOnlyTransaction readOnlyTransaction;
73 public void setUp() throws Exception {
74 nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(NODE_ID)));
75 when(dataBroker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
76 deviceFlowRegistry = new DeviceFlowRegistryImpl(dataBroker, nodeInstanceIdentifier);
77 final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(1).build();
78 key = FlowRegistryKeyFactory.create(flowStats);
79 descriptor = FlowDescriptorFactory.create(key.getTableId(), new FlowId("ut:1"));
81 Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
82 deviceFlowRegistry.store(key, descriptor);
83 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
87 public void testFill() throws Exception {
88 final InstanceIdentifier<FlowCapableNode> path = nodeInstanceIdentifier.augmentation(FlowCapableNode.class);
90 final Flow flow = new FlowBuilder()
93 .setCookie(new FlowCookie(BigInteger.TEN))
94 .setId(new FlowId("HELLO"))
97 final Table table = new TableBuilder()
98 .setFlow(Collections.singletonList(flow))
101 final FlowCapableNode flowCapableNode = new FlowCapableNodeBuilder()
102 .setTable(Collections.singletonList(table))
105 final Map<FlowRegistryKey, FlowDescriptor> allFlowDescriptors = testFill(path, flowCapableNode);
106 final FlowRegistryKey key = FlowRegistryKeyFactory.create(flow);
108 InOrder order = inOrder(dataBroker, readOnlyTransaction);
109 order.verify(dataBroker).newReadOnlyTransaction();
110 order.verify(readOnlyTransaction).read(LogicalDatastoreType.CONFIGURATION, path);
111 order.verify(dataBroker).newReadOnlyTransaction();
112 order.verify(readOnlyTransaction).read(LogicalDatastoreType.OPERATIONAL, path);
113 assertTrue(allFlowDescriptors.containsKey(key));
115 deviceFlowRegistry.removeDescriptor(key);
119 public void testFailedFill() throws Exception {
120 final InstanceIdentifier<FlowCapableNode> path = nodeInstanceIdentifier.augmentation(FlowCapableNode.class);
122 testFill(path, null);
124 testFill(path, new FlowCapableNodeBuilder()
128 testFill(path, new FlowCapableNodeBuilder()
129 .setTable(Collections.singletonList(null))
132 testFill(path, new FlowCapableNodeBuilder()
133 .setTable(Collections.singletonList(new TableBuilder()
138 testFill(path, new FlowCapableNodeBuilder()
139 .setTable(Collections.singletonList(new TableBuilder()
140 .setFlow(Collections.singletonList(null))
144 testFill(path, new FlowCapableNodeBuilder()
145 .setTable(Collections.singletonList(new TableBuilder()
146 .setFlow(Collections.singletonList(new FlowBuilder()
152 verify(dataBroker, times(12)).newReadOnlyTransaction();
153 verify(readOnlyTransaction, times(6)).read(LogicalDatastoreType.CONFIGURATION, path);
154 verify(readOnlyTransaction, times(6)).read(LogicalDatastoreType.OPERATIONAL, path);
156 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
159 private Map<FlowRegistryKey, FlowDescriptor> testFill(final InstanceIdentifier<FlowCapableNode> path,
160 final FlowCapableNode flowCapableNode) throws Exception {
161 when(readOnlyTransaction.read(any(), any())).thenReturn(Futures.immediateCheckedFuture(Optional.fromNullable(flowCapableNode)));
162 deviceFlowRegistry.fill().get();
163 return deviceFlowRegistry.getAllFlowDescriptors();
167 public void testRetrieveIdForFlow() throws Exception {
168 Assert.assertEquals(descriptor, deviceFlowRegistry.retrieveIdForFlow(key));
172 public void testStore() throws Exception {
173 //store the same key with different value
174 final FlowDescriptor descriptor2 = FlowDescriptorFactory.create(key.getTableId(), new FlowId("ut:2"));
175 deviceFlowRegistry.store(key, descriptor2);
176 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
177 Assert.assertEquals("ut:2", deviceFlowRegistry.retrieveIdForFlow(key).getFlowId().getValue());
179 // store new key with old value
180 final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build();
181 final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(flowStats);
182 deviceFlowRegistry.store(key2, descriptor);
183 Assert.assertEquals(2, deviceFlowRegistry.getAllFlowDescriptors().size());
184 Assert.assertEquals("ut:1", deviceFlowRegistry.retrieveIdForFlow(key2).getFlowId().getValue());
188 public void testStoreIfNecessary() throws Exception {
192 newFlowId = deviceFlowRegistry.storeIfNecessary(key);
194 Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
195 Assert.assertEquals(descriptor, deviceFlowRegistry.retrieveIdForFlow(key));
196 Assert.assertEquals(descriptor.getFlowId(), newFlowId);
199 final String alienPrefix = "#UF$TABLE*2-";
200 final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build());
201 newFlowId = deviceFlowRegistry.storeIfNecessary(key2);
203 Assert.assertTrue(newFlowId.getValue().startsWith(alienPrefix));
204 Assert.assertTrue(deviceFlowRegistry.retrieveIdForFlow(key2).getFlowId().getValue().startsWith(alienPrefix));
205 Assert.assertEquals(2, deviceFlowRegistry.getAllFlowDescriptors().size());
209 public void testRemoveDescriptor() throws Exception {
210 deviceFlowRegistry.removeDescriptor(key);
211 Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
215 public void testClose() throws Exception {
216 deviceFlowRegistry.close();
217 Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
221 public void createAlienFlowIdTest() throws Exception {
222 final String alienFlowId1 = DeviceFlowRegistryImpl.createAlienFlowId(DUMMY_TABLE_ID).getValue();
223 final Integer index1 = parseIndex(alienFlowId1);
224 final String alienFlowId2 = DeviceFlowRegistryImpl.createAlienFlowId(DUMMY_TABLE_ID).getValue();
225 final Integer index2 = parseIndex(alienFlowId2);
227 assertNotNull("index1 parsing failed: " + alienFlowId1, index1);
228 assertNotNull("index2 parsing failed: " + alienFlowId2, index2);
229 assertTrue(index1 < index2);
232 private static Integer parseIndex(String alienFlowIdValue) {
233 final Matcher mach = INDEX_PATTERN.matcher(alienFlowIdValue);
236 return Integer.valueOf(mach.group(1));