2 * Copyright (c) 2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package io.fd.honeycomb.translate.v3po.vppclassifier;
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23 import static org.mockito.Matchers.any;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
29 import io.fd.honeycomb.translate.v3po.test.TestHelperUtils;
30 import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest;
31 import io.fd.honeycomb.translate.write.WriteFailedException;
32 import java.util.concurrent.CompletableFuture;
33 import java.util.concurrent.ExecutionException;
34 import org.junit.Test;
35 import org.mockito.ArgumentCaptor;
36 import org.mockito.Mock;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.PacketHandlingAction;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifier;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNode;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTable;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableKey;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.openvpp.jvpp.VppBaseCallException;
47 import org.openvpp.jvpp.core.dto.ClassifyAddDelTable;
48 import org.openvpp.jvpp.core.dto.ClassifyAddDelTableReply;
49 import org.openvpp.jvpp.core.dto.L2InterfaceVlanTagRewriteReply;
51 public class ClassifyTableWriterTest extends WriterCustomizerTest {
53 private static final int TABLE_INDEX = 123;
54 private static final String TABLE_NAME = "table123";
57 private VppClassifierContextManager classifierContext;
59 private ClassifyTableWriter customizer;
62 public void setUp() throws Exception {
63 customizer = new ClassifyTableWriter(api, classifierContext);
66 private static ClassifyTable generateClassifyTable(final String name) {
67 final ClassifyTableBuilder builder = new ClassifyTableBuilder();
68 builder.setName(name);
69 builder.setClassifierNode(new VppNodeName("ip4-classifier"));
70 builder.setKey(new ClassifyTableKey(name));
71 builder.setSkipNVectors(0L);
72 builder.setNbuckets(2L);
73 builder.setMemorySize(2L << 20);
74 builder.setMissNext(new VppNode(PacketHandlingAction.Permit));
75 builder.setMask(new HexString("00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"));
76 return builder.build();
79 private static InstanceIdentifier<ClassifyTable> getClassifyTableId(final String name) {
80 return InstanceIdentifier.create(VppClassifier.class)
81 .child(ClassifyTable.class, new ClassifyTableKey(name));
84 private void whenClassifyAddDelTableThenSuccess() throws ExecutionException, InterruptedException {
85 final CompletableFuture<ClassifyAddDelTableReply> replyFuture = new CompletableFuture<>();
86 final ClassifyAddDelTableReply reply = new ClassifyAddDelTableReply();
87 reply.newTableIndex = TABLE_INDEX;
88 replyFuture.complete(reply);
89 doReturn(replyFuture).when(api).classifyAddDelTable(any(ClassifyAddDelTable.class));
92 private void whenClassifyAddDelTableThenFailure() throws ExecutionException, InterruptedException {
93 doReturn(TestHelperUtils.<L2InterfaceVlanTagRewriteReply>createFutureException()).when(api)
94 .classifyAddDelTable(any(ClassifyAddDelTable.class));
97 private void verifyClassifyAddDelTableAddWasInvoked(final ClassifyAddDelTable expected) {
98 ArgumentCaptor<ClassifyAddDelTable> argumentCaptor = ArgumentCaptor.forClass(ClassifyAddDelTable.class);
99 verify(api).classifyAddDelTable(argumentCaptor.capture());
100 final ClassifyAddDelTable actual = argumentCaptor.getValue();
101 assertEquals(expected.isAdd, actual.isAdd);
102 assertEquals(~0, actual.tableIndex);
103 assertEquals(expected.nbuckets, actual.nbuckets);
104 assertEquals(expected.memorySize, actual.memorySize);
105 assertEquals(expected.skipNVectors, actual.skipNVectors);
106 assertEquals(expected.matchNVectors, actual.matchNVectors);
107 assertEquals(expected.nextTableIndex, actual.nextTableIndex);
108 assertEquals(expected.missNextIndex, actual.missNextIndex);
109 assertArrayEquals(expected.mask, actual.mask);
112 private void verifyClassifyAddDelTableDeleteWasInvoked(final ClassifyAddDelTable expected) {
113 ArgumentCaptor<ClassifyAddDelTable> argumentCaptor = ArgumentCaptor.forClass(ClassifyAddDelTable.class);
114 verify(api).classifyAddDelTable(argumentCaptor.capture());
115 final ClassifyAddDelTable actual = argumentCaptor.getValue();
116 assertEquals(expected.isAdd, actual.isAdd);
117 assertEquals(expected.tableIndex, actual.tableIndex);
120 private static ClassifyAddDelTable generateClassifyAddDelTable(final byte isAdd, final int tableIndex) {
121 final ClassifyAddDelTable request = new ClassifyAddDelTable();
122 request.isAdd = isAdd;
123 request.tableIndex = tableIndex;
124 request.nbuckets = 2;
125 request.memorySize = 2 << 20;
126 request.skipNVectors = 0;
127 request.matchNVectors = 1;
128 request.nextTableIndex = ~0;
129 request.missNextIndex = ~0;
131 new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
132 (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
137 public void testCreate() throws Exception {
138 final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
139 final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
141 whenClassifyAddDelTableThenSuccess();
143 customizer.writeCurrentAttributes(id, classifyTable, writeContext);
145 verifyClassifyAddDelTableAddWasInvoked(generateClassifyAddDelTable((byte) 1, TABLE_INDEX));
146 verify(classifierContext)
147 .addTable(TABLE_INDEX, classifyTable.getName(), classifyTable.getClassifierNode(), mappingContext);
151 public void testCreateFailed() throws Exception {
152 final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
153 final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
155 whenClassifyAddDelTableThenFailure();
158 customizer.writeCurrentAttributes(id, classifyTable, writeContext);
159 } catch (WriteFailedException.CreateFailedException e) {
160 assertTrue(e.getCause() instanceof VppBaseCallException);
161 verifyClassifyAddDelTableAddWasInvoked(generateClassifyAddDelTable((byte) 1, TABLE_INDEX));
162 verify(classifierContext, times(0))
163 .addTable(TABLE_INDEX, classifyTable.getName(), classifyTable.getClassifierNode(), mappingContext);
166 fail("WriteFailedException.CreateFailedException was expected");
170 public void testDelete() throws Exception {
171 final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
172 final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
174 when(classifierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
175 when(classifierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
176 whenClassifyAddDelTableThenSuccess();
178 customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
180 verifyClassifyAddDelTableDeleteWasInvoked(generateClassifyAddDelTable((byte) 0, TABLE_INDEX));
184 public void testDeleteFailed() throws Exception {
185 final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
186 final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
188 when(classifierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
189 when(classifierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
190 whenClassifyAddDelTableThenFailure();
193 customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
194 } catch (WriteFailedException.DeleteFailedException e) {
195 assertTrue(e.getCause() instanceof VppBaseCallException);
196 verifyClassifyAddDelTableDeleteWasInvoked(generateClassifyAddDelTable((byte) 0, TABLE_INDEX));
199 fail("WriteFailedException.DeleteFailedException was expected");
201 customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
204 @Test(expected = UnsupportedOperationException.class)
205 public void testUpdate() throws Exception {
206 final ClassifyTable classifyTableBefore = generateClassifyTable(TABLE_NAME);
207 final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
208 customizer.updateCurrentAttributes(id, classifyTableBefore, new ClassifyTableBuilder().build(), writeContext);