ch.entwine.weblounge.kernel.command.TestCommand.java Source code

Java tutorial

Introduction

Here is the source code for ch.entwine.weblounge.kernel.command.TestCommand.java

Source

/*
 *  Weblounge: Web Content Management System
 *  Copyright (c) 2003 - 2011 The Weblounge Team
 *  http://entwinemedia.com/weblounge
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser 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 ch.entwine.weblounge.kernel.command;

import ch.entwine.weblounge.common.impl.util.WebloungeDateFormat;
import ch.entwine.weblounge.common.impl.util.config.ConfigurationUtils;
import ch.entwine.weblounge.common.site.Environment;
import ch.entwine.weblounge.common.site.Site;
import ch.entwine.weblounge.testing.IntegrationTest;

import org.apache.commons.lang.StringUtils;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

/**
 * OSGi shell command implementation for the test harness.
 */
public final class TestCommand {

    /** Logger */
    private static final Logger logger = LoggerFactory.getLogger(TestCommand.class);

    /** The tests */
    private final List<IntegrationTest> tests = new ArrayList<IntegrationTest>();

    /** The current environment */
    private Environment environment = null;

    /** Comparator used to get the test suite in order */
    private static final IntegrationTestComparator testComparator = new IntegrationTestComparator();

    /**
     * Callback for OSGi's declarative services component activation.
     * 
     * @param context
     *          the component context
     * @throws Exception
     *           if component activation fails
     */
    void activate(ComponentContext context) {
        BundleContext bundleContext = context.getBundleContext();
        logger.debug("Registering test commands");
        Dictionary<String, Object> commands = new Hashtable<String, Object>();
        commands.put("osgi.command.scope", "weblounge");
        commands.put("osgi.command.function", new String[] { "lt", "test", "tests" });
        bundleContext.registerService(getClass().getName(), this, commands);
    }

    /**
     * Adds <code>test</code> to the list of integration tests. This method will
     * usually be called as a result of on {@link IntegrationTest} being published
     * in the OSGi service registry.
     * 
     * @param test
     *          the test implementation
     */
    void addIntegrationTest(IntegrationTest test) {
        if (!tests.contains(test)) {
            tests.add(test);
            Collections.sort(tests, testComparator);
            logger.debug("Installing {}", test.getName());
        }
    }

    /**
     * Removes <code>test</code> from the list of integration tests. This method
     * will usually be called as a result of on {@link IntegrationTest}
     * disappearing from the OSGi service registry.
     * 
     * @param test
     *          the test to remove
     */
    void removeIntegrationTest(IntegrationTest test) {
        tests.remove(test);
        logger.debug("Removed {}", test.getName());
    }

    /**
     * Command signature that allows to do
     * <ul>
     * <li><code>test list</code></li>
     * <li><code>test all</code></li>
     * <li><code>test <id></li>
     * </ul>
     * 
     * @param args
     *          the list of arguments to this command
     */
    public void test(String[] args) {
        if (args.length == 0) {
            list();
            return;
        } else if (args.length == 1) {
            if ("list".equals(args[0])) {
                list();
            } else if ("all".equals(args[0])) {

                if (environment == null) {
                    System.out.println("Environment is still unknown");
                    return;
                }

                executeAll(tests);
            } else {
                if (environment == null) {
                    System.out.println("Environment is still unknown");
                    return;
                }

                String id = args[0];

                // Look up the test
                IntegrationTest test = null;
                try {
                    int testIndex = Integer.parseInt(id);
                    test = tests.get(testIndex - 1);
                    List<IntegrationTest> tests = new ArrayList<IntegrationTest>();
                    tests.add(test);
                    executeAll(tests);
                } catch (NumberFormatException e) {
                    System.out.println("Unknown test: " + id);
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.println("Unknown test: " + id + " Please choose between [1.." + tests.size() + "]");
                    return;
                }
            }
        } else {
            printUsage();
        }
    }

    /**
     * OSGi callback to set the environment.
     * 
     * @param environment
     *          the environment
     */
    void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    /**
     * Prints a list of currently registered tests.
     */
    private void list() {
        // Are there any tests?
        if (tests.size() == 0) {
            System.out.println("No tests found");
            return;
        }

        // Memorize the group
        String currentGroup = "";

        // Display the test list
        for (int i = 0; i < tests.size(); i++) {
            IntegrationTest test = tests.get(i);
            String group = StringUtils.trimToEmpty(test.getGroup());
            if ("".equals(group))
                group = "DEFAULT";
            if (!group.equals(currentGroup)) {
                System.out.println("");
                System.out.println(group);
                System.out.println("   ID|Name");
                currentGroup = group;
            }
            StringBuffer buf = new StringBuffer();
            System.out.format("%5s", Integer.toString(i + 1));
            buf.append("|");
            buf.append(test.getName());
            System.out.println(buf.toString());
        }
        System.out.println("");
    }

    /**
     * Prints the command usage to the commandline.
     */
    private void printUsage() {
        System.out.println("  Usage:");
        System.out.println("    test list");
        System.out.println("    test all");
        System.out.println("    test <id>");
    }

    /**
     * Executes all registered tests.
     */
    private void executeAll(List<IntegrationTest> tests) {
        List<IntegrationTest> succeeded = new ArrayList<IntegrationTest>();
        List<IntegrationTest> failed = new ArrayList<IntegrationTest>();

        // Print the test header
        Date startDate = new Date();
        logger.info("------------------------------------------------------------------------");
        logger.info("Running Integration Tests");
        logger.info("------------------------------------------------------------------------");
        logger.info("Tests: " + tests.size());
        logger.info("Started at: " + WebloungeDateFormat.formatStatic(startDate));

        // Execute the tests
        for (IntegrationTest test : tests) {
            if (execute(test))
                succeeded.add(test);
            else
                failed.add(test);
        }

        Date endDate = new Date();
        long time = endDate.getTime() - startDate.getTime();
        String testcount = Integer.toString(tests.size());

        // Print the summary
        logger.info(" ");
        logger.info(" ");
        logger.info("------------------------------------------------------------------------");
        logger.info("Test Summary:");
        logger.info("------------------------------------------------------------------------");
        for (IntegrationTest test : tests) {
            StringBuffer buf = new StringBuffer();

            // Test number
            int pos = 0;
            for (int i = 0; i < this.tests.size(); i++) {
                if (this.tests.get(i) == test) {
                    pos = i + 1;
                    break;
                }
            }

            // Test number
            String num = Integer.toString(pos);
            for (int i = num.length(); i < testcount.length(); i++)
                buf.append(" ");
            buf.append(num);
            buf.append(" ");

            // Test name
            buf.append(test.getName());
            buf.append(" ");

            int testNameLenght = buf.length();
            if (succeeded.contains(test)) {
                for (int i = 0; i < 64 - testNameLenght; i++)
                    buf.append(".");
                buf.append(" SUCCESS");
            } else {
                for (int i = 0; i < 64 - testNameLenght; i++)
                    buf.append(".");
                buf.append(" FAILURE");
            }
            logger.info(buf.toString());
            pos++;
        }
        logger.info("------------------------------------------------------------------------");
        logger.info("------------------------------------------------------------------------");
        if (failed.size() == 0)
            logger.info("SUCCESS: " + succeeded.size() + " TEST" + (succeeded.size() > 1 ? "S" : "") + " PASSED");
        else
            logger.info("FAILURE: " + failed.size() + " TEST" + (succeeded.size() > 1 ? "S" : "") + " FAILED");
        logger.info("------------------------------------------------------------------------");
        logger.info("Total time: " + ConfigurationUtils.toHumanReadableDuration(time));
        logger.info("Finished at: " + WebloungeDateFormat.formatStatic(endDate));
        logger.info("------------------------------------------------------------------------");
    }

    /**
     * Executes a single integration test and returns <code>true</code> if the
     * test passed, <code>false</code> otherwise.
     * 
     * @param test
     *          the test to run
     * @return <code>true</code> if the test passed
     */
    private boolean execute(IntegrationTest test) {
        logger.info("");
        logger.info("------------------------------------------------------------------------");
        logger.info("Running test '" + test + "'");
        logger.info("------------------------------------------------------------------------");
        try {
            Site site = test.getSite();
            if (site == null) {
                logger.warn("Test {} has no site associated", test.getName());
                return false;
            }
            test.init(environment);
            test.execute(test.getSite().getHostname(environment).toExternalForm());
            logger.info("Test '" + test + "' succeeded");
            return true;
        } catch (Throwable t) {
            logger.warn("Test '" + test + "' failed: {}", t.getMessage(), t);
            return false;
        }
    }

    /**
     * Helper class used to sort the integration tests.
     */
    private static final class IntegrationTestComparator implements Comparator<IntegrationTest> {

        /**
         * Creates a new comparator.
         */
        IntegrationTestComparator() {
            // Nothing to do here.
        }

        /**
         * {@inheritDoc}
         * 
         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
         */
        public int compare(IntegrationTest test, IntegrationTest otherTest) {
            // Sort by test group
            String testGroup = StringUtils.trimToEmpty(test.getGroup());
            String otherTestGroup = StringUtils.trimToEmpty(otherTest.getGroup());
            int groupComparison = testGroup.compareTo(otherTestGroup);
            if (groupComparison != 0) {
                if (IntegrationTest.WEBLOUNGE_CONTENT_TEST_GROUP.equals(testGroup))
                    return -1;
                else if (IntegrationTest.WEBLOUNGE_ENDPOINT_TEST_GROUP.equals(otherTestGroup))
                    return -1;
                else if (IntegrationTest.WEBLOUNGE_CONTENT_TEST_GROUP.equals(otherTestGroup))
                    return 1;
                else if (IntegrationTest.WEBLOUNGE_ENDPOINT_TEST_GROUP.equals(otherTestGroup))
                    return 1;
                return groupComparison;
            }

            // Sort by order
            Integer testOrder = Integer.valueOf(test.getExecutionOrder());
            Integer otherTestOrder = Integer.valueOf(otherTest.getExecutionOrder());
            int orderComparison = testOrder.compareTo(otherTestOrder);
            if (orderComparison != 0)
                return orderComparison;
            return test.getName().compareTo(otherTest.getName());
        }

    }

}