diff options
Diffstat (limited to 'src/ext_depends/D-YAML/source/dyaml/test/common.d')
-rw-r--r-- | src/ext_depends/D-YAML/source/dyaml/test/common.d | 223 |
1 files changed, 223 insertions, 0 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 new file mode 100644 index 0000000..a6bafa9 --- /dev/null +++ b/src/ext_depends/D-YAML/source/dyaml/test/common.d @@ -0,0 +1,223 @@ + +// 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) |