/*
* Copyright (c) 2015 Huawei, 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.nic.nemo.renderer;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
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.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.BeginTransactionInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.BeginTransactionOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.CommonRpcResult.ResultCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.EndTransactionInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.EndTransactionOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.NemoIntentService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.RegisterUserInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.RegisterUserOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.StructureStyleNemoUpdateInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.StructureStyleNemoUpdateOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
/**
* Unit test class for {@link NEMORenderer}.
*/
@PrepareForTest({ NEMORenderer.class, FrameworkUtil.class })
@RunWith(PowerMockRunner.class)
public class NEMORendererTest {
/**
* Object for the class NEMORenderer.
*/
private NEMORenderer nemoRenderer;
/**
* create a mock object for DataBroker class.
*/
@Mock
private DataBroker dataBroker;
/**
* create a mock object for RpcProviderRegistry class.
*/
@Mock
private RpcProviderRegistry rpcProviderRegistry;
/**
* create a mock object for the class Bundle.
*/
@Mock
private Bundle bundle;
/**
* create a mock Object for the class BundleContext.
*/
@Mock
private BundleContext context;
/**
* create a mock Object for the class ServiceRegistration.
*/
@Mock
ServiceRegistration<NEMORenderer> nicConsoleRegistration;
/**
* create a mock Object for the class ListenerRegistration.
*/
@Mock
ListenerRegistration<DataChangeListener> nemoRendererListenerRegistration;
/**
* create a mock Object for the class WriteTransaction.
*/
@Mock
WriteTransaction writeTransactionMock;
/**
* create a mock Object for the class ReadTransaction.
*/
@Mock
ReadOnlyTransaction readTransactionMock;
/**
* create a mock Object for the class ReadWriteTransaction.
*/
@Mock
ReadWriteTransaction readWriteTransactionMock;
/**
* create a mock Object for the class CheckedFuture.
*/
@Mock
CheckedFuture<Void, TransactionCommitFailedException> checkedFuture;
/**
* create a mock Object for the class NemoIntentService.
*/
@Mock
NemoIntentService nemoEngine;
@Mock
CheckedFuture<Optional<User>, ReadFailedException> mockUserFuture;
/**
* Initial set up.
*/
@Before
public void setUp() {
/**
* Here creates objects and defines mocking functionality for mock objects.
*/
PowerMockito.mockStatic(FrameworkUtil.class);
when(FrameworkUtil.getBundle(NEMORenderer.class)).thenReturn(bundle);
when(bundle.getBundleContext()).thenReturn(context);
when(context.registerService(NEMORenderer.class, nemoRenderer, null)).thenReturn(nicConsoleRegistration);
when(
dataBroker.registerDataChangeListener(eq(LogicalDatastoreType.CONFIGURATION),
eq(NEMORenderer.INTENT_IID), isA(DataChangeListener.class), eq(DataChangeScope.SUBTREE)))
.thenReturn(nemoRendererListenerRegistration);
when(rpcProviderRegistry.getRpcService(NemoIntentService.class)).thenReturn(nemoEngine);
when(writeTransactionMock.submit()).thenReturn(checkedFuture);
when(dataBroker.newWriteOnlyTransaction()).thenReturn(writeTransactionMock);
when(dataBroker.newReadOnlyTransaction()).thenReturn(readTransactionMock);
when(dataBroker.newReadWriteTransaction()).thenReturn(readWriteTransactionMock);
nemoRenderer = new NEMORenderer(dataBroker, rpcProviderRegistry);
}
/**
* Test method for {@link NEMORenderer#init()}.
*/
@Test
public void testInit() {
/**
* It should initialize operational and default config data in MD-SAL data store.
*/
nemoRenderer.init();
/**
* Verifying nemoRendere has been registered as a DataChangeListerner.
*/
// verify(context).registerService(NEMORenderer.class, nemoRenderer, null);
verify(dataBroker).registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, NEMORenderer.INTENT_IID,
nemoRenderer, DataChangeScope.SUBTREE);
PowerMockito.verifyStatic(times(1));
}
/**
* Test
*
* @throws ExecutionException
* @throws InterruptedException
*
* @throws Exception
*/
@Test
public void testCreateOrUpdateIntent() throws InterruptedException, ExecutionException {
when(nemoEngine.registerUser(any(RegisterUserInput.class))).thenReturn(
RpcResultBuilder.success(new RegisterUserOutputBuilder().setResultCode(ResultCode.Ok)).buildFuture());
when(nemoEngine.beginTransaction(any(BeginTransactionInput.class))).thenReturn(
RpcResultBuilder.success(new BeginTransactionOutputBuilder().setResultCode(ResultCode.Ok))
.buildFuture());
when(nemoEngine.structureStyleNemoUpdate(any(StructureStyleNemoUpdateInput.class))).thenReturn(
RpcResultBuilder.success(new StructureStyleNemoUpdateOutputBuilder().setResultCode(ResultCode.Ok))
.buildFuture());
when(nemoEngine.endTransaction(any(EndTransactionInput.class))).thenReturn(
RpcResultBuilder.success(new EndTransactionOutputBuilder().setResultCode(ResultCode.Ok)).buildFuture());
IntentKey intentKey = new IntentKey(new Uuid(UUID.randomUUID().toString()));
InstanceIdentifier<User> userPath = InstanceIdentifier.builder(Users.class)
.child(User.class, new UserKey(new UserId(intentKey.getId().getValue()))).build();
when(readTransactionMock.read(LogicalDatastoreType.CONFIGURATION, userPath)).thenReturn(mockUserFuture);
when(mockUserFuture.get()).thenReturn(Optional.of(new UserBuilder().build()));
nemoRenderer.init();
// empty intent
Intent emptyIntent = new IntentBuilder().setKey(intentKey).build();
assertFalse("Should not be able to process empty intent", nemoRenderer.createOrUpdateIntent(emptyIntent));
verifyZeroInteractions(nemoEngine);
// BandwidthOnDemand intent
Intent intent = NEMOIntentParserTest.getBandwidthOnDemandIntent(intentKey);
assertTrue("Should be able to process BoD intent", nemoRenderer.createOrUpdateIntent(intent));
verify(nemoEngine).beginTransaction(any(BeginTransactionInput.class));
verify(nemoEngine).structureStyleNemoUpdate(any(StructureStyleNemoUpdateInput.class));
verify(nemoEngine).endTransaction(any(EndTransactionInput.class));
}
/**
* Test method for {@link nemoRenderer#Close()}.
*
* @throws Exception
*/
@Test
public void testClose() throws Exception {
/**
* Valid scenario - it should initialize operational and default config data in MD-SAL data store and should
* close listeners properly. Verifying nicConsoleRegistration object invoking unregister method. Verifying
* nemoRendererListener object invoking close method.
*/
nemoRenderer.init();
nemoRenderer.close();
verify(nemoRendererListenerRegistration).close();
}
}