2011-08-16 12:53:13 +00:00
// 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.testconstructor ;
import std.datetime ;
import std.exception ;
import std.path ;
2011-10-11 13:58:23 +00:00
import std.string ;
2011-08-16 12:53:13 +00:00
2011-08-20 20:15:20 +00:00
import dyaml.tag ;
2011-08-16 12:53:13 +00:00
import dyaml.testcommon ;
///Expected results of loading test inputs.
Node [ ] [ string ] expected ;
///Initialize expected.
static this ( )
{
2011-10-11 13:58:23 +00:00
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 ( ) ;
2011-08-16 12:53:13 +00:00
}
///Construct a pair of nodes with specified values.
Node . Pair pair ( A , B ) ( A a , B b )
{
2011-10-11 13:58:23 +00:00
return Node . Pair ( a , b ) ;
2011-08-16 12:53:13 +00:00
}
///Test cases:
2011-10-11 13:58:23 +00:00
Node [ ] constructAliasesCDumperBug ( )
{
return [ Node ( [ "today" , "today" ] ) ] ;
}
2011-08-16 12:53:13 +00:00
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." ;
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "canonical" , canonical ) ,
2011-08-16 12:53:13 +00:00
pair ( "generic" , generic ) ,
pair ( "description" , description ) ] ) ] ;
}
Node [ ] constructBool ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "canonical" , true ) ,
2011-08-16 12:53:13 +00:00
pair ( "answer" , false ) ,
pair ( "logical" , true ) ,
pair ( "option" , true ) ,
pair ( "but" , [ pair ( "y" , "is a string" ) , pair ( "n" , "is a string" ) ] ) ] ) ] ;
}
Node [ ] constructCustom ( )
{
2011-10-17 10:53:38 +00:00
return [ Node ( [ Node ( new TestClass ( 1 , 2 , 3 ) ) ,
2011-10-11 13:58:23 +00:00
Node ( TestStruct ( 10 ) ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructFloat ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "canonical" , cast ( real ) 685230.15 ) ,
2011-08-16 12:53:13 +00:00
pair ( "exponential" , cast ( real ) 685230.15 ) ,
pair ( "fixed" , cast ( real ) 685230.15 ) ,
pair ( "sexagesimal" , cast ( real ) 685230.15 ) ,
pair ( "negative infinity" , - real . infinity ) ,
pair ( "not a number" , real . nan ) ] ) ] ;
}
Node [ ] constructInt ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "canonical" , 685230L ) ,
2011-08-16 12:53:13 +00:00
pair ( "decimal" , 685230L ) ,
pair ( "octal" , 685230L ) ,
pair ( "hexadecimal" , 685230L ) ,
pair ( "binary" , 685230L ) ,
pair ( "sexagesimal" , 685230L ) ] ) ] ;
}
Node [ ] constructMap ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "Block style" ,
2011-08-16 12:53:13 +00:00
[ pair ( "Clark" , "Evans" ) ,
pair ( "Brian" , "Ingerson" ) ,
pair ( "Oren" , "Ben-Kiki" ) ] ) ,
pair ( "Flow style" ,
[ pair ( "Clark" , "Evans" ) ,
pair ( "Brian" , "Ingerson" ) ,
pair ( "Oren" , "Ben-Kiki" ) ] ) ] ) ] ;
}
Node [ ] constructMerge ( )
{
2011-10-11 13:58:23 +00:00
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 ) ] ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructNull ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( YAMLNull ( ) ) ,
Node ( [ pair ( "empty" , YAMLNull ( ) ) ,
2011-08-16 12:53:13 +00:00
pair ( "canonical" , YAMLNull ( ) ) ,
pair ( "english" , YAMLNull ( ) ) ,
pair ( YAMLNull ( ) , "null key" ) ] ) ,
2011-10-11 13:58:23 +00:00
Node ( [ pair ( "sparse" ,
[ Node ( YAMLNull ( ) ) ,
Node ( "2nd entry" ) ,
Node ( YAMLNull ( ) ) ,
Node ( "4th entry" ) ,
Node ( YAMLNull ( ) ) ] ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructOMap ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "Bestiary" ,
2011-08-16 12:53:13 +00:00
[ pair ( "aardvark" , "African pig-like ant eater. Ugly." ) ,
pair ( "anteater" , "South-American ant eater. Two species." ) ,
pair ( "anaconda" , "South-American constrictor snake. Scaly." ) ] ) ,
pair ( "Numbers" , [ pair ( "one" , 1L ) ,
pair ( "two" , 2L ) ,
pair ( "three" , 3L ) ] ) ] ) ] ;
}
Node [ ] constructPairs ( )
{
2011-10-11 13:58:23 +00:00
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" ) ) ,
2011-08-16 12:53:13 +00:00
pair ( "Flow tasks" ,
2011-10-11 13:58:23 +00:00
Node ( [ pair ( "meeting" , "with team" ) ,
pair ( "meeting" , "with boss" ) ] , "tag:yaml.org,2002:pairs" ) ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructSeq ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "Block style" ,
[ Node ( "Mercury" ) , Node ( "Venus" ) , Node ( "Earth" ) , Node ( "Mars" ) ,
Node ( "Jupiter" ) , Node ( "Saturn" ) , Node ( "Uranus" ) , Node ( "Neptune" ) ,
Node ( "Pluto" ) ] ) ,
2011-08-16 12:53:13 +00:00
pair ( "Flow style" ,
2011-10-11 13:58:23 +00:00
[ Node ( "Mercury" ) , Node ( "Venus" ) , Node ( "Earth" ) , Node ( "Mars" ) ,
Node ( "Jupiter" ) , Node ( "Saturn" ) , Node ( "Uranus" ) , Node ( "Neptune" ) ,
Node ( "Pluto" ) ] ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructSet ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "baseball players" ,
[ Node ( "Mark McGwire" ) , Node ( "Sammy Sosa" ) , Node ( "Ken Griffey" ) ] ) ,
2011-08-16 12:53:13 +00:00
pair ( "baseball teams" ,
2011-10-11 13:58:23 +00:00
[ Node ( "Boston Red Sox" ) , Node ( "Detroit Tigers" ) , Node ( "New York Yankees" ) ] ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructStrASCII ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "ascii string" ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructStr ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "string" , "abcd" ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructStrUTF8 ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430" ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] constructTimestamp ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "canonical" , SysTime ( DateTime ( 2001 , 12 , 15 , 2 , 59 , 43 ) , FracSec . from ! "hnsecs" ( 1000000 ) , UTC ( ) ) ) ,
2011-08-16 12:53:13 +00:00
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 ( ) ) ) ,
pair ( "date (00:00:00Z)" , SysTime ( DateTime ( 2002 , 12 , 14 ) , UTC ( ) ) ) ] ) ] ;
}
Node [ ] constructValue ( )
{
2011-10-11 13:58:23 +00:00
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 ) ] ) ] ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] duplicateMergeKey ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( "foo" , "bar" ) ,
2011-08-16 12:53:13 +00:00
pair ( "x" , 1L ) ,
pair ( "y" , 2L ) ,
pair ( "z" , 3L ) ,
pair ( "t" , 4L ) ] ) ] ;
}
Node [ ] floatRepresenterBug ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ pair ( cast ( real ) 1.0 , 1L ) ,
2011-08-16 12:53:13 +00:00
pair ( real . infinity , 10L ) ,
pair ( - real . infinity , - 10L ) ,
pair ( real . nan , 100L ) ] ) ] ;
}
Node [ ] invalidSingleQuoteBug ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( [ Node ( "foo \'bar\'" ) , Node ( "foo\n\'bar\'" ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] moreFloats ( )
{
2011-10-11 13:58:23 +00:00
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 ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] negativeFloatBug ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( cast ( real ) - 1.0 ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] singleDotFloatBug ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "." ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] timestampBugs ( )
{
2011-10-11 13:58:23 +00:00
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 ( ) ) ) ] ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] utf16be ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "UTF-16-BE" ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] utf16le ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "UTF-16-LE" ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] utf8 ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "UTF-8" ) ] ;
2011-08-16 12:53:13 +00:00
}
Node [ ] utf8implicit ( )
{
2011-10-11 13:58:23 +00:00
return [ Node ( "implicit UTF-8" ) ] ;
2011-08-16 12:53:13 +00:00
}
///Testing custom YAML class type.
class TestClass
{
int x , y , z ;
this ( int x , int y , int z )
{
this . x = x ;
this . y = y ;
this . z = z ;
}
override bool opEquals ( Object rhs )
{
if ( typeid ( rhs ) ! = typeid ( TestClass ) ) { return false ; }
auto t = cast ( TestClass ) rhs ;
return x = = t . x & & y = = t . y & & z = = t . z ;
}
2011-10-11 13:58:23 +00:00
override string toString ( )
{
return format ( "TestClass(" , x , ", " , y , ", " , z , ")" ) ;
}
2011-08-16 12:53:13 +00:00
}
///Testing custom YAML struct type.
struct TestStruct
{
int value ;
bool opEquals ( const ref TestStruct rhs ) const
{
return value = = rhs . value ;
}
}
///Constructor function for TestClass.
2011-10-17 10:53:38 +00:00
TestClass constructClass ( Mark start , Mark end , ref Node node )
2011-08-16 12:53:13 +00:00
{
2011-10-17 10:53:38 +00:00
try
2011-08-16 12:53:13 +00:00
{
2011-10-22 15:06:32 +00:00
return new TestClass ( node [ "x" ] . as ! int , node [ "y" ] . as ! int , node [ "z" ] . as ! int ) ;
2011-10-17 10:53:38 +00:00
}
catch ( NodeException e )
{
throw new ConstructorException ( "Error constructing TestClass (missing data members?) "
~ e . msg , start , end ) ;
2011-08-16 12:53:13 +00:00
}
}
2011-10-11 13:58:23 +00:00
Node representClass ( ref Node node , Representer representer )
{
2011-10-22 15:06:32 +00:00
auto value = node . as ! TestClass ;
2011-10-11 13:58:23 +00:00
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 ;
}
2011-08-16 12:53:13 +00:00
///Constructor function for TestStruct.
2011-10-17 10:53:38 +00:00
TestStruct constructStruct ( Mark start , Mark end , ref Node node )
2011-08-16 12:53:13 +00:00
{
2011-10-22 15:06:32 +00:00
return TestStruct ( to ! int ( node . as ! string ) ) ;
2011-08-16 12:53:13 +00:00
}
2011-10-11 13:58:23 +00:00
///Representer function for TestStruct.
Node representStruct ( ref Node node , Representer representer )
{
string [ ] keys , values ;
2011-10-22 15:06:32 +00:00
auto value = node . as ! TestStruct ;
2011-10-11 13:58:23 +00:00
return representer . representScalar ( "!tag2" , to ! string ( value . value ) ) ;
}
2011-08-16 12:53:13 +00:00
/ * *
* Constructor unittest .
*
* Params : verbose = Print verbose output ?
* dataFilename = File name to read from .
* codeDummy = Dummy . code filename , used to determine that
* . data file with the same name should be used in this test .
* /
void testConstructor ( bool verbose , string dataFilename , string codeDummy )
{
2011-10-11 13:58:23 +00:00
string base = dataFilename . baseName . stripExtension ;
2011-08-16 12:53:13 +00:00
enforce ( ( base in expected ) ! is null ,
new Exception ( "Unimplemented constructor test: " ~ base ) ) ;
auto constructor = new Constructor ;
2011-10-17 10:53:38 +00:00
constructor . addConstructorMapping ( "!tag1" , & constructClass ) ;
constructor . addConstructorScalar ( "!tag2" , & constructStruct ) ;
2011-08-16 12:53:13 +00:00
2011-10-12 21:49:42 +00:00
auto loader = Loader ( dataFilename ) ;
loader . constructor = constructor ;
loader . resolver = new Resolver ;
2011-08-16 12:53:13 +00:00
2011-10-11 13:58:23 +00:00
Node [ ] exp = expected [ base ] ;
2011-08-16 12:53:13 +00:00
//Compare with expected results document by document.
size_t i = 0 ;
foreach ( node ; loader )
{
2011-10-30 17:12:02 +00:00
if ( ! node . equals ! false ( exp [ i ] ) )
2011-08-16 12:53:13 +00:00
{
if ( verbose )
{
writeln ( "Expected value:" ) ;
2011-10-11 13:58:23 +00:00
writeln ( exp [ i ] . debugString ) ;
2011-08-16 12:53:13 +00:00
writeln ( "\n" ) ;
writeln ( "Actual value:" ) ;
writeln ( node . debugString ) ;
}
assert ( false ) ;
}
+ + i ;
}
2011-10-11 13:58:23 +00:00
assert ( i = = exp . length ) ;
2011-08-16 12:53:13 +00:00
}
unittest
{
writeln ( "D:YAML Constructor unittest" ) ;
run ( "testConstructor" , & testConstructor , [ "data" , "code" ] ) ;
}