| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.netbeans.junit; |
| |
| import java.lang.reflect.Constructor; |
| import java.util.*; |
| import junit.framework.TestSuite; |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| |
| /** |
| * NetBeans extension to JUnit's TestSuite class. |
| */ |
| public class NbTestSuite extends TestSuite implements NbTest { |
| |
| |
| private Filter fFilter; |
| |
| static boolean ignoreRandomFailures() { |
| return Boolean.getBoolean("ignore.random.failures"); |
| } |
| |
| /** |
| * Constructs an empty TestSuite. |
| */ |
| public NbTestSuite() { |
| super(); |
| } |
| |
| /** |
| * Constructs a TestSuite from the given class. Adds all the methods |
| * starting with "test" as test cases to the suite. |
| * |
| */ |
| public NbTestSuite(Class<? extends TestCase> theClass) { |
| super(testCaseClassOrDummy(theClass)); |
| } |
| private static Class<? extends TestCase> testCaseClassOrDummy(Class<? extends TestCase> testClass) { |
| if (ignoreRandomFailures() && testClass.isAnnotationPresent(RandomlyFails.class)) { |
| System.err.println("Skipping " + testClass.getName()); |
| return APIJail.Dummy.class; |
| } else { |
| return testClass; |
| } |
| } |
| private static class APIJail { // prevents Dummy from appearing as a public member |
| public static class Dummy extends TestCase { |
| public Dummy(String name) { |
| super(name); |
| } |
| public void testNothing() {} |
| } |
| } |
| |
| /** |
| * Constructs an empty TestSuite. |
| */ |
| public NbTestSuite(String name) { |
| super(name); |
| } |
| |
| void addTests(Class<? extends TestCase> clazz, String... names) throws Exception { |
| Constructor cnt = clazz.getConstructor(String.class); |
| for (String n : names) { |
| Test t = (Test)cnt.newInstance(n); |
| addTest(t); |
| } |
| } |
| |
| |
| /** |
| * Adds a test to the suite. |
| */ |
| @Override |
| public void addTest(Test test) { |
| if (test instanceof NbTest) { |
| //System.out.println("NbTestSuite.addTest(): Adding test with filter, test:"+test); |
| ((NbTest)test).setFilter(fFilter); |
| } else { |
| //System.out.println("NbTestSuite.addTest(): Adding test, test:"+test); |
| } |
| super.addTest(test); |
| } |
| |
| |
| /** |
| * adds a test suite to this test suite |
| */ |
| @Override |
| public void addTestSuite(Class<? extends TestCase> testClass) { |
| if (ignoreRandomFailures() && testClass.isAnnotationPresent(RandomlyFails.class)) { |
| System.err.println("Skipping " + testClass.getName()); |
| return; |
| } |
| NbTest t = new NbTestSuite(testClass); |
| t.setFilter(fFilter); |
| addTest(t); |
| } |
| |
| /** |
| * Sets active filter. |
| * @param filter Filter to be set as active for current test, null will reset filtering. |
| */ |
| public void setFilter(Filter filter) { |
| Enumeration e; |
| |
| this.fFilter = filter; |
| e = this.tests(); |
| while(e.hasMoreElements()) { |
| Object test = e.nextElement(); |
| if (test instanceof NbTest) { |
| //System.out.println("NbTestSuite.setFilter(): Setting filter:"+filter); |
| ((NbTest)test).setFilter(filter); |
| } |
| |
| } |
| } |
| /** |
| * Checks if a test isn't filtered out by the active filter. |
| */ |
| public boolean canRun() { |
| return true; // suite can always run |
| } |
| |
| public String getExpectedFail() { |
| return null; |
| } |
| |
| |
| /** Factory method to create a special execution suite that not only |
| * executes the tests but also measures the times each execution took. |
| * It then compares the times and fails if the difference is too big. |
| * Test tests can be executed more times to eliminate the effect |
| * of GC and hotspot compiler. |
| * |
| * @param clazz the class to create tests for (from methods starting with test) |
| * @param slowness this must be true: slowness * min < max |
| * @param repeat number of times to repeat the test |
| */ |
| public static NbTestSuite speedSuite (Class<? extends TestCase> clazz, int slowness, int repeat) { |
| if (ignoreRandomFailures()) { |
| System.err.println("Skipping " + clazz.getName()); |
| return new NbTestSuite("skipping"); |
| } |
| return new SpeedSuite (clazz, repeat, slowness, SpeedSuite.CONSTANT); |
| } |
| |
| /** Factory method to create a special execution suite that not only |
| * executes the tests but also measures the times each execution took. |
| * It then compares the times devided by the size of query |
| * and fails if the difference is too big. |
| * Test tests can be executed more times to eliminate the effect |
| * of GC and hotspot compiler. |
| * |
| * @param clazz the class to create tests for (from methods starting with test) |
| * @param slowness this must be true: slowness * min < max |
| * @param repeat number of times to repeat the test |
| */ |
| public static NbTestSuite linearSpeedSuite (Class<? extends TestCase> clazz, int slowness, int repeat) { |
| if (ignoreRandomFailures()) { |
| System.err.println("Skipping " + clazz.getName()); |
| return new NbTestSuite("skipping"); |
| } |
| return new SpeedSuite (clazz, repeat, slowness, SpeedSuite.LINEAR); |
| } |
| |
| |
| /** Allows enhanced execution and comparition of speed of a set of |
| * tests. |
| */ |
| private static final class SpeedSuite extends NbTestSuite { |
| public static final int CONSTANT = 0; |
| public static final int LINEAR = 1; |
| |
| /** number of repeats to try, if there is a failure */ |
| private int repeat; |
| /** the maximum difference between the slowest and fastest test */ |
| private int slowness; |
| /** type of query CONSTANT, LINEAR, etc. */ |
| private int type; |
| |
| public SpeedSuite (Class<? extends TestCase> clazz, int repeat, int slowness, int type) { |
| super (clazz); |
| this.repeat = repeat; |
| this.slowness = slowness; |
| this.type = type; |
| } |
| |
| @Override |
| public void run (junit.framework.TestResult result) { |
| StringBuffer error = new StringBuffer (); |
| for (int i = 0; i < repeat; i++) { |
| super.run(result); |
| |
| error.setLength (0); |
| |
| if (!result.wasSuccessful ()) { |
| // if there was a failure, end the test |
| return; |
| } |
| |
| { |
| Enumeration en = tests (); |
| while (en.hasMoreElements ()) { |
| Object t = en.nextElement (); |
| if (t instanceof NbTestCase) { |
| NbTestCase test = (NbTestCase)t; |
| error.append ("Test "); error.append (test.getName ()); |
| error.append(" took "); error.append(test.getExecutionTime() / 1000000); |
| error.append (" ms\n"); |
| } else { |
| error.append ("Test "); error.append (t); |
| error.append (" is not NbTestCase"); |
| } |
| |
| } |
| } |
| |
| double min = Long.MAX_VALUE; |
| double max = Long.MIN_VALUE; |
| |
| { |
| Enumeration en = tests (); |
| while (en.hasMoreElements ()) { |
| Object t = en.nextElement (); |
| if (t instanceof NbTestCase) { |
| double l = ((NbTestCase)t).getExecutionTime (); |
| |
| if (type == LINEAR) { |
| l = l / ((NbTestCase)t).getTestNumber (); |
| } |
| |
| if (l > max) max = l; |
| if (l < min) min = l; |
| } |
| } |
| } |
| |
| System.err.println(error.toString ()); |
| |
| if (max <= min * slowness) { |
| // ok |
| return; |
| } |
| } |
| |
| result.addFailure (this, new junit.framework.AssertionFailedError ( |
| "Execution times of tests differ too much;\n" + |
| "the results are supposed to be " + typeName () + ":\n" |
| + error.toString () |
| )); |
| } |
| |
| private String typeName () { |
| switch (type) { |
| case CONSTANT: return "constant"; |
| case LINEAR: return "linear"; |
| default: NbTestCase.fail ("This is not supported type: " + type); |
| } |
| return null; |
| } |
| } |
| } |