From 355c2205a7088bc7b3ccabc278c477b838975c65 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Fri, 1 Apr 2016 12:33:39 +0200 Subject: VPP API <-> YANG translation layer integration #2(Writers) Change-Id: If91364f1900693b040aee163f1c6e092381b0efd Signed-off-by: Maros Marsalek Signed-off-by: Marek Gradzki --- .../v3po/impl/data/VPPConfigDataTreeTest.java | 54 +++-- .../VppDataBrokerInitializationProviderTest.java | 5 +- .../impl/trans/VppApiInvocationExceptionTest.java | 46 ++++ .../trans/w/util/TransactionWriteContextTest.java | 122 ++++++++++ .../impl/trans0/VppApiInvocationExceptionTest.java | 46 ---- .../v3po/impl/vpp/BridgeDomainCustomizerTest.java | 269 +++++++++++++++++++++ .../v3po/impl/vpp/BridgeDomainTestUtils.java | 64 +++++ .../io/fd/honeycomb/v3po/impl/vpp/VppTest.java | 13 +- 8 files changed, 542 insertions(+), 77 deletions(-) create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationExceptionTest.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContextTest.java delete mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationExceptionTest.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizerTest.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainTestUtils.java (limited to 'v3po/impl/src/test') diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VPPConfigDataTreeTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VPPConfigDataTreeTest.java index 4e855f447..6aa9da57c 100644 --- a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VPPConfigDataTreeTest.java +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VPPConfigDataTreeTest.java @@ -16,10 +16,12 @@ package io.fd.honeycomb.v3po.impl.data; +import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -31,17 +33,17 @@ import static org.mockito.MockitoAnnotations.initMocks; import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; -import io.fd.honeycomb.v3po.impl.trans0.VppApiInvocationException; -import io.fd.honeycomb.v3po.impl.trans0.VppWriter; +import io.fd.honeycomb.v3po.impl.trans.w.WriteContext; +import io.fd.honeycomb.v3po.impl.trans.VppApiInvocationException; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Test; +import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -67,7 +69,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailed public class VPPConfigDataTreeTest { @Mock - private VppWriter vppWriter; + private VppWriterRegistry vppWriter; @Mock private BindingNormalizedNodeSerializer serializer; @Mock @@ -135,7 +137,8 @@ public class VPPConfigDataTreeTest { proxy.commit(modification); // Verify all changes were processed: - verify(vppWriter).process(dataBefore, dataAfter); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore)), + eq(singletonList(dataAfter)), any(WriteContext.class)); // Verify modification was validated verify(dataTree).validate(modification); @@ -155,8 +158,9 @@ public class VPPConfigDataTreeTest { final List> processedChanges = new ArrayList<>(); // reject third applied change - final Answer answer = new VppWriterAnswer(processedChanges, Arrays.asList(1,2), Collections.singletonList(3)); - doAnswer(answer).when(vppWriter).process(any(DataObject.class), any(DataObject.class)); + final Answer answer = new VppWriterAnswer(processedChanges, Arrays.asList(1,2), singletonList(3)); + doAnswer(answer).when(vppWriter).update(Matchers.>any(), anyListOf(DataObject.class), + anyListOf(DataObject.class), any(WriteContext.class)); // Prepare modification: final DataTreeCandidateNode rootNode = mockRootNode(); @@ -172,16 +176,20 @@ public class VPPConfigDataTreeTest { proxy.commit(modification); } catch (DataValidationFailedException | VppApiInvocationException e) { // verify that all changes were processed: - verify(vppWriter).process(dataBefore1, dataAfter1); - verify(vppWriter).process(dataBefore2, dataAfter2); - verify(vppWriter).process(dataBefore3, dataAfter3); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore1)), + eq(singletonList(dataAfter1)), any(WriteContext.class)); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore2)), + eq(singletonList(dataAfter2)), any(WriteContext.class)); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore3)), + eq(singletonList(dataAfter3)), any(WriteContext.class)); // verify that only two changes were processed successfully: assertEquals(2, processedChanges.size()); // verify that successful changes were undone for (final Map.Entry change : processedChanges) { - verify(vppWriter).process(change.getValue(), change.getKey()); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(change.getValue())), + eq(singletonList(change.getKey())), any(WriteContext.class)); } return; } @@ -204,7 +212,8 @@ public class VPPConfigDataTreeTest { // reject third applied change and fourth (first undo): final List> processedChanges = new ArrayList<>(); final Answer answer = new VppWriterAnswer(processedChanges, Arrays.asList(1,2), Arrays.asList(3,4)); - doAnswer(answer).when(vppWriter).process(any(DataObject.class), any(DataObject.class)); + doAnswer(answer).when(vppWriter).update(Matchers.>any(), anyListOf(DataObject.class), + anyListOf(DataObject.class), any(WriteContext.class)); // Prepare modification: final DataTreeCandidateNode rootNode = mockRootNode(); @@ -220,20 +229,25 @@ public class VPPConfigDataTreeTest { proxy.commit(modification); } catch (DataValidationFailedException | VppApiInvocationException e) { // verify that all changes were processed: - verify(vppWriter).process(dataBefore1, dataAfter1); - verify(vppWriter).process(dataBefore2, dataAfter2); - verify(vppWriter).process(dataBefore3, dataAfter3); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore1)), + eq(singletonList(dataAfter1)), any(WriteContext.class)); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore2)), + eq(singletonList(dataAfter2)), any(WriteContext.class)); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(dataBefore3)), + eq(singletonList(dataAfter3)), any(WriteContext.class)); // verify that only two changes were processed successfully: assertEquals(2, processedChanges.size()); // verify we tried to undo the last successful change: Map.Entry change = processedChanges.get(1); - verify(vppWriter).process(change.getValue(), change.getKey()); + verify(vppWriter).update(Matchers.>any(), eq(singletonList(change.getValue())), + eq(singletonList(change.getKey())), any(WriteContext.class)); // but failed, and did not try to undo the first: change = processedChanges.get(0); - verify(vppWriter, never()).process(change.getValue(), change.getKey()); + verify(vppWriter, never()).update(Matchers.>any(), eq(singletonList(change.getValue())), + eq(singletonList(change.getKey())), any(WriteContext.class)); return; } @@ -295,12 +309,12 @@ public class VPPConfigDataTreeTest { public Object answer(final InvocationOnMock invocation) throws Throwable { ++count; if (toCapture.contains(count)) { - final DataObject dataBefore = (DataObject)invocation.getArguments()[0]; - final DataObject dataAfter = (DataObject)invocation.getArguments()[1]; + final DataObject dataBefore = (DataObject) ((List)invocation.getArguments()[1]).get(0); + final DataObject dataAfter = (DataObject) ((List)invocation.getArguments()[2]).get(0); capturedChanges.add(new AbstractMap.SimpleImmutableEntry<>(dataBefore, dataAfter)); } if (toReject.contains(count)) { - throw mock(VppApiInvocationException.class); + throw mock(RuntimeException.class); } return null; } diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProviderTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProviderTest.java index 5ac1f0130..30cebf2f9 100644 --- a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProviderTest.java +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerInitializationProviderTest.java @@ -44,14 +44,17 @@ public class VppDataBrokerInitializationProviderTest { private WriteTransaction writeTx; @Mock private ReaderRegistry readerRegistry; + @Mock + private VppWriterRegistry writerRegistry; private VppDataBrokerInitializationProvider provider; + @Before public void setUp() throws Exception { initMocks(this); doReturn(writeTx).when(bindingBroker).newWriteOnlyTransaction(); - provider = new VppDataBrokerInitializationProvider(bindingBroker, readerRegistry); + provider = new VppDataBrokerInitializationProvider(bindingBroker, readerRegistry, writerRegistry); } @Test diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationExceptionTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationExceptionTest.java new file mode 100644 index 000000000..fed792a3b --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationExceptionTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.trans; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Random; +import org.junit.Test; + +public class VppApiInvocationExceptionTest { + + @Test + public void testInstantiation() { + final String apiMethodName = "methodName"; + final int ctxId = 1; + final int code = -1; + VppApiInvocationException e = new VppApiInvocationException(apiMethodName, ctxId, code); + assertEquals(apiMethodName, e.getMethodName()); + assertEquals(ctxId, e.getCtxId()); + assertEquals(code, e.getErrorCode()); + assertTrue(e.getMessage().contains(apiMethodName)); + assertTrue(e.getMessage().contains(String.valueOf(code))); + assertTrue(e.getMessage().contains(String.valueOf(ctxId))); + } + + @Test(expected = IllegalArgumentException.class) + public void testInstantiationFailed() { + final int code = new Random().nextInt(Integer.MAX_VALUE); + VppApiInvocationException e = new VppApiInvocationException("apiMethodName", 1, code); + } +} diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContextTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContextTest.java new file mode 100644 index 000000000..1a6cf3a5b --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContextTest.java @@ -0,0 +1,122 @@ +package io.fd.honeycomb.v3po.impl.trans.w.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import io.fd.honeycomb.v3po.impl.trans.util.Context; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +public class TransactionWriteContextTest { + + @Mock + private BindingNormalizedNodeSerializer serializer; + @Mock + private DOMDataReadOnlyTransaction beforeTx; + @Mock + private DOMDataReadOnlyTransaction afterTx; + @Mock + private CheckedFuture>, ReadFailedException> future; + @Mock + private Optional> optional; + @Mock + private Map.Entry entry; + + private TransactionWriteContext transactionWriteContext; + + @Before + public void setUp() { + initMocks(this); + transactionWriteContext = new TransactionWriteContext(serializer, beforeTx, afterTx); + } + + @Test + public void testReadBeforeNoData() throws Exception { + when(beforeTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(future); + when(future.checkedGet()).thenReturn(optional); + when(optional.isPresent()).thenReturn(false); + + final InstanceIdentifier instanceId = + InstanceIdentifier.create(Vpp.class).child(BridgeDomains.class).child(BridgeDomain.class); + + final List dataObjects = transactionWriteContext.readBefore(instanceId); + assertNotNull(dataObjects); + assertTrue(dataObjects.isEmpty()); + + verify(serializer).toYangInstanceIdentifier(instanceId); + verify(serializer, never()).fromNormalizedNode(any(YangInstanceIdentifier.class), any(NormalizedNode.class)); + } + + + @Test + public void testReadBefore() throws Exception { + when(beforeTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(future); + when(future.checkedGet()).thenReturn(optional); + when(optional.isPresent()).thenReturn(true); + + final InstanceIdentifier instanceId = + InstanceIdentifier.create(Vpp.class).child(BridgeDomains.class).child(BridgeDomain.class); + final YangInstanceIdentifier yangId = YangInstanceIdentifier.builder().node(VppState.QNAME).node( + BridgeDomains.QNAME).node(BridgeDomain.QNAME).build(); + when(serializer.toYangInstanceIdentifier(any(InstanceIdentifier.class))).thenReturn(yangId); + when(serializer.fromNormalizedNode(eq(yangId), any(NormalizedNode.class))).thenReturn(entry); + + final List dataObjects = transactionWriteContext.readBefore(instanceId); + assertNotNull(dataObjects); + assertFalse(dataObjects.isEmpty()); + + verify(serializer).toYangInstanceIdentifier(instanceId); + verify(serializer).fromNormalizedNode(eq(yangId), any(NormalizedNode.class)); + } + + @Test(expected = IllegalStateException.class) + public void testReadBeforeFailed() throws Exception { + when(beforeTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(future); + when(future.checkedGet()).thenThrow(ReadFailedException.class); + transactionWriteContext.readBefore(mock(InstanceIdentifier.class)); + } + + @Test(expected = IllegalStateException.class) + public void testReadAfterFailed() throws Exception { + when(afterTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(future); + when(future.checkedGet()).thenThrow(ReadFailedException.class); + transactionWriteContext.readAfter(mock(InstanceIdentifier.class)); + } + + @Test + public void testGetContext() throws Exception { + assertNotNull(transactionWriteContext.getContext()); + } + + @Test + public void testClose() throws Exception { + final Context context = transactionWriteContext.getContext(); + transactionWriteContext.close(); + // TODO verify context was closed + } +} \ No newline at end of file diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationExceptionTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationExceptionTest.java deleted file mode 100644 index e83e541d1..000000000 --- a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/trans0/VppApiInvocationExceptionTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.v3po.impl.trans0; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Random; -import org.junit.Test; - -public class VppApiInvocationExceptionTest { - - @Test - public void testInstantiation() { - final String apiMethodName = "methodName"; - final int ctxId = 1; - final int code = -1; - VppApiInvocationException e = new VppApiInvocationException(apiMethodName, ctxId, code); - assertEquals(apiMethodName, e.getMethodName()); - assertEquals(ctxId, e.getCtxId()); - assertEquals(code, e.getErrorCode()); - assertTrue(e.getMessage().contains(apiMethodName)); - assertTrue(e.getMessage().contains(String.valueOf(code))); - assertTrue(e.getMessage().contains(String.valueOf(ctxId))); - } - - @Test(expected = IllegalArgumentException.class) - public void testInstantiationFailed() { - final int code = new Random().nextInt(Integer.MAX_VALUE); - VppApiInvocationException e = new VppApiInvocationException("apiMethodName", 1, code); - } -} diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizerTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizerTest.java new file mode 100644 index 000000000..4614b875a --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainCustomizerTest.java @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.vpp; + +import static io.fd.honeycomb.v3po.impl.vpp.BridgeDomainTestUtils.BD_NAME_TO_ID_ANSWER; +import static io.fd.honeycomb.v3po.impl.vpp.BridgeDomainTestUtils.bdIdentifierForName; +import static io.fd.honeycomb.v3po.impl.vpp.BridgeDomainTestUtils.bdNameToID; +import static io.fd.honeycomb.v3po.impl.vpp.BridgeDomainTestUtils.booleanToByte; +import static io.fd.honeycomb.v3po.impl.vpp.BridgeDomainTestUtils.intToBoolean; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import io.fd.honeycomb.v3po.impl.trans.util.Context; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.openvpp.vppjapi.vppApi; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@SuppressStaticInitializationFor("org.openvpp.vppjapi.vppConn") +@PrepareForTest(vppApi.class) +public class BridgeDomainCustomizerTest { + + private static final int RESPONSE_NOT_READY = -77; + private static final byte ADD_OR_UPDATE_BD = (byte) 1; + private static final byte ZERO = 0; + private vppApi api; + + @Mock + private Context ctx; + + private BridgeDomainCustomizer customizer; + + @Before + public void setUp() throws Exception { + // TODO create base class for tests using vppApi + api = PowerMockito.mock(vppApi.class); + initMocks(this); + customizer = new BridgeDomainCustomizer(api); + + PowerMockito.doAnswer(BD_NAME_TO_ID_ANSWER).when(api).findOrAddBridgeDomainId(anyString()); + PowerMockito.doAnswer(BD_NAME_TO_ID_ANSWER).when(api).bridgeDomainIdFromName(anyString()); + PowerMockito.when(api.getRetval(anyInt(), anyInt())).thenReturn(RESPONSE_NOT_READY).thenReturn(0); + PowerMockito.doReturn(0).when(api).getRetval(anyInt(), anyInt()); + } + + private BridgeDomain generateBridgeDomain(final String bdName) { + final byte arpTerm = 0; + final byte flood = 1; + final byte forward = 0; + final byte learn = 1; + final byte uuf = 0; + return generateBridgeDomain(bdName, arpTerm, flood, forward, learn, uuf); + } + + private BridgeDomain generateBridgeDomain(final String bdName, final int arpTerm, final int flood, + final int forward, final int learn, final int uuf) { + return new BridgeDomainBuilder() + .setName(bdName) + .setArpTermination(intToBoolean(arpTerm)) + .setFlood(intToBoolean(flood)) + .setForward(intToBoolean(forward)) + .setLearn(intToBoolean(learn)) + .setUnknownUnicastFlood(intToBoolean(uuf)) + .build(); + } + + private final int verifyBridgeDomainAddOrUpdateWasInvoked(final BridgeDomain bd) { + final int bdn1Id = bdNameToID(bd.getName()); + final byte arpTerm = booleanToByte(bd.isArpTermination()); + final byte flood = booleanToByte(bd.isFlood()); + final byte forward = booleanToByte(bd.isForward()); + final byte learn = booleanToByte(bd.isLearn()); + final byte uuf = booleanToByte(bd.isUnknownUnicastFlood()); + return verify(api).bridgeDomainAddDel(bdn1Id, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); + } + + private int verifyBridgeDomainAddOrUpdateWasNotInvoked(final BridgeDomain bd) { + final int bdn1Id = bdNameToID(bd.getName()); + final byte arpTerm = booleanToByte(bd.isArpTermination()); + final byte flood = booleanToByte(bd.isFlood()); + final byte forward = booleanToByte(bd.isForward()); + final byte learn = booleanToByte(bd.isLearn()); + final byte uuf = booleanToByte(bd.isUnknownUnicastFlood()); + return verify(api, never()).bridgeDomainAddDel(bdn1Id, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); + } + + private int verifyBridgeDomainDeletedWasInvoked(final BridgeDomain bd) { + final int bdn1Id = bdNameToID(bd.getName()); + return verify(api).bridgeDomainAddDel(bdn1Id, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO); + } + + private int verifyBridgeDomainDeletedWasNotInvoked(final BridgeDomain bd) { + final int bdn1Id = bdNameToID(bd.getName()); + return verify(api, never()).bridgeDomainAddDel(bdn1Id, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO); + } + + @Test + public void testAddBridgeDomain() { + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain("bd1"); + + customizer.writeCurrentAttributes(bdIdentifierForName(bdName), bd, ctx); + + verifyBridgeDomainAddOrUpdateWasInvoked(bd); + } + + @Test + public void testBridgeDomainNameCreateFailed() { + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain("bd1"); + + // make vpp api fail to create id for our bd name + PowerMockito.doReturn(-1).when(api).findOrAddBridgeDomainId(bdName); + + try { + customizer.writeCurrentAttributes(bdIdentifierForName(bdName), bd, ctx); + } catch (IllegalStateException e) { + verifyBridgeDomainAddOrUpdateWasNotInvoked(bd); + return; + } + fail("IllegalStateException was expected"); + } + + @Test + public void testAddBridgeDomainFailed() { + // make any call to vpp fail + PowerMockito.doReturn(-1).when(api).getRetval(anyInt(), anyInt()); + + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain(bdName); + + try { + customizer.writeCurrentAttributes(bdIdentifierForName(bdName), bd, ctx); + } catch (IllegalStateException e) { + verifyBridgeDomainAddOrUpdateWasInvoked(bd); + return; + } + fail("IllegalStateException was expected"); + } + + @Test + public void testDeleteBridgeDomain() { + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain("bd1"); + + customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, ctx); + + verifyBridgeDomainDeletedWasInvoked(bd); + } + + @Test + public void testDeleteUnknownBridgeDomain() { + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain("bd1"); + + // make vpp api not find our bd + PowerMockito.doReturn(-1).when(api).bridgeDomainIdFromName(bdName); + + try { + customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, ctx); + } catch (IllegalStateException e) { + verifyBridgeDomainDeletedWasNotInvoked(bd); + return; + } + fail("IllegalStateException was expected"); + } + + @Test + public void testDeleteBridgeDomainFailed() { + // make any call to vpp fail + PowerMockito.doReturn(-1).when(api).getRetval(anyInt(), anyInt()); + + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain(bdName); + + try { + customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, ctx); + } catch (IllegalStateException e) { + verifyBridgeDomainDeletedWasInvoked(bd); + return; + } + fail("IllegalStateException was expected"); + } + + @Test + public void testUpdateBridgeDomain() throws Exception { + final String bdName = "bd1"; + final byte arpTermBefore = 1; + final byte floodBefore = 1; + final byte forwardBefore = 0; + final byte learnBefore = 1; + final byte uufBefore = 0; + + final BridgeDomain dataBefore = + generateBridgeDomain(bdName, arpTermBefore, floodBefore, forwardBefore, learnBefore, uufBefore); + final BridgeDomain dataAfter = + generateBridgeDomain(bdName, arpTermBefore ^ 1, floodBefore ^ 1, forwardBefore ^ 1, learnBefore ^ 1, + uufBefore ^ 1); + + final KeyedInstanceIdentifier id = bdIdentifierForName(bdName); + + customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx); + + verifyBridgeDomainAddOrUpdateWasInvoked(dataAfter); + } + + @Test + public void testUpdateUnknownBridgeDomain() throws Exception { + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain("bd1"); + + // make vpp api not find our bd + PowerMockito.doReturn(-1).when(api).bridgeDomainIdFromName(bdName); + + try { + customizer.updateCurrentAttributes(bdIdentifierForName(bdName), bd, bd, ctx); + } catch (IllegalStateException e) { + verifyBridgeDomainAddOrUpdateWasNotInvoked(bd); + return; + } + fail("IllegalStateException was expected"); + } + + @Test + public void testUpdateBridgeDomainFailed() { + // make any call to vpp fail + PowerMockito.doReturn(-1).when(api).getRetval(anyInt(), anyInt()); + + final String bdName = "bd1"; + final BridgeDomain bd = generateBridgeDomain(bdName); + + try { + customizer.updateCurrentAttributes(bdIdentifierForName(bdName), bd, bd, ctx); + } catch (IllegalStateException e) { + verifyBridgeDomainAddOrUpdateWasInvoked(bd); + return; + } + fail("IllegalStateException was expected"); + } + +} \ No newline at end of file diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainTestUtils.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainTestUtils.java new file mode 100644 index 000000000..6930493b6 --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/BridgeDomainTestUtils.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.vpp; + +import javax.annotation.Nullable; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +final class BridgeDomainTestUtils { + + private BridgeDomainTestUtils() { + throw new UnsupportedOperationException("Utility class cannot be instantiated."); + } + + public static byte booleanToByte(@Nullable final Boolean value) { + return value != null && value ? (byte) 1 : (byte) 0; + } + + @Nullable + public static Boolean intToBoolean(final int value) { + if (value == 0) { + return Boolean.FALSE; + } + if (value == 1) { + return Boolean.TRUE; + } + return null; + } + + public static int bdNameToID(String bName) { + return Integer.parseInt(((Character)bName.charAt(bName.length() - 1)).toString()); + } + + public static KeyedInstanceIdentifier bdIdentifierForName( + final String bdName) { + return InstanceIdentifier.create(BridgeDomains.class).child(BridgeDomain.class, new BridgeDomainKey(bdName)); + } + + public static final Answer BD_NAME_TO_ID_ANSWER = new Answer() { + @Override + public Integer answer(final InvocationOnMock invocationOnMock) throws Throwable { + return bdNameToID((String) invocationOnMock.getArguments()[0]); + } + }; +} \ No newline at end of file diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/VppTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/VppTest.java index beec76ab1..bf7b9de4b 100644 --- a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/VppTest.java +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vpp/VppTest.java @@ -16,6 +16,7 @@ package io.fd.honeycomb.v3po.impl.vpp; +import static io.fd.honeycomb.v3po.impl.vpp.BridgeDomainTestUtils.BD_NAME_TO_ID_ANSWER; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; @@ -33,8 +34,6 @@ import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains; @@ -71,14 +70,8 @@ public class VppTest { public void setUp() throws Exception { api = PowerMockito.mock(vppApi.class); ctx = mock(WriteContext.class); - PowerMockito.doAnswer(new Answer() { - @Override - public Integer answer(final InvocationOnMock invocationOnMock) throws Throwable { - final String bName = (String) invocationOnMock.getArguments()[0]; - return Integer.parseInt(((Character)bName.charAt(bName.length() - 1)).toString()); - } - }).when(api).findOrAddBridgeDomainId(anyString()); - PowerMockito.doReturn(1).when(api).bridgeDomainIdFromName(anyString()); + PowerMockito.doAnswer(BD_NAME_TO_ID_ANSWER).when(api).findOrAddBridgeDomainId(anyString()); + PowerMockito.doAnswer(BD_NAME_TO_ID_ANSWER).when(api).bridgeDomainIdFromName(anyString()); PowerMockito.doReturn(1).when(api).getRetval(anyInt(), anyInt()); vppWriter = VppUtils.getVppWriter(api); rootRegistry = new DelegatingWriterRegistry( -- cgit 1.2.3-korg