aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d')
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/suitehelpers.d224
1 files changed, 224 insertions, 0 deletions
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;
+}