From 34b11405d4ec6a94a4f4d1f51837d32009903175 Mon Sep 17 00:00:00 2001 From: Ferdinand Majerech Date: Wed, 12 Oct 2011 23:49:42 +0200 Subject: [PATCH] Implemented the resolver unittest. Changed Loader API to be in line with Dumper, and updated examples, tutorials and docs. --- docsrc/articles/spec_differences.rst | 6 +- docsrc/tutorials/custom_types.rst | 39 +-- docsrc/tutorials/getting_started.rst | 38 ++- docsrc/tutorials/yaml_syntax.rst | 11 +- dyaml/dumper.d | 10 +- dyaml/loader.d | 352 ++++++++++++--------------- examples/constructor/main.d | 5 +- examples/getting_started/main.d | 2 +- examples/resolver/main.d | 6 +- test/src/compare.d | 4 +- test/src/constructor.d | 5 +- test/src/emitter.d | 22 +- test/src/errors.d | 8 +- test/src/inputoutput.d | 6 +- test/src/representer.d | 7 +- test/src/resolver.d | 20 +- 16 files changed, 262 insertions(+), 279 deletions(-) diff --git a/docsrc/articles/spec_differences.rst b/docsrc/articles/spec_differences.rst index c864fb5..00ed069 100644 --- a/docsrc/articles/spec_differences.rst +++ b/docsrc/articles/spec_differences.rst @@ -9,7 +9,7 @@ are caused by difficulty of implementation of some features, such as multiple Unicode encodings within single stream, and some by unnecessary restrictions or ambiguities in the specification. -Still, D:YAML tries to be as close to the specification as possible. D:YAML should +Still, D:YAML tries to be as close to the specification as possible. It should never load documents with different meaning than according to the specification, and documents that fail to load should be very rare (for instance, very few files use multiple Unicode encodings). @@ -21,10 +21,6 @@ List of known differences: Differences that can cause valid YAML documents not to load: -* At the moment, all mappings in the internal representation are ordered, - and a comparison for equality between equal mappings with differing order - will return false. This will be fixed once Phobos has a usable map type or - D associative arrays work with variants. * No support for byte order marks and multiple Unicode encodings in a stream. * Plain scalars in flow context cannot contain ``,``, ``:`` and ``?``. This might change with ``:`` in the future. diff --git a/docsrc/tutorials/custom_types.rst b/docsrc/tutorials/custom_types.rst index ff6f3c8..a5fcf26 100644 --- a/docsrc/tutorials/custom_types.rst +++ b/docsrc/tutorials/custom_types.rst @@ -2,10 +2,10 @@ Custom YAML data types ====================== -Often you will want to serialize complex data types such as classes. You can use -functions to process nodes; e.g. a mapping containing class data members indexed -by name. Alternatively, YAML supports custom data types using identifiers called -*tags*. That is the topic of this tutorial. +Often you might want to serialize complex data types such as classes. You can +use functions to process nodes such as a mapping containing class data members +indexed by name. Alternatively, YAML supports custom data types using +identifiers called *tags*. That is the topic of this tutorial. Each YAML node has a tag specifying its type. For instance: strings use the tag ``tag:yaml.org,2002:str``. Tags of most default types are *implicitly resolved* @@ -19,9 +19,9 @@ Constructor D:YAML uses the *Constructor* class to process each node to hold data type corresponding to its tag. *Constructor* stores a function for each supported -tag to process it. These functions can be supplied by the user using the -*addConstructor()* method. *Constructor* is then passed to *Loader*, which will -parse YAML input. +tag to process it. These functions are supplied by the user using the +*addConstructor()* method. *Constructor* is then passed to *Loader*, which +parses YAML input. We will implement support for an RGB color type. It is implemented as the following struct: @@ -111,7 +111,7 @@ RRGGBB, or from a mapping, where we use the following format: return Color(cast(ubyte)r, cast(ubyte)g, cast(ubyte)b); } -Next, we need some YAML code using our new tag. Create a file called input.yaml +Next, we need some YAML data using our new tag. Create a file called input.yaml with the following contents: .. code-block:: yaml @@ -144,9 +144,10 @@ Finally, the code to put it all together: constructor.addConstructor("!color", &constructColorScalar); constructor.addConstructor("!color-mapping", &constructColorMapping); - auto loader = new Loader("input.yaml", constructor, new Resolver); + auto loader = Loader("input.yaml"); + loader.constructor = constructor; - auto root = loader.loadSingleDocument(); + auto root = loader.load(); if(root["scalar-red"].get!Color == red && root["mapping-red"].get!Color == red && @@ -166,10 +167,9 @@ Finally, the code to put it all together: } First, we create a *Constructor* and pass functions to handle the ``!color`` -and ``!color-mapping`` tag. We construct a *Loader* using the *Constructor*. -We also need a *Resolver*, but for now we just default-construct it. We then -load the YAML document, and finally, read the colors using *get()* method to -test if they were loaded as expected. +and ``!color-mapping`` tag. We construct a *Loader*m and pass the *Constructor* +to it. We then load the YAML document, and finally, read the colors using +*get()* method to test if they were loaded as expected. You can find the source code for what we've done so far in the ``examples/constructor`` directory in the D:YAML package. @@ -180,8 +180,8 @@ Resolver -------- Specifying tag for every color value can be tedious. D:YAML can implicitly -resolve tag of a scalar using a regular expression. This is how default types, -e.g. int, are resolved. We will use the *Resolver* class to add implicit tag +resolve scalar tags using regular expressions. This is how default types such as +int are resolved. We will use the *Resolver* class to add implicit tag resolution for the Color data type (in its scalar form). We use the *addImplicitResolver* method of *Resolver*, passing the tag, regular @@ -203,11 +203,14 @@ Add this to your code to add implicit resolution of ``!color``. resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}", "0123456789abcdefABCDEF")); - auto loader = new Loader("input.yaml", constructor, resolver); + auto loader = Loader("input.yaml"); + + loader.constructor = constructor; + loader.resolver = resolver; //code from the previous example... -Now, change contents of input.dyaml to this: +Now, change contents of input.yaml to this: .. code-block:: yaml diff --git a/docsrc/tutorials/getting_started.rst b/docsrc/tutorials/getting_started.rst index de07390..c19b89d 100644 --- a/docsrc/tutorials/getting_started.rst +++ b/docsrc/tutorials/getting_started.rst @@ -26,10 +26,8 @@ Download the version of DMD for your operating system and install it. .. note:: Other D compilers exist, such as `GDC `_ and - `LDC `_. - Setting up with either one of them should be similar to DMD, - however, at the moment they are not as up to date as DMD. - + `LDC `_. Setting up with either one of + them should be similar to DMD, but they are not yet as stable as DMD. ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Download and compile D:YAML @@ -84,7 +82,7 @@ into the file: void main() { - yaml.Node root = yaml.load("input.yaml"); + Node root = Loader("input.yaml").load(); foreach(string word; root["Hello World"]) { writeln(word); @@ -100,22 +98,23 @@ Explanation of the code First, we import the *yaml* module. This is the only module you need to import to use D:YAML - it automatically imports all needed modules. -Next we load the file using the *yaml.load()* function - this loads the file as +Next we load the file using the *Loader.load()* method. *Loader* is the struct +used for parsing YAML documents, and *load()* is a method that loads the file as **one** YAML document and throws *YAMLException*, D:YAML exception type, if the file could not be parsed or does not contain exactly one document. Note that we don't do any error checking here in order to keep the example as simple as possible. -*yaml.Node* represents a node in a YAML document. It can be a sequence (array), +*Node* represents a node in a YAML document. It can be a sequence (array), mapping (associative array) or a scalar (value). Here the root node is a mapping, and we use the index operator to get subnodes with keys "Hello World" and "Answer". We iterate over the first, as it is a sequence, and use the -*yaml.Node.get()* method on the second to get its value as an integer. +*Node.get()* method on the second to get its value as an integer. You can iterate over a mapping or sequence as if it was an associative or normal array. If you try to iterate over a scalar, it will throw a *YAMLException*. -You can iterate over subnodes using yaml.Node as the iterated type, or specify +You can iterate over subnodes using *Node* as the iterated type, or specify the type subnodes are expected to have. D:YAML will automatically convert iterated subnodes to that type if possible. Here we specify the *string* type, so we iterate over the "Hello World" sequence as an array of strings. If it is @@ -123,8 +122,8 @@ not possible to convert to iterated type, a *YAMLException* is thrown. For instance, if we specified *int* here, we would get an error, as "Hello" cannot be converted to an integer. -The *yaml.Node.get()* method is used to get value of a scalar node as specified -type. D:YAML will try to return the scalar as specified type, converting if +The *Node.get()* method is used to get value of a scalar node, allowing to +specify type. D:YAML will try to return the scalar as this type, converting if needed, throwing *YAMLException* if not possible. @@ -135,16 +134,15 @@ Compiling To compile your project, you must give DMD the directories containing import modules and the library. You also need to tell it to link with D:YAML. The import directory should be the D:YAML package directory. You can specify it using the -``-I`` option of DMD. The library directory should point to where you put the -compiled D:YAML library. On Unix/Linux you can specify it using the ``-L-L`` -option, and link with D:YAML using the ``-L-l`` option. On Windows, the import -directory is used as the library directory. To link with the library on Windows, -just add the path to it relative to the current directory. +``-I`` option of DMD. The library directory should be where you put the compiled +D:YAML library. On Unix/Linux you can specify it using the ``-L-L`` option, and +link with D:YAML using the ``-L-l`` option. On Windows, the import directory is +used as the library directory. To link with the library on Windows, just add the +path to it relative to the current directory. -For example, if you extracted D:YAML to ``/home/xxx/dyaml`` and compiled it in -that directory, your project is in ``/home/xxx/dyaml-project``, and you are -currently in that directory, you can compile the project with the following -command on Unix/Linux:: +For example, if you extracted and compiled D:YAML in ``/home/xxx/dyaml``, your +project is in ``/home/xxx/dyaml-project``, and you are currently in that +directory, you can compile the project with the following command on Unix/Linux:: dmd -I../dyaml -L-L../dyaml -L-ldyaml main.d diff --git a/docsrc/tutorials/yaml_syntax.rst b/docsrc/tutorials/yaml_syntax.rst index 09fe3af..17eeb43 100644 --- a/docsrc/tutorials/yaml_syntax.rst +++ b/docsrc/tutorials/yaml_syntax.rst @@ -8,14 +8,14 @@ which this article is based on, `Chapter 2 of the YAML specification `_ or the `Wikipedia page `_. -YAML is a data serialization format designed to be as human readable as -possible. YAML is a recursive acronym for "YAML Ain't Markup Language". +YAML is a data serialization format designed for human readability. YAML is a +recursive acronym for "YAML Ain't Markup Language". YAML is similar to JSON, and in fact, JSON is a subset of YAML 1.2; but YAML has -some more advanced features and is easier to read. However, YAML is also more +some more advanced features and is easier to read. However, it is also more difficult to parse (and probably somewhat slower). Data is stored in mappings (associative arrays), sequences (lists) and scalars (single values). Data -structure hierarchy either depends on indentation (block context, similar to +structure hierarchy depends either on indentation (block context, similar to Python code), or nesting of brackets and braces (flow context, similar to JSON). YAML comments begin with ``#`` and continue until the end of line. @@ -25,8 +25,7 @@ Documents --------- A YAML stream consists of one or more documents starting with ``---`` and -optionally ending with ``...`` . If there is only one document, ``---`` can be -left out. +optionally ending with ``...`` . ``---`` can be left out for the first document. Single document with no explicit start or end: diff --git a/dyaml/dumper.d b/dyaml/dumper.d index 47df296..727f45a 100644 --- a/dyaml/dumper.d +++ b/dyaml/dumper.d @@ -40,14 +40,14 @@ import dyaml.tagdirectives; * Write to a file: * -------------------- * auto node = Node([1, 2, 3, 4, 5]); - * Dumper("file.txt").dump(node); + * Dumper("file.yaml").dump(node); * -------------------- * * Write multiple YAML documents to a file: * -------------------- * auto node1 = Node([1, 2, 3, 4, 5]); * auto node2 = Node("This document contains only one string"); - * Dumper("file.txt").dump(node1, node2); + * Dumper("file.yaml").dump(node1, node2); * -------------------- * * Write to memory: @@ -65,8 +65,8 @@ import dyaml.tagdirectives; * auto resolver = new Resolver(); * * //Add representer functions / resolver expressions here... - * -------------------- - * auto dumper = Dumper("file.txt"); + * + * auto dumper = Dumper("file.yaml"); * dumper.representer = representer; * dumper.resolver = resolver; * dumper.dump(node); @@ -259,7 +259,7 @@ struct Dumper * * Example: * -------------------- - * Dumper dumper = Dumper("file.txt"); + * Dumper dumper = Dumper("file.yaml"); * //This will emit tags starting with "tag:long.org,2011" * //with a "!short!" prefix instead. * dumper.tags("short", "tag:long.org,2011:"); diff --git a/dyaml/loader.d b/dyaml/loader.d index 90522fe..657dd1e 100644 --- a/dyaml/loader.d +++ b/dyaml/loader.d @@ -28,43 +28,36 @@ import dyaml.token; /** - * Load single YAML document from a file. + * Loads YAML documents from files or streams. * - * If there is no or more than one YAML document in the file, this will throw. - * Use $(LREF loadAll) for such files. - * - * Params: filename = Name of the file to _load from. - * - * Returns: Root node of the document. - * - * Throws: YAMLException if there wasn't exactly one document in the file, - * the file could not be opened or on a YAML parsing error. - */ -Node load(in string filename) -{ - auto loader = Loader(filename); - return loader.loadSingleDocument(); -} - -/** - * Load single YAML document from a stream. - * - * You can use this to e.g _load YAML from memory. - * - * If there is no or more than one YAML document in the stream, this will throw. - * Use $(LREF loadAll) for such files. - * - * Params: input = Stream to read from. Must be readable. - * name = Name of the stream, used in error messages. - * - * Returns: Root node of the document. - * - * Throws: YAMLException if there wasn't exactly one document in the stream, - * the stream could not be read from or on a YAML parsing error. + * User specified Constructor and/or Resolver can be used to support new + * tags / data types. * * Examples: * - * Loading YAML from memory: + * Load single YAML document from a file: + * -------------------- + * auto rootNode = Loader("file.yaml").load(); + * ... + * -------------------- + * + * Load all YAML documents from a file: + * -------------------- + * auto nodes = Loader("file.yaml").loadAll(); + * ... + * -------------------- + * + * Iterate over YAML documents in a file, lazily loading them: + * -------------------- + * auto loader = Loader("file.yaml"); + * + * foreach(ref node; loader) + * { + * ... + * } + * -------------------- + * + * Load YAML from memory: * -------------------- * import std.stream; * import std.stdio; @@ -73,74 +66,27 @@ Node load(in string filename) * "green: '#00ff00'\n" * "blue: '#0000ff'"; * - * auto colors = yaml.load(new MemoryStream(cast(char[])yaml_input)); + * auto colors = Loader(new MemoryStream(cast(char[])yaml_input)).load(); * * foreach(string color, string value; colors) * { * writeln(color, " is ", value, " in HTML/CSS"); * } * -------------------- + * + * Use a custom constructor/resolver to support custom data types and/or implicit tags: + * -------------------- + * auto constructor = new Constructor(); + * auto resolver = new Resolver(); + * + * //Add constructor functions / resolver expressions here... + * + * auto loader = Loader("file.yaml"); + * loader.constructor = constructor; + * loader.resolver = resolver; + * auto rootNode = loader.load(node); + * -------------------- */ -Node load(Stream input, in string name = "") -{ - auto loader = Loader(input, name, new Constructor, new Resolver); - return loader.loadSingleDocument(); -} -unittest -{ - import std.stream; - import std.stdio; - - string yaml_input = "red: '#ff0000'\n" - "green: '#00ff00'\n" - "blue: '#0000ff'"; - - auto colors = load(new MemoryStream(cast(char[])yaml_input)); - - foreach(string color, string value; colors) - { - writeln(color, " is ", value, " in HTML/CSS"); - } -} - -/** - * Load all YAML documents from a file. - * - * Params: filename = Name of the file to load from. - * - * Returns: Array of root nodes of documents in the stream. - * If the stream is empty, empty array will be returned. - * - * Throws: YAMLException if the file could not be opened or on a YAML parsing error. - */ -Node[] loadAll(in string filename) -{ - auto loader = Loader(filename); - Node[] result; - foreach(ref node; loader){result ~= node;} - return result; -} - -/** - * Load all YAML documents from a stream. - * - * Params: input = Stream to read from. Must be readable. - * name = Name of the stream, used in error messages. - * - * Returns: Array of root nodes of documents in the file. - * If the file is empty, empty array will be returned. - * - * Throws: YAMLException if the stream could not be read from or on a YAML parsing error. - */ -Node[] loadAll(Stream input, in string name = "") -{ - auto loader = Loader(input, name, new Constructor, new Resolver); - Node[] result; - foreach(ref node; loader){result ~= node;} - return result; -} - -///Loads YAML documents from files or streams. struct Loader { private: @@ -154,12 +100,8 @@ struct Loader Resolver resolver_; ///Constructs YAML data types. Constructor constructor_; - ///Composes YAML nodes. - Composer composer_; ///Name of the input file or stream, used in error messages. - string name_; - ///Input file stream, if the stream is created by Loader itself. - File file_ = null; + string name_ = ""; public: /** @@ -171,60 +113,33 @@ struct Loader */ this(in string filename) { - try{file_ = new File(filename);} + try + { + name = filename; + this(new File(filename)); + } catch(StreamException e) { throw new YAMLException("Unable to load YAML file " ~ filename ~ " : " ~ e.msg); } - this(file_, filename, new Constructor, new Resolver); } /** - * Construct a Loader to load YAML from a file, with provided _constructor and _resolver. + * Construct a Loader to load YAML from a stream. * - * Constructor and _resolver can be used to implement custom data types in YAML. - * - * Params: filename = Name of the file to load from. - * constructor = Constructor to use. - * resolver = Resolver to use. - * - * Throws: YAMLException if the file could not be opened or read from. - */ - this(in string filename, Constructor constructor, Resolver resolver) - { - try{file_ = new File(filename);} - catch(StreamException e) - { - throw new YAMLException("Unable to load YAML file " ~ filename ~ " : " ~ e.msg); - } - - this(file_, filename, constructor, resolver); - } - - /** - * Construct a Loader to load YAML from a stream with provided _constructor and _resolver. - * - * Stream can be used to load YAML from memory and other sources. - * Constructor and _resolver can be used to implement custom data types in YAML. - * - * Params: input = Stream to read from. Must be readable. - * name = Name of the stream. Used in error messages. - * constructor = Constructor to use. - * resolver = Resolver to use. + * Params: stream = Stream to read from. Must be readable. * * Throws: YAMLException if the stream could not be read from. */ - this(Stream input, in string name, Constructor constructor, Resolver resolver) + this(Stream stream) { try { - reader_ = new Reader(input); + reader_ = new Reader(stream); scanner_ = new Scanner(reader_); parser_ = new Parser(scanner_); - resolver_ = resolver; - constructor_ = constructor; - composer_ = new Composer(parser_, resolver_, constructor_); - name_ = name; + resolver_ = new Resolver; + constructor_ = new Constructor; Anchor.addReference(); TagDirectives.addReference(); } @@ -235,58 +150,6 @@ struct Loader } } - /** - * Load single YAML document. - * - * If no or more than one YAML document is found, this will throw a YAMLException. - * - * Returns: Root node of the document. - * - * Throws: YAMLException if there wasn't exactly one document - * or on a YAML parsing error. - */ - Node loadSingleDocument() - { - try - { - enforce(composer_.checkNode(), new YAMLException("No YAML document to load")); - return composer_.getSingleNode(); - } - catch(YAMLException e) - { - e.name = name_; - throw e; - } - } - - /** - * Foreach over YAML documents. - * - * Parses documents lazily, as they are needed. - * - * Throws: YAMLException on a parsing error. - */ - int opApply(int delegate(ref Node) dg) - { - try - { - int result = 0; - while(composer_.checkNode()) - { - auto node = composer_.getNode(); - result = dg(node); - if(result){break;} - } - - return result; - } - catch(YAMLException e) - { - e.name = name_; - throw e; - } - } - ///Destroy the Loader. ~this() { @@ -295,9 +158,97 @@ struct Loader clear(reader_); clear(scanner_); clear(parser_); - clear(composer_); - //Can't clear constructor, resolver: they might be supplied by the user. - if(file_ !is null){file_.close();} + } + + ///Set stream name. Used in debugging messages. + @property void name(string name) + { + name_ = name; + } + + ///Set Resolver to use. + @property void resolver(Resolver resolver) + { + resolver_ = resolver; + } + + ///Set Constructor to use. + @property void constructor(Constructor constructor) + { + constructor_ = constructor; + } + + /** + * Load single YAML document. + * + * If no or more than one YAML document is found, this will throw a YAMLException. + * + * Returns: Root node of the document. + * + * Throws: YAMLException if there wasn't exactly one document + * or on a YAML parsing error. + */ + Node load() + { + try + { + auto composer = new Composer(parser_, resolver_, constructor_); + enforce(composer.checkNode(), new YAMLException("No YAML document to load")); + return composer.getSingleNode(); + } + catch(YAMLException e) + { + e.name = name_; + throw e; + } + } + + /** + * Load all YAML documents. + * + * Returns: Array of root nodes of all documents in the file/stream. + * + * Throws: YAMLException if there wasn't exactly one document + * or on a YAML parsing error. + */ + Node[] loadAll() + { + Node[] nodes; + foreach(ref node; this) + { + nodes ~= node; + } + return nodes; + } + + /** + * Foreach over YAML documents. + * + * Parses documents lazily, as they are needed. + * + * Throws: YAMLException on a parsing error. + */ + int opApply(int delegate(ref Node) dg) + { + try + { + auto composer = new Composer(parser_, resolver_, constructor_); + + int result = 0; + while(composer.checkNode()) + { + auto node = composer.getNode(); + result = dg(node); + if(result){break;} + } + + return result; + } + catch(YAMLException e) + { + e.name = name_; + throw e; + } } package: @@ -333,3 +284,20 @@ struct Loader } } } + +unittest +{ + import std.stream; + import std.stdio; + + string yaml_input = "red: '#ff0000'\n" + "green: '#00ff00'\n" + "blue: '#0000ff'"; + + auto colors = Loader(new MemoryStream(cast(char[])yaml_input)).load(); + + foreach(string color, string value; colors) + { + writeln(color, " is ", value, " in HTML/CSS"); + } +} diff --git a/examples/constructor/main.d b/examples/constructor/main.d index d5bf39a..7cd5e2f 100644 --- a/examples/constructor/main.d +++ b/examples/constructor/main.d @@ -88,9 +88,10 @@ void main() constructor.addConstructor("!color", &constructColorScalar); constructor.addConstructor("!color-mapping", &constructColorMapping); - auto loader = new Loader("input.yaml", constructor, new Resolver); + auto loader = Loader("input.yaml"); + loader.constructor = constructor; - auto root = loader.loadSingleDocument(); + auto root = loader.load(); if(root["scalar-red"].get!Color == red && root["mapping-red"].get!Color == red && diff --git a/examples/getting_started/main.d b/examples/getting_started/main.d index 8e4330a..eb0567b 100644 --- a/examples/getting_started/main.d +++ b/examples/getting_started/main.d @@ -3,7 +3,7 @@ import yaml; void main() { - yaml.Node root = yaml.load("input.yaml"); + yaml.Node root = Loader("input.yaml").load(); foreach(string word; root["Hello World"]) { writeln(word); diff --git a/examples/resolver/main.d b/examples/resolver/main.d index 2794f51..fd06cb4 100644 --- a/examples/resolver/main.d +++ b/examples/resolver/main.d @@ -92,9 +92,11 @@ void main() resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"), "0123456789abcdefABCDEF"); - auto loader = new Loader("input.yaml", constructor, resolver); + auto loader = Loader("input.yaml"); + loader.constructor = constructor; + loader.resolver = resolver; - auto root = loader.loadSingleDocument(); + auto root = loader.load(); if(root["scalar-red"].get!Color == red && root["mapping-red"].get!Color == red && diff --git a/test/src/compare.d b/test/src/compare.d index 5e10765..4e69c13 100644 --- a/test/src/compare.d +++ b/test/src/compare.d @@ -42,8 +42,8 @@ void testParser(bool verbose, string dataFilename, string canonicalFilename) */ void testLoader(bool verbose, string dataFilename, string canonicalFilename) { - auto data = loadAll(dataFilename); - auto canonical = loadAll(canonicalFilename); + auto data = Loader(dataFilename).loadAll; + auto canonical = Loader(canonicalFilename).loadAll; assert(data.length == canonical.length, "Unequal node count"); foreach(n; 0 .. data.length) diff --git a/test/src/constructor.d b/test/src/constructor.d index f7ce613..2f97813 100644 --- a/test/src/constructor.d +++ b/test/src/constructor.d @@ -398,8 +398,9 @@ void testConstructor(bool verbose, string dataFilename, string codeDummy) constructor.addConstructor("!tag1", &constructClass); constructor.addConstructor("!tag2", &constructStruct); - auto resolver = new Resolver; - auto loader = Loader(dataFilename, constructor, resolver); + auto loader = Loader(dataFilename); + loader.constructor = constructor; + loader.resolver = new Resolver; Node[] exp = expected[base]; diff --git a/test/src/emitter.d b/test/src/emitter.d index 66eb439..f8d43c7 100644 --- a/test/src/emitter.d +++ b/test/src/emitter.d @@ -92,8 +92,12 @@ void testEmitterOnData(bool verbose, string dataFilename, string canonicalFilena writeln("ORIGINAL:\n", readText(dataFilename)); writeln("OUTPUT:\n", cast(string)emitStream.data); } - auto loadStream = new MemoryStream(emitStream.data); - auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse(); + + auto loader2 = Loader(new MemoryStream(emitStream.data)); + loader2.name = "TEST"; + loader2.constructor = new Constructor; + loader2.resolver = new Resolver; + auto newEvents = loader2.parse(); assert(compareEvents(events, newEvents)); } @@ -121,8 +125,11 @@ void testEmitterOnCanonical(bool verbose, string canonicalFilename) writeln("OUTPUT (canonical=", canonical, "):\n", cast(string)emitStream.data); } - auto loadStream = new MemoryStream(emitStream.data); - auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse(); + auto loader2 = Loader(new MemoryStream(emitStream.data)); + loader2.name = "TEST"; + loader2.constructor = new Constructor; + loader2.resolver = new Resolver; + auto newEvents = loader2.parse(); assert(compareEvents(events, newEvents)); } } @@ -179,8 +186,11 @@ void testEmitterStyles(bool verbose, string dataFilename, string canonicalFilena to!string(style), ")"); writeln(emitStream.data); } - auto loadStream = new MemoryStream(emitStream.data); - auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse(); + auto loader2 = Loader(new MemoryStream(emitStream.data)); + loader2.name = "TEST"; + loader2.constructor = new Constructor; + loader2.resolver = new Resolver; + auto newEvents = loader2.parse(); assert(compareEvents(events, newEvents)); } } diff --git a/test/src/errors.d b/test/src/errors.d index 157225f..5356099 100644 --- a/test/src/errors.d +++ b/test/src/errors.d @@ -22,7 +22,7 @@ void testLoaderError(bool verbose, string errorFilename) scope(exit){file.close();} Node[] nodes; - try{nodes = loadAll(file, errorFilename);} + try{nodes = Loader(file).loadAll();} catch(YAMLException e) { if(verbose){writeln(typeid(e).toString(), "\n", e);} @@ -48,7 +48,7 @@ void testLoaderErrorString(bool verbose, string errorFilename) try { - auto nodes = loadAll(new MemoryStream(buffer), errorFilename); + auto nodes = Loader(new MemoryStream(buffer)).loadAll(); } catch(YAMLException e) { @@ -66,7 +66,7 @@ void testLoaderErrorString(bool verbose, string errorFilename) */ void testLoaderErrorFilename(bool verbose, string errorFilename) { - try{auto nodes = loadAll(errorFilename);} + try{auto nodes = Loader(errorFilename).loadAll();} catch(YAMLException e) { if(verbose){writeln(typeid(e).toString(), "\n", e);} @@ -83,7 +83,7 @@ void testLoaderErrorFilename(bool verbose, string errorFilename) */ void testLoaderErrorSingle(bool verbose, string errorFilename) { - try{auto nodes = load(errorFilename);} + try{auto nodes = Loader(errorFilename).load();} catch(YAMLException e) { if(verbose){writeln(typeid(e).toString(), "\n", e);} diff --git a/test/src/inputoutput.d b/test/src/inputoutput.d index 1895384..1bce158 100644 --- a/test/src/inputoutput.d +++ b/test/src/inputoutput.d @@ -57,13 +57,13 @@ void testUnicodeInput(bool verbose, string unicodeFilename) string data = readText(unicodeFilename); string expected = data.split().join(" "); - Node output = load(new MemoryStream(to!(char[])(data)), unicodeFilename); + Node output = Loader(new MemoryStream(to!(char[])(data))).load(); assert(output.get!string == expected); foreach(stream; [new MemoryStream(cast(byte[])(bom16() ~ to!(wchar[])(data))), new MemoryStream(cast(byte[])(bom32() ~ to!(dchar[])(data)))]) { - output = load(stream, unicodeFilename); + output = Loader(stream).load(); assert(output.get!string == expected); } } @@ -82,7 +82,7 @@ void testUnicodeInputErrors(bool verbose, string unicodeFilename) new MemoryStream(cast(byte[])(bom16(true) ~ to!(wchar[])(data))), new MemoryStream(cast(byte[])(bom32(true) ~ to!(dchar[])(data)))]) { - try{load(stream, unicodeFilename);} + try{Loader(stream).load();} catch(YAMLException e) { if(verbose){writeln(typeid(e).toString(), "\n", e);} diff --git a/test/src/representer.d b/test/src/representer.d index ff34e13..aa33889 100644 --- a/test/src/representer.d +++ b/test/src/representer.d @@ -61,9 +61,10 @@ void testRepresenterTypes(bool verbose, string codeFilename) constructor.addConstructor("!tag1", &constructClass); constructor.addConstructor("!tag2", &constructStruct); - auto resolver = new Resolver; - auto loader = Loader(loadStream, "DUMMY", constructor, resolver); - foreach(node; loader){readNodes ~= node;} + auto loader = Loader(loadStream); + loader.name = "TEST"; + loader.constructor = constructor; + readNodes = loader.loadAll(); assert(expectedNodes.length == readNodes.length); foreach(n; 0 .. expectedNodes.length) diff --git a/test/src/resolver.d b/test/src/resolver.d index 8989196..6dc6f30 100644 --- a/test/src/resolver.d +++ b/test/src/resolver.d @@ -17,27 +17,31 @@ import dyaml.testcommon; * Implicit tag resolution unittest. * * Params: verbose = Print verbose output? - * dataFilename = TODO - * detectFilename = TODO + * dataFilename = File with unittest data. + * detectFilename = Dummy filename used to specify which data filenames to use. */ void testImplicitResolver(bool verbose, string dataFilename, string detectFilename) { string correctTag; Node node; - scope(exit) + scope(failure) { - if(verbose) + if(true) { writeln("Correct tag: ", correctTag); writeln("Node: ", node.debugString); - assert(node.isSequence); - assert(node.tag.get == correctTag); } } - correctTag = readText(dataFilename).strip(); - node = yaml.load(dataFilename); + correctTag = readText(detectFilename).strip(); + node = Loader(dataFilename).load(); + assert(node.isSequence); + foreach(ref Node scalar; node) + { + assert(scalar.isScalar); + assert(scalar.tag.get == correctTag); + } }