com.github.anba.test262.util.Test262Info.java Source code

Java tutorial

Introduction

Here is the source code for com.github.anba.test262.util.Test262Info.java

Source

/**
 * Copyright (c) 2011-2012 Andr Bargull
 * Alle Rechte vorbehalten / All Rights Reserved.  Use is subject to license terms.
 *
 * <https://github.com/anba/test262-junit>
 */
package com.github.anba.test262.util;

import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.LineIterator;
import org.apache.commons.io.input.BOMInputStream;

/**
 * Parses and returns test case information from test262 js-doc comments
 * 
 * {@link http://wiki.ecmascript.org/doku.php?id=test262:test_case_format}
 * 
 * @author Andr Bargull
 * 
 */
public class Test262Info {
    // private static final Pattern tags = Pattern
    // .compile("\\s*\\*\\s*@(\\w+)\\s*(?:\\:\\s*(.*);|;)?\\s*");
    private static final Pattern tags = Pattern.compile("\\s*\\*\\s*@(\\w+)\\s*(.+)?\\s*");
    private static final Pattern start = Pattern.compile("\\s*/\\*\\*.*");
    private static final Pattern end = Pattern.compile("\\s*\\*/.*");

    private String description, errorType;
    private boolean onlyStrict, noStrict, negative;

    private Test262Info() {
        // private constructor
    }

    /**
     * Returns the description for the test case
     */
    public String getDescription() {
        return description;
    }

    /**
     * Returns the expected error-type if any
     */
    public String getErrorType() {
        return errorType;
    }

    /**
     * Returns whether the test should only be run in strict-mode
     */
    public boolean isOnlyStrict() {
        return onlyStrict;
    }

    /**
     * Returns whether the test should not be run in strict-mode
     */
    public boolean isNoStrict() {
        return noStrict;
    }

    /**
     * Returns {@code true} iff the test case is expected to fail
     */
    public boolean isNegative() {
        return negative;
    }

    /**
     * Counterpart to {@link Objects#requireNonNull(Object, String)}
     */
    private static final <T> T requireNull(T t) {
        if (t != null)
            throw new IllegalStateException("object is not null");
        return t;
    }

    /**
     * Returns an empty test-info object
     */
    public static Test262Info empty() {
        return new Test262Info();
    }

    /**
     * Parses the test-info from the input file and returns a
     * {@link Test262Info} object
     */
    public static Test262Info from(Path path, String defaultCharset) throws IOException {
        Test262Info info = new Test262Info();
        InputStream stream = Files.newInputStream(path);
        Reader reader = newReader(stream, defaultCharset);
        try ($LineIterator lines = new $LineIterator(reader)) {
            boolean preamble = true;
            for (String line : iterable(lines)) {
                if (preamble) {
                    if (start.matcher(line).matches()) {
                        preamble = false;
                    }
                } else if (end.matcher(line).matches()) {
                    break;
                } else {
                    Matcher m = tags.matcher(line);
                    if (m.matches()) {
                        String type = m.group(1);
                        String val = m.group(2);
                        switch (type) {
                        case "description":
                            info.description = requireNonNull(val, "description must not be null");
                            break;
                        case "noStrict":
                            requireNull(val);
                            info.noStrict = true;
                            break;
                        case "onlyStrict":
                            requireNull(val);
                            info.onlyStrict = true;
                            break;
                        case "negative":
                            info.negative = true;
                            info.errorType = Objects.toString(val, info.errorType);
                            break;
                        case "hostObject":
                        case "reviewers":
                        case "generator":
                        case "verbatim":
                        case "noHelpers":
                        case "bestPractice":
                        case "implDependent":
                            // ignore for now
                            break;
                        // legacy
                        case "strict_mode_negative":
                            info.negative = true;
                            info.onlyStrict = true;
                            info.errorType = Objects.toString(val, info.errorType);
                            break;
                        case "strict_only":
                            requireNull(val);
                            info.onlyStrict = true;
                            break;
                        case "errortype":
                            info.errorType = requireNonNull(val, "error-type must not be null");
                            break;
                        case "assertion":
                        case "section":
                        case "path":
                        case "comment":
                        case "name":
                            // ignore for now
                            break;
                        default:
                            // error
                            System.err.printf("unhandled type '%s'\n", type);
                        }
                    }
                }
            }
        }
        return info;
    }

    private static final <T> Iterable<T> iterable(final Iterator<T> iterator) {
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return iterator;
            }
        };
    }

    // inject AutoCloseable into LineIterator
    private static final class $LineIterator extends LineIterator implements AutoCloseable {
        public $LineIterator(Reader reader) throws IllegalArgumentException {
            super(reader);
        }
    }

    private static Reader newReader(InputStream stream, String defaultCharset) throws IOException {
        BOMInputStream bomstream = new BOMInputStream(stream, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE,
                ByteOrderMark.UTF_16BE);
        String charset = defaultIfNull(bomstream.getBOMCharsetName(), defaultCharset);
        return new InputStreamReader(bomstream, charset);
    }
}