Package com.streamreduce.core.service

Source Code of com.streamreduce.core.service.EventServiceITCase

/*
* Copyright 2012 Nodeable Inc
*
*    Licensed 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 com.streamreduce.core.service;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.streamreduce.AbstractServiceTestCase;
import com.streamreduce.ConnectionNotFoundException;
import com.streamreduce.Constants;
import com.streamreduce.ProviderIdConstants;
import com.streamreduce.connections.AuthType;
import com.streamreduce.connections.ConnectionProvider;
import com.streamreduce.connections.ConnectionProviderFactory;
import com.streamreduce.core.event.EventId;
import com.streamreduce.core.model.Account;
import com.streamreduce.core.model.Connection;
import com.streamreduce.core.model.ConnectionCredentials;
import com.streamreduce.core.model.Event;
import com.streamreduce.core.model.InventoryItem;
import com.streamreduce.core.model.ObjectWithId;
import com.streamreduce.core.model.SobaObject;
import com.streamreduce.core.model.User;
import com.streamreduce.core.model.messages.SobaMessage;
import com.streamreduce.core.service.exception.AccountNotFoundException;
import com.streamreduce.core.service.exception.InventoryItemNotFoundException;
import com.streamreduce.core.service.exception.MessageNotFoundException;
import com.streamreduce.core.service.exception.UserNotFoundException;
import org.apache.shiro.authc.AuthenticationException;
import org.bson.types.ObjectId;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.util.ReflectionTestUtils;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Test to ensure {@link EventService} works as expected.
*/
public class EventServiceITCase extends AbstractServiceTestCase {

    @Autowired
    ConnectionProviderFactory connectionProviderFactory;

    /**
     * Tests that the events created to this point for the test account and test user
     * are as expected.
     *
     * @throws Exception if anything goes wrong
     */
    @Test
    @Ignore("Integration Tests depended on sensitive account keys, ignoring until better harness is in place.")
    public void testExpectedEventsForTestAccountAndTestUser() throws Exception {
        EventService eventService = applicationManager.getEventService();
        List<Event> events = eventService.getEventsForAccount(getTestAccount());

        // At this point, there should be exactly 3 CREATE events
        List<Event> createEvents = Lists.newArrayList(Iterables.filter(events, new Predicate<Event>() {
            @Override
            public boolean apply(@Nullable Event input) {
                return input != null && input.getEventId() == EventId.CREATE;
            }
        }));

        Assert.assertEquals(3, createEvents.size());
    }


    /**
     * Tests that {@link EventService#createEvent(com.streamreduce.core.event.EventId, com.streamreduce.core.model.ObjectWithId,
     * java.util.Map)}
     * works as expected when a user is not logged in and we are creating an event.
     */
    @Test
    @Ignore("Integration Tests depended on sensitive account keys, ignoring until better harness is in place.")
    public void testCreateEvent_ReadEventWithNoLoggedInUser() throws Exception {
        // Test creating an event with no logged in user
        EventService eventService = applicationManager.getEventService();
        SecurityService mockSecurityService = mock(SecurityService.class);
        when(mockSecurityService.getCurrentUser()).thenThrow(new AuthenticationException());
        ReflectionTestUtils.setField(eventService, "securityService", mockSecurityService);


        Event event = eventService.createEvent(EventId.READ, testUser, null);
        Assert.assertNull(event);
    }

    /**
     * Tests that {@link EventService#createEvent(com.streamreduce.core.event.EventId, com.streamreduce.core.model.ObjectWithId,
     * java.util.Map)}
     * works as expected when a user is not logged in and we are creating a SobaMessage
     */
    @Test
    @Ignore("Integration Tests depended on sensitive account keys, ignoring until better harness is in place.")
    public void testCreateEvent_CreateSobaMessageWithNoLoggedInUser() throws Exception {
        // Test creating an event with no logged in user
        EventService eventService = applicationManager.getEventService();
        SecurityService mockSecurityService = mock(SecurityService.class);
        when(mockSecurityService.getCurrentUser()).thenThrow(new AuthenticationException());
        ReflectionTestUtils.setField(eventService, "securityService", mockSecurityService);


        // Test creating a SobaObject event with no logged in user
        Connection connection = new Connection.Builder()
                .provider(connectionProviderFactory.connectionProviderFromId(ProviderIdConstants.GITHUB_PROVIDER_ID))
                .account(testAccount)
                .alias("Test GitHub Connection")
                .description("This is a test GitHub connection.")
                .user(testUser)
                .authType(AuthType.USERNAME_PASSWORD)
                .credentials(new ConnectionCredentials("somegithubusername", "somegithubpassword"))
                .build();

        Event event = eventService.createEvent(EventId.CREATE, connection, null);

        Assert.assertNotNull(event);
    }


    /**
     * Tests that {@link EventService#createEvent(com.streamreduce.core.event.EventId, com.streamreduce.core.model.ObjectWithId,
     * java.util.Map)}
     */
    @Test
    @Ignore("Integration Tests depended on sensitive account keys, ignoring until better harness is in place.")
    public void testCreateEvent_CreateEventWithLoggedInUser() throws Exception {
        // Test creating an event as a logged in user
        // (We have to mock a few things since logging a user in programmatically isn't an option)
        EventService esMock = getEventServiceMock();

        Event event = esMock.createEvent(EventId.CREATE_GLOBAL_MESSAGE, null, null);

        verifyEvent(event, EventId.CREATE_GLOBAL_MESSAGE, testUser, testAccount, null, null);
    }

    /**
     * Test that will attempt to retrieve all {@link Event} objects and verify them.
     *
     * @throws Exception if anything goes wrong
     */
    @Test
    @Ignore("Integration Tests depended on sensitive account keys, ignoring until better harness is in place.")
    public void testAllGeneratedEvents() throws Exception {
        EventService eventService = applicationManager.getEventService();
        List<Event> allEvents = eventService.getAllEvents();

        // TODO: It would be nice to test every event scenario when time permits

        for (Event event : allEvents) {
            verifyEvent(event);
        }
    }

    /**
     * Creates a mock {@link EventService} that is mocked so a user is logged in.
     *
     * @return the mock ApplicationManager
     */

    private EventService getEventServiceMock() {
        SecurityService ssMock = Mockito.mock(SecurityService.class);
        UserService usMock = Mockito.spy(applicationManager.getUserService());
        EventService esMock = Mockito.spy(applicationManager.getEventService());

        ReflectionTestUtils.setField(esMock, "userService", usMock);
        ReflectionTestUtils.setField(esMock, "securityService", ssMock);
        ReflectionTestUtils.setField(usMock, "eventService", esMock);
        Mockito.when(ssMock.getCurrentUser()).thenReturn(testUser);

        return esMock;
    }

    /**
     * Validates historical events, where possible, by looking up the event's user, account and target
     * and then using that information in calling {@link #verifyEvent(com.streamreduce.core.model.Event,
     * com.streamreduce.core.event.EventId, com.streamreduce.core.model.User, com.streamreduce.core.model.Account,
     * com.streamreduce.core.model.ObjectWithId, java.util.Map)}.
     *
     * @param event the event to verify
     */
    private void verifyEvent(Event event) {
        Map<String, Object> eventMetadata = event.getMetadata();
        String eventType = (String) eventMetadata.get("targetType");
        User eventUser = null;
        Account eventAccount = null;
        ObjectWithId eventTarget = null;

        // TODO: Bubble the event participants lookup to event service methods

        if (event.getUserId() != null) {
            try {
                eventUser = applicationManager.getUserService().getUserById(event.getUserId());
            } catch (UserNotFoundException e) {
                // Do nothing
            }
        }

        if (event.getAccountId() != null) {
            try {
                eventAccount = applicationManager.getUserService().getAccount(event.getAccountId());
            } catch (AccountNotFoundException e) {
                // Do nothing
            }
        }

        if (event.getTargetId() != null) {
            ObjectId eventTargetId = event.getTargetId();

            if (eventType.equals(Account.class.getSimpleName())) {
                try {
                    eventTarget = applicationManager.getUserService().getAccount(eventTargetId);
                } catch (AccountNotFoundException e) {
                    // Do nothing
                }
            } else if (eventType.equals(InventoryItem.class.getSimpleName())) {
                try {
                    eventTarget = applicationManager.getInventoryService().getInventoryItem(eventTargetId);
                } catch (InventoryItemNotFoundException e) {
                    // Do nothing
                }
            } else if (eventType.equals(Connection.class.getSimpleName())) {
                try {
                    eventTarget = applicationManager.getConnectionService().getConnection(eventTargetId);
                } catch (ConnectionNotFoundException e) {
                    // Do nothing
                }
            } else if (eventType.equals(SobaMessage.class.getSimpleName())) {
                try {
                    eventTarget = applicationManager.getMessageService().getMessage(eventAccount, eventTargetId);
                } catch (MessageNotFoundException e) {
                    // Do nothing
                }
            } else if (eventType.equals(User.class.getSimpleName())) {
                try {
                    eventTarget = applicationManager.getUserService().getUserById(eventTargetId);
                } catch (UserNotFoundException e) {
                    // Do nothing
                }
            } else if (eventType.equals(SobaMessage.class.getSimpleName())) {
                try {
                    eventTarget = applicationManager.getMessageService().getMessage(eventAccount, eventTargetId);
                } catch (MessageNotFoundException e) {
                    // Do nothing
                }
            } else {
                Assert.fail("Unable to handle target class of type: " + eventType + ".");
            }
        }

        // We cannot actually validate events where we cannot lookup the object by id for historical events
        if (event.getUserId() != null && eventUser != null &&
                event.getAccountId() != null && eventAccount != null &&
                event.getTargetId() != null && eventTarget != null) {
            verifyEvent(event, event.getEventId(), eventUser, eventAccount, eventTarget, eventMetadata);
        } else {
            System.out.println("[TEST WARN] Historical Event (" + event.getId() + ") could not be validated for " +
                    "content due to the user, account and/or target no longer being in the " +
                    "database.");
        }
    }

    /**
     * Validates the event against expected event pieces.
     *
     * @param event                 the event to validate
     * @param expectedEventId       the expected event id
     * @param expectedUser          the expected user
     * @param expectedAccount       the expected account
     * @param expectedTarget        the expected target
     * @param expectedExtraMetadata the expected extra metadata
     */
    private <T extends ObjectWithId> void verifyEvent(Event event, EventId expectedEventId, User expectedUser,
                                                      Account expectedAccount, T expectedTarget,
                                                      Map<String, Object> expectedExtraMetadata) {
        Map<String, Object> eventMetadata = event.getMetadata();

        // Validate the event id
        Assert.assertEquals(expectedEventId, event.getEventId());

        // Validate the user
        Assert.assertEquals(expectedUser != null ? expectedUser.getId() : null, event.getUserId());

        // Validate the account
        Assert.assertEquals(expectedAccount != null ? expectedAccount.getId() : null, event.getAccountId());

        // Validate the target
        Assert.assertEquals(expectedTarget != null ? expectedTarget.getId() : null, event.getTargetId());

        // Validate the timestamp
        Assert.assertNotNull(event.getTimestamp());

        // Validate the extra metadata
        if (expectedExtraMetadata != null) {
            for (String key : expectedExtraMetadata.keySet()) {
                Assert.assertEquals(expectedExtraMetadata.get(key), eventMetadata.get(key));
            }
        }

        // Validate metadata automatically generated at event creation

        // Validate user generated event metadata
        Map<String, Object> expectedUserMetadata = new HashMap<>();

        expectedUserMetadata.put("sourceAlias", expectedUser != null ? expectedUser.getAlias() : null);
        expectedUserMetadata.put("sourceFuid", expectedUser != null ? expectedUser.getFuid() : null);
        expectedUserMetadata.put("sourceFullname", expectedUser != null ? expectedUser.getFullname() : null);
        expectedUserMetadata.put("sourceUsername", expectedUser != null ? expectedUser.getUsername() : null);
        expectedUserMetadata.put("sourceVersion", expectedUser != null ? expectedUser.getVersion() : null);

        validateEventMetadata(eventMetadata, expectedUserMetadata, expectedUser != null);

        // Validate account generated event metadata
        Map<String, Object> expectedAccountMetadata = new HashMap<>();

        expectedAccountMetadata.put("accountFuid", expectedAccount != null ? expectedAccount.getFuid() : null);
        expectedAccountMetadata.put("accountName", expectedAccount != null ? expectedAccount.getName() : null);
        expectedAccountMetadata.put("accountVersion", expectedAccount != null ? expectedAccount.getVersion() : null);

        validateEventMetadata(eventMetadata, expectedAccountMetadata, expectedAccount != null);

        // Validate target generated metadata
        if (expectedTarget != null) {
            // Validate object version
            Assert.assertEquals(eventMetadata.get("targetVersion"), expectedTarget.getVersion());

            // Validate object type (Class's simple name)
            Assert.assertEquals(eventMetadata.get("targetType"), expectedTarget.getClass().getSimpleName());

            // Validate SobaObject generated metadata
            if (expectedTarget instanceof SobaObject) {
                SobaObject tSobaObject = (SobaObject) expectedTarget;
                Map<String, Object> sExpectedMetadata = new HashMap<>();

                sExpectedMetadata.put("targetAlias", tSobaObject.getAlias());
                sExpectedMetadata.put("targetHashtags", tSobaObject.getHashtags());

                validateEventMetadata(eventMetadata, sExpectedMetadata, true);
            }

            // Validate the generated metadata based on object type

            Map<String, Object> expectedObjectMetadata = new HashMap<>();

            if (expectedTarget instanceof Account) {
                Account tAccount = (Account) expectedTarget;

                expectedObjectMetadata.put("targetFuid", tAccount.getFuid());
                expectedObjectMetadata.put("targetName", tAccount.getName());
            } else if (expectedTarget instanceof InventoryItem) {
                InventoryItem tInventoryItem = (InventoryItem) expectedTarget;
                Connection tConnection = tInventoryItem.getConnection();
                ConnectionProvider tConnectionProvider =
                        applicationManager.getConnectionProviderFactory()
                                .connectionProviderFromId(tConnection.getProviderId());
                Map<String, Object> expectedInventoryItemMetadata = new HashMap<>();
                InventoryService inventoryService = applicationManager.getInventoryService();

                expectedObjectMetadata.put("targetExternalId", tInventoryItem.getExternalId());

                expectedInventoryItemMetadata.put("targetConnectionId", tConnection.getId());
                expectedInventoryItemMetadata.put("targetConnectionAlias", tConnection.getAlias());
                expectedInventoryItemMetadata.put("targetConnectionHashtags", tConnection.getHashtags());
                expectedInventoryItemMetadata.put("targetConnectionVersion", tConnection.getVersion());
                expectedInventoryItemMetadata.put("targetProviderId", tConnectionProvider.getId());
                expectedInventoryItemMetadata.put("targetProviderDisplayName", tConnectionProvider.getDisplayName());
                expectedInventoryItemMetadata.put("targetProviderType", tConnectionProvider.getType());

                if (tInventoryItem.getConnection().getProviderId().equals(ProviderIdConstants.AWS_PROVIDER_ID)) {
                    Location zone = inventoryService.getLocationByScope(tInventoryItem, LocationScope.ZONE);
                    Location region = inventoryService.getLocationByScope(tInventoryItem, LocationScope.REGION);
                    Set<String> iso3166Codes = zone != null ? zone.getIso3166Codes() : null;
                    String iso3166Code = iso3166Codes != null && iso3166Codes.size() >= 1 ?
                            iso3166Codes.iterator().next() :
                            null;

                    if (tInventoryItem.getType().equals(Constants.COMPUTE_INSTANCE_TYPE)) {
                        expectedObjectMetadata.put("targetIP",
                                inventoryService.getComputeInstanceIPAddress(tInventoryItem));
                        expectedObjectMetadata.put("targetOS",
                                inventoryService.getComputeInstanceOSName(tInventoryItem));
                    }

                    if (iso3166Code != null) {
                        expectedObjectMetadata.put("targetISO3166Code", iso3166Code);
                    }
                    if (zone != null) {
                        expectedObjectMetadata.put("targetZone", zone.getId());
                    }
                    if (region != null) {
                        expectedObjectMetadata.put("targetRegion", region.getId());
                    }
                }

                validateEventMetadata(eventMetadata, expectedInventoryItemMetadata, true);
            } else if (expectedTarget instanceof Connection) {
                Connection tConnection = (Connection) expectedTarget;
                ConnectionProvider tConnectionProvider = applicationManager.getConnectionProviderFactory()
                        .connectionProviderFromId(
                                tConnection.getProviderId());

                expectedObjectMetadata.put("targetProviderId", tConnectionProvider.getId());
                expectedObjectMetadata.put("targetProviderDisplayName", tConnectionProvider.getDisplayName());
                expectedObjectMetadata.put("targetProviderType", tConnectionProvider.getType());
            } else if (expectedTarget instanceof User) {
                User tUser = (User) expectedTarget;

                expectedObjectMetadata.put("targetFuid", tUser.getFuid());
                expectedObjectMetadata.put("targetFullname", tUser.getFullname());
                expectedObjectMetadata.put("targetUsername", tUser.getUsername());
            }

            if (expectedObjectMetadata.size() > 0) {
                validateEventMetadata(eventMetadata, expectedObjectMetadata, true);
            }
        }
    }

    /**
     * Helper method to check the event metadata for values or make sure the values aren't there.
     *
     * @param eventMetadata         the event's actual metadata
     * @param expectedEventMetadata the expected event metadata
     * @param keysExpected          whether the expected event metadata keys should or should not exist
     */
    private void validateEventMetadata(Map<String, Object> eventMetadata, Map<String, Object> expectedEventMetadata,
                                       boolean keysExpected) {
        if (keysExpected) {
            for (Map.Entry<String, Object> entry : expectedEventMetadata.entrySet()) {
                String key = entry.getKey();
                Object actualValue = eventMetadata.get(entry.getKey());
                Object expectedValue = expectedEventMetadata.get(key);

                try {
                    if (actualValue instanceof Collection || expectedValue instanceof Collection) {
                        Assert.assertEquals(actualValue != null ? ((Collection) actualValue).size() : 0,
                                expectedValue != null ? ((Collection) expectedValue).size() : 0);
                    } else {
                        Assert.assertEquals(actualValue, expectedValue);
                    }
                } catch (AssertionError ae) {
                    System.out.println("Expected event metadata key (" + key + ") did not match expected " +
                            "value: " + expectedEventMetadata.get(key));
                    throw ae;
                }
            }
        } else {
            for (String key : expectedEventMetadata.keySet()) {
                try {
                    Assert.assertFalse(eventMetadata.containsKey(key));
                } catch (AssertionError ae) {
                    System.out.println("Unexpected event metadata key was present: " + key);
                }
            }
        }
    }

}
TOP

Related Classes of com.streamreduce.core.service.EventServiceITCase

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.