Most of emitter work done. There are some more changes left until 0.2,
and the turorials and documentation still need some updating.
This commit is contained in:
parent
967fe8c48b
commit
934df763ad
38 changed files with 3976 additions and 404 deletions
|
@ -1,3 +0,0 @@
|
|||
dumper = yaml.Dumper(StringIO())
|
||||
dumper.open()
|
||||
dumper.open()
|
|
@ -1,4 +0,0 @@
|
|||
dumper = yaml.Dumper(StringIO())
|
||||
dumper.open()
|
||||
dumper.close()
|
||||
dumper.open()
|
|
@ -1,4 +0,0 @@
|
|||
dumper = yaml.Dumper(StringIO())
|
||||
dumper.open()
|
||||
dumper.close()
|
||||
dumper.serialize(yaml.ScalarNode(tag='!foo', value='bar'))
|
|
@ -1,2 +0,0 @@
|
|||
dumper = yaml.Dumper(StringIO())
|
||||
dumper.close()
|
|
@ -1,2 +0,0 @@
|
|||
dumper = yaml.Dumper(StringIO())
|
||||
dumper.serialize(yaml.ScalarNode(tag='!foo', value='bar'))
|
|
@ -1 +0,0 @@
|
|||
yaml.safe_dump(object)
|
|
@ -1 +0,0 @@
|
|||
tag:yaml.org,2002:yaml
|
|
@ -93,9 +93,10 @@ string[][string] findTestFilenames(in string dir)
|
|||
{
|
||||
if(isFile(name))
|
||||
{
|
||||
string base = name.getName();
|
||||
string ext = name.getExt();
|
||||
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;
|
||||
|
|
|
@ -10,6 +10,7 @@ module dyaml.testconstructor;
|
|||
import std.datetime;
|
||||
import std.exception;
|
||||
import std.path;
|
||||
import std.string;
|
||||
|
||||
import dyaml.tag;
|
||||
import dyaml.testcommon;
|
||||
|
@ -21,68 +22,64 @@ Node[][string] expected;
|
|||
///Initialize expected.
|
||||
static this()
|
||||
{
|
||||
expected["construct-binary.data"] = constructBinary();
|
||||
expected["construct-bool.data"] = constructBool();
|
||||
expected["construct-custom.data"] = constructCustom();
|
||||
expected["construct-float.data"] = constructFloat();
|
||||
expected["construct-int.data"] = constructInt();
|
||||
expected["construct-map.data"] = constructMap();
|
||||
expected["construct-merge.data"] = constructMerge();
|
||||
expected["construct-null.data"] = constructNull();
|
||||
expected["construct-omap.data"] = constructOMap();
|
||||
expected["construct-pairs.data"] = constructPairs();
|
||||
expected["construct-seq.data"] = constructSeq();
|
||||
expected["construct-set.data"] = constructSet();
|
||||
expected["construct-str-ascii.data"] = constructStrASCII();
|
||||
expected["construct-str.data"] = constructStr();
|
||||
expected["construct-str-utf8.data"] = constructStrUTF8();
|
||||
expected["construct-timestamp.data"] = constructTimestamp();
|
||||
expected["construct-value.data"] = constructValue();
|
||||
expected["duplicate-merge-key.data"] = duplicateMergeKey();
|
||||
expected["float-representer-2.3-bug.data"] = floatRepresenterBug();
|
||||
expected["invalid-single-quote-bug.data"] = invalidSingleQuoteBug();
|
||||
expected["more-floats.data"] = moreFloats();
|
||||
expected["negative-float-bug.data"] = negativeFloatBug();
|
||||
expected["single-dot-is-not-float-bug.data"] = singleDotFloatBug();
|
||||
expected["timestamp-bugs.data"] = timestampBugs();
|
||||
expected["utf16be.data"] = utf16be();
|
||||
expected["utf16le.data"] = utf16le();
|
||||
expected["utf8.data"] = utf8();
|
||||
expected["utf8-implicit.data"] = utf8implicit();
|
||||
}
|
||||
|
||||
///Construct a node with specified value.
|
||||
Node node(T)(T value)
|
||||
{
|
||||
static if(Node.Value.allowed!T){return Node.rawNode(Node.Value(value));}
|
||||
else{return Node.rawNode(Node.userValue(value));}
|
||||
expected["aliases-cdumper-bug"] = constructAliasesCDumperBug();
|
||||
expected["construct-binary"] = constructBinary();
|
||||
expected["construct-bool"] = constructBool();
|
||||
expected["construct-custom"] = constructCustom();
|
||||
expected["construct-float"] = constructFloat();
|
||||
expected["construct-int"] = constructInt();
|
||||
expected["construct-map"] = constructMap();
|
||||
expected["construct-merge"] = constructMerge();
|
||||
expected["construct-null"] = constructNull();
|
||||
expected["construct-omap"] = constructOMap();
|
||||
expected["construct-pairs"] = constructPairs();
|
||||
expected["construct-seq"] = constructSeq();
|
||||
expected["construct-set"] = constructSet();
|
||||
expected["construct-str-ascii"] = constructStrASCII();
|
||||
expected["construct-str"] = constructStr();
|
||||
expected["construct-str-utf8"] = constructStrUTF8();
|
||||
expected["construct-timestamp"] = constructTimestamp();
|
||||
expected["construct-value"] = constructValue();
|
||||
expected["duplicate-merge-key"] = duplicateMergeKey();
|
||||
expected["float-representer-2.3-bug"] = floatRepresenterBug();
|
||||
expected["invalid-single-quote-bug"] = invalidSingleQuoteBug();
|
||||
expected["more-floats"] = moreFloats();
|
||||
expected["negative-float-bug"] = negativeFloatBug();
|
||||
expected["single-dot-is-not-float-bug"] = singleDotFloatBug();
|
||||
expected["timestamp-bugs"] = timestampBugs();
|
||||
expected["utf16be"] = utf16be();
|
||||
expected["utf16le"] = utf16le();
|
||||
expected["utf8"] = utf8();
|
||||
expected["utf8-implicit"] = utf8implicit();
|
||||
}
|
||||
|
||||
///Construct a pair of nodes with specified values.
|
||||
Node.Pair pair(A, B)(A a, B b)
|
||||
{
|
||||
static if(is(A == Node) && is(B == Node)){return Node.Pair(a, b);}
|
||||
else static if(is(A == Node)) {return Node.Pair(a, node(b));}
|
||||
else static if(is(B == Node)) {return Node.Pair(node(a), b);}
|
||||
else {return Node.Pair(node(a), node(b));}
|
||||
return Node.Pair(a,b);
|
||||
}
|
||||
|
||||
///Test cases:
|
||||
|
||||
Node[] constructAliasesCDumperBug()
|
||||
{
|
||||
return [Node(["today", "today"])];
|
||||
}
|
||||
|
||||
Node[] constructBinary()
|
||||
{
|
||||
auto canonical = cast(ubyte[])"GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;";
|
||||
auto generic = cast(ubyte[])"GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;";
|
||||
auto description = "The binary value above is a tiny arrow encoded as a gif image.";
|
||||
|
||||
return [node([pair("canonical", canonical),
|
||||
return [Node([pair("canonical", canonical),
|
||||
pair("generic", generic),
|
||||
pair("description", description)])];
|
||||
}
|
||||
|
||||
Node[] constructBool()
|
||||
{
|
||||
return [node([pair("canonical", true),
|
||||
return [Node([pair("canonical", true),
|
||||
pair("answer", false),
|
||||
pair("logical", true),
|
||||
pair("option", true),
|
||||
|
@ -91,14 +88,14 @@ Node[] constructBool()
|
|||
|
||||
Node[] constructCustom()
|
||||
{
|
||||
return [node([node(new TestClass(1, 0, 0)),
|
||||
node(new TestClass(1, 2, 3)),
|
||||
node(TestStruct(10))])];
|
||||
return [Node([Node(new TestClass(1, 0, 0)),
|
||||
Node(new TestClass(1, 2, 3)),
|
||||
Node(TestStruct(10))])];
|
||||
}
|
||||
|
||||
Node[] constructFloat()
|
||||
{
|
||||
return [node([pair("canonical", cast(real)685230.15),
|
||||
return [Node([pair("canonical", cast(real)685230.15),
|
||||
pair("exponential", cast(real)685230.15),
|
||||
pair("fixed", cast(real)685230.15),
|
||||
pair("sexagesimal", cast(real)685230.15),
|
||||
|
@ -108,7 +105,7 @@ Node[] constructFloat()
|
|||
|
||||
Node[] constructInt()
|
||||
{
|
||||
return [node([pair("canonical", 685230L),
|
||||
return [Node([pair("canonical", 685230L),
|
||||
pair("decimal", 685230L),
|
||||
pair("octal", 685230L),
|
||||
pair("hexadecimal", 685230L),
|
||||
|
@ -118,7 +115,7 @@ Node[] constructInt()
|
|||
|
||||
Node[] constructMap()
|
||||
{
|
||||
return [node([pair("Block style",
|
||||
return [Node([pair("Block style",
|
||||
[pair("Clark", "Evans"),
|
||||
pair("Brian", "Ingerson"),
|
||||
pair("Oren", "Ben-Kiki")]),
|
||||
|
@ -130,34 +127,34 @@ Node[] constructMap()
|
|||
|
||||
Node[] constructMerge()
|
||||
{
|
||||
return [node([node([pair("x", 1L), pair("y", 2L)]),
|
||||
node([pair("x", 0L), pair("y", 2L)]),
|
||||
node([pair("r", 10L)]),
|
||||
node([pair("r", 1L)]),
|
||||
node([pair("x", 1L), pair("y", 2L), pair("r", 10L), pair("label", "center/big")]),
|
||||
node([pair("r", 10L), pair("label", "center/big"), pair("x", 1L), pair("y", 2L)]),
|
||||
node([pair("label", "center/big"), pair("x", 1L), pair("y", 2L), pair("r", 10L)]),
|
||||
node([pair("x", 1L), pair("label", "center/big"), pair("r", 10L), pair("y", 2L)])])];
|
||||
return [Node([Node([pair("x", 1L), pair("y", 2L)]),
|
||||
Node([pair("x", 0L), pair("y", 2L)]),
|
||||
Node([pair("r", 10L)]),
|
||||
Node([pair("r", 1L)]),
|
||||
Node([pair("x", 1L), pair("y", 2L), pair("r", 10L), pair("label", "center/big")]),
|
||||
Node([pair("r", 10L), pair("label", "center/big"), pair("x", 1L), pair("y", 2L)]),
|
||||
Node([pair("label", "center/big"), pair("x", 1L), pair("y", 2L), pair("r", 10L)]),
|
||||
Node([pair("x", 1L), pair("label", "center/big"), pair("r", 10L), pair("y", 2L)])])];
|
||||
}
|
||||
|
||||
Node[] constructNull()
|
||||
{
|
||||
return [node(YAMLNull()),
|
||||
node([pair("empty", YAMLNull()),
|
||||
return [Node(YAMLNull()),
|
||||
Node([pair("empty", YAMLNull()),
|
||||
pair("canonical", YAMLNull()),
|
||||
pair("english", YAMLNull()),
|
||||
pair(YAMLNull(), "null key")]),
|
||||
node([pair("sparse",
|
||||
[node(YAMLNull()),
|
||||
node("2nd entry"),
|
||||
node(YAMLNull()),
|
||||
node("4th entry"),
|
||||
node(YAMLNull())])])];
|
||||
Node([pair("sparse",
|
||||
[Node(YAMLNull()),
|
||||
Node("2nd entry"),
|
||||
Node(YAMLNull()),
|
||||
Node("4th entry"),
|
||||
Node(YAMLNull())])])];
|
||||
}
|
||||
|
||||
Node[] constructOMap()
|
||||
{
|
||||
return [node([pair("Bestiary",
|
||||
return [Node([pair("Bestiary",
|
||||
[pair("aardvark", "African pig-like ant eater. Ugly."),
|
||||
pair("anteater", "South-American ant eater. Two species."),
|
||||
pair("anaconda", "South-American constrictor snake. Scaly.")]),
|
||||
|
@ -168,54 +165,54 @@ Node[] constructOMap()
|
|||
|
||||
Node[] constructPairs()
|
||||
{
|
||||
return [node([pair("Block tasks",
|
||||
[pair("meeting", "with team."),
|
||||
pair("meeting", "with boss."),
|
||||
pair("break", "lunch."),
|
||||
pair("meeting", "with client.")]),
|
||||
return [Node([pair("Block tasks",
|
||||
Node([pair("meeting", "with team."),
|
||||
pair("meeting", "with boss."),
|
||||
pair("break", "lunch."),
|
||||
pair("meeting", "with client.")], "tag:yaml.org,2002:pairs")),
|
||||
pair("Flow tasks",
|
||||
[pair("meeting", "with team"),
|
||||
pair("meeting", "with boss")])])];
|
||||
Node([pair("meeting", "with team"),
|
||||
pair("meeting", "with boss")], "tag:yaml.org,2002:pairs"))])];
|
||||
}
|
||||
|
||||
Node[] constructSeq()
|
||||
{
|
||||
return [node([pair("Block style",
|
||||
[node("Mercury"), node("Venus"), node("Earth"), node("Mars"),
|
||||
node("Jupiter"), node("Saturn"), node("Uranus"), node("Neptune"),
|
||||
node("Pluto")]),
|
||||
return [Node([pair("Block style",
|
||||
[Node("Mercury"), Node("Venus"), Node("Earth"), Node("Mars"),
|
||||
Node("Jupiter"), Node("Saturn"), Node("Uranus"), Node("Neptune"),
|
||||
Node("Pluto")]),
|
||||
pair("Flow style",
|
||||
[node("Mercury"), node("Venus"), node("Earth"), node("Mars"),
|
||||
node("Jupiter"), node("Saturn"), node("Uranus"), node("Neptune"),
|
||||
node("Pluto")])])];
|
||||
[Node("Mercury"), Node("Venus"), Node("Earth"), Node("Mars"),
|
||||
Node("Jupiter"), Node("Saturn"), Node("Uranus"), Node("Neptune"),
|
||||
Node("Pluto")])])];
|
||||
}
|
||||
|
||||
Node[] constructSet()
|
||||
{
|
||||
return [node([pair("baseball players",
|
||||
[node("Mark McGwire"), node("Sammy Sosa"), node("Ken Griffey")]),
|
||||
return [Node([pair("baseball players",
|
||||
[Node("Mark McGwire"), Node("Sammy Sosa"), Node("Ken Griffey")]),
|
||||
pair("baseball teams",
|
||||
[node("Boston Red Sox"), node("Detroit Tigers"), node("New York Yankees")])])];
|
||||
[Node("Boston Red Sox"), Node("Detroit Tigers"), Node("New York Yankees")])])];
|
||||
}
|
||||
|
||||
Node[] constructStrASCII()
|
||||
{
|
||||
return [node("ascii string")];
|
||||
return [Node("ascii string")];
|
||||
}
|
||||
|
||||
Node[] constructStr()
|
||||
{
|
||||
return [node([pair("string", "abcd")])];
|
||||
return [Node([pair("string", "abcd")])];
|
||||
}
|
||||
|
||||
Node[] constructStrUTF8()
|
||||
{
|
||||
return [node("\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430")];
|
||||
return [Node("\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430")];
|
||||
}
|
||||
|
||||
Node[] constructTimestamp()
|
||||
{
|
||||
return [node([pair("canonical", SysTime(DateTime(2001, 12, 15, 2, 59, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
return [Node([pair("canonical", SysTime(DateTime(2001, 12, 15, 2, 59, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
pair("valid iso8601", SysTime(DateTime(2001, 12, 15, 2, 59, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
pair("space separated", SysTime(DateTime(2001, 12, 15, 2, 59, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
pair("no time zone (Z)", SysTime(DateTime(2001, 12, 15, 2, 59, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
|
@ -224,16 +221,16 @@ Node[] constructTimestamp()
|
|||
|
||||
Node[] constructValue()
|
||||
{
|
||||
return[node([pair("link with",
|
||||
[node("library1.dll"), node("library2.dll")])]),
|
||||
node([pair("link with",
|
||||
[node([pair("=", "library1.dll"), pair("version", cast(real)1.2)]),
|
||||
node([pair("=", "library2.dll"), pair("version", cast(real)2.3)])])])];
|
||||
return[Node([pair("link with",
|
||||
[Node("library1.dll"), Node("library2.dll")])]),
|
||||
Node([pair("link with",
|
||||
[Node([pair("=", "library1.dll"), pair("version", cast(real)1.2)]),
|
||||
Node([pair("=", "library2.dll"), pair("version", cast(real)2.3)])])])];
|
||||
}
|
||||
|
||||
Node[] duplicateMergeKey()
|
||||
{
|
||||
return [node([pair("foo", "bar"),
|
||||
return [Node([pair("foo", "bar"),
|
||||
pair("x", 1L),
|
||||
pair("y", 2L),
|
||||
pair("z", 3L),
|
||||
|
@ -242,7 +239,7 @@ Node[] duplicateMergeKey()
|
|||
|
||||
Node[] floatRepresenterBug()
|
||||
{
|
||||
return [node([pair(cast(real)1.0, 1L),
|
||||
return [Node([pair(cast(real)1.0, 1L),
|
||||
pair(real.infinity, 10L),
|
||||
pair(-real.infinity, -10L),
|
||||
pair(real.nan, 100L)])];
|
||||
|
@ -250,58 +247,58 @@ Node[] floatRepresenterBug()
|
|||
|
||||
Node[] invalidSingleQuoteBug()
|
||||
{
|
||||
return [node([node("foo \'bar\'"), node("foo\n\'bar\'")])];
|
||||
return [Node([Node("foo \'bar\'"), Node("foo\n\'bar\'")])];
|
||||
}
|
||||
|
||||
Node[] moreFloats()
|
||||
{
|
||||
return [node([node(cast(real)0.0),
|
||||
node(cast(real)1.0),
|
||||
node(cast(real)-1.0),
|
||||
node(real.infinity),
|
||||
node(-real.infinity),
|
||||
node(real.nan),
|
||||
node(real.nan)])];
|
||||
return [Node([Node(cast(real)0.0),
|
||||
Node(cast(real)1.0),
|
||||
Node(cast(real)-1.0),
|
||||
Node(real.infinity),
|
||||
Node(-real.infinity),
|
||||
Node(real.nan),
|
||||
Node(real.nan)])];
|
||||
}
|
||||
|
||||
Node[] negativeFloatBug()
|
||||
{
|
||||
return [node(cast(real)-1.0)];
|
||||
return [Node(cast(real)-1.0)];
|
||||
}
|
||||
|
||||
Node[] singleDotFloatBug()
|
||||
{
|
||||
return [node(".")];
|
||||
return [Node(".")];
|
||||
}
|
||||
|
||||
Node[] timestampBugs()
|
||||
{
|
||||
return [node([node(SysTime(DateTime(2001, 12, 15, 3, 29, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
node(SysTime(DateTime(2001, 12, 14, 16, 29, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), FracSec.from!"hnsecs"(10100), UTC())),
|
||||
node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), new SimpleTimeZone(60))),
|
||||
node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), new SimpleTimeZone(-90))),
|
||||
node(SysTime(DateTime(2005, 7, 8, 17, 35, 4), FracSec.from!"hnsecs"(5176000), UTC()))])];
|
||||
return [Node([Node(SysTime(DateTime(2001, 12, 15, 3, 29, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
Node(SysTime(DateTime(2001, 12, 14, 16, 29, 43), FracSec.from!"hnsecs"(1000000), UTC())),
|
||||
Node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), FracSec.from!"hnsecs"(10100), UTC())),
|
||||
Node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), new SimpleTimeZone(60))),
|
||||
Node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), new SimpleTimeZone(-90))),
|
||||
Node(SysTime(DateTime(2005, 7, 8, 17, 35, 4), FracSec.from!"hnsecs"(5176000), UTC()))])];
|
||||
}
|
||||
|
||||
Node[] utf16be()
|
||||
{
|
||||
return [node("UTF-16-BE")];
|
||||
return [Node("UTF-16-BE")];
|
||||
}
|
||||
|
||||
Node[] utf16le()
|
||||
{
|
||||
return [node("UTF-16-LE")];
|
||||
return [Node("UTF-16-LE")];
|
||||
}
|
||||
|
||||
Node[] utf8()
|
||||
{
|
||||
return [node("UTF-8")];
|
||||
return [Node("UTF-8")];
|
||||
}
|
||||
|
||||
Node[] utf8implicit()
|
||||
{
|
||||
return [node("implicit UTF-8")];
|
||||
return [Node("implicit UTF-8")];
|
||||
}
|
||||
|
||||
///Testing custom YAML class type.
|
||||
|
@ -322,6 +319,11 @@ class TestClass
|
|||
auto t = cast(TestClass)rhs;
|
||||
return x == t.x && y == t.y && z == t.z;
|
||||
}
|
||||
|
||||
override string toString()
|
||||
{
|
||||
return format("TestClass(", x, ", ", y, ", ", z, ")");
|
||||
}
|
||||
}
|
||||
|
||||
///Testing custom YAML struct type.
|
||||
|
@ -352,6 +354,17 @@ TestClass constructClass(Mark start, Mark end, Node.Pair[] pairs)
|
|||
|
||||
return new TestClass(x, y, z);
|
||||
}
|
||||
|
||||
Node representClass(ref Node node, Representer representer)
|
||||
{
|
||||
auto value = node.get!TestClass;
|
||||
auto pairs = [Node.Pair("x", value.x),
|
||||
Node.Pair("y", value.y),
|
||||
Node.Pair("z", value.z)];
|
||||
auto result = representer.representMapping("!tag1", pairs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///Constructor function for TestStruct.
|
||||
TestStruct constructStruct(Mark start, Mark end, string value)
|
||||
|
@ -359,6 +372,14 @@ TestStruct constructStruct(Mark start, Mark end, string value)
|
|||
return TestStruct(to!int(value));
|
||||
}
|
||||
|
||||
///Representer function for TestStruct.
|
||||
Node representStruct(ref Node node, Representer representer)
|
||||
{
|
||||
string[] keys, values;
|
||||
auto value = node.get!TestStruct;
|
||||
return representer.representScalar("!tag2", to!string(value.value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor unittest.
|
||||
*
|
||||
|
@ -369,7 +390,7 @@ TestStruct constructStruct(Mark start, Mark end, string value)
|
|||
*/
|
||||
void testConstructor(bool verbose, string dataFilename, string codeDummy)
|
||||
{
|
||||
string base = dataFilename.basename;
|
||||
string base = dataFilename.baseName.stripExtension;
|
||||
enforce((base in expected) !is null,
|
||||
new Exception("Unimplemented constructor test: " ~ base));
|
||||
|
||||
|
@ -380,16 +401,18 @@ void testConstructor(bool verbose, string dataFilename, string codeDummy)
|
|||
auto resolver = new Resolver;
|
||||
auto loader = Loader(dataFilename, constructor, resolver);
|
||||
|
||||
Node[] exp = expected[base];
|
||||
|
||||
//Compare with expected results document by document.
|
||||
size_t i = 0;
|
||||
foreach(node; loader)
|
||||
{
|
||||
if(!node.equals!(Node, false)(expected[base][i]))
|
||||
if(!node.equals!(Node, false)(exp[i]))
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
writeln("Expected value:");
|
||||
writeln(expected[base][i].debugString);
|
||||
writeln(exp[i].debugString);
|
||||
writeln("\n");
|
||||
writeln("Actual value:");
|
||||
writeln(node.debugString);
|
||||
|
@ -398,7 +421,7 @@ void testConstructor(bool verbose, string dataFilename, string codeDummy)
|
|||
}
|
||||
++i;
|
||||
}
|
||||
assert(i == expected[base].length);
|
||||
assert(i == exp.length);
|
||||
}
|
||||
|
||||
|
||||
|
|
196
test/src/emitter.d
Normal file
196
test/src/emitter.d
Normal file
|
@ -0,0 +1,196 @@
|
|||
|
||||
// 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.testemitter;
|
||||
|
||||
|
||||
import std.algorithm;
|
||||
import std.file;
|
||||
import std.range;
|
||||
|
||||
import dyaml.dumper;
|
||||
import dyaml.event;
|
||||
import dyaml.testcommon;
|
||||
import dyaml.token;
|
||||
|
||||
|
||||
/**
|
||||
* Determine if events in events1 are equivalent to events in events2.
|
||||
*
|
||||
* Params: events1 = First event array to compare.
|
||||
* events2 = Second event array to compare.
|
||||
*
|
||||
* Returns: true if the events are equivalent, false otherwise.
|
||||
*/
|
||||
bool compareEvents(Event[] events1, Event[] events2)
|
||||
{
|
||||
if(events1.length != events2.length){return false;}
|
||||
|
||||
for(uint e = 0; e < events1.length; ++e)
|
||||
{
|
||||
auto e1 = events1[e];
|
||||
auto e2 = events2[e];
|
||||
|
||||
//Different event types.
|
||||
if(e1.id != e2.id){return false;}
|
||||
//Different anchor (if applicable).
|
||||
if([EventID.SequenceStart,
|
||||
EventID.MappingStart,
|
||||
EventID.Alias,
|
||||
EventID.Scalar].canFind(e1.id)
|
||||
&& e1.anchor != e2.anchor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//Different collection tag (if applicable).
|
||||
if([EventID.SequenceStart, EventID.MappingStart].canFind(e1.id) && e1.tag != e2.tag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(e1.id == EventID.Scalar)
|
||||
{
|
||||
//Different scalar tag (if applicable).
|
||||
if(![e1.implicit, e1.implicit_2, e2.implicit, e2.implicit_2].canFind(true)
|
||||
&& e1.tag != e2.tag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//Different scalar value.
|
||||
if(e1.value != e2.value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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: verbose = Print verbose output?
|
||||
* dataFilename = YAML file to parse.
|
||||
* canonicalFilename = Canonical YAML file used as dummy to determine
|
||||
* which data files to load.
|
||||
*/
|
||||
void testEmitterOnData(bool verbose, string dataFilename, string canonicalFilename)
|
||||
{
|
||||
//Must exist due to Anchor, Tags reference counts.
|
||||
auto loader = Loader(dataFilename);
|
||||
auto events = loader.parse();
|
||||
auto emitStream = new MemoryStream;
|
||||
Dumper(emitStream).emit(events);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
writeln(dataFilename);
|
||||
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();
|
||||
assert(compareEvents(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: verbose = Print verbose output?
|
||||
* canonicalFilename = Canonical YAML file to parse.
|
||||
*/
|
||||
void testEmitterOnCanonical(bool verbose, string canonicalFilename)
|
||||
{
|
||||
//Must exist due to Anchor, Tags reference counts.
|
||||
auto loader = Loader(canonicalFilename);
|
||||
auto events = loader.parse();
|
||||
foreach(canonical; [false, true])
|
||||
{
|
||||
auto emitStream = new MemoryStream;
|
||||
auto dumper = Dumper(emitStream);
|
||||
dumper.canonical = canonical;
|
||||
dumper.emit(events);
|
||||
if(verbose)
|
||||
{
|
||||
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();
|
||||
assert(compareEvents(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: verbose = Print verbose output?
|
||||
* dataFilename = YAML file to parse.
|
||||
* canonicalFilename = Canonical YAML file used as dummy to determine
|
||||
* which data files to load.
|
||||
*/
|
||||
void testEmitterStyles(bool verbose, string dataFilename, string canonicalFilename)
|
||||
{
|
||||
foreach(filename; [dataFilename, canonicalFilename])
|
||||
{
|
||||
//must exist due to Anchor, Tags reference counts
|
||||
auto loader = Loader(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.implicit_2],
|
||||
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 = new MemoryStream;
|
||||
Dumper(emitStream).emit(styledEvents);
|
||||
if(verbose)
|
||||
{
|
||||
writeln("OUTPUT (", filename, ", ", to!string(flowStyle), ", ",
|
||||
to!string(style), ")");
|
||||
writeln(emitStream.data);
|
||||
}
|
||||
auto loadStream = new MemoryStream(emitStream.data);
|
||||
auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse();
|
||||
assert(compareEvents(events, newEvents));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
writeln("D:YAML Emitter unittest");
|
||||
run("testEmitterOnData", &testEmitterOnData, ["data", "canonical"]);
|
||||
run("testEmitterOnCanonical", &testEmitterOnCanonical, ["canonical"]);
|
||||
run("testEmitterStyles", &testEmitterStyles, ["data", "canonical"]);
|
||||
}
|
|
@ -27,8 +27,8 @@ wchar bom16(bool wrong = false) pure
|
|||
{
|
||||
wchar little = *(cast(wchar*)ByteOrderMarks[BOM.UTF16LE]);
|
||||
wchar big = *(cast(wchar*)ByteOrderMarks[BOM.UTF16BE]);
|
||||
if(!wrong){return endian == Endian.LittleEndian ? little : big;}
|
||||
return endian == Endian.LittleEndian ? big : little;
|
||||
if(!wrong){return endian == Endian.littleEndian ? little : big;}
|
||||
return endian == Endian.littleEndian ? big : little;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,8 +42,8 @@ dchar bom32(bool wrong = false) pure
|
|||
{
|
||||
dchar little = *(cast(dchar*)ByteOrderMarks[BOM.UTF32LE]);
|
||||
dchar big = *(cast(dchar*)ByteOrderMarks[BOM.UTF32BE]);
|
||||
if(!wrong){return endian == Endian.LittleEndian ? little : big;}
|
||||
return endian == Endian.LittleEndian ? big : little;
|
||||
if(!wrong){return endian == Endian.littleEndian ? little : big;}
|
||||
return endian == Endian.littleEndian ? big : little;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
80
test/src/representer.d
Normal file
80
test/src/representer.d
Normal file
|
@ -0,0 +1,80 @@
|
|||
|
||||
// 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.testrepresenter;
|
||||
|
||||
|
||||
import std.path;
|
||||
import std.exception;
|
||||
|
||||
import dyaml.testcommon;
|
||||
import dyaml.testconstructor;
|
||||
|
||||
|
||||
/**
|
||||
* Representer unittest.
|
||||
*
|
||||
* Params: verbose = Print verbose output?
|
||||
* codeFilename = File name to determine test case from.
|
||||
* Nothing is read from this file, it only exists
|
||||
* to specify that we need a matching unittest.
|
||||
*/
|
||||
void testRepresenterTypes(bool verbose, string codeFilename)
|
||||
{
|
||||
string baseName = codeFilename.baseName.stripExtension;
|
||||
enforce((baseName in dyaml.testconstructor.expected) !is null,
|
||||
new Exception("Unimplemented representer test: " ~ baseName));
|
||||
|
||||
Node[] expectedNodes = expected[baseName];
|
||||
foreach(encoding; [Encoding.UTF_8, Encoding.UTF_16, Encoding.UTF_32])
|
||||
{
|
||||
string output;
|
||||
Node[] readNodes;
|
||||
|
||||
scope(failure)
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
writeln("Expected nodes:");
|
||||
foreach(ref n; expectedNodes){writeln(n.debugString, "\n---\n");}
|
||||
writeln("Read nodes:");
|
||||
foreach(ref n; readNodes){writeln(n.debugString, "\n---\n");}
|
||||
writeln("OUTPUT:\n", output);
|
||||
}
|
||||
}
|
||||
|
||||
auto emitStream = new MemoryStream;
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!TestClass(&representClass);
|
||||
representer.addRepresenter!TestStruct(&representStruct);
|
||||
auto dumper = Dumper(emitStream);
|
||||
dumper.representer = representer;
|
||||
dumper.encoding = encoding;
|
||||
dumper.dump(expectedNodes);
|
||||
|
||||
output = cast(string)emitStream.data;
|
||||
auto loadStream = new MemoryStream(emitStream.data);
|
||||
auto constructor = new Constructor;
|
||||
constructor.addConstructor("!tag1", &constructClass);
|
||||
constructor.addConstructor("!tag2", &constructStruct);
|
||||
|
||||
auto resolver = new Resolver;
|
||||
auto loader = Loader(loadStream, "DUMMY", constructor, resolver);
|
||||
foreach(node; loader){readNodes ~= node;}
|
||||
|
||||
assert(expectedNodes.length == readNodes.length);
|
||||
foreach(n; 0 .. expectedNodes.length)
|
||||
{
|
||||
assert(expectedNodes[n].equals!(Node, false)(readNodes[n]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
writeln("D:YAML Representer unittest");
|
||||
run("testRepresenterTypes", &testRepresenterTypes, ["code"]);
|
||||
}
|
48
test/src/resolver.d
Normal file
48
test/src/resolver.d
Normal file
|
@ -0,0 +1,48 @@
|
|||
|
||||
// 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.testresolver;
|
||||
|
||||
|
||||
import std.file;
|
||||
import std.string;
|
||||
|
||||
import dyaml.testcommon;
|
||||
|
||||
|
||||
/**
|
||||
* Implicit tag resolution unittest.
|
||||
*
|
||||
* Params: verbose = Print verbose output?
|
||||
* dataFilename = TODO
|
||||
* detectFilename = TODO
|
||||
*/
|
||||
void testImplicitResolver(bool verbose, string dataFilename, string detectFilename)
|
||||
{
|
||||
string correctTag;
|
||||
Node node;
|
||||
|
||||
scope(exit)
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
writeln("Correct tag: ", correctTag);
|
||||
writeln("Node: ", node.debugString);
|
||||
assert(node.isSequence);
|
||||
assert(node.tag.get == correctTag);
|
||||
}
|
||||
}
|
||||
|
||||
correctTag = readText(dataFilename).strip();
|
||||
node = yaml.load(dataFilename);
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
writeln("D:YAML Resolver unittest");
|
||||
run("testImplicitResolver", &testImplicitResolver, ["data", "detect"]);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue