/** * Copyright (c) 2015 NEC Corporation. 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.nic.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; import java.net.UnknownHostException; import java.security.AccessController; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.Executor; import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.nic.mapping.api.IntentMappingService; import org.opendaylight.nic.utils.IntentUtils; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.nic.api.NicConsoleProvider; import org.opendaylight.nic.compiler.api.IntentCompiler; import org.opendaylight.nic.compiler.api.IntentCompilerException; import org.opendaylight.nic.compiler.api.IntentCompilerFactory; import org.opendaylight.nic.compiler.api.Policy; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.Allow; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.Block; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Actions; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Subjects; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceRegistration; @PrepareForTest({ FrameworkUtil.class, IntentCompilerFactory.class, BundleContext.class, AccessController.class }) @RunWith(PowerMockRunner.class) /** * JUnit test for {@link NicProvider}. */ public class NicProviderTest { /** * Mock instance of DataBroker to perform unit testing. */ private DataBroker mockDataBroker; /** * Mock instance of WriteTransaction to perform unit testing. */ private WriteTransaction mockWriteTransaction; /** * Mock instance of ReadOnlyTransaction to perform unit testing. */ private ReadOnlyTransaction mockReadOnlyTransaction; /** * Mock instance of CheckedFuture to perform unit testing. */ private CheckedFuture mockListenableFuture; /** * Instance of NicProvider to perform unit testing. */ private NicProvider nicProvider; /** * Instance of NicProvider to perform unit testing. */ private IntentMappingService mockMappingService; /** * It creates the required objects for every unit test cases. * * @throws Exception */ @Before public void setup() throws Exception { /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ mockListenableFuture = mock(CheckedFuture.class); mockWriteTransaction = mock(WriteTransaction.class); mockReadOnlyTransaction = mock(ReadOnlyTransaction.class); mockDataBroker = mock(DataBroker.class); mockMappingService = mock(IntentMappingService.class); when(mockWriteTransaction.submit()).thenReturn(mockListenableFuture); when(mockDataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTransaction); when(mockDataBroker.newReadOnlyTransaction()).thenReturn(mockReadOnlyTransaction); nicProvider = new NicProvider(mockDataBroker, mockMappingService); } /** * Test case for {@link NicProvider#init()} */ @Test public void testInit() throws TransactionCommitFailedException { /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ nicProvider = spy(nicProvider); PowerMockito.mockStatic(FrameworkUtil.class); Bundle mockBundle = mock(Bundle.class); BundleContext mockBundleContext = mock(BundleContext.class); doNothing().when(nicProvider).initIntentsOperational(); doNothing().when(nicProvider).initIntentsConfiguration(); when(FrameworkUtil.getBundle(nicProvider.getClass())).thenReturn(mockBundle); when(mockBundle.getBundleContext()).thenReturn(mockBundleContext); /** * Here verifying init() should initialize operational and default * config data in MD-SAL data store. */ nicProvider.init(); verify(nicProvider, times(1)).initIntentsOperational(); verify(nicProvider, times(1)).initIntentsConfiguration(); } /** * Test case for {@link NicProvider#close()} */ @Test public void testClose() throws Exception { nicProvider = spy(nicProvider); /** * Here verifying close() should close active registrations. */ nicProvider.close(); } /** * Test case for {@link NicProvider#initIntentsOperational()} */ @Test public void testInitIntentsOperational() { nicProvider.initIntentsOperational(); /** * Here verifying initIntentsOperational() should interact with * DataBroker, WriteTransaction and ListenableFuture to put the Intents * operational data into the MD-SAL data store. */ verify(mockDataBroker, times(1)).newWriteOnlyTransaction(); verify(mockWriteTransaction, times(1)).put( eq(LogicalDatastoreType.OPERATIONAL), eq(IntentUtils.INTENTS_IID), isA(Intents.class)); verify(mockWriteTransaction, times(1)).submit(); verify(mockListenableFuture, times(1)).addListener(isA(Runnable.class), isA(Executor.class)); } /** * Test case for {@link NicProvider#initIntentsConfiguration()} */ @Test public void testInitIntentsConfiguration() { nicProvider.initIntentsConfiguration(); /** * Here verifying initIntentsOperational() should interact with * DataBroker, WriteTransaction to place default config data in data * store tree. */ verify(mockDataBroker, times(3)).newWriteOnlyTransaction(); verify(mockWriteTransaction, times(2)).put( eq(LogicalDatastoreType.CONFIGURATION), eq(IntentUtils.INTENTS_IID), isA(Intents.class)); verify(mockWriteTransaction, times(1)).delete( eq(LogicalDatastoreType.CONFIGURATION), isA(KeyedInstanceIdentifier.class)); verify(mockWriteTransaction, times(3)).submit(); } /** * Test case for {@link NicProvider#addIntent()} */ @Test public void testAddIntent() { Intent mockIntent = mock(Intent.class); boolean actualResult, expectedResult; /** * Here verifying addIntent() should return true if it added given * Intent to data store tree. */ expectedResult = true; actualResult = nicProvider.addIntent(mockIntent); assertEquals(expectedResult, actualResult); verify(mockDataBroker, times(1)).newWriteOnlyTransaction(); verify(mockWriteTransaction, times(1)).put( eq(LogicalDatastoreType.CONFIGURATION), eq(IntentUtils.INTENTS_IID), isA(Intents.class)); verify(mockWriteTransaction, times(1)).submit(); /** * Here verifying addIntent() should return false if unable to add given * Intent due to some exception raised when adding given Intent to data * store tree. */ doThrow(new RuntimeException()).when(mockWriteTransaction).put( eq(LogicalDatastoreType.CONFIGURATION), eq(IntentUtils.INTENTS_IID), isA(Intents.class)); expectedResult = false; actualResult = nicProvider.addIntent(mockIntent); assertEquals(expectedResult, actualResult); verify(mockDataBroker, times(2)).newWriteOnlyTransaction(); verify(mockWriteTransaction, times(2)).put( eq(LogicalDatastoreType.CONFIGURATION), eq(IntentUtils.INTENTS_IID), isA(Intents.class)); verify(mockWriteTransaction, times(1)).submit(); } /** * Test case for {@link NicProvider#removeIntent()} */ @Test public void testRemoveIntent() { Uuid mockUuid = mock(Uuid.class); boolean actualResult, expectedResult; /** * Here verifying removeIntent() should return ture if it removed given * Intent from data store tree. */ expectedResult = true; actualResult = nicProvider.removeIntent(mockUuid); assertEquals(expectedResult, actualResult); verify(mockDataBroker, times(1)).newWriteOnlyTransaction(); verify(mockWriteTransaction, times(1)).delete( eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class)); verify(mockWriteTransaction, times(1)).submit(); /** * Here verifying removeIntent() should return false if unable to remove * given Intent due to some exception raised when removing given Intent * to data store tree. */ doThrow(new RuntimeException()).when(mockWriteTransaction).delete( eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class)); expectedResult = false; actualResult = nicProvider.removeIntent(mockUuid); assertEquals(expectedResult, actualResult); verify(mockDataBroker, times(2)).newWriteOnlyTransaction(); verify(mockWriteTransaction, times(2)).delete( eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class)); verify(mockWriteTransaction, times(1)).submit(); } /** * Test case for {@link NicProvider#listIntents()} */ @Test public void testListIntents() throws Exception { List<Intent> actualListOfIntents; /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ List<Intent> mockListOfIntentsForConfiguration = mock(List.class); List<Intent> mockListOfIntentsForOperational = mock(List.class); Intents mockIntents = mock(Intents.class); Optional mockOptional = mock(Optional.class); CheckedFuture mockCheckedFuture = mock(CheckedFuture.class); when(mockIntents.getIntent()).thenReturn(mockListOfIntentsForConfiguration); when(mockOptional.isPresent()).thenReturn(true); when(mockOptional.get()).thenReturn(mockIntents); when(mockCheckedFuture.checkedGet()).thenReturn(mockOptional); when(mockReadOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, IntentUtils.INTENTS_IID)).thenReturn(mockCheckedFuture); Intents mockIntentsTwo = mock(Intents.class); Optional mockOptionalTwo = mock(Optional.class); CheckedFuture mockCheckedFutureTwo = mock(CheckedFuture.class); when(mockIntentsTwo.getIntent()).thenReturn(mockListOfIntentsForOperational); when(mockOptionalTwo.isPresent()).thenReturn(true); when(mockOptionalTwo.get()).thenReturn(mockIntentsTwo); when(mockCheckedFutureTwo.checkedGet()).thenReturn(mockOptionalTwo); when(mockReadOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, IntentUtils.INTENTS_IID)).thenReturn(mockCheckedFutureTwo); /** * Here verifying listIntents() should return list of Intents from * configuration data store if isConfigurationDatastore is true. */ actualListOfIntents = nicProvider.listIntents(true); assertEquals(mockListOfIntentsForConfiguration, actualListOfIntents); verify(mockDataBroker, times(1)).newReadOnlyTransaction(); verify(mockReadOnlyTransaction, times(1)).read( LogicalDatastoreType.CONFIGURATION, IntentUtils.INTENTS_IID); verify(mockCheckedFuture, times(1)).checkedGet(); verify(mockOptional, times(1)).isPresent(); verify(mockOptional, times(1)).get(); verify(mockIntents, times(1)).getIntent(); /** * Here verifying listIntents() should return list of Intents from * operational data store if isConfigurationDatastore is false. */ actualListOfIntents = nicProvider.listIntents(false); assertEquals(mockListOfIntentsForOperational, actualListOfIntents); verify(mockDataBroker, times(2)).newReadOnlyTransaction(); verify(mockReadOnlyTransaction, times(1)).read( LogicalDatastoreType.OPERATIONAL, IntentUtils.INTENTS_IID); verify(mockCheckedFutureTwo, times(1)).checkedGet(); verify(mockOptionalTwo, times(1)).isPresent(); verify(mockOptionalTwo, times(1)).get(); verify(mockIntentsTwo, times(1)).getIntent(); /** * Here verifying listIntents() should return null if any exception * raised when reading Intents from specific data store. */ doThrow(new RuntimeException()).when(mockReadOnlyTransaction).read( LogicalDatastoreType.CONFIGURATION, IntentUtils.INTENTS_IID); actualListOfIntents = nicProvider.listIntents(true); assertEquals(new ArrayList<>(), actualListOfIntents); assertTrue(actualListOfIntents.isEmpty()); } /** * Test case for {@link NicProvider#listIntentsWithEmptyConfigTree()} */ @Test public void testListIntentsWithEmpytConfigTree() throws Exception { List<Intent> actualListOfIntents; /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ List<Intent> mockListOfIntentsForConfiguration = mock(List.class); List<Intent> mockListOfIntentsForOperational = mock(List.class); Optional mockOptional = mock(Optional.class); CheckedFuture mockCheckedFuture = mock(CheckedFuture.class); when(mockCheckedFuture.checkedGet()).thenReturn(mockOptional); when(mockOptional.isPresent()).thenReturn(false); when(mockReadOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, IntentUtils.INTENTS_IID)).thenReturn(mockCheckedFuture); /** * Here verifying listIntents() should return list of Intents from * configuration data store if isConfigurationDatastore is true. */ actualListOfIntents = nicProvider.listIntents(true); verify(mockDataBroker, times(1)).newReadOnlyTransaction(); verify(mockReadOnlyTransaction, times(1)).read( LogicalDatastoreType.CONFIGURATION, IntentUtils.INTENTS_IID); verify(mockCheckedFuture, times(1)).checkedGet(); verify(mockOptional, times(1)).isPresent(); assertTrue(actualListOfIntents.isEmpty()); } /** * Test case for {@link NicProvider#getIntent()} */ @Test public void testGetIntent() throws Exception { Intent actualIntent; Uuid uuid = Uuid.getDefaultInstance("b9a13232-525e-4d8c-be21-cd65e3436037"); /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ Intent mockIntentForConfiguration = mock(Intent.class); Intent mockIntentForOperational = mock(Intent.class); Optional mockOptional = mock(Optional.class); CheckedFuture mockCheckedFuture = mock(CheckedFuture.class); when(mockOptional.get()).thenReturn(mockIntentForConfiguration, null, mockIntentForOperational); when(mockCheckedFuture.checkedGet()).thenReturn(mockOptional); when(mockReadOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class))).thenReturn(mockCheckedFuture); when(mockReadOnlyTransaction.read(eq(LogicalDatastoreType.OPERATIONAL), isA(InstanceIdentifier.class))).thenReturn(mockCheckedFuture); /** * Here verifying getIntent() should return Intent from configuration * data store. */ actualIntent = nicProvider.getIntent(uuid); assertEquals(mockIntentForConfiguration, actualIntent); verify(mockReadOnlyTransaction, times(1)).read( eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class)); verify(mockReadOnlyTransaction, times(0)).read( eq(LogicalDatastoreType.OPERATIONAL), isA(InstanceIdentifier.class)); verify(mockCheckedFuture, times(1)).checkedGet(); verify(mockOptional, times(1)).get(); /** * Here verifying getIntent() should return Intent from operational data * store. */ actualIntent = nicProvider.getIntent(uuid); assertEquals(mockIntentForOperational, actualIntent); verify(mockReadOnlyTransaction, times(2)).read( eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class)); verify(mockReadOnlyTransaction, times(1)).read( eq(LogicalDatastoreType.OPERATIONAL), isA(InstanceIdentifier.class)); verify(mockCheckedFuture, times(3)).checkedGet(); verify(mockOptional, times(3)).get(); /** * Here verifying getIntent() should return null if it is unable to read * Intent due to some exception raised at the time of reading from data * store. */ doThrow(new RuntimeException()).when(mockReadOnlyTransaction).read( eq(LogicalDatastoreType.CONFIGURATION), isA(InstanceIdentifier.class)); actualIntent = nicProvider.getIntent(uuid); assertEquals(null, actualIntent); } /** * Test case for {@link NicProvider#compile()} */ @Test public void testCompile() throws Exception { String expectedResult, actualResult; List<Intent> listOfIntent = new ArrayList<Intent>(); List<Subjects> listOfSubjects = new ArrayList<Subjects>(); /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ IntentCompiler mockIntentCompiler = mock(IntentCompiler.class); Policy mockPolicy = mock(Policy.class); Intent mockIntent = mock(Intent.class); nicProvider = spy(nicProvider); EndPointGroup mockEndPointGroupForSource = mock(EndPointGroup.class); EndPointGroup mockEndPointGroupForDestination = mock(EndPointGroup.class); Subjects mockSubjects = mock(Subjects.class); Actions mockActions = mock(Actions.class); Action mockAllow = mock(Allow.class); Block mockBlock = mock(Block.class); Action mockAction = mock(Action.class); org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup mockEndPointGroup = mock(org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup.class); org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup mockEndPointGroupTwo = mock(org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup.class); IntentCompilerException mockIntentCompilerException = mock(IntentCompilerException.class); when(mockIntentCompiler.createPolicy(isA(Set.class), isA(Set.class), isA(Set.class))).thenReturn(mockPolicy); PowerMockito.stub(PowerMockito.method(IntentCompilerFactory.class, "createIntentCompiler")).toReturn(mockIntentCompiler); doReturn(listOfIntent).when(nicProvider).listIntents(eq(true)); listOfIntent.add(mockIntent); listOfSubjects.add(mockSubjects); listOfSubjects.add(mockSubjects); when(mockSubjects.getSubject()).thenReturn(mockEndPointGroupForSource, mockEndPointGroupForDestination); when(mockIntent.getSubjects()).thenReturn(listOfSubjects); when(mockActions.getAction()).thenReturn(mockAllow, mockBlock, mockAction, mockBlock); List<Actions> listOfActions = new ArrayList<Actions>(); listOfActions.add(mockActions); when(mockIntent.getActions()).thenReturn(listOfActions); when(mockEndPointGroup.getName()).thenReturn("Mock EndPointGroupOne"); when(mockEndPointGroupTwo.getName()).thenReturn("Mock EndPointGroupTwo"); when(mockEndPointGroupForSource.getEndPointGroup()).thenReturn(mockEndPointGroup); when(mockEndPointGroupForDestination.getEndPointGroup()).thenReturn(mockEndPointGroupTwo); /** * Here verifying compile() should return specific pattern string if * action is of type allow. */ expectedResult = ">>> Original policies:\n" + mockPolicy + "\n\n>>> Compiled policies:\n"; actualResult = nicProvider.compile(); assertEquals(expectedResult, actualResult); /** * Here verifying compile() should return specific pattern string if * action is of type block. */ expectedResult = ">>> Original policies:\n" + mockPolicy + "\n\n>>> Compiled policies:\n"; actualResult = nicProvider.compile(); assertEquals(expectedResult, actualResult); /** * Here verifying compile() should return specific pattern string if * action is not either allow type nor block type. */ expectedResult = "[ERROR] Invalid action: " + mockAction.getClass().getName(); actualResult = nicProvider.compile(); assertEquals(expectedResult, actualResult); /** * Here verifying compile() should return specific pattern string if any * exception raised during the compiling the given policies. */ List<Policy> listOfPolicy = new ArrayList<Policy>(); listOfPolicy.add(mockPolicy); when(mockIntentCompilerException.getMessage()).thenReturn("mockito msg.."); when(mockIntentCompilerException.getRelatedPolicies()).thenReturn(listOfPolicy); doThrow(mockIntentCompilerException).when(mockIntentCompiler).compile(isA(Collection.class)); expectedResult = "[ERROR] Compilation failure: mockito msg..\nRelated policies:\n " + mockPolicy + "\n"; actualResult = nicProvider.compile(); assertEquals(expectedResult, actualResult); /** * Here verifying compile() should return specific pattern string if any * exception raised during the parsing the endpointgroup with * destination subject. */ when(mockSubjects.getSubject()).thenReturn(mockEndPointGroupForSource, mockEndPointGroupForDestination); when(mockIntentCompiler.parseEndpointGroup("Mock EndPointGroupTwo")).thenThrow(new UnknownHostException("")); expectedResult = "[ERROR] Invalid subject: " + "Mock EndPointGroupTwo"; actualResult = nicProvider.compile(); assertEquals(expectedResult, actualResult); /** * Here verifying compile() should return specific pattern string if any * exception raised during the parsing the endpointgroup with source * subject. */ when(mockSubjects.getSubject()).thenReturn(mockEndPointGroupForSource, mockEndPointGroupForDestination); when(mockIntentCompiler.parseEndpointGroup(eq("Mock EndPointGroupOne"))).thenThrow(new UnknownHostException("")); expectedResult = "[ERROR] Invalid subject: " + "Mock EndPointGroupOne"; actualResult = nicProvider.compile(); assertEquals(expectedResult, actualResult); } /** * Test case for {@link NicProvider#formatPolicies()} */ @Test public void testFormatPolicies() throws Exception { Collection<Policy> listOfPolicy = new ArrayList<Policy>(); /** * Here creates required mock objects and defines mocking functionality * for mock objects. */ Policy mockPolicyOne, mockPolicyTwo; mockPolicyOne = mock(Policy.class); mockPolicyTwo = mock(Policy.class); listOfPolicy.add(mockPolicyOne); listOfPolicy.add(mockPolicyTwo); /** * Here verifying formatPolicies() should return specific pattern string * by reading given policies. */ String actualResult, expectedResult; expectedResult = mockPolicyOne + "\n" + mockPolicyTwo + "\n"; actualResult = Whitebox.invokeMethod(nicProvider, "formatPolicies", listOfPolicy); assertEquals(expectedResult, actualResult); } }