/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.mozilla; import static com.github.anba.es6draft.util.Resources.loadConfiguration; import static com.github.anba.es6draft.util.Resources.loadTests; import static com.github.anba.es6draft.util.matchers.ErrorMessageMatcher.hasErrorMessage; import static org.hamcrest.Matchers.containsString; import static org.junit.Assume.assumeTrue; import java.io.IOException; import java.nio.file.Path; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.configuration.Configuration; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.Timeout; import org.junit.runner.RunWith; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized.UseParametersRunnerFactory; import com.github.anba.es6draft.runtime.ExecutionContext; import com.github.anba.es6draft.runtime.internal.Properties; import com.github.anba.es6draft.runtime.types.Intrinsics; import com.github.anba.es6draft.runtime.types.ScriptObject; import com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject; import com.github.anba.es6draft.util.NullConsole; import com.github.anba.es6draft.util.Parallelized; import com.github.anba.es6draft.util.ParameterizedRunnerFactory; import com.github.anba.es6draft.util.TestConfiguration; import com.github.anba.es6draft.util.TestGlobals; import com.github.anba.es6draft.util.TestInfo; import com.github.anba.es6draft.util.rules.ExceptionHandlers.ScriptExceptionHandler; import com.github.anba.es6draft.util.rules.ExceptionHandlers.StandardErrorHandler; import com.github.anba.es6draft.util.rules.ExceptionHandlers.StopExecutionHandler; /** * Test suite for the Mozilla jit-tests. */ @RunWith(Parallelized.class) @UseParametersRunnerFactory(ParameterizedRunnerFactory.class) @TestConfiguration(name = "mozilla.test.jittests", file = "resource:/test-configuration.properties") public final class MozillaJitTest { private static final Configuration configuration = loadConfiguration(MozillaJitTest.class); @Parameters(name = "{0}") public static List<MozTest> suiteValues() throws IOException { return loadTests(configuration, MozillaJitTest::createTest); } @BeforeClass public static void setUpClass() throws IOException { MozTestGlobalObject.testLoadInitializationScript(); } @ClassRule public static TestGlobals<MozTestGlobalObject, MozTest> globals = new TestGlobals<>(configuration, MozTestGlobalObject::new); @Rule public Timeout maxTime = new Timeout(120, TimeUnit.SECONDS); @Rule public StandardErrorHandler errorHandler = StandardErrorHandler.none(); @Rule public ScriptExceptionHandler exceptionHandler = ScriptExceptionHandler.none(); @Rule public StopExecutionHandler stopHandler = new StopExecutionHandler(); @Rule public ExpectedException expected = ExpectedException.none(); @Parameter(0) public MozTest moztest; private static final class MozTest extends TestInfo { String error = null; public MozTest(Path basedir, Path script) { super(basedir, script); } } private MozTestGlobalObject global; @Before public void setUp() throws Throwable { assumeTrue("Test disabled", moztest.isEnabled()); global = globals.newGlobal(new NullConsole(), moztest); exceptionHandler.setExecutionContext(global.getRealm().defaultContext()); global.createGlobalProperties(new TestEnvironment(), TestEnvironment.class); if (moztest.error == null) { errorHandler.match(StandardErrorHandler.defaultMatcher()); exceptionHandler.match(ScriptExceptionHandler.defaultMatcher()); } else { ExecutionContext cx = global.getRealm().defaultContext(); expected.expect( Matchers.either(StandardErrorHandler.defaultMatcher()).or(ScriptExceptionHandler.defaultMatcher())); expected.expect(hasErrorMessage(cx, containsString(moztest.error))); } } @After public void tearDown() { globals.release(global); } @Test public void runTest() throws Throwable { // Evaluate actual test-script global.eval(moztest.getScript(), moztest.toFile()); // Wait for pending tasks to finish global.getRealm().getWorld().runEventLoop(); } public static final class TestEnvironment { @Properties.Value(name = "libdir") public String libdir() { return "lib/"; } @Properties.Value(name = "environment") public ScriptObject environment(ExecutionContext cx) { return OrdinaryObject.ObjectCreate(cx, Intrinsics.ObjectPrototype); } @Properties.Value(name = "os") public ScriptObject os(ExecutionContext cx) { OrdinaryObject os = OrdinaryObject.ObjectCreate(cx, Intrinsics.ObjectPrototype); Properties.createProperties(cx, os, new OS(), OS.class); return os; } } public static final class OS { @Properties.Function(name = "getenv", arity = 1) public String getenv(String name) { return System.getenv().get(name); } } private static final Pattern testInfoPattern = Pattern.compile("//\\s*\\|(.+?)\\|\\s*(.*)"); private static BiFunction<Path, Iterator<String>, MozTest> createTest(Path basedir) { return (file, lines) -> { MozTest test = new MozTest(basedir, file); String line = lines.next(); Matcher m = testInfoPattern.matcher(line); if (!m.matches()) { // Ignore if pattern invalid or not present return test; } if (!"jit-test".equals(m.group(1))) { System.err.printf("invalid tag '%s' in line: %s\n", m.group(1), line); return test; } String content = m.group(2); for (String p : content.split(";")) { int sep = p.indexOf(':'); if (sep != -1) { String name = p.substring(0, sep).trim(); String value = p.substring(sep + 1).trim(); switch (name) { case "error": test.error = value; break; case "exitstatus": // Ignore for now... break; default: System.err.printf("unknown option '%s' in line: %s\n", name, content); } } else { String name = p.trim(); switch (name) { case "slow": // Don't run slow tests test.setEnabled(false); break; case "debug": // Don't run debug-mode tests test.setEnabled(false); break; case "allow-oom": case "allow-overrecursed": case "allow-unhandlable-oom": case "valgrind": case "tz-pacific": case "mjitalways": case "mjit": case "no-jm": case "no-ion": case "ion-eager": case "dump-bytecode": case "--fuzzing-safe": case "--no-threads": case "--no-ion": case "--no-baseline": // Ignore for now... break; case "": // Ignore empty string break; default: System.err.printf("unknown option '%s' in line: %s [%s]\n", name, content, file); } } } return test; }; } }