package org.camunda.bpm.extension.osgi.configadmin.impl;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
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.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.ProcessEngines;
import org.camunda.bpm.extension.osgi.configadmin.ManagedProcessEngineFactory;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
public class ManagedProcessEngineFactoryImplTest {
@Test
public void getName() {
ManagedProcessEngineFactoryImpl factory = new ManagedProcessEngineFactoryImpl();
assertThat(factory.getName(), is(ManagedProcessEngineFactory.SERVICE_PID));
}
@SuppressWarnings("unchecked")
@Test
public void updateEmptyConfiguration() throws ConfigurationException {
Bundle bundle = mock(Bundle.class);
BundleContext bundleContext = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bundleContext);
ManagedProcessEngineFactoryImpl factory = new ManagedProcessEngineFactoryImpl(bundle);
factory.updated("id", new Hashtable<String, String>());
verify(bundleContext, never()).registerService(eq(ProcessEngine.class), any(ProcessEngine.class), any(Dictionary.class));
}
@SuppressWarnings("unchecked")
@Test
public void updateConfigurationWithOnlyPidAndFactoryPid() throws ConfigurationException {
Bundle bundle = mock(Bundle.class);
BundleContext bundleContext = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bundleContext);
ManagedProcessEngineFactoryImpl factory = new ManagedProcessEngineFactoryImpl(bundle);
Hashtable<String, String> properties = new Hashtable<String, String>();
properties.put(Constants.SERVICE_PID, "id");
properties.put("service.factoryPid", "factory id");
factory.updated("id", properties);
verify(bundleContext, never()).registerService(eq(ProcessEngine.class), any(ProcessEngine.class), any(Dictionary.class));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void updatedNewConfiguration() throws Exception {
String engineName = "TestEngine";
Bundle bundle = mock(Bundle.class);
// mock stuff the BundleDelegatingClassLoader does/needs
mockGetResource(bundle);
mockLoadClass(bundle);
BundleContext bundleContext = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bundleContext);
when(bundleContext.registerService(eq(ProcessEngine.class), any(ProcessEngine.class), any(Dictionary.class))).thenReturn(mock(ServiceRegistration.class));
ManagedProcessEngineFactoryImpl factory = new ManagedProcessEngineFactoryImpl(bundle);
Hashtable<String, String> properties = createEngineProperties(engineName);
factory.updated("id", properties);
ArgumentCaptor<Dictionary> propsCapture = ArgumentCaptor.forClass(Dictionary.class);
ArgumentCaptor<ProcessEngine> engineCapture = ArgumentCaptor.forClass(ProcessEngine.class);
verify(bundleContext, times(1)).registerService(eq(ProcessEngine.class), engineCapture.capture(), propsCapture.capture());
assertThat(engineCapture.getValue(), is(notNullValue()));
assertThat(propsCapture.getValue().get("process-engine-name"), is((Object) engineName));
assertThat(ProcessEngines.getProcessEngine(engineName), is(notNullValue()));
}
private Hashtable<String, String> createEngineProperties(String engineName) {
Hashtable<String, String> properties = new Hashtable<String, String>();
properties.put("processEngineName", engineName);
properties.put("jdbcUrl", "jdbc:h2:mem:camunda;DB_CLOSE_DELAY=-1");
properties.put("databaseSchemaUpdate", "true");
return properties;
}
/**
* Although the call from the framework to delete a Pid that doesn't exist
* seems unrealistic the factory shouldn't collaps when it happens anyway.
*/
@Test
public void deleteForNonExistingId(){
Bundle bundle = mock(Bundle.class);
BundleContext bundleContext = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bundleContext);
ManagedProcessEngineFactoryImpl factory = new ManagedProcessEngineFactoryImpl(bundle);
factory.deleted("notRegisteredId");
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void deleteEngine() throws Throwable{
String engineName = "TestEngine";
Bundle bundle = mock(Bundle.class);
// mock stuff the BundleDelegatingClassLoader does/needs
mockGetResource(bundle);
mockLoadClass(bundle);
BundleContext bundleContext = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bundleContext);
ServiceRegistration registrationMock = mock(ServiceRegistration.class);
when(bundleContext.registerService(eq(ProcessEngine.class), any(ProcessEngine.class), any(Dictionary.class))).thenReturn(registrationMock);
ManagedProcessEngineFactoryImpl factory = new ManagedProcessEngineFactoryImpl(bundle);
Hashtable<String, String> properties = createEngineProperties(engineName);
factory.updated("id", properties);
factory.deleted("id");
verify(registrationMock, times(1)).unregister();
assertThat(ProcessEngines.getProcessEngine(engineName), is(nullValue()));
}
@SuppressWarnings("rawtypes")
private void mockLoadClass(Bundle bundle) throws ClassNotFoundException {
final ArgumentCaptor<String> classCaptor = ArgumentCaptor.forClass(String.class);
when(bundle.loadClass(classCaptor.capture())).thenAnswer(new Answer<Class>() {
@Override
public Class answer(InvocationOnMock invocation) throws Throwable {
return this.getClass().getClassLoader().loadClass(classCaptor.getValue());
}
});
}
private void mockGetResource(Bundle bundle) {
final ArgumentCaptor<String> resourceCaptor = ArgumentCaptor.forClass(String.class);
when(bundle.getResource(resourceCaptor.capture())).thenAnswer(new Answer<URL>() {
@Override
public URL answer(InvocationOnMock invocation) throws Throwable {
return this.getClass().getResource(resourceCaptor.getValue());
}
});
}
}