package org.camunda.bpm.extension.osgi.el; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.isA; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.util.Arrays; import org.camunda.bpm.engine.delegate.JavaDelegate; import org.camunda.bpm.engine.impl.javax.el.ELContext; import org.camunda.bpm.engine.impl.javax.el.MethodNotFoundException; import org.camunda.bpm.engine.impl.javax.el.PropertyNotFoundException; import org.camunda.bpm.engine.impl.pvm.delegate.ActivityBehavior; import org.camunda.bpm.extension.osgi.TestActivityBehaviour; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; public class OSGiELResolverTest { private TestOSGiELResolver resolver; private ELContext elContext; private ArgumentCaptor<Boolean> booleanCaptor; @Before public void setUp() { resolver = new TestOSGiELResolver(); resolver.ctx = mock(BundleContext.class); elContext = mock(ELContext.class); booleanCaptor = ArgumentCaptor.forClass(Boolean.class); } @Test public void getValueThatCantBeResolved() { Object value = resolver.getValue(elContext, null, "myServiceTask"); assertThat(value, is(nullValue())); // make sure nobody called setPropertyResolved() verifyZeroInteractions(elContext); } @Test public void getValueForBaseNotNull() { Object value = resolver.getValue(elContext, new Object(), "myServiceTask"); assertThat(value, is(nullValue())); // make sure nobody called setPropertyResolved() verifyZeroInteractions(elContext); } @Test public void getValueForMatchingLdapFilter() throws InvalidSyntaxException { String lookupName = "myServiceTask"; String ldapFilter = "(processExpression=" + lookupName + ")"; Object serviceObject = new Object(); ServiceReference<Object> reference = mockService(serviceObject); registerServiceRefsAtContext((Class<Object>) null, ldapFilter, reference); Object value = resolver.getValue(elContext, null, lookupName); assertThat(value, is(sameInstance(serviceObject))); wasPropertyResolved(); } @SuppressWarnings("unchecked") @Test(expected = RuntimeException.class) public void getValueForTooManyMatchingLdapFilter() throws InvalidSyntaxException { String lookupName = "everybodysServiceTask"; String ldapFilter = "(processExpression=" + lookupName + ")"; registerServiceRefsAtContext(null, ldapFilter, mock(ServiceReference.class), mock(ServiceReference.class)); resolver.getValue(elContext, null, lookupName); } @Test public void getValueForSingleJavaDelegate() throws InvalidSyntaxException { String lookupName = "testJavaDelegate"; JavaDelegate serviceObject = new TestJavaDelegate(); ServiceReference<JavaDelegate> reference = mockService(serviceObject); registerServiceRefsAtContext(JavaDelegate.class, null, reference); JavaDelegate value = (JavaDelegate) resolver.getValue(elContext, null, lookupName); assertThat(value, is(sameInstance(serviceObject))); wasPropertyResolved(); } @SuppressWarnings("unchecked") @Test public void getValueForTwoJavaDelegates() throws InvalidSyntaxException { String lookupName = "testJavaDelegate"; JavaDelegate serviceObject = new TestJavaDelegate(); JavaDelegate anotherServiceObject = mock(JavaDelegate.class); ServiceReference<JavaDelegate> reference1 = mockService(serviceObject); ServiceReference<JavaDelegate> reference2 = mockService(anotherServiceObject); registerServiceRefsAtContext(JavaDelegate.class, null, reference1, reference2); JavaDelegate value = (JavaDelegate) resolver.getValue(elContext, null, lookupName); assertThat(value, is(sameInstance(serviceObject))); wasPropertyResolved(); } @SuppressWarnings("unchecked") @Test(expected = RuntimeException.class) public void getValueForTwoJavaDelegatesWithSameName() throws InvalidSyntaxException { String lookupName = "testJavaDelegate"; ServiceReference<JavaDelegate> reference1 = mockService((JavaDelegate) new TestJavaDelegate()); ServiceReference<JavaDelegate> reference2 = mockService((JavaDelegate) new TestJavaDelegate()); registerServiceRefsAtContext(JavaDelegate.class, null, reference1, reference2); resolver.getValue(elContext, null, lookupName); } @Test public void getValueForSingleActivityBehavior() throws InvalidSyntaxException { String lookupName = "testActivityBehaviour"; ActivityBehavior serviceObject = new TestActivityBehaviour(); ServiceReference<ActivityBehavior> reference = mockService(serviceObject); registerServiceRefsAtContext(ActivityBehavior.class, null, reference); ActivityBehavior value = (ActivityBehavior) resolver.getValue(elContext, null, lookupName); assertThat(value, is(sameInstance(serviceObject))); wasPropertyResolved(); } @SuppressWarnings("unchecked") @Test public void getValueForTwoActivityBehaviors() throws InvalidSyntaxException { String lookupName = "testActivityBehaviour"; ActivityBehavior serviceObject = new TestActivityBehaviour(); ActivityBehavior anotherServiceObject = mock(ActivityBehavior.class); ServiceReference<ActivityBehavior> reference1 = mockService(serviceObject); ServiceReference<ActivityBehavior> reference2 = mockService(anotherServiceObject); registerServiceRefsAtContext(ActivityBehavior.class, null, reference1, reference2); ActivityBehavior value = (ActivityBehavior) resolver.getValue(elContext, null, lookupName); assertThat(value, is(sameInstance(serviceObject))); wasPropertyResolved(); } @SuppressWarnings("unchecked") @Test(expected = RuntimeException.class) public void getValueForTwoActivityBehaviorsWithSameName() throws InvalidSyntaxException { String lookupName = "testActivityBehaviour"; ActivityBehavior behaviour1 = new TestActivityBehaviour(); ActivityBehavior behaviour2 = new TestActivityBehaviour(); ServiceReference<ActivityBehavior> reference1 = mockService(behaviour1); ServiceReference<ActivityBehavior> reference2 = mockService(behaviour2); registerServiceRefsAtContext(ActivityBehavior.class, null, reference1, reference2); resolver.getValue(elContext, null, lookupName); } @SuppressWarnings("unchecked") private <T> void registerServiceRefsAtContext(Class<T> clazz, String ldapFilter, ServiceReference<T> ref) { registerServiceRefsAtContext(clazz, ldapFilter, new ServiceReference[] { ref }); } private <T> void registerServiceRefsAtContext(Class<T> clazz, String ldapFilter, ServiceReference<T>... refs) { try { if (clazz != null) { when(resolver.ctx.getServiceReferences(clazz, ldapFilter)).thenReturn(Arrays.asList(refs)); } else { when(resolver.ctx.getServiceReferences((String) null, ldapFilter)).thenReturn(refs); } } catch (InvalidSyntaxException e) { // wont happen fail(e.getMessage()); } } @SuppressWarnings("unchecked") private <T> ServiceReference<T> mockService(T service) { ServiceReference<T> ref = mock(ServiceReference.class); when(resolver.ctx.getService(eq(ref))).thenReturn(service); return ref; } private void wasPropertyResolved() { verify(elContext).setPropertyResolved(booleanCaptor.capture()); assertThat(booleanCaptor.getValue(), is(true)); } private class TestOSGiELResolver extends OSGiELResolver { private BundleContext ctx; @Override protected BundleContext getBundleContext() { return ctx; } } @Test public void isReadonly() { assertThat(resolver.isReadOnly(null, null, null), is(true)); } @Test public void getCommonPropertyType() { assertThat(resolver.getCommonPropertyType(null, new Object()), isA(Object.class)); } @Test public void getFeatureDescriptors() { assertThat(resolver.getFeatureDescriptors(null, null), is(nullValue())); } @Test public void getValueForGetterProperty() { TestJavaBean bean = new TestJavaBean(); Object value = new Object(); bean.setValue(value); Object object = resolver.getValue(elContext, bean, "value"); assertThat(object, is(sameInstance(value))); wasPropertyResolved(); } @Test public void getValueForIsProperty() { TestJavaBean bean = new TestJavaBean(); bean.setCalled(true); Boolean object = (Boolean) resolver.getValue(elContext, bean, "called"); assertThat(object, is(true)); wasPropertyResolved(); } @Test public void getValueForAbsentProperty() { TestJavaBean bean = new TestJavaBean(); resolver.getValue(elContext, bean, "foo"); verifyZeroInteractions(elContext); } @Test public void setValue() { TestJavaBean bean = new TestJavaBean(); Object value = new Object(); resolver.setValue(elContext, bean, "value", value); assertThat(bean.getValue(), is(sameInstance(value))); wasPropertyResolved(); } @Test(expected = PropertyNotFoundException.class) public void setValueForAbsentProperty() { TestJavaBean bean = new TestJavaBean(); resolver.setValue(elContext, bean, "bar", new Object()); verifyZeroInteractions(elContext); } @Test public void invoke() { TestJavaBean bean = new TestJavaBean(); Object value = new Object(); bean.setValue(value); Object invoke = resolver.invoke(elContext, bean, "getValue", new Class[0], null); assertThat(invoke, is(sameInstance(value))); } @Test(expected = MethodNotFoundException.class) public void invokeAbsentMethod() { TestJavaBean bean = new TestJavaBean(); resolver.invoke(elContext, bean, "method", new Class[0], null); verifyZeroInteractions(elContext); } }