diff options
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.d | 224 |
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; +} |