/*=============================================================================#
# Copyright (c) 2015-2016 David Green and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# David Green - initial API and implementation in Mylyn
# Stephan Wahlbrink (WalWare.de)
#=============================================================================*/
package de.walware.docmlet.wikitext.internal.commonmark.core.spec;
import static de.walware.docmlet.wikitext.internal.commonmark.core.CommonmarkAsserts.assertContent;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.mylyn.wikitext.core.util.LocationTrackingReader;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import de.walware.jcommons.collections.ImCollections;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
import de.walware.docmlet.wikitext.commonmark.core.CommonmarkLanguage;
@RunWith(Parameterized.class)
public class CommonMarkSpecTest {
private static final String SPEC_VERSION = "0.26";
private static final URI COMMONMARK_SPEC_URI = URI.create(
String.format("https://raw.githubusercontent.com/jgm/CommonMark/%s/spec.txt", SPEC_VERSION) );
private static final String CASE_START= "```````````````````````````````` example";
private static final String CASE_SEP= ".";
private static final String CASE_END= "````````````````````````````````";
private static final List<String> HEADING_EXCLUSIONS = ImCollections.newList();
private static final List<Integer> LINE_EXCLUSIONS = ImCollections.newList();
public static class Expectation {
final String input;
final String expected;
public Expectation(String input, String expected) {
this.input = input;
this.expected = expected;
}
@Override
public String toString() {
return Objects.toStringHelper(Expectation.class).add("input", input).add("expected", expected).toString();
}
}
private final Expectation expectation;
private final String heading;
private final int lineNumber;
public CommonMarkSpecTest(String heading, int num, int lineNumber, Expectation expectation) {
this.heading = heading;
this.lineNumber = lineNumber;
this.expectation = expectation;
}
@Before
public void preconditions() {
assumeTrue(!HEADING_EXCLUSIONS.contains(heading));
assumeTrue(!LINE_EXCLUSIONS.contains(Integer.valueOf(lineNumber)));
}
@Test
public void test() {
try {
CommonmarkLanguage language = createCommonmarkLanguage();
assertContent(language, expectation.expected, expectation.input);
} catch (Error | RuntimeException e) {
String info= this.heading + ": lineNumber= " + this.lineNumber;
e.addSuppressed(new Exception(info + "\n===\n" + expectation.input + "\n===\n"));
throw e;
}
}
private CommonmarkLanguage createCommonmarkLanguage() {
CommonmarkLanguage language = new CommonmarkLanguage();
return language;
}
@Parameters (name= "{index}: {0} - {1}, lineNumber= {2}")
public static List<Object[]> parameters() {
List<Object[]> parameters = new ArrayList<>();
loadSpec(parameters);
return ImCollections.toList(parameters);
}
private static void loadSpec(List<Object[]> parameters) {
Pattern headingPattern = Pattern.compile("#+\\s*(.+)");
try {
String spec = loadCommonMarkSpec();
LocationTrackingReader reader = new LocationTrackingReader(new StringReader(spec));
String heading = "unspecified";
String line;
int num= 1;
while ((line = reader.readLine()) != null) {
line = line.replace('→', '\t');
if (line.trim().equals(CASE_START)) {
int testLineNumber = reader.getLineNumber();
Expectation expectation = readExpectation(reader);
parameters.add(
new Object[] { heading, num, testLineNumber + 1, expectation });
num++;
}
Matcher headingMatcher = headingPattern.matcher(line);
if (headingMatcher.matches()) {
heading = headingMatcher.group(1);
}
}
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
private static Expectation readExpectation(LocationTrackingReader reader) throws IOException {
String input = readUntilDelimiter(reader, CASE_SEP);
String expected = readUntilDelimiter(reader, CASE_END);
return new Expectation(input, expected);
}
private static String readUntilDelimiter(LocationTrackingReader reader, String end) throws IOException {
List<String> lines = new ArrayList<>();
String line;
while ((line = reader.readLine()) != null) {
line = line.replace('→', '\t');
if (line.trim().equals(end)) {
break;
}
lines.add(line);
}
return Joiner.on("\n").join(lines);
}
private static String loadCommonMarkSpec() throws IOException {
File tmpFolder = new File("./tmp");
if (!tmpFolder.exists()) {
tmpFolder.mkdir();
}
assertTrue(tmpFolder.getAbsolutePath(), tmpFolder.exists());
File spec = new File(tmpFolder, String.format("spec%s.txt", SPEC_VERSION));
// spec.delete();
if (!spec.exists()) {
try (FileOutputStream out = new FileOutputStream(spec)) {
Resources.copy(COMMONMARK_SPEC_URI.toURL(), out);
}
}
try (InputStream in = new FileInputStream(spec)) {
return CharStreams.toString(new InputStreamReader(in, StandardCharsets.UTF_8));
}
}
}