com.eucalyptus.upgrade.TestHarness.java Source code

Java tutorial

Introduction

Here is the source code for com.eucalyptus.upgrade.TestHarness.java

Source

/*************************************************************************
 * Copyright 2009-2012 Eucalyptus Systems, Inc.
 *
 * 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 3 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, see http://www.gnu.org/licenses/.
 *
 * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
 * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
 * additional information or have any questions.
 *
 * This file may incorporate work covered under the following copyright
 * and permission notice:
 *
 *   Software License Agreement (BSD License)
 *
 *   Copyright (c) 2008, Regents of the University of California
 *   All rights reserved.
 *
 *   Redistribution and use of this software in source and binary forms,
 *   with or without modification, are permitted provided that the
 *   following conditions are met:
 *
 *     Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *     Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer
 *     in the documentation and/or other materials provided with the
 *     distribution.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
 *   THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
 *   COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
 *   AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
 *   IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
 *   SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
 *   WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
 *   REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
 *   IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
 *   NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
 ************************************************************************/

package com.eucalyptus.upgrade;

import java.io.File;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runners.Parameterized.Parameters;
import com.eucalyptus.bootstrap.ServiceJarDiscovery;
import com.eucalyptus.component.ComponentDiscovery;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;

public class TestHarness {
    public static Integer LINE_BYTES = 0;
    static {
        String defaultLevel = System.getProperty("verbose");
        String columns = System.getenv("COLUMNS");
        System.setProperty("test.output.console", "INFO");
        System.setProperty("test.output.terminal", "INFO");
        if (columns != null && !"".equals(columns)) {
            LINE_BYTES = Integer.parseInt(System.getenv("COLUMNS"));
            System.setProperty("test.output.terminal", defaultLevel != null ? defaultLevel : "INFO");
        } else {
            LINE_BYTES = 85;
            System.setProperty("test.output.console", "INFO");
        }
    }

    public static int count = 1;
    private static Logger LOG = Logger.getLogger(TestHarness.class);
    private static List<Class<? extends Annotation>> testAnnotations = Lists.newArrayList(Before.class, After.class,
            Test.class, Parameters.class);

    public static void main(String[] args) {
        boolean anyFail = false;
        try {
            System.out.println(Arrays.asList(args));
            final Options opts = getCliOptions();
            final GnuParser cliParser = new GnuParser();
            final CommandLine cmd = cliParser.parse(opts, args);

            try {
                anyFail = Iterables.any(Lists.newArrayList(Opts.values()), new Predicate<Opts>() {
                    public boolean apply(Opts o) {
                        return !o.run(cmd, opts);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(0); //This is necessary now; some shutdown process is hanging
        //return (anyFail) ? 1 : 0;
    }

    enum Opts {
        help {
            @Override
            public boolean run(CommandLine cmd, Options opts) {
                if (cmd.hasOption(Opts.help.toString()) || !cmd.getArgList().isEmpty()
                        || cmd.getOptionValues("test") == null) {
                    printHelp(opts);
                    System.exit(0);
                }
                return true;
            }
        },
        runTest {
            @Override
            public boolean run(CommandLine cmd, Options opts) {
                try {
                    System.setProperty("euca.log.level", "TRACE");
                    System.setProperty("euca.log.appender", "console");
                    System.setProperty("euca.log.exhaustive.cc", "FATAL");
                    System.setProperty("euca.log.exhaustive.db", "FATAL");
                    System.setProperty("euca.log.exhaustive.external", "FATAL");
                    System.setProperty("euca.log.exhaustive.user", "FATAL");
                    System.setProperty("euca.var.dir", System.getProperty("euca.home") + "/var/lib/eucalyptus/");
                    System.setProperty("euca.conf.dir",
                            System.getProperty("euca.home") + "/etc/eucalyptus/cloud.d/");
                    System.setProperty("euca.log.dir", System.getProperty("euca.home") + "/var/log/eucalyptus/");
                    System.setProperty("euca.lib.dir", System.getProperty("euca.home") + "/usr/share/eucalyptus/");
                    boolean doTrace = "TRACE".equals(System.getProperty("euca.log.level"));
                    boolean doDebug = "DEBUG".equals(System.getProperty("euca.log.level")) || doTrace;
                    //               Logs.DEBUG = doDebug;
                    //               Logs.TRACE = doDebug;

                    if ((StandalonePersistence.eucaDest = System.getProperty("euca.upgrade.destination")) == null) {
                        throw new RuntimeException("Failed to find required 'euca.upgrade.destination' property");
                    }
                    ServiceJarDiscovery.processLibraries();
                    ServiceJarDiscovery.runDiscovery(new ComponentDiscovery());
                    StandalonePersistence.setupInitProviders();
                    StandalonePersistence.setupProviders();
                    StandalonePersistence.setupNewDatabase();
                } catch (Exception e) {
                    throw new RuntimeException("Standalone persistence setup failed", e);
                }

                runMethods(cmd, opts);
                return true;
            }
        };

        public abstract boolean run(CommandLine cmd, Options opts);
    }

    @SuppressWarnings("static-access")
    private static Options getCliOptions() {
        final Options opts = new Options();
        opts.addOption(OptionBuilder.withLongOpt("test").hasArgs().withDescription(
                "Run the specified test; this option can appear multiple times. Parameters can be set as key=value pairs. e.g. ConcurrencyTest:threads=16")
                .withArgName("TEST_CLASS[:PARAM=VALUE]*").create("t"));
        opts.addOption(OptionBuilder.withLongOpt(Opts.help.name()).withDescription("Show this help information.")
                .create("h"));
        return opts;
    }

    @SuppressWarnings({ "static-access" })
    private static void printHelp(Options opts) {
        try {
            PrintWriter out = new PrintWriter(System.out);
            HelpFormatter help = new HelpFormatter();
            help.setArgName("TESTS");
            help.printHelp(out, LINE_BYTES, "java -jar test.jar", "Options controlling the test harness.", opts, 2,
                    4, "", true);
            Multimap<Class, Method> testMethods = getTestMethods();
            help = new HelpFormatter();
            help.setLongOptPrefix("");
            help.setOptPrefix("");
            help.setSyntaxPrefix("");
            help.setLeftPadding(0);
            Options testOptions = new Options();
            for (Class c : testMethods.keySet()) {
                testOptions.addOption(
                        OptionBuilder.withDescription(getDescription(c)).withLongOpt(c.getSimpleName()).create());
                for (Method m : testMethods.get(c)) {
                    testOptions.addOption(OptionBuilder.withDescription(getDescription(m))
                            .withLongOpt(c.getSimpleName() + "." + m.getName()).create());
                }
            }
            help.printHelp(out, LINE_BYTES, " ", "Tests:", testOptions, 0, 2, "", false);
            out.flush();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(1);
        }
    }

    @SuppressWarnings("unchecked")
    private static String getDescription(Object o) {
        Class c = null;
        Method m = null;
        if (o instanceof Class && ((c = (Class) o).getAnnotation(TestDescription.class)) != null) {
            return ((TestDescription) c.getAnnotation(TestDescription.class)).value();
        } else if (o instanceof Method && ((m = (Method) o).getAnnotation(TestDescription.class)) != null) {
            StringBuffer sb = new StringBuffer();
            for (Class a : Lists.newArrayList(Before.class, After.class, Test.class, Ignore.class,
                    Parameters.class)) {
                if (m.getAnnotation(a) != null)
                    sb.append("  @").append(String.format("%-9.9s", a.getSimpleName())).append(" ");
            }
            return sb.append(" ").append(((TestDescription) m.getAnnotation(TestDescription.class)).value())
                    .toString();
        }
        return "";
    }

    @SuppressWarnings("unchecked")
    private static Multimap<Class, Method> getTestMethods() throws Exception {
        final Multimap<Class, Method> testMethods = ArrayListMultimap.create();
        List<Class> classList = Lists.newArrayList();
        for (File f : new File(System.getProperty("euca.home") + "/usr/share/eucalyptus").listFiles()) {
            if (f.getName().startsWith("eucalyptus") && f.getName().endsWith(".jar")
                    && !f.getName().matches(".*-ext-.*")) {
                try {
                    JarFile jar = new JarFile(f);
                    Enumeration<JarEntry> jarList = jar.entries();
                    for (JarEntry j : Collections.list(jar.entries())) {
                        if (j.getName().matches(".*\\.class.{0,1}")) {
                            String classGuess = j.getName().replaceAll("/", ".").replaceAll("\\.class.{0,1}", "");
                            try {
                                Class candidate = ClassLoader.getSystemClassLoader().loadClass(classGuess);
                                for (final Method m : candidate.getDeclaredMethods()) {
                                    if (Iterables.any(testAnnotations,
                                            new Predicate<Class<? extends Annotation>>() {
                                                public boolean apply(Class<? extends Annotation> arg0) {
                                                    return m.getAnnotation(arg0) != null;
                                                }
                                            })) {
                                        System.out.println("Added test class: " + candidate.getCanonicalName());
                                        testMethods.put(candidate, m);
                                    }
                                }
                            } catch (ClassNotFoundException e) {
                            }
                        }
                    }
                    jar.close();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                    continue;
                }
            }
        }
        return testMethods;
    }

    public static boolean runTests(List<Class> tests) {
        System.out.println("TEST LIST SIZE:" + tests.size());
        for (Class testClass : tests) {
            System.out.println("Test:" + testClass);
        }
        JUnitCore core = new JUnitCore();
        // core.run( Cleanup.class );
        core.addListener(new TestListener());
        boolean rv = true;
        for (Class clazz : tests) {
            Result res = core.run(clazz);
            if (res == null || !res.wasSuccessful()) {
                rv = false;
            }
        }
        return rv;
        // tests = Lists.newArrayList( tests );
        // tests.add( Cleanup.class );
        // Result res = core.run( ( Class<?>[] ) tests.toArray( new Class[] {})
        // );
        // return res != null ? res.wasSuccessful( ) : false;
    }

    @SuppressWarnings("unchecked")
    private static void runMethods(final CommandLine cmd, final Options opts) {
        String[] optVals = cmd.getOptionValues("test");
        for (int i = 0; i < optVals.length; i++) {
            String[] argParts = optVals[i].split(":");
            String className = argParts[0];
            String methodName = argParts[1];
            String[] methodArgsArray = new String[0];
            if (argParts.length > 2) {
                methodArgsArray = argParts[2].split(",");
                System.out.printf("Executing class:%s method:%s args:%s\n", className, methodName, argParts[2]);
            } else {
                System.out.printf("Executing class:%s method:%s\n", className, methodName);
            }
            Class[] params = new Class[methodArgsArray.length];
            for (int j = 0; j < params.length; j++) {
                params[j] = String.class;
            }

            try {
                Class clazz = Class.forName(className);
                clazz.getDeclaredMethod(methodName, params).invoke(null, (Object[]) methodArgsArray);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            System.out.println("Executed method");
        }
        // List<Class> testList = Lists.transform( Lists.newArrayList(
        // cmd.getOptionValues( "test" ) ), new Function<String, Class>( ) {
        // public Class apply( String arg ) {
        // String[] argParts = arg.split(":");
        // String className = argParts[0];
        // System.out.println("CLASS NAME:" + className);
        // Class targetClass = null;
        // try {
        // targetClass = Class.forName( className );
        // } catch ( Exception e ) {
        // try {
        // targetClass = Class.forName( className + "Test" );
        // } catch ( Exception e1 ) {
        // }
        // }
        // if( targetClass == null ) {
        // printHelp( opts );
        // System.exit( 1 );
        // } else {
        // for( int i = 1; i < argParts.length; i++ ) {
        // String property = argParts[i].replaceAll("=.*","");
        // String value = argParts[i].replaceAll(".*=","");
        // try {
        // targetClass.getDeclaredMethod( property, String.class ).invoke( null,
        // value );
        // } catch ( Exception e ) {
        // System.out.println( e );
        // System.exit( 1 );
        // }
        // }
        // }
        // return targetClass;
        // }
        // } );
        // return testList;
    }
}