From 29b49e1e72edd4b81181e095c03c294653e6cbb5 Mon Sep 17 00:00:00 2001 From: Jozef Gloncak Date: Mon, 28 Sep 2015 08:24:57 +0200 Subject: [PATCH] BUG-4340: raise test coverage to 80% - multipart callback related - covered on success - most code paths: - MultipartRequestOnTheFlyCallback - MultipartRequestCallback Change-Id: Ia462410587a7650ff69a932a8454c26736104ca9 Signed-off-by: Jozef Gloncak --- .../MultipartRequestCallbackTest.java | 96 ++++++++++ .../MultipartRequestOnTheFlyCallbackTest.java | 164 ++++++++++++++---- 2 files changed, 230 insertions(+), 30 deletions(-) create mode 100644 openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallbackTest.java diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallbackTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallbackTest.java new file mode 100644 index 0000000000..12f5de2af3 --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestCallbackTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.openflowplugin.impl.services; + +import java.util.List; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; +import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; +import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector; +import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier; +import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput; +import org.opendaylight.yangtools.yang.common.RpcResult; + +/** + * Test for {@link MultipartRequestCallback}. + */ +@RunWith(MockitoJUnitRunner.class) +public class MultipartRequestCallbackTest { + + @Mock + private DeviceContext deviceContext; + @Mock + private RequestContext> requestContext; + @Mock + private MessageSpy spy; + @Mock + private MultiMsgCollector multiMsgCollector; + @Captor + private ArgumentCaptor>> rpcResultCapt; + + private MultipartRequestCallback multipartRequestCallback; + + @Before + public void setUp() throws Exception { + Mockito.doNothing().when(requestContext).setResult(rpcResultCapt.capture()); + Mockito.when(deviceContext.getMessageSpy()).thenReturn(spy); + Mockito.when(deviceContext.getMultiMsgCollector(Matchers.any())).thenReturn(multiMsgCollector); + multipartRequestCallback = new MultipartRequestCallback(requestContext, MultipartRequestInput.class, deviceContext); + } + + /** + * end collecting + * + * @throws Exception + */ + @Test + public void testOnSuccess1() throws Exception { + multipartRequestCallback.onSuccess(null); + Mockito.verify(multiMsgCollector).endCollecting(Matchers.any()); + } + + /** + * fail adding to collection + * + * @throws Exception + */ + @Test + public void testOnSuccess2() throws Exception { + multipartRequestCallback.onSuccess(new EchoOutputBuilder().build()); + final RpcResult> rpcResult = rpcResultCapt.getValue(); + Assert.assertNotNull(rpcResult); + Assert.assertFalse(rpcResult.isSuccessful()); + } + + /** + * successfully added to collection + * + * @throws Exception + */ + @Test + public void testOnSuccess3() throws Exception { + final MultipartReplyMessage replyMessage = new MultipartReplyMessageBuilder().build(); + multipartRequestCallback.onSuccess(replyMessage); + Mockito.verify(multiMsgCollector).addMultipartMsg(Matchers.eq(replyMessage), Matchers.any()); + } +} \ No newline at end of file diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java index 227b2f45d5..3db9c1aca5 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java @@ -1,78 +1,118 @@ package org.opendaylight.openflowplugin.impl.services; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Matchers; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.openflowplugin.api.OFConstants; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; +import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; +import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry; +import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey; import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier; import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext; import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyImpl; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements; -import org.opendaylight.yangtools.yang.binding.Augmentation; -import org.opendaylight.yangtools.yang.binding.DataContainer; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStatsBuilder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ExecutionException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(MockitoJUnitRunner.class) public class MultipartRequestOnTheFlyCallbackTest { - private static final String DUMMY_NODE_ID = "dummyNodeId"; private static final String DUMMY_EVENT_NAME = "dummy event name 1"; private static final String DUMMY_DEVICE_ID = "dummy device id 1"; private static final Long DUMMY_XID = 55L; + private static final KeyedInstanceIdentifier NODE_PATH = KeyedInstanceIdentifier + .create(Nodes.class) + .child(Node.class, new NodeKey(new NodeId("uf-node:123"))); + @Mock private DeviceContext mockedDeviceContext; - @Mock - RequestContext> mockedRequestContext; + private RequestContext> mockedRequestContext; @Mock - ConnectionContext mockedPrimaryConnection; + private ConnectionContext mockedPrimaryConnection; @Mock - NodeId mockedNodeId; - - private AbstractRequestContext> dummyRequestContext = new AbstractRequestContext>(DUMMY_XID) { - - @Override - public void close() { - - } - }; + private NodeId mockedNodeId; + @Mock + private FeaturesReply mockedFeaturesReply; + @Mock + private DeviceState mockedDeviceState; + @Mock + private GetFeaturesOutput mocketGetFeaturesOutput; + @Mock + private DeviceFlowRegistry mockedFlowRegistry; + private AbstractRequestContext> dummyRequestContext; private EventIdentifier dummyEventIdentifier = new EventIdentifier(DUMMY_EVENT_NAME, DUMMY_DEVICE_ID); + private MultipartRequestOnTheFlyCallback multipartRequestOnTheFlyCallback; @Before public void initialization() { when(mockedDeviceContext.getMessageSpy()).thenReturn(new MessageIntelligenceAgencyImpl()); when(mockedNodeId.toString()).thenReturn(DUMMY_NODE_ID); when(mockedPrimaryConnection.getNodeId()).thenReturn(mockedNodeId); + when(mockedPrimaryConnection.getFeatures()).thenReturn(mockedFeaturesReply); + when(mockedFeaturesReply.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3); + when(mockedFeaturesReply.getDatapathId()).thenReturn(BigInteger.valueOf(123L)); + when(mocketGetFeaturesOutput.getTables()).thenReturn((short) 0); when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimaryConnection); + when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(NODE_PATH); + when(mockedDeviceState.getFeatures()).thenReturn(mocketGetFeaturesOutput); + when(mockedDeviceState.deviceSynchronized()).thenReturn(true); + when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState); + when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(mockedFlowRegistry); + + dummyRequestContext = new AbstractRequestContext>(DUMMY_XID) { + + @Override + public void close() { + //NOOP + } + }; + multipartRequestOnTheFlyCallback = new MultipartRequestOnTheFlyCallback(dummyRequestContext, String.class, mockedDeviceContext, dummyEventIdentifier); } @Test public void testOnSuccessWithNull() throws Exception { - final MultipartRequestOnTheFlyCallback multipartRequestOnTheFlyCallback = new MultipartRequestOnTheFlyCallback(dummyRequestContext, String.class, mockedDeviceContext, dummyEventIdentifier); multipartRequestOnTheFlyCallback.onSuccess(null); final RpcResult> expectedRpcResult = RpcResultBuilder.success(Collections.emptyList()).build(); final RpcResult> actualResult = dummyRequestContext.getFuture().get(); @@ -83,7 +123,6 @@ public class MultipartRequestOnTheFlyCallbackTest { @Test public void testOnSuccessWithNotMultiNoMultipart() throws ExecutionException, InterruptedException { - final MultipartRequestOnTheFlyCallback multipartRequestOnTheFlyCallback = new MultipartRequestOnTheFlyCallback(dummyRequestContext, String.class, mockedDeviceContext, dummyEventIdentifier); HelloMessage mockedHelloMessage = mock(HelloMessage.class); multipartRequestOnTheFlyCallback.onSuccess(mockedHelloMessage); @@ -100,5 +139,70 @@ public class MultipartRequestOnTheFlyCallbackTest { assertEquals(expectedRpcResult.getResult(), actualResult.getResult()); assertEquals(expectedRpcResult.isSuccessful(), actualResult.isSuccessful()); + Mockito.verify(mockedDeviceContext, Mockito.never()).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), + Matchers.any(), Matchers.any()); + Mockito.verify(mockedDeviceContext).submitTransaction(); + } + + /** + * not the last reply + * + * @throws ExecutionException + * @throws InterruptedException + */ + @Test + public void testOnSuccessWithValidMultipart1() throws ExecutionException, InterruptedException { + final MatchBuilder matchBuilder = new MatchBuilder() + .setMatchEntry(Collections.emptyList()); + final FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder() + .setTableId((short) 0) + .setPriority(2) + .setCookie(BigInteger.ZERO) + .setByteCount(BigInteger.TEN) + .setPacketCount(BigInteger.ONE) + .setDurationSec(11L) + .setDurationNsec(12L) + .setMatch(matchBuilder.build()) + .setFlags(new FlowModFlags(true, false, false, false, false)); + final MultipartReplyFlowBuilder multipartReplyFlowBuilder = new MultipartReplyFlowBuilder() + .setFlowStats(Collections.singletonList(flowStatsBuilder.build())); + final MultipartReplyFlowCaseBuilder multipartReplyFlowCaseBuilder = new MultipartReplyFlowCaseBuilder() + .setMultipartReplyFlow(multipartReplyFlowBuilder.build()); + MultipartReplyMessageBuilder mpReplyMessage = new MultipartReplyMessageBuilder() + .setType(MultipartType.OFPMPFLOW) + .setFlags(new MultipartRequestFlags(true)) + .setMultipartReplyBody(multipartReplyFlowCaseBuilder.build()) + .setXid(21L); + + multipartRequestOnTheFlyCallback.onSuccess(mpReplyMessage.build()); + + Mockito.verify(mockedFlowRegistry).storeIfNecessary(Matchers.any(), Matchers.anyShort()); + Mockito.verify(mockedDeviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), + Matchers.any(), Matchers.any()); + } + + /** + * the last reply + * + * @throws ExecutionException + * @throws InterruptedException + */ + @Test + public void testOnSuccessWithValidMultipart2() throws ExecutionException, InterruptedException { + MultipartReplyMessageBuilder mpReplyMessage = new MultipartReplyMessageBuilder() + .setType(MultipartType.OFPMPDESC) + .setFlags(new MultipartRequestFlags(false)); + + multipartRequestOnTheFlyCallback.onSuccess(mpReplyMessage.build()); + + final RpcResult> actualResult = dummyRequestContext.getFuture().get(); + assertNotNull(actualResult.getErrors()); + assertTrue(actualResult.getErrors().isEmpty()); + assertNotNull(actualResult.getResult()); + assertTrue(actualResult.getResult().isEmpty()); + + Mockito.verify(mockedFlowRegistry, Mockito.never()).storeIfNecessary(Matchers.any(), Matchers.anyShort()); + Mockito.verify(mockedDeviceContext, Mockito.never()).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), + Matchers.any(), Matchers.any()); } } \ No newline at end of file -- 2.36.6