/*
* Copyright (c) 2016 Saugo360 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.tsdr.datacollection;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Set;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.yang.config.tsdr.restconf.collector.AbstractTSDRRestconfCollectorModuleFactory;
import org.opendaylight.controller.config.yang.config.tsdr.restconf.collector.TSDRRestconfCollectorModule;
import org.opendaylight.controller.config.yang.config.tsdr.restconf.collector.TSDRRestconfCollectorModuleFactory;
import org.opendaylight.tsdr.restconf.collector.TSDRRestconfCollectorFilter;
import org.opendaylight.tsdr.restconf.collector.TSDRRestconfCollectorLogger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
/**
* This class is responsible for testing the TSDRRestconfCollectorModule class.
*
* @author <a href="mailto:a.alhamali93@gmail.com">AbdulRahman AlHamali</a>
*
* Created: Dec 16th, 2016
*
*/
public class TSDRRestconfCollectorModuleTest {
/**
* tests filter registration when other filters are already registered but our filter isn't.
* the list should remain the same with our filter appended to it.
*/
@Test
public void testRegisterFilterWhenOtherFiltersExistButTSDRFilterDoesNot() throws IOException {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put("customFilterList", "randomFilter");
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
ArgumentCaptor<Dictionary> argumentCaptor = ArgumentCaptor.forClass(Dictionary.class);
Mockito.verify(filterChainConfiguration).update(argumentCaptor.capture());
Dictionary argument = argumentCaptor.getValue();
Assert.assertEquals("randomFilter," + TSDRRestconfCollectorFilter.class.getName(),
argument.get("customFilterList"));
}
/**
* tests filter registration when our filter already exists.
* the list should remain the same
*/
@Test
public void testRegisterFilterWhenTSDRFilterExists() throws IOException {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put("customFilterList", "randomFilter1," + TSDRRestconfCollectorFilter.class.getName()
+ ",randomFilter2");
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
ArgumentCaptor<Dictionary> argumentCaptor = ArgumentCaptor.forClass(Dictionary.class);
Mockito.verify(filterChainConfiguration).update(argumentCaptor.capture());
Dictionary argument = argumentCaptor.getValue();
Assert.assertEquals("randomFilter1," + TSDRRestconfCollectorFilter.class.getName() + ",randomFilter2",
argument.get("customFilterList"));
}
/**
* tests filter registration when the list is empty.
* the list should contain only our filter
*/
@Test
public void testRegisterFilterWhenNoFiltersExist() throws IOException {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put("customFilterList", "");
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
ArgumentCaptor<Dictionary> argumentCaptor = ArgumentCaptor.forClass(Dictionary.class);
Mockito.verify(filterChainConfiguration).update(argumentCaptor.capture());
Dictionary argument = argumentCaptor.getValue();
Assert.assertEquals(TSDRRestconfCollectorFilter.class.getName(), argument.get("customFilterList"));
}
/**
* tests filter registration when the customFilterList property doesn't exist (perhaps it was removed by mistake).
* the property should be created and our filter should be added to it
*/
@Test
public void testRegisterFilterWhenCustomFilterListDoesntExist() throws IOException {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
ArgumentCaptor<Dictionary> argumentCaptor = ArgumentCaptor.forClass(Dictionary.class);
Mockito.verify(filterChainConfiguration).update(argumentCaptor.capture());
Dictionary argument = argumentCaptor.getValue();
Assert.assertEquals(TSDRRestconfCollectorFilter.class.getName(), argument.get("customFilterList"));
}
/**
* tests filter registration when the configuration admin is down.
* no attempts to modify the list should be done
*/
@Test
public void testRegisterFilterWhenConfigurationAdminDoesNotExist() throws IOException {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module, "X");
Dictionary<String, String> properties = new Hashtable<String, String>();
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties, false);
module.createInstance();
Mockito.verify(filterChainConfiguration, Mockito.never()).update(Mockito.any());
}
/**
* tests filter unregistration when our filter exists along with other filters.
* the list should remain the same with our filter removed from it
*/
@Test
public void testUnregisterFilterWhenFilterExistsWithOtherFilters() throws Exception {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put("customFilterList", "randomFilter1," + TSDRRestconfCollectorFilter.class.getName()
+ ",randomFilter2");
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
// To remove the old invocation
Mockito.reset(filterChainConfiguration);
Mockito.when(filterChainConfiguration.getProperties()).thenReturn(properties);
module.close();
ArgumentCaptor<Dictionary> argumentCaptor = ArgumentCaptor.forClass(Dictionary.class);
Mockito.verify(filterChainConfiguration).update(argumentCaptor.capture());
Dictionary argument = argumentCaptor.getValue();
Assert.assertEquals("randomFilter1,randomFilter2", argument.get("customFilterList"));
}
/**
* tests filter unregistration when only our filter exists.
* the list should become empty
*/
@Test
public void testUnregisterFilterWhenFilterExistsAlone() throws Exception {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put("customFilterList", TSDRRestconfCollectorFilter.class.getName());
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
// To remove the old invocation
Mockito.reset(filterChainConfiguration);
Mockito.when(filterChainConfiguration.getProperties()).thenReturn(properties);
module.close();
ArgumentCaptor<Dictionary> argumentCaptor = ArgumentCaptor.forClass(Dictionary.class);
Mockito.verify(filterChainConfiguration).update(argumentCaptor.capture());
Dictionary argument = argumentCaptor.getValue();
Assert.assertEquals("", argument.get("customFilterList"));
}
/**
* tests filter unregistration when the customFilterList property doesn't even exist (perhaps it was removed).
* no changes should be done
*/
@Test
public void testUnregisterFilterWhenCustomFilterListDoesntExist() throws Exception {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
// To remove the old invocation
Mockito.reset(filterChainConfiguration);
properties.remove("customFilterList");
Mockito.when(filterChainConfiguration.getProperties()).thenReturn(properties);
module.close();
Mockito.verify(filterChainConfiguration, Mockito.never()).update(Mockito.any());
}
/**
* tests filter unregistration when our filter doesn't exist.
* the list should remain the same, no changes should be done
*/
@Test
public void testUnregisterFilterWhenFilterDoesntExist() throws Exception {
TSDRRestconfCollectorModule module = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module,"X");
Dictionary<String, String> properties = new Hashtable<String, String>();
Configuration filterChainConfiguration = prepareModuleForFilterRegistration(module, properties);
module.createInstance();
// To remove the old invocation
Mockito.reset(filterChainConfiguration);
properties.put("customFilterList", "randomFilter1,randomFilter2");
Mockito.when(filterChainConfiguration.getProperties()).thenReturn(properties);
module.close();
Mockito.verify(filterChainConfiguration, Mockito.never()).update(Mockito.any());
}
/**
* Used to increase code coverage because of a bug in odlparent.
*/
@Test
public void codeCoverageModule() throws Exception {
TSDRRestconfCollectorModuleFactory mf = new TSDRRestconfCollectorModuleFactory();
mf.createModule("X", null, null);
DynamicMBeanWithInstance moduleInstance = Mockito.mock(DynamicMBeanWithInstance.class);
Mockito.when(moduleInstance.getModule()).thenReturn(new TSDRRestconfCollectorModule(null, null));
mf.createModule("X", null, moduleInstance, null);
new TSDRRestconfCollectorModule(null,null,null,null);
TSDRRestconfCollectorModule module1 = new TSDRRestconfCollectorModule(null,null);
TSDRRestconfCollectorModule module2 = new TSDRRestconfCollectorModule(null,null);
TSDRRestconfCollectorModule module3 = new TSDRRestconfCollectorModule(null,null);
setupModuleWithMocks(module1,"X");
setupModuleWithMocks(module2,"X");
setupModuleWithMocks(module3,"Y");
module1.equals(new TSDRRestconfCollectorModule(null,null));
module1.canReuseInstance(module2);
module1.getRpcRegistry();
module1.getLogger();
module1.getIdentifier();
module1.reuseInstance(module1);
module1.hashCode();
module1.isSame(module1);
module1.isSame(module2);
module1.isSame(module3);
try {
module1.isSame(null);
} catch (IllegalArgumentException e) {
Assert.assertTrue(e != null);
}
module1.validate();
try {
executeResolveDependencies(module1);
} catch (Exception e) {
e.printStackTrace();
}
module1.setRpcRegistry(null);
AbstractTSDRRestconfCollectorModuleFactory factory = new AbstractTSDRRestconfCollectorModuleFactory() {
@Override
public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
return super.getImplementedServiceIntefaces();
}
@Override
public Module createModule(String instanceName, DependencyResolver dependencyResolver,
BundleContext bundleContext) {
return super.createModule(instanceName, dependencyResolver, bundleContext);
}
@Override
public Module createModule(String instanceName, DependencyResolver dependencyResolver,
DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
return super.createModule(instanceName, dependencyResolver, old, bundleContext);
}
@Override
public TSDRRestconfCollectorModule instantiateModule(String instanceName,
DependencyResolver dependencyResolver, TSDRRestconfCollectorModule oldModule, AutoCloseable oldInstance,
BundleContext bundleContext) {
return super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext);
}
@Override
public TSDRRestconfCollectorModule instantiateModule(String instanceName,
DependencyResolver dependencyResolver, BundleContext bundleContext) {
return super.instantiateModule(instanceName, dependencyResolver, bundleContext);
}
@Override
public TSDRRestconfCollectorModule handleChangedClass(DynamicMBeanWithInstance old) throws Exception {
return super.handleChangedClass(old);
}
@Override
public Set<TSDRRestconfCollectorModule> getDefaultModules(
DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) {
return super.getDefaultModules(dependencyResolverFactory, bundleContext);
}
};
factory.getImplementationName();
factory.getImplementedServiceIntefaces();
factory.getDefaultModules(null,null);
factory.isModuleImplementingServiceInterface(AbstractServiceInterface.class);
try {
factory.handleChangedClass(null);
} catch (Exception e) {
e.printStackTrace();
}
try {
DependencyResolver dpr = Mockito.mock(DependencyResolver.class);
BundleContext b = Mockito.mock(BundleContext.class);
factory.createModule("tsdr-syslog-collector",dpr , b);
} catch (Exception e) {
e.printStackTrace();
}
try {
DependencyResolver dpr = Mockito.mock(DependencyResolver.class);
BundleContext b = Mockito.mock(BundleContext.class);
DynamicMBeanWithInstance old = Mockito.mock(DynamicMBeanWithInstance.class);
factory.createModule("tsdr-syslog-collector",dpr , old,b);
} catch (Exception e){
e.printStackTrace();
}
try {
factory.instantiateModule(null, null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public void executeResolveDependencies(Object module) throws NoSuchMethodException, InvocationTargetException,
IllegalAccessException {
Method methods[] = module.getClass().getSuperclass().getDeclaredMethods();
for(Method m:methods){
if(m.getName().equals("resolveDependencies")){
m.setAccessible(true);
m.invoke(module,null);
return;
}
}
}
/**
* sets up the module and provides it with the necessary mocks.
* @param obj the module to be set up
* @param factoryName the name of the module
*/
public static final void setupModuleWithMocks(Object obj,String factoryName) {
try {
org.opendaylight.controller.sal.binding.api.RpcProviderRegistry rpcProviderRegistry
= Mockito.mock(org.opendaylight.controller.sal.binding.api.RpcProviderRegistry.class);
DependencyResolver dpr = Mockito.mock(DependencyResolver.class);
javax.management.ObjectName rpcRegistry = Mockito.mock(javax.management.ObjectName.class);
ModuleIdentifier id = Mockito.mock(ModuleIdentifier.class);
Mockito.when(id.getFactoryName()).thenReturn(factoryName);
Mockito.when(id.getInstanceName()).thenReturn(factoryName);
Mockito.doNothing().when(dpr).validateDependency(Mockito.any(Class.class),
Mockito.any(javax.management.ObjectName.class),
Mockito.any(org.opendaylight.controller.config.api.JmxAttribute.class));
Field field = findField("rpcRegistryDependency",obj.getClass());
if (field != null) {
field.set(obj, rpcProviderRegistry);
}
field = findField("identifier",obj.getClass());
if (field != null) {
field.set(obj, id);
}
field = findField("dependencyResolver",obj.getClass());
if (field != null) {
field.set(obj, dpr);
}
field = findField("rpcRegistry",obj.getClass());
if (field != null) {
field.set(obj, rpcRegistry);
}
} catch (IllegalAccessException e) {
}
}
public static final Field findField(String name, Class clz) {
Field[] fields = clz.getDeclaredFields();
for (Field f: fields) {
if (f.getName().equals(name)) {
f.setAccessible(true);
return f;
}
}
if (clz.getSuperclass() == null) {
return null;
}
return findField(name, clz.getSuperclass());
}
/**
* This function takes the module, and the properties that need to be initially found in the filter chain
* configuration. It then creates a bundle context that would eventually give the module these properties.
* Finally, the function returns the filterChainConfiguration, so that the caller of the function can then check
* out whether filterChainConfiguration.update function was called with the correct parameters.
* @param module the module to be configured
* @param properties the properties that we want the module to find when querying the filterchain configuration
* @param isConfigurationAdminInstalled when set to false, the configuration admin will be null
* @return the configuration object of the filter chain, could be used to check if its update method is called
*/
private Configuration prepareModuleForFilterRegistration(TSDRRestconfCollectorModule module, Dictionary properties,
boolean isConfigurationAdminInstalled) throws IOException {
ServiceReference configurationAdminServiceReference = null;
if (isConfigurationAdminInstalled) {
configurationAdminServiceReference = Mockito.mock(ServiceReference.class);
}
Configuration filterChainConfiguration = Mockito.mock(Configuration.class);
Mockito.when(filterChainConfiguration.getProperties()).thenReturn(properties);
ConfigurationAdmin configurationAdmin = Mockito.mock(ConfigurationAdmin.class);
Mockito.when(configurationAdmin.getConfiguration("org.opendaylight.aaa.filterchain"))
.thenReturn(filterChainConfiguration);
BundleContext bundleContext = Mockito.mock(BundleContext.class);
Mockito.when(bundleContext.getServiceReference(ConfigurationAdmin.class.getName()))
.thenReturn(configurationAdminServiceReference);
Mockito.when(bundleContext.getService(configurationAdminServiceReference)).thenReturn(configurationAdmin);
module.setBundleContext(bundleContext);
return filterChainConfiguration;
}
/**
* This function takes the module, and the properties that need to be initially found in the filter chain
* configuration. It then creates a bundle context that would eventually give the module these properties.
* Finally, the function returns the filterChainConfiguration, so that the caller of the function can then check
* out whether filterChainConfiguration.update function was called with the correct parameters.
* @param module the module to be configured
* @param properties the properties that we want the module to find when querying the filterchain configuration
* @return the configuration object of the filter chain, could be used to check if its update method is called
*/
private Configuration prepareModuleForFilterRegistration(TSDRRestconfCollectorModule module, Dictionary properties)
throws IOException {
return prepareModuleForFilterRegistration(module, properties, true);
}
/**
* called after each test to make sure that the TSDRRestconfCollectorLogger instance is cleaned.
*/
@After
public void teardown() {
TSDRRestconfCollectorLogger.setInstance(null);
}
}