interactivespaces.activity.component.ActivityComponentContextTest.java Source code

Java tutorial

Introduction

Here is the source code for interactivespaces.activity.component.ActivityComponentContextTest.java

Source

/*
 * Copyright (C) 2013 Google 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 interactivespaces.activity.component;

import interactivespaces.activity.SupportedActivity;
import interactivespaces.configuration.Configuration;
import interactivespaces.util.InteractiveSpacesUtilities;

import com.google.common.collect.Lists;

import org.apache.commons.logging.Log;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Unit tests for {@link ActivityComponentContext}
 *
 * @author Keith M. Hughes
 */
public class ActivityComponentContextTest {

    private SupportedActivity activity;

    private ActivityComponentFactory componentFactory;

    private ActivityComponentContext context;

    private ExecutorService executor;

    private Log log;

    private Configuration activityConfiguration;

    @Before
    public void setup() {
        executor = Executors.newFixedThreadPool(10);

        activity = Mockito.mock(SupportedActivity.class);

        activityConfiguration = Mockito.mock(Configuration.class);
        Mockito.when(activity.getConfiguration()).thenReturn(activityConfiguration);

        log = Mockito.mock(Log.class);
        Mockito.when(activity.getLog()).thenReturn(log);

        componentFactory = Mockito.mock(ActivityComponentFactory.class);

        context = new ActivityComponentContext(activity, componentFactory);
    }

    @After
    public void cleanup() {
        executor.shutdown();
    }

    /**
     * Test that handler enters and exits are noted properly.
     */
    @Test
    public void testHandlerEnterExit() {
        // Should be nothing yet as is a fresh context
        Assert.assertFalse(context.areProcessingHandlers());

        context.enterHandler();
        Assert.assertTrue(context.areProcessingHandlers());
        context.enterHandler();
        Assert.assertTrue(context.areProcessingHandlers());
        context.enterHandler();
        Assert.assertTrue(context.areProcessingHandlers());

        context.exitHandler();
        Assert.assertTrue(context.areProcessingHandlers());
        context.exitHandler();
        Assert.assertTrue(context.areProcessingHandlers());
        context.exitHandler();
        Assert.assertFalse(context.areProcessingHandlers());
    }

    /**
     * Test that there were never any processing handlers and Wait return
     * immediately.
     */
    @Test
    public void testWaitNoProcessingHandlersEver() {
        Assert.assertTrue(context.waitOnNoProcessingHandlings(500, 2000));
    }

    /**
     * Test that there is a processing handler that never exits and the wait has
     * to exit.
     */
    @Test
    public void testWaitOneProcessingHandlers() {
        context.enterHandler();
        Assert.assertFalse(context.waitOnNoProcessingHandlings(500, 2000));
    }

    /**
     * Test that there is a processing handler that never exits and the wait has
     * to exit.
     */
    @Test
    public void testWaitMultithreadedProcessingHandlers() throws Exception {
        final CountDownLatch latch = new CountDownLatch(2);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                context.enterHandler();
                latch.countDown();
                InteractiveSpacesUtilities.delay(1000);
                context.exitHandler();
            }
        };

        executor.execute(runnable);
        executor.execute(runnable);

        // Make sure they have both entered before starting the wait.
        Assert.assertTrue(latch.await(500, TimeUnit.MILLISECONDS));

        Assert.assertTrue(context.waitOnNoProcessingHandlings(500, 4000));
    }

    /**
     * Tests the context failing to startup in time when waiting for the context
     * to signal startup complete.
     */
    @Test
    public void testFailedStartupWait() {
        Assert.assertFalse(context.awaitStartup());
    }

    /**
     * Make a couple of threads start running and see if they properly stop
     * running when the context signals startup successful.
     */
    @Test
    public void testStartupWaitWithTwoThreadsSuccess() throws Exception {
        final CountDownLatch startLatch = new CountDownLatch(2);
        final CountDownLatch stopLatch = new CountDownLatch(2);
        final AtomicInteger countAllowedHandlers = new AtomicInteger(0);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                startLatch.countDown();

                if (context.canHandlerRun()) {
                    countAllowedHandlers.incrementAndGet();
                }

                stopLatch.countDown();
            }
        };

        executor.execute(runnable);
        executor.execute(runnable);

        // Make sure they have both entered before starting the wait.
        Assert.assertTrue(startLatch.await(500, TimeUnit.MILLISECONDS));

        context.endStartupPhase(true);

        // Make sure they have both entered before starting the wait.
        Assert.assertTrue(stopLatch.await(500, TimeUnit.MILLISECONDS));

        // All handlers should have been allowed.
        Assert.assertEquals(2, countAllowedHandlers.get());
    }

    /**
     * Make a couple of threads start running and see if they properly stop
     * running when the context signals startup failure.
     */
    @Test
    public void testStartupWaitWithTwoThreadsFailure() throws Exception {
        final CountDownLatch startLatch = new CountDownLatch(2);
        final CountDownLatch stopLatch = new CountDownLatch(2);
        final AtomicInteger countAllowedHandlers = new AtomicInteger(0);

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                startLatch.countDown();

                if (context.canHandlerRun()) {
                    countAllowedHandlers.incrementAndGet();
                }

                stopLatch.countDown();
            }
        };

        executor.execute(runnable);
        executor.execute(runnable);

        // Make sure they have both entered before starting the wait.
        Assert.assertTrue(startLatch.await(500, TimeUnit.MILLISECONDS));

        context.endStartupPhase(false);

        // Make sure they have both entered before starting the wait.
        Assert.assertTrue(stopLatch.await(500, TimeUnit.MILLISECONDS));

        // No handlers should have been allowed.
        Assert.assertEquals(0, countAllowedHandlers.get());
    }

    /**
     * Add in a single component and have it start successfully.
     */
    @Test
    public void addSingleComponentSuccess() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component1.getName()).thenReturn("foo");

        context.addComponent(component1);

        context.initialStartupComponents();

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1).startupComponent();
    }

    /**
     * Add in a single component and have it fail on startup.
     */
    @Test
    public void addSingleComponentFailStartup() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component1.getName()).thenReturn("foo");

        Exception e = new RuntimeException();
        Mockito.doThrow(e).when(component1).startupComponent();

        context.addComponent(component1);

        try {
            context.initialStartupComponents();

            Assert.fail();
        } catch (Exception e1) {
            // Where we want to be
        }

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1).startupComponent();
    }

    /**
     * Add in a single component and have it fail on configuration.
     */
    @Test
    public void addSingleComponentFailConfigure() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component1.getName()).thenReturn("foo");

        Exception e = new RuntimeException();
        Mockito.doThrow(e).when(component1).configureComponent(activityConfiguration);

        context.addComponent(component1);

        try {
            context.initialStartupComponents();

            Assert.fail();
        } catch (Exception e1) {
            // Where we want to be
        }

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1, Mockito.never()).startupComponent();
    }

    /**
     * Add in multiple components and have them start successfully.
     */
    @Test
    public void addMultipleComponentsSuccess() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component1.getName()).thenReturn("foo");

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("bar");

        context.addComponent(component1);
        context.addComponent(component2);

        context.initialStartupComponents();

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1).startupComponent();

        Mockito.verify(component2).configureComponent(activityConfiguration);
        Mockito.verify(component2).startupComponent();
    }

    /**
     * Add in multiple components and have the first fail on startup.
     */
    @Test
    public void addMultipleComponentFailStartup1() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        String component1Name = "foo";
        Mockito.when(component1.getName()).thenReturn(component1Name);

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("banana");
        Mockito.when(component2.getDependencies()).thenReturn(Lists.newArrayList(component1Name));

        Exception e = new RuntimeException();
        Mockito.doThrow(e).when(component1).startupComponent();

        context.addComponent(component1);
        context.addComponent(component2);

        try {
            context.initialStartupComponents();

            Assert.fail();
        } catch (Exception e1) {
            // Where we want to be
        }

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1).startupComponent();

        Mockito.verify(component2).configureComponent(activityConfiguration);
        Mockito.verify(component2, Mockito.never()).startupComponent();
    }

    /**
     * Add in multiple components and have the second fail on startup.
     */
    @Test
    public void addMultipleComponentFailStartup2() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        String component1Name = "foo";
        Mockito.when(component1.getName()).thenReturn(component1Name);

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("banana");
        Mockito.when(component2.getDependencies()).thenReturn(Lists.newArrayList(component1Name));

        Exception e = new RuntimeException();
        Mockito.doThrow(e).when(component2).startupComponent();

        context.addComponent(component1);
        context.addComponent(component2);

        try {
            context.initialStartupComponents();

            Assert.fail();
        } catch (Exception e1) {
            // Where we want to be
        }

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1).startupComponent();
        Mockito.verify(component1).shutdownComponent();

        Mockito.verify(component2).configureComponent(activityConfiguration);
        Mockito.verify(component2).startupComponent();
        Mockito.verify(component2, Mockito.never()).shutdownComponent();
    }

    /**
     * Add in multiple components and have the first one fail on configuration.
     */
    @Test
    public void addMultipleComponentFailConfigure1() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        String component1Name = "blerg";
        Mockito.when(component1.getName()).thenReturn(component1Name);

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("garg");
        Mockito.when(component2.getDependencies()).thenReturn(Lists.newArrayList(component1Name));

        Exception e = new RuntimeException();
        Mockito.doThrow(e).when(component1).configureComponent(activityConfiguration);

        context.addComponent(component1);
        context.addComponent(component2);

        try {
            context.initialStartupComponents();

            Assert.fail();
        } catch (Exception e1) {
            // Where we want to be
        }

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1, Mockito.never()).startupComponent();
        Mockito.verify(component1, Mockito.never()).shutdownComponent();

        Mockito.verify(component2, Mockito.never()).configureComponent(activityConfiguration);
        Mockito.verify(component2, Mockito.never()).startupComponent();
        Mockito.verify(component2, Mockito.never()).shutdownComponent();
    }

    /**
     * Add in multiple components and have the second one fail on configuration.
     */
    @Test
    public void addMultipleComponentFailConfigure2() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        String component1Name = "blerg";
        Mockito.when(component1.getName()).thenReturn(component1Name);

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("garg");
        Mockito.when(component2.getDependencies()).thenReturn(Lists.newArrayList(component1Name));

        Exception e = new RuntimeException();
        Mockito.doThrow(e).when(component2).configureComponent(activityConfiguration);

        context.addComponent(component1);
        context.addComponent(component2);

        try {
            context.initialStartupComponents();

            Assert.fail();
        } catch (Exception e1) {
            // Where we want to be
        }

        Mockito.verify(component1).configureComponent(activityConfiguration);
        Mockito.verify(component1, Mockito.never()).startupComponent();
        Mockito.verify(component1, Mockito.never()).shutdownComponent();

        Mockito.verify(component2).configureComponent(activityConfiguration);
        Mockito.verify(component2, Mockito.never()).startupComponent();
        Mockito.verify(component2, Mockito.never()).shutdownComponent();
    }

    /**
     * Add in multiple components and have all succeed on shutdown.
     */
    @Test
    public void shutdownAllComponentsSuccess() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component1.getName()).thenReturn("blerg");

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("garg");

        context.addComponent(component1);
        context.addComponent(component2);

        context.initialStartupComponents();

        Assert.assertTrue(context.shutdownAndClear());

        Mockito.verify(component1).shutdownComponent();
        Mockito.verify(component2).shutdownComponent();
    }

    /**
     * Add in multiple components and have all fail on shutdown.
     */
    @Test
    public void shutdownAllComponentsFailure() throws Throwable {
        ActivityComponent component1 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component1.getName()).thenReturn("blerg");

        ActivityComponent component2 = Mockito.mock(ActivityComponent.class);
        Mockito.when(component2.getName()).thenReturn("garg");

        Exception e1 = new RuntimeException();
        Mockito.doThrow(e1).when(component1).shutdownComponent();

        Exception e2 = new RuntimeException();
        Mockito.doThrow(e2).when(component2).shutdownComponent();

        context.addComponent(component1);
        context.addComponent(component2);

        context.initialStartupComponents();

        Assert.assertFalse(context.shutdownAndClear());

        Mockito.verify(component1).shutdownComponent();
        Mockito.verify(component2).shutdownComponent();
    }
}