org.rhq.core.pc.inventory.ResourceContainerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.core.pc.inventory.ResourceContainerTest.java

Source

/*
 * RHQ Management Platform
 * Copyright (C) 2005-2013 Red Hat, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

package org.rhq.core.pc.inventory;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

import java.io.File;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.component.ComponentInvocationContextImpl;
import org.rhq.core.pc.util.FacetLockType;
import org.rhq.core.pluginapi.availability.AvailabilityFacet;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.core.pluginapi.operation.OperationFacet;
import org.rhq.core.pluginapi.operation.OperationResult;

/**
 * Unit test for {@link ResourceContainer}.
 *
 * @author Ian Springer
 */
@Test
public class ResourceContainerTest {
    private static final Log LOG = LogFactory.getLog(ResourceContainerTest.class);

    @BeforeClass
    protected void beforeClass() {
        PluginContainerConfiguration config = new PluginContainerConfiguration();
        File dataDir = new File("target/PluginContainerTest");
        dataDir.mkdirs();
        config.setDataDirectory(dataDir);
        PluginContainer pc = PluginContainer.getInstance();
        pc.setConfiguration(config);
        pc.initialize();
    }

    @AfterClass
    protected void afterClass() {
        PluginContainer.getInstance().shutdown();
    }

    public void testCreateResourceComponentProxy() throws Exception {
        ResourceContainer resourceContainer = getResourceContainer();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Testing proxy call that should timeout...");
        }
        AvailabilityFacet resourceComponentProxy = resourceContainer.createResourceComponentProxy(
                AvailabilityFacet.class, FacetLockType.NONE, 1000L, true, false, true);
        try {
            resourceComponentProxy.getAvailability();
            assert (false);
        } catch (RuntimeException e) {
            assert (e instanceof TimeoutException) : "[" + e
                    + "] is not a org.rhq.core.pc.inventory.TimeoutException.";
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("SUCCESS!");
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("Testing proxy call that should complete successfully...");
        }
        resourceComponentProxy = resourceContainer.createResourceComponentProxy(AvailabilityFacet.class,
                FacetLockType.NONE, 2000L, true, false, true);
        AvailabilityType avail = resourceComponentProxy.getAvailability();
        assert (avail == AvailabilityType.UP);
        if (LOG.isDebugEnabled()) {
            LOG.debug("SUCCESS!");
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("Testing proxy call that should fail...");
        }
        ResourceComponent naughtyResourceComponent = new MockResourceComponent(true);
        resourceContainer.setResourceComponent(naughtyResourceComponent);
        resourceComponentProxy = resourceContainer.createResourceComponentProxy(AvailabilityFacet.class,
                FacetLockType.NONE, Long.MAX_VALUE, true, false, true);
        try {
            resourceComponentProxy.getAvailability();
            assert (false);
        } catch (RuntimeException e) {
            assert (e instanceof MockRuntimeException);
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("SUCCESS!");
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("Testing proxy call should not timeout; its not to a declared method in proxied interface");
        }
        resourceComponentProxy = resourceContainer.createResourceComponentProxy(AvailabilityFacet.class,
                FacetLockType.NONE, 1000L, true, false, true);
        String string = resourceComponentProxy.toString();
        assert (string.equals(MockResourceComponent.class.toString()));
        if (LOG.isDebugEnabled()) {
            LOG.debug("SUCCESS!");
        }
        // TODO: Test proxy locking.
    }

    public void testInterruptedComponentInvocationContext() throws Exception {
        ResourceContainer resourceContainer = getResourceContainer();
        OperationFacet proxy = resourceContainer.createResourceComponentProxy(OperationFacet.class,
                FacetLockType.WRITE, SECONDS.toMillis(1L), true, false, true);
        try {
            proxy.invokeOperation("op", new Configuration());
            fail("Expected invokeOperation to throw a TimeoutException");
        } catch (TimeoutException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Caught expected TimeoutException: " + e.getMessage());
            }
            MockResourceComponent component = (MockResourceComponent) resourceContainer.getResourceComponent();
            for (int i = 0; i < 5 && !component.caughtInterruptedComponentInvocation(); i++) {
                Thread.sleep(SECONDS.toMillis(2));
            }
            assertTrue(component.caughtInterruptedComponentInvocation());
        }
    }

    public void testUninterruptedComponentInvocationContext() throws Exception {
        ResourceContainer resourceContainer = getResourceContainer();
        OperationFacet proxy = resourceContainer.createResourceComponentProxy(OperationFacet.class,
                FacetLockType.WRITE, SECONDS.toMillis(10L), true, false, true);
        try {
            OperationResult op = proxy.invokeOperation("op", new Configuration());
            assertTrue(op.getSimpleResult().equals(MockResourceComponent.OPERATION_RESULT));
        } catch (Exception e) {
            fail("Caught unexpected Exception: " + e.getClass().getName());
            assertFalse(((MockResourceComponent) resourceContainer.getResourceComponent())
                    .caughtInterruptedComponentInvocation());
        }
    }

    private ResourceContainer getResourceContainer() throws Exception {
        Resource resource = new Resource("TestPlatformKey", "MyTestPlatform",
                PluginMetadataManager.TEST_PLATFORM_TYPE);
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        ResourceContainer resourceContainer = new ResourceContainer(resource, contextClassLoader);
        ResourceContext resourceContext = new ResourceContext(resource, null, null, null, null, null, null, null,
                null, null, null, null, null, null, new ComponentInvocationContextImpl());
        resourceContainer.setResourceContext(resourceContext);
        ResourceComponent resourceComponent = new MockResourceComponent(false);
        resourceContainer.setResourceComponent(resourceComponent);
        resourceComponent.start(resourceContext);
        return resourceContainer;
    }

    private class MockResourceComponent implements ResourceComponent, OperationFacet {
        static final String OPERATION_RESULT = "uninterrupted";
        boolean naughty;
        volatile boolean caughtInterruptedComponentInvocation;
        ResourceContext resourceContext;

        MockResourceComponent(boolean naughty) {
            this.naughty = naughty;
        }

        @Override
        public void start(ResourceContext resourceContext) throws Exception {
            this.resourceContext = resourceContext;
        }

        @Override
        public void stop() {
            this.resourceContext = null;
        }

        @Override
        public AvailabilityType getAvailability() {
            if (this.naughty) {
                throw new MockRuntimeException();
            }
            try {
                Thread.sleep(1100L);
            } catch (InterruptedException e) {
                return AvailabilityType.DOWN;
            }
            return AvailabilityType.UP;
        }

        @Override
        public String toString() {
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return this.getClass().toString();
        }

        @Override
        public OperationResult invokeOperation(String name, Configuration parameters) throws Exception {
            caughtInterruptedComponentInvocation = false;
            sleep(SECONDS.toMillis(5));
            if (resourceContext.getComponentInvocationContext().isInterrupted()) {
                caughtInterruptedComponentInvocation = true;
                throw new InterruptedException();
            }
            return new OperationResult(OPERATION_RESULT);
        }

        private void sleep(long millis) {
            // Do not return before 'millis' have elapsed, even if the thread is interrupted
            long start = System.currentTimeMillis();
            for (long stop = System.currentTimeMillis(); stop - start < millis; stop = System.currentTimeMillis()) {
                try {
                    Thread.sleep(millis - (stop - start));
                } catch (InterruptedException e) {
                }
            }
        }

        boolean caughtInterruptedComponentInvocation() {
            return caughtInterruptedComponentInvocation;
        }
    }

    class MockRuntimeException extends RuntimeException {
    }
}