com.github.anba.es6draft.chakra.ChakraTest.java Source code

Java tutorial

Introduction

Here is the source code for com.github.anba.es6draft.chakra.ChakraTest.java

Source

/**
 * 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.chakra;

import static com.github.anba.es6draft.util.Resources.loadConfiguration;
import static com.github.anba.es6draft.util.Resources.loadTests;
import static org.junit.Assume.assumeTrue;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.input.BOMInputStream;
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.ErrorCollector;
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 org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.github.anba.es6draft.runtime.internal.Properties.Function;
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.Resources;
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;

/**
 * Test suite for the ChakraCore tests.
 */
@RunWith(Parallelized.class)
@UseParametersRunnerFactory(ParameterizedRunnerFactory.class)
@TestConfiguration(name = "chakra.test", file = "resource:/test-configuration.properties")
public final class ChakraTest {
    private static final Configuration configuration = loadConfiguration(ChakraTest.class);

    @Parameters(name = "{0}")
    public static List<ChakraTestInfo> suiteValues() throws IOException {
        return loadTests(configuration, createTestFunction());
    }

    @BeforeClass
    public static void setUpClass() throws IOException {
        ChakraTestGlobalObject.testLoadInitializationScript();
    }

    @ClassRule
    public static TestGlobals<ChakraTestGlobalObject, TestInfo> globals = new TestGlobals<>(configuration,
            ChakraTestGlobalObject::new);

    @Rule
    public Timeout maxTime = new Timeout(120, TimeUnit.SECONDS);

    @Rule
    public ErrorCollector collector = new ErrorCollector();

    @Rule
    public StandardErrorHandler errorHandler = new StandardErrorHandler();

    @Rule
    public ScriptExceptionHandler exceptionHandler = new ScriptExceptionHandler();

    @Parameter(0)
    public ChakraTestInfo test;

    private static final class ChakraTestInfo extends TestInfo {
        String baseline;
        Iterator<String> expected = Collections.emptyIterator();

        public ChakraTestInfo(Path basedir, Path file) {
            super(basedir, file);
        }
    }

    private ChakraTestGlobalObject global;

    @Before
    public void setUp() throws Throwable {
        assumeTrue("Test disabled", test.isEnabled());

        global = globals.newGlobal(new NullConsole(), test);
        exceptionHandler.setExecutionContext(global.getRealm().defaultContext());

        if (test.baseline != null && !test.baseline.isEmpty()) {
            global.createGlobalProperties(new MessageProducer(), MessageProducer.class);
            test.expected = lineIterator(test.toFile().resolveSibling(test.baseline));
        }
    }

    @After
    public void tearDown() {
        globals.release(global);
    }

    @Test
    public void runTest() throws Throwable {
        // Evaluate actual test-script
        global.eval(test.getScript(), test.toFile());

        // Wait for pending tasks to finish
        global.getRealm().getWorld().runEventLoop();
    }

    public final class MessageProducer {
        @Function(name = "$MESSAGE", arity = 0)
        public String message() {
            if (test.expected.hasNext()) {
                return test.expected.next();
            }
            return null;
        }
    }

    private static final class TestSetting {
        String baseline;
        boolean disabled;
    }

    private static BiFunction<Path, Path, ChakraTestInfo> createTestFunction() {
        HashMap<Path, Map<String, TestSetting>> settingsMapping = new HashMap<>();

        return (basedir, file) -> {
            ChakraTestInfo testInfo = new ChakraTestInfo(basedir, file);
            Path dir = basedir.resolve(file).getParent();
            Map<String, TestSetting> map = settingsMapping.computeIfAbsent(dir, ChakraTest::readSettings);
            TestSetting setting = map.get(file.getFileName().toString());
            if (setting != null) {
                testInfo.baseline = setting.baseline;
                testInfo.setEnabled(!setting.disabled);
            }
            return testInfo;
        };
    }

    private static Map<String, TestSetting> readSettings(Path dir) {
        Path settingsFile = dir.resolve("rlexe.xml");
        if (Files.isRegularFile(settingsFile)) {
            try (Reader reader = bomReader(Files.newInputStream(settingsFile))) {
                Document doc = Resources.xml(reader);
                NodeList elements = doc.getElementsByTagName("default");
                HashMap<String, TestSetting> settingMap = new HashMap<>();
                for (int i = 0, length = elements.getLength(); i < length; ++i) {
                    Element element = (Element) elements.item(i);
                    String files = element.getElementsByTagName("files").item(0).getTextContent();
                    TestSetting setting = new TestSetting();
                    NodeList baseline = element.getElementsByTagName("baseline");
                    if (baseline.getLength() > 0) {
                        setting.baseline = baseline.item(0).getTextContent();
                    }
                    NodeList compileFlags = element.getElementsByTagName("compile-flags");
                    if (compileFlags.getLength() > 0) {
                        String flags = compileFlags.item(0).getTextContent();
                        setting.disabled = flags.contains("-verbose") || flags.contains("-dump:")
                                || flags.contains("-trace:") || flags.contains("-testtrace:")
                                || flags.contains("-testTrace:");
                    }
                    settingMap.putIfAbsent(files, setting);
                }
                return settingMap;
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
        return Collections.emptyMap();
    }

    private static Iterator<String> lineIterator(Path p) throws IOException {
        try (BufferedReader reader = bomReader(Files.newInputStream(p))) {
            ArrayList<String> list = new ArrayList<>();
            for (;;) {
                String line = reader.readLine();
                if (line == null)
                    break;
                list.add(line);
            }
            return list.iterator();
        }
    }

    private static BufferedReader bomReader(InputStream is) throws IOException {
        BOMInputStream bis = new BOMInputStream(is);
        Charset cs = charsetFor(bis, StandardCharsets.UTF_8);
        return new BufferedReader(new InputStreamReader(bis, cs));
    }

    private static Charset charsetFor(BOMInputStream bis, Charset defaultCharset) throws IOException {
        ByteOrderMark bom = bis.getBOM();
        if (ByteOrderMark.UTF_8.equals(bom)) {
            return StandardCharsets.UTF_8;
        }
        if (ByteOrderMark.UTF_16LE.equals(bom)) {
            return StandardCharsets.UTF_16LE;
        }
        if (ByteOrderMark.UTF_16BE.equals(bom)) {
            return StandardCharsets.UTF_16BE;
        }
        return defaultCharset;
    }
}