diff options
Diffstat (limited to 'src/ext_depends/D-YAML/testsuite')
-rw-r--r-- | src/ext_depends/D-YAML/testsuite/dub.json | 8 | ||||
-rw-r--r-- | src/ext_depends/D-YAML/testsuite/source/app.d | 323 |
2 files changed, 331 insertions, 0 deletions
diff --git a/src/ext_depends/D-YAML/testsuite/dub.json b/src/ext_depends/D-YAML/testsuite/dub.json new file mode 100644 index 0000000..fece639 --- /dev/null +++ b/src/ext_depends/D-YAML/testsuite/dub.json @@ -0,0 +1,8 @@ +{ + "name": "testsuite", + "targetType": "executable", + "dependencies": + { + "dyaml": "*" + } +} diff --git a/src/ext_depends/D-YAML/testsuite/source/app.d b/src/ext_depends/D-YAML/testsuite/source/app.d new file mode 100644 index 0000000..6c26b32 --- /dev/null +++ b/src/ext_depends/D-YAML/testsuite/source/app.d @@ -0,0 +1,323 @@ +module dyaml.testsuite; + +import dyaml; +import dyaml.event; + +import std.algorithm; +import std.conv; +import std.file; +import std.format; +import std.json; +import std.path; +import std.range; +import std.stdio; +import std.string; +import std.typecons; +import std.utf; + +auto dumpEventString(string str) @safe +{ + string[] output; + try + { + auto events = Loader.fromString(str).parse(); + foreach (event; events) + { + string line; + final switch (event.id) + { + case EventID.scalar: + line = "=VAL "; + if (event.anchor != "") + { + line ~= text("&", event.anchor, " "); + } + if (event.tag != "") + { + line ~= text("<", event.tag, "> "); + } + switch(event.scalarStyle) + { + case ScalarStyle.singleQuoted: + line ~= "'"; + break; + case ScalarStyle.doubleQuoted: + line ~= '"'; + break; + case ScalarStyle.literal: + line ~= "|"; + break; + case ScalarStyle.folded: + line ~= ">"; + break; + default: + line ~= ":"; + break; + } + if (event.value != "") + { + line ~= text(event.value.substitute("\n", "\\n", `\`, `\\`, "\r", "\\r", "\t", "\\t", "\b", "\\b")); + } + break; + case EventID.streamStart: + line = "+STR"; + break; + case EventID.documentStart: + line = "+DOC"; + if (event.explicitDocument) + { + line ~= text(" ---"); + } + break; + case EventID.mappingStart: + line = "+MAP"; + if (event.anchor != "") + { + line ~= text(" &", event.anchor); + } + if (event.tag != "") + { + line ~= text(" <", event.tag, ">"); + } + break; + case EventID.sequenceStart: + line = "+SEQ"; + if (event.anchor != "") + { + line ~= text(" &", event.anchor); + } + if (event.tag != "") + { + line ~= text(" <", event.tag, ">"); + } + break; + case EventID.streamEnd: + line = "-STR"; + break; + case EventID.documentEnd: + line = "-DOC"; + if (event.explicitDocument) + { + line ~= " ..."; + } + break; + case EventID.mappingEnd: + line = "-MAP"; + break; + case EventID.sequenceEnd: + line = "-SEQ"; + break; + case EventID.alias_: + line = text("=ALI *", event.anchor); + break; + case EventID.invalid: + assert(0, "Invalid EventID produced"); + } + output ~= line; + } + } + catch (Exception) {} //Exceptions should just stop adding output + return output.join("\n"); +} + +enum TestState +{ + success, + skipped, + failure +} + +struct TestResult +{ + string name; + TestState state; + string failMsg; + + const void toString(OutputRange)(ref OutputRange writer) + if (isOutputRange!(OutputRange, char)) + { + ubyte statusColour; + string statusString; + final switch (state) { + case TestState.success: + statusColour = 32; + statusString = "Succeeded"; + break; + case TestState.failure: + statusColour = 31; + statusString = "Failed"; + break; + case TestState.skipped: + statusColour = 93; + statusString = "Skipped"; + break; + } + writer.formattedWrite!"[\033[%s;1m%s\033[0m] %s"(statusColour, statusString, name); + if (state != TestState.success) + { + writer.formattedWrite!" (%s)"(failMsg.replace("\n", " ")); + } + } +} + +TestResult runTests(string tml) @safe +{ + TestResult output; + output.state = TestState.success; + auto splitFile = tml.splitter("\n--- "); + output.name = splitFile.front.findSplit("=== ")[2]; + bool loadFailed, shouldFail; + string failMsg; + JSONValue json; + Node[] nodes; + string yamlString; + Nullable!string compareYAMLString; + Nullable!string events; + ulong testsRun; + + void fail(string msg) @safe + { + output.state = TestState.failure; + output.failMsg = msg; + } + void skip(string msg) @safe + { + output.state = TestState.skipped; + output.failMsg = msg; + } + void parseYAML(string yaml) @safe + { + yamlString = yaml; + try { + nodes = Loader.fromString(yamlString).array; + } + catch (Exception e) + { + loadFailed = true; + failMsg = e.msg; + } + } + void compareLineByLine(const string a, const string b, const string msg) @safe + { + foreach (line1, line2; zip(a.lineSplitter, b.lineSplitter)) + { + if (line1 != line2) + { + fail(text(msg, " Got ", line1, ", expected ", line2)); + break; + } + } + } + foreach (section; splitFile.drop(1)) + { + auto splitSection = section.findSplit("\n"); + auto splitSectionHeader = splitSection[0].findSplit(":"); + const splitSectionName = splitSectionHeader[0].findSplit("("); + const sectionName = splitSectionName[0]; + const sectionParams = splitSectionName[2].findSplit(")")[0]; + string sectionData = splitSection[2]; + if (sectionData != "") + { + //< means dedent. + if (sectionParams.canFind("<")) + { + sectionData = sectionData[4..$].substitute("\n ", "\n", "<SPC>", " ", "<TAB>", "\t").toUTF8; + } + else + { + sectionData = sectionData.substitute("<SPC>", " ", "<TAB>", "\t").toUTF8; + } + //Not sure what + means. + } + switch(sectionName) + { + case "in-yaml": + parseYAML(sectionData); + break; + case "in-json": + json = parseJSON(sectionData); + break; + case "test-event": + events = sectionData; + break; + case "error": + shouldFail = true; + testsRun++; + break; + case "out-yaml": + compareYAMLString = sectionData; + break; + case "emit-yaml": + // TODO: Figure out how/if to implement this + //fail("Unhandled test - emit-yaml"); + break; + case "lex-token": + // TODO: Should this be implemented? + //fail("Unhandled test - lex-token"); + break; + case "from": break; + case "tags": break; + default: assert(false, text("Unhandled section ", sectionName, "in ", output.name)); + } + } + if (!loadFailed && !compareYAMLString.isNull && !shouldFail) + { + Appender!string buf; + dumper().dump(buf); + compareLineByLine(buf.data, compareYAMLString.get, "Dumped YAML mismatch"); + testsRun++; + } + if (!loadFailed && !events.isNull && !shouldFail) + { + const compare = dumpEventString(yamlString); + compareLineByLine(compare, events.get, "Event mismatch"); + testsRun++; + } + if (loadFailed && !shouldFail) + { + fail(failMsg); + } + if (shouldFail && !loadFailed) + { + fail("Invalid YAML accepted"); + } + if ((testsRun == 0) && (output.state != TestState.failure)) + { + skip("No tests run"); + } + return output; +} + +// Can't be @safe due to dirEntries() +void main(string[] args) @system +{ + string path = "yaml-test-suite/test"; + + void printResult(string id, TestResult result) + { + writeln(id, " ", result); + } + + if (args.length > 1) + { + path = args[1]; + } + + ulong total; + ulong successes; + foreach (file; dirEntries(path, "*.tml", SpanMode.shallow)) + { + auto result = runTests(readText(file)); + if (result.state == TestState.success) + { + debug(verbose) printResult(file.baseName, result); + successes++; + } + else + { + printResult(file.baseName, result); + } + total++; + } + writefln!"%d/%d tests passed"(successes, total); +} |