aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ext_depends/D-YAML/source/dyaml/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext_depends/D-YAML/source/dyaml/test')
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/common.d223
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/compare.d51
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/constructor.d40
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/emitter.d132
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/errors.d64
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d92
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/reader.d37
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/representer.d10
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/resolver.d39
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/suite.d384
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d224
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/tokens.d93
12 files changed, 613 insertions, 776 deletions
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/common.d b/src/ext_depends/D-YAML/source/dyaml/test/common.d
deleted file mode 100644
index a6bafa9..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/common.d
+++ /dev/null
@@ -1,223 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.common;
-
-version(unittest)
-{
-
-import dyaml.node;
-import dyaml.event;
-
-import core.exception;
-import std.algorithm;
-import std.array;
-import std.conv;
-import std.file;
-import std.range;
-import std.path;
-import std.traits;
-import std.typecons;
-
-package:
-
-/**
-Run a test.
-
-Params:
- testFunction = Unittest function.
- unittestExt = Extensions of data files needed for the unittest.
- skipExt = Extensions that must not be used for the unittest.
- */
-void run(D)(D testFunction, string[] unittestExt, string[] skipExt = [])
-{
- immutable string dataDir = __FILE_FULL_PATH__.dirName ~ "/../../../test/data";
- auto testFilenames = findTestFilenames(dataDir);
-
- if (unittestExt.length > 0)
- {
- outer: foreach (base, extensions; testFilenames)
- {
- string[] filenames;
- foreach (ext; unittestExt)
- {
- if (!extensions.canFind(ext))
- {
- continue outer;
- }
- filenames ~= base ~ '.' ~ ext;
- }
- foreach (ext; skipExt)
- {
- if (extensions.canFind(ext))
- {
- continue outer;
- }
- }
-
- execute(testFunction, filenames);
- }
- }
- else
- {
- execute(testFunction, string[].init);
- }
-}
-
-// TODO: remove when a @safe ubyte[] file read can be done.
-/**
-Reads a file as an array of bytes.
-
-Params:
- filename = Full path to file to read.
-
-Returns: The file's data.
-*/
-ubyte[] readData(string filename) @trusted
-{
- import std.file : read;
- return cast(ubyte[])read(filename);
-}
-void assertNodesEqual(const scope Node gotNode, const scope Node expectedNode) @safe
-{
- import std.format : format;
- assert(gotNode == expectedNode, format!"got %s, expected %s"(gotNode.debugString, expectedNode.debugString));
-}
-
-/**
-Determine if events in events1 are equivalent to events in events2.
-
-Params:
- events1 = A range of events to compare with.
- events2 = A second range of events to compare.
-
-Returns: true if the events are equivalent, false otherwise.
-*/
-bool compareEvents(T, U)(T events1, U events2)
-if (isInputRange!T && isInputRange!U && is(ElementType!T == Event) && is(ElementType!U == Event))
-{
- foreach (e1, e2; zip(events1, events2))
- {
- //Different event types.
- if (e1.id != e2.id)
- {
- return false;
- }
- //Different anchor (if applicable).
- if (e1.id.among!(EventID.sequenceStart, EventID.mappingStart, EventID.alias_, EventID.scalar)
- && e1.anchor != e2.anchor)
- {
- return false;
- }
- //Different collection tag (if applicable).
- if (e1.id.among!(EventID.sequenceStart, EventID.mappingStart) && e1.tag != e2.tag)
- {
- return false;
- }
- if (e1.id == EventID.scalar)
- {
- //Different scalar tag (if applicable).
- if (!(e1.implicit || e2.implicit) && e1.tag != e2.tag)
- {
- return false;
- }
- //Different scalar value.
- if (e1.value != e2.value)
- {
- return false;
- }
- }
- }
- return true;
-}
-/**
-Throw an Error if events in events1 aren't equivalent to events in events2.
-
-Params:
- events1 = First event array to compare.
- events2 = Second event array to compare.
-*/
-void assertEventsEqual(T, U)(T events1, U events2)
-if (isInputRange!T && isInputRange!U && is(ElementType!T == Event) && is(ElementType!U == Event))
-{
- auto events1Copy = events1.array;
- auto events2Copy = events2.array;
- assert(compareEvents(events1Copy, events2Copy), text("Got '", events1Copy, "', expected '", events2Copy, "'"));
-}
-
-private:
-
-/**
-Find unittest input filenames.
-
-Params: dir = Directory to look in.
-
-Returns: Test input base filenames and their extensions.
-*/
- //@trusted due to dirEntries
-string[][string] findTestFilenames(const string dir) @trusted
-{
- //Groups of extensions indexed by base names.
- string[][string] names;
- foreach (string name; dirEntries(dir, SpanMode.shallow))
- {
- if (isFile(name))
- {
- string base = name.stripExtension();
- string ext = name.extension();
- if (ext is null)
- {
- ext = "";
- }
- if (ext[0] == '.')
- {
- ext = ext[1 .. $];
- }
-
- //If the base name doesn't exist yet, add it; otherwise add new extension.
- names[base] = ((base in names) is null) ? [ext] : names[base] ~ ext;
- }
- }
- return names;
-}
-
-/**
-Recursively copy an array of strings to a tuple to use for unittest function input.
-
-Params:
- index = Current index in the array/tuple.
- tuple = Tuple to copy to.
- strings = Strings to copy.
-*/
-void stringsToTuple(uint index, F ...)(ref F tuple, const string[] strings)
-in(F.length == strings.length)
-do
-{
- tuple[index] = strings[index];
- static if (index > 0)
- {
- stringsToTuple!(index - 1, F)(tuple, strings);
- }
-}
-
-/**
-Execute an unittest on specified files.
-
-Params:
- testName = Name of the unittest.
- testFunction = Unittest function.
- filenames = Names of input files to test with.
- */
-void execute(D)(D testFunction, string[] filenames)
-{
- //Convert filenames to parameters tuple and call the test function.
- alias F = Parameters!D[0..$];
- F parameters;
- stringsToTuple!(F.length - 1, F)(parameters, filenames);
- testFunction(parameters);
-}
-
-} // version(unittest)
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/compare.d b/src/ext_depends/D-YAML/source/dyaml/test/compare.d
deleted file mode 100644
index 5a37fd0..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/compare.d
+++ /dev/null
@@ -1,51 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.compare;
-
-@safe unittest
-{
- import dyaml : Loader;
- import dyaml.test.common : assertNodesEqual, compareEvents, run;
-
- /**
- Test parser by comparing output from parsing two equivalent YAML files.
-
- Params:
- dataFilename = YAML file to parse.
- canonicalFilename = Another file to parse, in canonical YAML format.
- */
- static void testParser(string dataFilename, string canonicalFilename) @safe
- {
- auto dataEvents = Loader.fromFile(dataFilename).parse();
- auto canonicalEvents = Loader.fromFile(canonicalFilename).parse();
-
- //BUG: the return value isn't checked! This test currently fails...
- compareEvents(dataEvents, canonicalEvents);
- }
-
- /**
- Test loader by comparing output from loading two equivalent YAML files.
-
- Params:
- dataFilename = YAML file to load.
- canonicalFilename = Another file to load, in canonical YAML format.
- */
- static void testLoader(string dataFilename, string canonicalFilename) @safe
- {
- import std.array : array;
- auto data = Loader.fromFile(dataFilename).array;
- auto canonical = Loader.fromFile(canonicalFilename).array;
-
- assert(data.length == canonical.length, "Unequal node count");
- foreach (n; 0 .. data.length)
- {
- assertNodesEqual(data[n], canonical[n]);
- }
- }
- run(&testParser, ["data", "canonical"]);
- run(&testLoader, ["data", "canonical"], ["test_loader_skip"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/constructor.d b/src/ext_depends/D-YAML/source/dyaml/test/constructor.d
index aeb8653..ad9fb62 100644
--- a/src/ext_depends/D-YAML/source/dyaml/test/constructor.d
+++ b/src/ext_depends/D-YAML/source/dyaml/test/constructor.d
@@ -6,10 +6,9 @@
module dyaml.test.constructor;
+package version(unittest):
-version(unittest)
-{
-
+import std.algorithm;
import std.conv;
import std.datetime;
import std.exception;
@@ -920,38 +919,3 @@ struct TestStruct
return Node(value.to!string, "!tag2");
}
}
-
-} // version(unittest)
-
-
-@safe unittest
-{
- import dyaml.test.common : assertNodesEqual, run;
- /**
- Constructor unittest.
-
- Params:
- dataFilename = File name to read from.
- codeDummy = Dummy .code filename, used to determine that
- .data file with the same name should be used in this test.
- */
- static void testConstructor(string dataFilename, string codeDummy) @safe
- {
- string base = dataFilename.baseName.stripExtension;
- assert((base in expected) !is null, "Unimplemented constructor test: " ~ base);
-
- auto loader = Loader.fromFile(dataFilename);
-
- Node[] exp = expected[base];
-
- //Compare with expected results document by document.
- size_t i;
- foreach (node; loader)
- {
- assertNodesEqual(node, exp[i]);
- ++i;
- }
- assert(i == exp.length);
- }
- run(&testConstructor, ["data", "code"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/emitter.d b/src/ext_depends/D-YAML/source/dyaml/test/emitter.d
deleted file mode 100644
index 293f236..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/emitter.d
+++ /dev/null
@@ -1,132 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011-2014.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.emitter;
-
-@safe unittest
-{
- import std.array : Appender;
- import std.range : ElementType, isInputRange;
-
- import dyaml : CollectionStyle, LineBreak, Loader, Mark, ScalarStyle;
- import dyaml.emitter : Emitter;
- import dyaml.event : Event, EventID, mappingStartEvent, scalarEvent, sequenceStartEvent;
- import dyaml.test.common : assertEventsEqual, run;
-
- // Try to emit an event range.
- static void emitTestCommon(T)(ref Appender!string emitStream, T events, bool canonical = false) @safe
- if (isInputRange!T && is(ElementType!T == Event))
- {
- auto emitter = Emitter!(typeof(emitStream), char)(emitStream, canonical, 2, 80, LineBreak.unix);
- foreach (ref event; events)
- {
- emitter.emit(event);
- }
- }
- /**
- Test emitter by getting events from parsing a file, emitting them, parsing
- the emitted result and comparing events from parsing the emitted result with
- originally parsed events.
-
- Params:
- dataFilename = YAML file to parse.
- canonicalFilename = Canonical YAML file used as dummy to determine
- which data files to load.
- */
- static void testEmitterOnData(string dataFilename, string canonicalFilename) @safe
- {
- //Must exist due to Anchor, Tags reference counts.
- auto loader = Loader.fromFile(dataFilename);
- auto events = loader.parse();
- auto emitStream = Appender!string();
- emitTestCommon(emitStream, events);
-
- auto loader2 = Loader.fromString(emitStream.data);
- loader2.name = "TEST";
- auto newEvents = loader2.parse();
- assertEventsEqual(events, newEvents);
- }
- /**
- Test emitter by getting events from parsing a canonical YAML file, emitting
- them both in canonical and normal format, parsing the emitted results and
- comparing events from parsing the emitted result with originally parsed events.
-
- Params: canonicalFilename = Canonical YAML file to parse.
- */
- static void testEmitterOnCanonical(string canonicalFilename) @safe
- {
- //Must exist due to Anchor, Tags reference counts.
- auto loader = Loader.fromFile(canonicalFilename);
- auto events = loader.parse();
- foreach (canonical; [false, true])
- {
- auto emitStream = Appender!string();
- emitTestCommon(emitStream, events, canonical);
-
- auto loader2 = Loader.fromString(emitStream.data);
- loader2.name = "TEST";
- auto newEvents = loader2.parse();
- assertEventsEqual(events, newEvents);
- }
- }
- /**
- Test emitter by getting events from parsing a file, emitting them with all
- possible scalar and collection styles, parsing the emitted results and
- comparing events from parsing the emitted result with originally parsed events.
-
- Params:
- dataFilename = YAML file to parse.
- canonicalFilename = Canonical YAML file used as dummy to determine
- which data files to load.
- */
- static void testEmitterStyles(string dataFilename, string canonicalFilename) @safe
- {
- foreach (filename; [dataFilename, canonicalFilename])
- {
- //must exist due to Anchor, Tags reference counts
- auto loader = Loader.fromFile(canonicalFilename);
- auto events = loader.parse();
- foreach (flowStyle; [CollectionStyle.block, CollectionStyle.flow])
- {
- foreach (style; [ScalarStyle.literal, ScalarStyle.folded,
- ScalarStyle.doubleQuoted, ScalarStyle.singleQuoted,
- ScalarStyle.plain])
- {
- Event[] styledEvents;
- foreach (event; events)
- {
- if (event.id == EventID.scalar)
- {
- event = scalarEvent(Mark(), Mark(), event.anchor, event.tag,
- event.implicit,
- event.value, style);
- }
- else if (event.id == EventID.sequenceStart)
- {
- event = sequenceStartEvent(Mark(), Mark(), event.anchor,
- event.tag, event.implicit, flowStyle);
- }
- else if (event.id == EventID.mappingStart)
- {
- event = mappingStartEvent(Mark(), Mark(), event.anchor,
- event.tag, event.implicit, flowStyle);
- }
- styledEvents ~= event;
- }
- auto emitStream = Appender!string();
- emitTestCommon(emitStream, styledEvents);
- auto loader2 = Loader.fromString(emitStream.data);
- loader2.name = "TEST";
- auto newEvents = loader2.parse();
- assertEventsEqual(events, newEvents);
- }
- }
- }
- }
- run(&testEmitterOnData, ["data", "canonical"]);
- run(&testEmitterOnCanonical, ["canonical"]);
- run(&testEmitterStyles, ["data", "canonical"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/errors.d b/src/ext_depends/D-YAML/source/dyaml/test/errors.d
deleted file mode 100644
index 43b019c..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/errors.d
+++ /dev/null
@@ -1,64 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011-2014
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.errors;
-
-@safe unittest
-{
- import std.array : array;
- import std.exception : assertThrown;
-
- import dyaml : Loader;
- import dyaml.test.common : run;
-
- /**
- Loader error unittest from file stream.
-
- Params: errorFilename = File name to read from.
- */
- static void testLoaderError(string errorFilename) @safe
- {
- assertThrown(Loader.fromFile(errorFilename).array,
- __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
- }
-
- /**
- Loader error unittest from string.
-
- Params: errorFilename = File name to read from.
- */
- static void testLoaderErrorString(string errorFilename) @safe
- {
- assertThrown(Loader.fromFile(errorFilename).array,
- __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
- }
-
- /**
- Loader error unittest from filename.
-
- Params: errorFilename = File name to read from.
- */
- static void testLoaderErrorFilename(string errorFilename) @safe
- {
- assertThrown(Loader.fromFile(errorFilename).array,
- __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
- }
-
- /**
- Loader error unittest loading a single document from a file.
-
- Params: errorFilename = File name to read from.
- */
- static void testLoaderErrorSingle(string errorFilename) @safe
- {
- assertThrown(Loader.fromFile(errorFilename).load(),
- __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
- }
- run(&testLoaderError, ["loader-error"]);
- run(&testLoaderErrorString, ["loader-error"]);
- run(&testLoaderErrorFilename, ["loader-error"]);
- run(&testLoaderErrorSingle, ["single-loader-error"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d b/src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d
deleted file mode 100644
index 758def8..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d
+++ /dev/null
@@ -1,92 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011-2014.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.inputoutput;
-
-@safe unittest
-{
- import std.array : join, split;
- import std.conv : to;
- import std.exception : assertThrown;
- import std.file : readText;
- import std.system : endian, Endian;
-
- import dyaml : Loader, Node, YAMLException;
- import dyaml.test.common : run;
-
- /**
- Get an UTF-16 byte order mark.
-
- Params: wrong = Get the incorrect BOM for this system.
-
- Returns: UTF-16 byte order mark.
- */
- static wchar bom16(bool wrong = false) pure @safe
- {
- wchar little = '\uFEFF';
- wchar big = '\uFFFE';
- if (!wrong)
- {
- return endian == Endian.littleEndian ? little : big;
- }
- return endian == Endian.littleEndian ? big : little;
- }
- /**
- Get an UTF-32 byte order mark.
-
- Params: wrong = Get the incorrect BOM for this system.
-
- Returns: UTF-32 byte order mark.
- */
- static dchar bom32(bool wrong = false) pure @safe
- {
- dchar little = '\uFEFF';
- dchar big = '\uFFFE';
- if (!wrong)
- {
- return endian == Endian.littleEndian ? little : big;
- }
- return endian == Endian.littleEndian ? big : little;
- }
- /**
- Unicode input unittest. Tests various encodings.
-
- Params: unicodeFilename = File name to read from.
- */
- static void testUnicodeInput(string unicodeFilename) @safe
- {
- string data = readText(unicodeFilename);
- string expected = data.split().join(" ");
-
- Node output = Loader.fromString(data).load();
- assert(output.as!string == expected);
-
- foreach (buffer; [cast(ubyte[]) (bom16() ~ data.to!(wchar[])),
- cast(ubyte[]) (bom32() ~ data.to!(dchar[]))])
- {
- output = Loader.fromBuffer(buffer).load();
- assert(output.as!string == expected);
- }
- }
- /**
- Unicode input error unittest. Tests various encodings with incorrect BOMs.
-
- Params: unicodeFilename = File name to read from.
- */
- static void testUnicodeInputErrors(string unicodeFilename) @safe
- {
- string data = readText(unicodeFilename);
- foreach (buffer; [cast(ubyte[]) (data.to!(wchar[])),
- cast(ubyte[]) (data.to!(dchar[])),
- cast(ubyte[]) (bom16(true) ~ data.to!(wchar[])),
- cast(ubyte[]) (bom32(true) ~ data.to!(dchar[]))])
- {
- assertThrown(Loader.fromBuffer(buffer).load());
- }
- }
- run(&testUnicodeInput, ["unicode"]);
- run(&testUnicodeInputErrors, ["unicode"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/reader.d b/src/ext_depends/D-YAML/source/dyaml/test/reader.d
deleted file mode 100644
index c20df6f..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/reader.d
+++ /dev/null
@@ -1,37 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.reader;
-
-@safe unittest
-{
- import std.exception :assertThrown;
-
- import dyaml.test.common : readData, run;
- import dyaml.reader : Reader, ReaderException;
-
- /**
- Try reading entire file through Reader, expecting an error (the file is invalid).
-
- Params: data = Stream to read.
- */
- static void runReader(ubyte[] fileData) @safe
- {
- auto reader = new Reader(fileData);
- while(reader.peek() != '\0') { reader.forward(); }
- }
-
- /**
- Stream error unittest. Tries to read invalid input files, expecting errors.
-
- Params: errorFilename = File name to read from.
- */
- static void testStreamError(string errorFilename) @safe
- {
- assertThrown!ReaderException(runReader(readData(errorFilename)));
- }
- run(&testStreamError, ["stream-error"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/representer.d b/src/ext_depends/D-YAML/source/dyaml/test/representer.d
index 4a1ae67..eeac157 100644
--- a/src/ext_depends/D-YAML/source/dyaml/test/representer.d
+++ b/src/ext_depends/D-YAML/source/dyaml/test/representer.d
@@ -9,12 +9,12 @@ module dyaml.test.representer;
@safe unittest
{
import std.array : Appender, array;
+ import std.conv : text;
import std.meta : AliasSeq;
import std.path : baseName, stripExtension;
import std.utf : toUTF8;
import dyaml : dumper, Loader, Node;
- import dyaml.test.common : assertNodesEqual, run;
import dyaml.test.constructor : expected;
/**
@@ -38,13 +38,9 @@ module dyaml.test.representer;
auto loader = Loader.fromString(emitStream.data.toUTF8);
loader.name = "TEST";
- const readNodes = loader.array;
+ auto readNodes = loader.array;
- assert(expectedNodes.length == readNodes.length);
- foreach (n; 0 .. expectedNodes.length)
- {
- assertNodesEqual(expectedNodes[n], readNodes[n]);
- }
+ assert(expectedNodes == readNodes, text("Got '", readNodes, "', expected '", expectedNodes, "'"));
}
}
foreach (key, _; expected)
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/resolver.d b/src/ext_depends/D-YAML/source/dyaml/test/resolver.d
deleted file mode 100644
index ea93720..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/resolver.d
+++ /dev/null
@@ -1,39 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.resolver;
-
-@safe unittest
-{
- import std.conv : text;
- import std.file : readText;
- import std.string : strip;
-
- import dyaml : Loader, Node, NodeID;
- import dyaml.test.common : run;
-
-
- /**
- Implicit tag resolution unittest.
-
- Params:
- dataFilename = File with unittest data.
- detectFilename = Dummy filename used to specify which data filenames to use.
- */
- static void testImplicitResolver(string dataFilename, string detectFilename) @safe
- {
- const correctTag = readText(detectFilename).strip();
-
- auto node = Loader.fromFile(dataFilename).load();
- assert(node.nodeID == NodeID.sequence, text("Expected sequence when reading '", dataFilename, "', got ", node.nodeID));
- foreach (Node scalar; node)
- {
- assert(scalar.nodeID == NodeID.scalar, text("Expected sequence of scalars when reading '", dataFilename, "', got sequence of ", scalar.nodeID));
- assert(scalar.tag == correctTag, text("Expected tag '", correctTag, "' when reading '", dataFilename, "', got '", scalar.tag, "'"));
- }
- }
- run(&testImplicitResolver, ["data", "detect"]);
-}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/suite.d b/src/ext_depends/D-YAML/source/dyaml/test/suite.d
new file mode 100644
index 0000000..2146c37
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/suite.d
@@ -0,0 +1,384 @@
+module dyaml.test.suite;
+
+import std.algorithm;
+import std.conv;
+import std.datetime.stopwatch;
+import std.exception;
+import std.file;
+import std.format;
+import std.meta;
+import std.path;
+import std.range;
+import std.stdio;
+import std.string;
+import std.typecons;
+import dyaml;
+import dyaml.event;
+import dyaml.parser;
+import dyaml.reader;
+import dyaml.scanner;
+import dyaml.test.suitehelpers;
+
+private version(unittest):
+
+debug(verbose)
+{
+ enum alwaysPrintTestResults = true;
+}
+else
+{
+ enum alwaysPrintTestResults = false;
+}
+
+struct TestResult {
+ string name;
+ Nullable!bool emitter;
+ Nullable!bool constructor;
+ Nullable!bool loaderError;
+ Nullable!bool mark1Error;
+ Nullable!bool mark2Error;
+ Nullable!bool implicitResolver;
+ Nullable!bool events;
+ Nullable!bool specificLoaderError;
+ Nullable!Mark mark1;
+ Nullable!Mark mark2;
+ Event[] parsedData;
+ Event[][2 * 2 * 5] parsedDataResult;
+ Node[] loadedData;
+ Exception nonDYAMLException;
+ MarkedYAMLException exception;
+ string eventsExpected;
+ string eventsGenerated;
+ string generatedLoadErrorMessage;
+ string expectedLoadErrorMessage;
+ string expectedTags;
+ string generatedTags;
+}
+
+/// Pretty-print the differences between two arrays
+auto prettyDifferencePrinter(alias eqPred = (a,b) => a == b, T)(string title, T[] expected, T[] got, bool trimWhitespace = false) @safe
+{
+ struct Result
+ {
+ void foo() {
+ toString(nullSink);
+ }
+ void toString(W)(ref W writer) const
+ {
+ import std.format : formattedWrite;
+ import std.range : put;
+ import std.string : lineSplitter;
+ size_t minWidth = 10;
+ foreach (line; chain(expected, got))
+ {
+ if (line.text.length + 1 > minWidth)
+ {
+ minWidth = line.text.length + 1;
+ }
+ }
+ void writeSideBySide(ubyte colour, string a, string b)
+ {
+ if (trimWhitespace)
+ {
+ a = strip(a);
+ b = strip(b);
+ }
+ writer.formattedWrite!"%s%-(%s%)%s"(colourPrinter(colour, a), " ".repeat(minWidth - a.length), colourPrinter(colour, b));
+ }
+ writefln!"%-(%s%)%s%-(%s%)"("=".repeat(max(0, minWidth * 2 - title.length) / 2), title, "=".repeat(max(0, minWidth * 2 - title.length) / 2));
+ writeSideBySide(0, "Expected", "Got");
+ put(writer, "\n");
+ foreach (line1, line2; zip(StoppingPolicy.longest, expected, got))
+ {
+ static if (is(T : const char[]))
+ {
+ if (trimWhitespace)
+ {
+ line1 = strip(line1);
+ line2 = strip(line2);
+ }
+ }
+ ubyte colour = (eqPred(line1, line2)) ? 32 : 31;
+ writeSideBySide(colour, line1.text, line2.text);
+ put(writer, "\n");
+ }
+ }
+ }
+ return Result();
+}
+
+/**
+Run a single test from the test suite.
+Params:
+ name = The filename of the document to load, containing the test data
+*/
+TestResult runTest(string name, Node doc) @safe
+{
+ TestResult result;
+ string[string] testData;
+ void tryLoadTestData(string what)
+ {
+ if (what in doc)
+ {
+ testData[what] = doc[what].as!string;
+ doc.removeAt(what);
+ }
+ }
+ string yamlPath(string testName, string section)
+ {
+ return format!"%s:%s"(testName, section);
+ }
+ tryLoadTestData("name");
+ result.name = name~"#"~testData.get("name", "UNNAMED");
+ Nullable!Mark getMark(string key)
+ {
+ if (auto node = key in doc)
+ {
+ Mark mark;
+ if ("name" in *node)
+ {
+ mark.name = (*node)["name"].as!string;
+ }
+ else // default to the test name
+ {
+ // if we ever have multiple yaml blocks to parse, be sure to change this
+ mark.name = yamlPath(result.name, "yaml");
+ }
+ if ("line" in *node)
+ {
+ mark.line = cast(ushort)((*node)["line"].as!ushort - 1);
+ }
+ if ("column" in *node)
+ {
+ mark.column = cast(ushort)((*node)["column"].as!ushort - 1);
+ }
+ return Nullable!Mark(mark);
+ }
+ return Nullable!Mark.init;
+ }
+ tryLoadTestData("tags");
+ tryLoadTestData("from");
+ tryLoadTestData("yaml");
+ tryLoadTestData("fail");
+ tryLoadTestData("json"); //not yet implemented
+ tryLoadTestData("dump"); //not yet implemented
+ tryLoadTestData("detect");
+ tryLoadTestData("tree");
+ tryLoadTestData("error");
+ tryLoadTestData("code");
+ assert("yaml" in testData);
+ {
+ result.expectedLoadErrorMessage = testData.get("error", "");
+ result.mark1 = getMark("mark");
+ result.mark2 = getMark("mark2");
+ try
+ {
+ result.parsedData = parseData(testData["yaml"], yamlPath(result.name, "yaml")).array;
+ result.loadedData = Loader.fromString(testData["yaml"], yamlPath(result.name, "yaml")).array;
+ result.emitter = testEmitterStyles(yamlPath(result.name, "canonical"), result.parsedData, result.parsedDataResult);
+ result.mark1Error = result.mark1.isNull;
+ result.mark2Error = result.mark2.isNull;
+ }
+ catch (MarkedYAMLException e)
+ {
+ result.exception = e;
+ result.generatedLoadErrorMessage = e.msg;
+ result.mark1Error = !result.mark1.isNull && (result.mark1.get() == e.mark);
+ result.mark2Error = result.mark2 == e.mark2;
+ if (testData.get("fail", "false") == "false")
+ {
+ result.loaderError = false;
+ }
+ else
+ {
+ result.loaderError = true;
+ }
+ }
+ catch (Exception e)
+ {
+ // all non-DYAML exceptions are failures.
+ result.nonDYAMLException = e;
+ result.generatedLoadErrorMessage = e.msg;
+ result.loaderError = false;
+ }
+ result.specificLoaderError = strip(result.generatedLoadErrorMessage) == strip(result.expectedLoadErrorMessage);
+ }
+ if (result.loaderError.get(false))
+ {
+ // skip other tests if loading failure was expected, because we don't
+ // have a way to run them yet
+ return result;
+ }
+ if ("tree" in testData)
+ {
+ result.eventsGenerated = result.parsedData.map!(x => strip(x.text)).join("\n");
+ result.eventsExpected = testData["tree"].lineSplitter.map!(x => strip(x)).join("\n");
+ result.events = result.eventsGenerated == result.eventsExpected;
+ }
+ if ("code" in testData)
+ {
+ result.constructor = testConstructor(testData["yaml"], testData["code"]);
+ }
+ if ("detect" in testData)
+ {
+ result.implicitResolver = testImplicitResolver(yamlPath(result.name, "yaml"), testData["yaml"], testData["detect"], result.generatedTags, result.expectedTags);
+ }
+ foreach (string remaining, Node _; doc)
+ {
+ writeln("Warning: Unhandled section '", remaining, "' in ", result.name);
+ }
+ return result;
+}
+
+enum goodColour = 32;
+enum badColour = 31;
+/**
+Print something to the console in colour.
+Params:
+ colour = The id of the colour to print, using the 256-colour palette
+ data = Something to print
+*/
+private auto colourPrinter(T)(ubyte colour, T data) @safe pure
+{
+ struct Printer
+ {
+ void toString(S)(ref S sink)
+ {
+ sink.formattedWrite!"\033[%s;1m%s\033[0m"(colour, data);
+ }
+ }
+ return Printer();
+}
+
+/**
+Run all tests in the test suite and print relevant results. The test docs are
+all found in the ./test/data dir.
+*/
+bool runTests()
+{
+ auto stopWatch = StopWatch(AutoStart.yes);
+ bool failed;
+ uint testsRun, testSetsRun, testsFailed;
+ foreach (string name; dirEntries(buildNormalizedPath("test"), "*.yaml", SpanMode.depth)/*.chain(dirEntries(buildNormalizedPath("yaml-test-suite/src"), "*.yaml", SpanMode.depth))*/)
+ {
+ Node doc;
+ try
+ {
+ doc = Loader.fromFile(name).load();
+ }
+ catch (Exception e)
+ {
+ writefln!"[%s] %s"(colourPrinter(badColour, "FAIL"), name);
+ writeln(colourPrinter(badColour, e));
+ assert(0, "Could not load test doc '"~name~"', bailing");
+ }
+ assert (doc.nodeID == NodeID.sequence, name~"'s root node is not a sequence!");
+ foreach (Node test; doc)
+ {
+ testSetsRun++;
+ bool resultPrinted;
+ // make sure the paths are normalized on windows by replacing backslashes with slashes
+ TestResult result = runTest(name.replace("\\", "/"), test);
+ void printResult(string label, Nullable!bool value)
+ {
+ if (!value.isNull)
+ {
+ if (!value.get)
+ {
+ testsFailed++;
+ }
+ testsRun++;
+ }
+ if (alwaysPrintTestResults && value.get(false))
+ {
+ resultPrinted = true;
+ writef!"[%s]"(colourPrinter(goodColour, label));
+ }
+ else if (!value.get(true))
+ {
+ resultPrinted = true;
+ failed = true;
+ writef!"[%s]"(colourPrinter(badColour, label));
+ }
+ }
+ printResult("Emitter", result.emitter);
+ printResult("Constructor", result.constructor);
+ printResult("Mark", result.mark1Error);
+ printResult("Context mark", result.mark2Error);
+ printResult("LoaderError", result.loaderError);
+ printResult("Resolver", result.implicitResolver);
+ printResult("Events", result.events);
+ printResult("SpecificLoaderError", result.specificLoaderError);
+ if (resultPrinted)
+ {
+ writeln(" ", result.name);
+ }
+ if (!result.loaderError.get(true))
+ {
+ if (result.exception is null && result.nonDYAMLException is null)
+ {
+ writeln("\tNo Exception thrown");
+ }
+ else if (result.nonDYAMLException !is null)
+ {
+ writeln(result.nonDYAMLException);
+ }
+ else if (result.exception !is null)
+ {
+ writeln(result.exception);
+ }
+ }
+ else
+ {
+ if (!result.mark1Error.get(true))
+ {
+ writeln(prettyDifferencePrinter("Mark mismatch", [result.mark1.text], [result.exception.mark.text]));
+ }
+ if (!result.mark2Error.get(true))
+ {
+ writeln(prettyDifferencePrinter("Context mark mismatch", [result.mark2.text], [result.exception.mark2.text]));
+ }
+ }
+ if (!result.emitter.get(true))
+ {
+ enum titles = [ "Normal", "Canonical" ];
+ enum styleTitles =
+ [
+ "Block literal", "Block folded", "Block double-quoted", "Block single-quoted", "Block plain",
+ "Flow literal", "Flow folded", "Flow double-quoted", "Flow single-quoted", "Flow plain",
+ "Block literal", "Block folded", "Block double-quoted", "Block single-quoted", "Block plain",
+ "Flow literal", "Flow folded", "Flow double-quoted", "Flow single-quoted", "Flow plain",
+ ];
+ foreach (idx, parsed; result.parsedDataResult)
+ {
+ writeln(prettyDifferencePrinter!eventCompare(styleTitles[idx], result.parsedData, parsed));
+ }
+ }
+ if (!result.events.get(true))
+ {
+ writeln(prettyDifferencePrinter("Events", result.eventsExpected.splitLines, result.eventsGenerated.splitLines, true));
+ }
+ if (!result.specificLoaderError.get(true))
+ {
+ writeln(prettyDifferencePrinter("Expected error", result.expectedLoadErrorMessage.splitLines, result.generatedLoadErrorMessage.splitLines));
+ }
+ if (!result.implicitResolver.get(true))
+ {
+ writeln(prettyDifferencePrinter("Expected error", result.expectedTags.splitLines, result.generatedTags.splitLines));
+ }
+ }
+ }
+ if (alwaysPrintTestResults || failed)
+ {
+ if (testsFailed > 0)
+ {
+ writeln(colourPrinter(badColour, "tests failed: "), testsFailed);
+ }
+ writeln(testSetsRun, " test sets (", testsRun, " tests total) completed successfully in ", stopWatch.peek());
+ }
+ return failed;
+}
+
+unittest {
+ assert(!runTests());
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d b/src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d
new file mode 100644
index 0000000..3016843
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d
@@ -0,0 +1,224 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.suitehelpers;
+
+import dyaml;
+import dyaml.emitter;
+import dyaml.event;
+import dyaml.parser;
+import dyaml.reader;
+import dyaml.scanner;
+import dyaml.token;
+import dyaml.test.constructor;
+
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.exception;
+import std.file;
+import std.range;
+import std.string;
+
+package version(unittest):
+
+// Like other types, wchar and dchar use the system's endianness, so \uFEFF
+// will always be the 'correct' BOM and '\uFFFE' will always be the 'wrong' one
+enum wchar[] bom16 = ['\uFEFF', '\uFFFE'];
+enum dchar[] bom32 = ['\uFEFF', '\uFFFE'];
+
+Parser parseData(string data, string name = "TEST") @safe
+{
+ auto reader = Reader(cast(ubyte[])data.dup, name);
+ auto scanner = Scanner(reader);
+ return new Parser(scanner);
+}
+
+/**
+Test scanner by scanning a document, expecting no errors.
+
+Params:
+ name = Name of the document being scanned
+ data = Data to scan.
+*/
+void testScanner(string name, string data) @safe
+{
+ ubyte[] yamlData = cast(ubyte[])data.dup;
+ string[] tokens;
+ foreach (token; Scanner(Reader(yamlData, name)))
+ {
+ tokens ~= token.id.text;
+ }
+}
+
+/**
+Implicit tag resolution unittest.
+
+Params:
+ name = Name of the document being tested
+ data = Document to compare
+ detectData = The tag that each scalar should resolve to
+*/
+bool testImplicitResolver(string name, string data, string detectData, out string generatedTags, out string expectedTags) @safe
+{
+ const correctTag = detectData.strip();
+
+ const node = Loader.fromString(data, name).load();
+ if (node.nodeID != NodeID.sequence)
+ {
+ return false;
+ }
+ bool success = true;
+ foreach (const Node scalar; node)
+ {
+ generatedTags ~= scalar.tag ~ "\n";
+ expectedTags ~= correctTag ~ "\n";
+ if ((scalar.nodeID != NodeID.scalar) || (scalar.tag != correctTag))
+ {
+ success = false;
+ }
+ }
+ return success;
+}
+
+// Try to emit an event range.
+Event[] emitTestCommon(string name, Event[] events, bool canonical) @safe
+{
+ auto emitStream = new Appender!string();
+ auto emitter = Emitter!(typeof(emitStream), char)(emitStream, canonical, 2, 80, LineBreak.unix);
+ foreach (event; events)
+ {
+ emitter.emit(event);
+ }
+ return parseData(emitStream.data, name).array;
+}
+/**
+Test emitter by checking if events remain equal after round-tripping, with and
+without canonical output enabled.
+
+Params:
+ name = Name of the document being tested
+ events = Events to test
+ results = Events that were produced by round-tripping
+*/
+bool testEmitter(string name, Event[] events, out Event[][2] results) @safe
+{
+ bool matching = true;
+ foreach (idx, canonicalOutput; [false, true])
+ {
+ results[idx] = emitTestCommon(name, events, canonicalOutput);
+
+ if (!equal!eventCompare(events, results[idx]))
+ {
+ matching = false;
+ }
+ }
+ return matching;
+}
+/**
+Test emitter by checking if events remain equal after round-tripping, with all
+combinations of styles.
+
+Params:
+ name = Name of the document being tested
+ events = Events to test
+ results = Events that were produced by round-tripping
+*/
+bool testEmitterStyles(string name, Event[] events, out Event[][2 * 2 * 5] results) @safe
+{
+ size_t idx;
+ foreach (styles; cartesianProduct(
+ [CollectionStyle.block, CollectionStyle.flow],
+ [ScalarStyle.literal, ScalarStyle.folded,
+ ScalarStyle.doubleQuoted, ScalarStyle.singleQuoted,
+ ScalarStyle.plain],
+ [false, true]))
+ {
+ const collectionStyle = styles[0];
+ const scalarStyle = styles[1];
+ const canonical = styles[2];
+ Event[] styledEvents;
+ foreach (event; events)
+ {
+ if (event.id == EventID.scalar)
+ {
+ event = scalarEvent(Mark(), Mark(), event.anchor, event.tag,
+ event.implicit,
+ event.value, scalarStyle);
+ }
+ else if (event.id == EventID.sequenceStart)
+ {
+ event = sequenceStartEvent(Mark(), Mark(), event.anchor,
+ event.tag, event.implicit, collectionStyle);
+ }
+ else if (event.id == EventID.mappingStart)
+ {
+ event = mappingStartEvent(Mark(), Mark(), event.anchor,
+ event.tag, event.implicit, collectionStyle);
+ }
+ styledEvents ~= event;
+ }
+ auto newEvents = emitTestCommon(name, styledEvents, canonical);
+ results[idx++] = newEvents;
+ if (!equal!eventCompare(events, newEvents))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+Constructor unittest.
+
+Params:
+ data = The document being tested
+ base = A unique id corresponding to one of the premade sequences in dyaml.test.constructor
+*/
+bool testConstructor(string data, string base) @safe
+{
+ assert((base in expected) !is null, "Unimplemented constructor test: " ~ base);
+ auto loader = Loader.fromString(data);
+
+ Node[] exp = expected[base];
+
+ //Compare with expected results document by document.
+ return equal(loader, exp);
+}
+
+bool eventCompare(const Event a, const Event b) @safe pure
+{
+ //Different event types.
+ if (a.id != b.id)
+ {
+ return false;
+ }
+ //Different anchor (if applicable).
+ if (a.id.among!(EventID.sequenceStart, EventID.mappingStart, EventID.alias_, EventID.scalar)
+ && a.anchor != b.anchor)
+ {
+ return false;
+ }
+ //Different collection tag (if applicable).
+ if (a.id.among!(EventID.sequenceStart, EventID.mappingStart) && a.tag != b.tag)
+ {
+ return false;
+ }
+ if (a.id == EventID.scalar)
+ {
+ //Different scalar tag (if applicable).
+ if (!(a.implicit || b.implicit) && a.tag != b.tag)
+ {
+ return false;
+ }
+ //Different scalar value.
+ if (a.value != b.value)
+ {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/tokens.d b/src/ext_depends/D-YAML/source/dyaml/test/tokens.d
deleted file mode 100644
index d3dce6e..0000000
--- a/src/ext_depends/D-YAML/source/dyaml/test/tokens.d
+++ /dev/null
@@ -1,93 +0,0 @@
-
-// Copyright Ferdinand Majerech 2011.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-module dyaml.test.tokens;
-
-@safe unittest
-{
- import std.array : split;
- import std.conv : text;
- import std.file : readText;
-
- import dyaml.test.common : run;
- import dyaml.reader : Reader;
- import dyaml.scanner : Scanner;
- import dyaml.token : TokenID;
-
- // Read and scan a YAML doc, returning a range of tokens.
- static auto scanTestCommon(string filename) @safe
- {
- ubyte[] yamlData = cast(ubyte[])readText(filename).dup;
- return Scanner(new Reader(yamlData, filename));
- }
-
- /**
- Test tokens output by scanner.
-
- Params:
- dataFilename = File to scan.
- tokensFilename = File containing expected tokens.
- */
- static void testTokens(string dataFilename, string tokensFilename) @safe
- {
- //representations of YAML tokens in tokens file.
- auto replace = [
- TokenID.directive: "%",
- TokenID.documentStart: "---",
- TokenID.documentEnd: "...",
- TokenID.alias_: "*",
- TokenID.anchor: "&",
- TokenID.tag: "!",
- TokenID.scalar: "_",
- TokenID.blockSequenceStart: "[[",
- TokenID.blockMappingStart: "{{",
- TokenID.blockEnd: "]}",
- TokenID.flowSequenceStart: "[",
- TokenID.flowSequenceEnd: "]",
- TokenID.flowMappingStart: "{",
- TokenID.flowMappingEnd: "}",
- TokenID.blockEntry: ",",
- TokenID.flowEntry: ",",
- TokenID.key: "?",
- TokenID.value: ":"
- ];
-
- string[] tokens;
- string[] expectedTokens = readText(tokensFilename).split();
-
- foreach (token; scanTestCommon(dataFilename))
- {
- if (token.id != TokenID.streamStart && token.id != TokenID.streamEnd)
- {
- tokens ~= replace[token.id];
- }
- }
-
- assert(tokens == expectedTokens,
- text("In token test for '", tokensFilename, "', expected '", expectedTokens, "', got '", tokens, "'"));
- }
-
- /**
- Test scanner by scanning a file, expecting no errors.
-
- Params:
- dataFilename = File to scan.
- canonicalFilename = Another file to scan, in canonical YAML format.
- */
- static void testScanner(string dataFilename, string canonicalFilename) @safe
- {
- foreach (filename; [dataFilename, canonicalFilename])
- {
- string[] tokens;
- foreach (token; scanTestCommon(filename))
- {
- tokens ~= token.id.text;
- }
- }
- }
- run(&testTokens, ["data", "tokens"]);
- run(&testScanner, ["data", "canonical"]);
-}