Package org.openengsb.core.services.internal

Source Code of org.openengsb.core.services.internal.ConnectorManagerTest

/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.openengsb.core.services.internal;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.aopalliance.intercept.MethodInterceptor;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.openengsb.core.api.Connector;
import org.openengsb.core.api.ConnectorInstanceFactory;
import org.openengsb.core.api.ConnectorValidationFailedException;
import org.openengsb.core.api.Constants;
import org.openengsb.core.api.Domain;
import org.openengsb.core.api.DomainProvider;
import org.openengsb.core.api.LinkingSupport;
import org.openengsb.core.api.OsgiServiceNotAvailableException;
import org.openengsb.core.api.model.ConnectorDescription;
import org.openengsb.core.api.model.ModelDescription;
import org.openengsb.core.api.persistence.ConfigPersistenceService;
import org.openengsb.core.api.xlink.model.ModelViewMapping;
import org.openengsb.core.api.xlink.model.XLinkConnectorRegistration;
import org.openengsb.core.api.xlink.model.XLinkConnectorView;
import org.openengsb.core.api.xlink.model.XLinkConstants;
import org.openengsb.core.api.xlink.service.XLinkConnectorManager;
import org.openengsb.core.common.SecurityAttributeProviderImpl;
import org.openengsb.core.ekb.api.TransformationEngine;
import org.openengsb.core.persistence.internal.DefaultConfigPersistenceService;
import org.openengsb.core.services.internal.model.NullConnector;
import org.openengsb.core.services.internal.model.NullModel;
import org.openengsb.core.services.internal.xlink.ExampleObjectOrientedModel;
import org.openengsb.core.test.AbstractOsgiMockServiceTest;
import org.openengsb.core.test.DummyConfigPersistenceService;
import org.openengsb.core.test.DummyModel;
import org.openengsb.core.test.NullDomain;
import org.openengsb.core.test.NullDomainImpl;
import org.openengsb.core.util.DefaultOsgiUtilsService;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ConnectorManagerTest extends AbstractOsgiMockServiceTest {

    private DefaultOsgiUtilsService serviceUtils;
    private DefaultOsgiUtilsService mockedServiceUtils;
    private XLinkConnectorManager connectorManager;
    private ConnectorRegistrationManager serviceRegistrationManagerImpl;
    private ConnectorInstanceFactory factory;
    private DefaultConfigPersistenceService configPersistence;

    private LinkingSupport testConnector;

    private TransformationEngine transformationEngine;

    @Before
    public void setUp() throws Exception {
        registerMockedDomainProvider();
        registerMockedFactory();
        registerConfigPersistence();
        transformationEngine = mock(TransformationEngine.class);
        when(transformationEngine
            .performTransformation(any(ModelDescription.class), any(ModelDescription.class), any()))
            .thenAnswer(new Answer<Object>() {
                @Override
                public Object answer(InvocationOnMock invocation) throws Throwable {
                    return invocation.getArguments()[2];
                }
            });
        MethodInterceptor securityInterceptor = new ForwardMethodInterceptor();
        serviceRegistrationManagerImpl = new ConnectorRegistrationManager(bundleContext, transformationEngine,
            securityInterceptor, new SecurityAttributeProviderImpl());
        serviceUtils = new DefaultOsgiUtilsService(bundleContext);
        mockedServiceUtils = mock(DefaultOsgiUtilsService.class);
        mockedServiceUtils = mock(DefaultOsgiUtilsService.class);
        testConnector = mock(LinkingSupport.class);
        LinkingSupport testConnector2 = mock(LinkingSupport.class);
        Domain testConnector3 = mock(Domain.class);
        when(mockedServiceUtils.getService("(service.pid=test+test+test)", 100L)).thenReturn(testConnector);
        when(mockedServiceUtils.getService("(service.pid=test2+test2+test2)", 100L)).thenReturn(testConnector2);
        when(mockedServiceUtils.getService("(service.pid=test3+test3+test3)", 100L)).thenReturn(null);
        when(mockedServiceUtils.getService("(service.pid=test4+test4+test4)", 100L)).thenReturn(testConnector3);
        createServiceManager();
    }

    private void registerConfigPersistence() {
        DummyConfigPersistenceService<String> backend = new DummyConfigPersistenceService<String>();
        Dictionary<String, Object> props = new Hashtable<String, Object>();
        props.put(Constants.CONFIGURATION_ID, Constants.CONFIG_CONNECTOR);
        props.put(Constants.BACKEND_ID, "dummy");
        configPersistence = new DefaultConfigPersistenceService(backend);
        registerService(configPersistence, props, ConfigPersistenceService.class);
    }

    private void createServiceManager() {
        XLinkConnectorManagerImpl serviceManagerImpl = new XLinkConnectorManagerImpl();
        serviceManagerImpl.setRegistrationManager(serviceRegistrationManagerImpl);
        serviceManagerImpl.setConfigPersistence(configPersistence);
        serviceManagerImpl.setxLinkBaseUrl("http://localhost/openXLink");
        serviceManagerImpl.setUtilsService(mockedServiceUtils);
        connectorManager = serviceManagerImpl;
    }

    @Test
    public void testCreateService_shouldCreateInstanceWithFactory() throws Exception {
        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        connectorManager.create(connectorDescription);

        serviceUtils.getService("(foo=bar)", 100L);
    }

    @Test
    public void testCreateService_shouldExist() throws Exception {
        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        String id = connectorManager.create(connectorDescription);

        boolean exists = connectorManager.connectorExists(id);
        assertTrue("Service doesn't exist after creation", exists);
    }

    @Test
    public void testUpdateService_shouldUpdateInstance() throws Exception {
        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        String uuid = connectorManager.create(connectorDescription);

        connectorDescription.getProperties().put("foo", "42");
        connectorDescription.getAttributes().put("answer", "43");
        connectorManager.update(uuid, connectorDescription);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testCreateServiceWithInvalidAttributes_shouldFail() throws Exception {
        Map<String, String> errorMessages = new HashMap<String, String>();
        errorMessages.put("all", "because I don't like you");
        when(factory.getValidationErrors(anyMap())).thenReturn(errorMessages);
        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        try {
            connectorManager.create(connectorDescription);
            fail("Exception expected");
        } catch (RuntimeException e) {
            assertThat(((ConnectorValidationFailedException) e.getCause()).getErrorMessages(), is(errorMessages));
        }

        try {
            serviceUtils.getService(NullDomain.class, 100L);
            fail("service is available, but shouldn't be");
        } catch (OsgiServiceNotAvailableException e) {
            // expected. No service should be available because the attributes were invalid
        }
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testForceCreateServiceWithInvalidAttributes_shouldCreateConnector() throws Exception {
        Map<String, String> errorMessages = new HashMap<String, String>();
        errorMessages.put("all", "because I don't like you");
        when(factory.getValidationErrors(anyMap())).thenReturn(errorMessages);
        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        connectorManager.forceCreate(connectorDescription);

        try {
            serviceUtils.getService("(foo=bar)", 100L);
        } catch (OsgiServiceNotAvailableException e) {
            fail("service should be available because validation should have been skipped");
        }
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testUpdateServiceWithInvalidAttributes_shouldLeaveServiceUnchanged() throws Exception {
        Map<String, String> errorMessages = new HashMap<String, String>();
        errorMessages.put("all", "because I don't like you");
        when(factory.getValidationErrors(any(Connector.class), anyMap())).thenReturn(errorMessages);

        Map<String, String> attributes = new HashMap<String, String>();
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        String connectorId = connectorManager.create(connectorDescription);
        serviceUtils.getService("(foo=bar)", 1L);

        connectorDescription.getProperties().put("foo", "42");
        try {
            connectorManager.update(connectorId, connectorDescription);
            fail("Exception expected");
        } catch (RuntimeException e) {
            assertThat(((ConnectorValidationFailedException) e.getCause()).getErrorMessages(), is(errorMessages));
        }

        try {
            serviceUtils.getService("(foo=bar)", 1L);
        } catch (OsgiServiceNotAvailableException e) {
            fail("Service is not available with the old attributes");
        }

        try {
            serviceUtils.getService("(foo=42)", 1L);
            fail("Service should not be available with the new properties, but it is");
        } catch (OsgiServiceNotAvailableException e) {
            // expected. The properties should not have been updated, so no service is available.
        }
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testForceUpdateServiceWithInvalidAttributes_shouldUpdateService() throws Exception {
        Map<String, String> errorMessages = new HashMap<String, String>();
        errorMessages.put("all", "because I don't like you");
        when(factory.getValidationErrors(any(Connector.class), anyMap())).thenReturn(errorMessages);

        Map<String, String> attributes = new HashMap<String, String>();
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        String connectorId = connectorManager.create(connectorDescription);
        serviceUtils.getService("(foo=bar)", 1L);

        connectorDescription.getProperties().put("foo", "42");
        connectorManager.forceUpdate(connectorId, connectorDescription);

        try {
            serviceUtils.getService("(foo=bar)", 1L);
            fail("Service is only available with the old attributes");
        } catch (OsgiServiceNotAvailableException e) {
            // expected. The attributes have been overwritten
        }

        try {
            serviceUtils.getService("(foo=42)", 1L);
        } catch (OsgiServiceNotAvailableException e) {
            fail("Service should be available with the new properties, since validation should have been skipped");
        }
    }

    @Test
    public void testDeleteService_shouldNotBeAvailableAnymore() throws Exception {
        Map<String, String> attributes = new HashMap<String, String>();
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        String connectorId = connectorManager.create(connectorDescription);

        connectorManager.delete(connectorId);

        try {
            serviceUtils.getService("(foo=bar)", 100L);
            fail("service should not be available anymore");
        } catch (OsgiServiceNotAvailableException e) {
            // expected
        }

        try {
            connectorManager.getAttributeValues(connectorId);
            fail("service was still in persistence after deletion");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    @Test
    public void testDeleteService_shouldNotExistAnymore() throws Exception {
        Map<String, String> attributes = new HashMap<String, String>();
        Map<String, Object> properties = new Hashtable<String, Object>();
        boolean connectorExists;
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        String connectorId = connectorManager.create(connectorDescription);

        connectorManager.delete(connectorId);

        connectorExists = connectorManager.connectorExists(connectorId);
        assertFalse("service was still existing after deletion", connectorExists);
    }

    @Test
    public void testGetXLinkRegistration_isEmptyOnInitial() {
        String hostId = "127.0.0.1";
        assertTrue(connectorManager.getXLinkRegistrations(hostId).isEmpty());
    }

    @Test
    public void testGetXLinkRegistration_returnsConnectedRegistration() {
        String connectorId = "test+test+test";
        String hostId = "127.0.0.1";
        String toolName = "myTool";
        ModelViewMapping[] modelViewMappings = createModelViewsMappings(toolName);
        connectorManager.registerWithXLink(connectorId, hostId, toolName, modelViewMappings);
        List<XLinkConnectorRegistration> registrations = connectorManager.getXLinkRegistrations(hostId);
        assertEquals(1, registrations.size());
        assertThat(registrations.get(0).getHostId(), is(hostId));
        assertThat(registrations.get(0).getConnectorId(), is(connectorId));
        assertThat(registrations.get(0).getToolName(), is(toolName));
    }

    @Test
    public void testUnregisterFromXLink_OnMissingRegistration_NoFail() {
        String connectorId = "test+test+test";
        connectorManager.unregisterFromXLink(connectorId);
    }

    @Test
    public void testUnregisterFromXLink_isEmptyAfterDisconnect() {
        String connectorId = "test+test+test";
        String hostId = "127.0.0.1";
        String toolName = "myTool";
        ModelViewMapping[] modelViewMappings = createModelViewsMappings(toolName);
        connectorManager.registerWithXLink(connectorId, hostId, toolName, modelViewMappings);
        connectorManager.unregisterFromXLink(connectorId);
        assertTrue(connectorManager.getXLinkRegistrations(hostId).isEmpty());
    }

    // @Test(expected = DomainNotLinkableException.class)
    // public void testConnectorValidation_connectorIsNullAndFails() {
    // String connectorId = "test3+test3+test3";
    // String hostId = "127.0.0.1";
    // String toolName = "myTool";
    // ModelViewMapping[] modelViewMappings
    // = createModelViewsMappings(toolName);
    // connectorManager.registerForXLink(connectorId, hostId, toolName, modelViewMappings);
    // }
    //
    // @Test(expected = DomainNotLinkableException.class)
    // public void testConnectorValidation_connectorIsNotLinkableAndFails() {
    // String connectorId = "test4+test4+test4";
    // String hostId = "127.0.0.1";
    // String toolName = "myTool";
    // ModelViewMapping[] modelViewMappings
    // = createModelViewsMappings(toolName);
    // connectorManager.registerForXLink(connectorId, hostId, toolName, modelViewMappings);
    // }

    private ModelViewMapping[] createModelViewsMappings(String toolName) {
        String viewId1 = "exampleViewId_1";
        String viewId2 = "exampleViewId_2";
        ModelViewMapping[] modelViewMappings = new ModelViewMapping[1];
        Map<Locale, String> descriptions = new HashMap<>();
        List<XLinkConnectorView> views = new ArrayList<XLinkConnectorView>();

        descriptions.put(Locale.ENGLISH, "This is a demo view.");
        descriptions.put(Locale.GERMAN, "Das ist eine demonstration view.");
        views = new ArrayList<XLinkConnectorView>();
        views.add(new XLinkConnectorView(viewId1, toolName, descriptions));
        views.add(new XLinkConnectorView(viewId2, toolName, descriptions));

        modelViewMappings[0] =
            new ModelViewMapping(
                new ModelDescription(
                    ExampleObjectOrientedModel.class.getName(),
                    "3.0.0.SNAPSHOT")
                , views.toArray(new XLinkConnectorView[0]));
        return modelViewMappings;
    }

    @Test
    public void testGenerateXLink_shouldSucceed() {
        String connectorId = "testConnector";
        String context = "foo";
        String testClassName = "TestClass";
        ExampleObjectOrientedModel modelObject = new ExampleObjectOrientedModel();
        modelObject.setOoClassName(testClassName);
        String xlink = connectorManager.generateXLink(connectorId, context, modelObject);

        assertNotNull(xlink);

        // Trim baseURL away
        xlink = xlink.substring(xlink.indexOf("?") + 1);
        // Get parameters out of the link
        Map<String, String> parameterMap = new HashMap<>();
        for (String parameter : xlink.split("&")) {
            String[] keyValue = parameter.split("=");
            if (keyValue.length == 2) {
                parameterMap.put(keyValue[0], keyValue[1]);
            }
        }

        assertEquals(context, parameterMap.get(XLinkConstants.XLINK_CONTEXTID_KEY));

        assertNotNull(parameterMap.get(XLinkConstants.XLINK_IDENTIFIER_KEY));

        String className = parameterMap.get(XLinkConstants.XLINK_MODELCLASS_KEY);
        assertEquals(ExampleObjectOrientedModel.class.getName(), className);

        ObjectMapper mapper = new ObjectMapper();
        // Needed because OpenEngSB model tail can not be used here
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        String model = parameterMap.get(XLinkConstants.XLINK_IDENTIFIER_KEY);
        ExampleObjectOrientedModel exampleModel = null;
        try {
            exampleModel = mapper.readValue(urlDecodeParameter(model), ExampleObjectOrientedModel.class);
        } catch (IOException e) {
            fail("Should not have been thrown.");
        }

        assertNotNull(exampleModel);
        assertEquals(testClassName, exampleModel.getOoClassName());
    }

    private String urlDecodeParameter(String parameter) {
        try {
            return URLDecoder.decode(parameter, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }
        return parameter;
    }

    @Test
    public void testCreateConnectorWithSkipDomainType_shouldNotInvokeSetDomainType() throws Exception {
        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put(Constants.SKIP_SET_DOMAIN_TYPE, "true");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        NullDomainImpl mock2 = mock(NullDomainImpl.class);
        when(factory.createNewInstance(anyString())).thenReturn(mock2);
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);
        connectorManager.create(connectorDescription);
        verify(mock2, never()).setDomainId(anyString());
        verify(mock2, never()).setConnectorId(anyString());
    }

    @Test
    public void testCreateConnectorWithToolModel_shouldCreateTransformingProxy() throws Exception {
        NullConnector mockedConnector = mock(NullConnector.class);
        when(factory.createNewInstance(anyString())).thenReturn(mockedConnector);

        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        connectorManager.create(connectorDescription);

        NullDomain service = (NullDomain) serviceUtils.getService("(foo=bar)", 100L);
        service.nullMethod();
        verify(mockedConnector).nullMethod();
    }

    @Test
    public void testCallTransformingProxy_shouldTransformArguments() throws Exception {
        NullConnector mockedConnector = mock(NullConnector.class);
        when(factory.createNewInstance(anyString())).thenReturn(mockedConnector);

        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("answer", "42");
        Map<String, Object> properties = new Hashtable<String, Object>();
        properties.put("foo", "bar");
        ConnectorDescription connectorDescription = new ConnectorDescription("test", "testc", attributes, properties);

        connectorManager.create(connectorDescription);

        NullDomain service = (NullDomain) serviceUtils.getService("(foo=bar)", 100L);
        DummyModel dummyModel = new DummyModel();
        dummyModel.setId("42");
        dummyModel.setValue("foo");

        NullModel nullModel = new NullModel();
        nullModel.setId(42);
        nullModel.setValue("foo");
        when(transformationEngine.performTransformation(
            any(ModelDescription.class), any(ModelDescription.class), eq(dummyModel)))
            .thenReturn(nullModel);

        service.commitModel(dummyModel);
        verify(mockedConnector).commitModel(nullModel);
    }

    @SuppressWarnings("unchecked")
    private void registerMockedFactory() throws Exception {
        factory = mock(ConnectorInstanceFactory.class);
        when(factory.createNewInstance(anyString())).thenReturn(new NullDomainImpl());
        when(factory.applyAttributes(any(Connector.class), anyMap())).thenAnswer(new Answer<Connector>() {
            @Override
            public Connector answer(InvocationOnMock invocation) throws Throwable {
                return (Connector) invocation.getArguments()[0];
            }
        });
        Hashtable<String, Object> factoryProps = new Hashtable<String, Object>();
        factoryProps.put(Constants.CONNECTOR_KEY, "testc");
        factoryProps.put(Constants.DOMAIN_KEY, "test");
        registerService(factory, factoryProps, ConnectorInstanceFactory.class);
    }

    private void registerMockedDomainProvider() {
        DomainProvider domainProvider = mock(DomainProvider.class);
        when(domainProvider.getDomainInterface()).thenAnswer(new Answer<Class<? extends Domain>>() {
            @Override
            public Class<? extends Domain> answer(InvocationOnMock invocation) throws Throwable {
                return NullDomain.class;
            }
        });
        Hashtable<String, Object> domainProviderProps = new Hashtable<String, Object>();
        domainProviderProps.put("domain", "test");
        registerService(domainProvider, domainProviderProps, DomainProvider.class);
    }

}
TOP

Related Classes of org.openengsb.core.services.internal.ConnectorManagerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.