1
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*-
3
# $Id: test_yaml.rb 20319 2008-11-22 14:51:49Z yugui $
10
StructTest = Struct::new( :c )
13
class YAML_Unit_Tests < Test::Unit::TestCase
15
# Convert between YAML and the object to verify correct parsing and
18
def assert_to_yaml( obj, yaml )
19
assert_equal( obj, YAML::load( yaml ) )
20
assert_equal( obj, YAML::parse( yaml ).transform )
21
assert_equal( obj, YAML::load( obj.to_yaml ) )
22
assert_equal( obj, YAML::parse( obj.to_yaml ).transform )
23
assert_equal( obj, YAML::load(
24
obj.to_yaml( :UseVersion => true, :UseHeader => true, :SortKeys => true )
31
def assert_parse_only( obj, yaml )
32
assert_equal( obj, YAML::load( yaml ) )
33
assert_equal( obj, YAML::parse( yaml ).transform )
36
def assert_cycle( obj )
37
assert_equal( obj, YAML::load( obj.to_yaml ) )
40
def assert_path_segments( path, segments )
41
YAML::YPath.each_path( path ) { |choice|
42
assert_equal( choice.segments, segments.shift )
44
assert_equal( segments.length, 0, "Some segments leftover: #{ segments.inspect }" )
48
# Make a time with the time zone
50
def mktime( year, mon, day, hour, min, sec, usec, zone = "Z" )
51
usec = usec.to_s.to_f * 1000000
52
val = Time::utc( year.to_i, mon.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec )
54
hour = zone[0,3].to_i * 3600
55
min = zone[3,2].to_i * 60
57
val = Time.at( val.tv_sec - ofs, val.tv_nsec / 1000.0 )
63
# Tests modified from 00basic.t in YAML.pm
68
{ 'one' => 'foo', 'three' => 'baz', 'two' => 'bar' }, <<EOY
76
def test_basic_strings
82
{ 1 => 'simple string', 2 => 42, 3 => '1 Single Quoted String',
83
4 => 'YAML\'s Double "Quoted" String', 5 => "A block\n with several\n lines.\n",
84
6 => "A \"chomped\" block", 7 => "A folded\n string\n", 8 => ": started string" },
88
3: '1 Single Quoted String'
89
4: "YAML's Double \\\"Quoted\\\" String"
100
8: ": started string"
106
# Test the specification examples
107
# - Many examples have been changes because of whitespace problems that
108
# caused the two to be inequivalent, or keys to be sorted wrong
111
def test_spec_simple_implicit_sequence
112
# Simple implicit sequence
114
[ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ], <<EOY
122
def test_spec_simple_implicit_map
123
# Simple implicit map
125
{ 'hr' => 65, 'avg' => 0.278, 'rbi' => 147 }, <<EOY
133
def test_spec_simple_map_with_nested_sequences
134
# Simple mapping with nested sequences
137
[ 'Boston Red Sox', 'Detroit Tigers', 'New York Yankees' ],
139
[ 'New York Mets', 'Chicago Cubs', 'Atlanta Braves' ] }, <<EOY
152
def test_spec_simple_sequence_with_nested_map
153
# Simple sequence with nested map
156
{'name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278},
157
{'name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288}
171
def test_spec_sequence_of_sequences
172
# Simple sequence with inline sequences
175
[ 'name', 'hr', 'avg' ],
176
[ 'Mark McGwire', 65, 0.278 ],
177
[ 'Sammy Sosa', 63, 0.288 ]
179
- [ name , hr , avg ]
180
- [ Mark McGwire , 65 , 0.278 ]
181
- [ Sammy Sosa , 63 , 0.288 ]
186
def test_spec_mapping_of_mappings
187
# Simple map with inline maps
190
{ 'hr' => 65, 'avg' => 0.278 },
192
{ 'hr' => 63, 'avg' => 0.288 }
194
Mark McGwire: {hr: 65, avg: 0.278}
201
def test_ambiguous_comments
203
assert_to_yaml( "Call the method #dave", <<EOY )
204
--- "Call the method #dave"
208
def test_spec_nested_comments
209
# Map and sequences with comments
211
{ 'hr' => [ 'Mark McGwire', 'Sammy Sosa' ],
212
'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
213
hr: # 1998 hr ranking
224
def test_spec_anchors_and_aliases
225
# Anchors and aliases
228
[ 'Mark McGwire', 'Sammy Sosa' ],
230
[ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
233
# Name "Sammy Sosa" scalar SS
236
# So it can be referenced later.
243
[{"arrival"=>"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}], <<EOY
249
- { *F: MADF, *C: AUD, *D: SYD, *A: MEL }
250
- { *F: DFSF, *C: USD, *D: JFK, *A: MCO }
255
{"ALIASES"=>["fareref", "currency", "departure", "arrival"], "FARES"=>[{"arrival"=>"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}]}, <<EOY
257
ALIASES: [&f fareref, &c currency, &d departure, &a arrival]
279
def test_spec_mapping_between_sequences
281
dj = Date.new( 2001, 7, 23 )
283
{ [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
284
[ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ] }, <<EOY
291
? [ New York Yankees,
293
: [ 2001-07-02, 2001-08-12,
300
{ [ 'New York Yankees', 'Atlanta Braves' ] =>
301
[ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ),
302
Date.new( 2001, 8, 14 ) ],
303
[ 'Detroit Tigers', 'Chicago Cubs' ] =>
304
[ Date.new( 2001, 7, 23 ) ]
322
def test_spec_sequence_key_shortcut
323
# Shortcut sequence map
325
{ 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
326
'bill-to' => 'Chris Dumars', 'product' =>
327
[ { 'item' => 'Super Hoop', 'quantity' => 1 },
328
{ 'item' => 'Basketball', 'quantity' => 4 },
329
{ 'item' => 'Big Shoes', 'quantity' => 1 } ] }, <<EOY
332
bill-to: Chris Dumars
344
def test_spec_sequence_in_sequence_shortcut
346
assert_parse_only( [ [ [ 'one', 'two', 'three' ] ] ], <<EOY )
353
def test_spec_sequence_shortcuts
354
# Sequence shortcuts combined
361
[ { 'five' => [ 'six' ] } ],
378
def test_spec_single_literal
379
# Literal scalar block
380
assert_parse_only( [ "\\/|\\/|\n/ | |_\n" ], <<EOY )
387
def test_spec_single_folded
388
# Folded scalar block
390
[ "Mark McGwire's year was crippled by a knee injury.\n" ], <<EOY
399
def test_spec_preserve_indent
400
# Preserve indented spaces
402
"Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n", <<EOY
404
Sammy Sosa completed another
405
fine season with great stats.
408
0.288 Batting Average
415
def test_spec_indentation_determines_scope
417
{ 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n",
418
'stats' => "65 Home Runs\n0.278 Batting Average\n" }, <<EOY
421
Mark set a major league
422
home run record in 1998.
425
0.278 Batting Average
430
def test_spec_multiline_scalars
431
# Multiline flow scalars
433
{ 'plain' => 'This unquoted scalar spans many lines.',
434
'quoted' => "So does this quoted scalar.\n" }, <<EOY
445
def test_spec_type_int
447
{ 'canonical' => 12345, 'decimal' => 12345, 'octal' => '014'.oct, 'hexadecimal' => '0xC'.hex }, <<EOY
455
{ 'canonical' => 685230, 'decimal' => 685230, 'octal' => 02472256, 'hexadecimal' => 0x0A74AE, 'sexagesimal' => 685230 }, <<EOY)
459
hexadecimal: 0x0A,74,AE
460
sexagesimal: 190:20:30
464
def test_spec_type_float
466
{ 'canonical' => 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15,
467
'negative infinity' => -1.0/0.0 }, <<EOY)
468
canonical: 1.23015e+3
469
exponential: 12.3015e+02
471
negative infinity: -.inf
473
nan = YAML::load( <<EOY )
476
assert( nan['not a number'].nan? )
479
def test_spec_type_misc
481
{ nil => nil, true => true, false => false, 'string' => '12345' }, <<EOY
490
def test_spec_complex_invoice
491
# Complex invoice type
492
id001 = { 'given' => 'Chris', 'family' => 'Dumars', 'address' =>
493
{ 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak',
494
'state' => 'MI', 'postal' => 48046 } }
496
{ 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
497
'bill-to' => id001, 'ship-to' => id001, 'product' =>
498
[ { 'sku' => 'BL394D', 'quantity' => 4,
499
'description' => 'Basketball', 'price' => 450.00 },
500
{ 'sku' => 'BL4438H', 'quantity' => 1,
501
'description' => 'Super Hoop', 'price' => 2392.00 } ],
502
'tax' => 251.42, 'total' => 4443.52,
503
'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" }, <<EOY
521
description : Basketball
525
description : Super Hoop
530
Late afternoon is best.
531
Backup contact is Nancy
537
def test_spec_log_file
539
YAML::load_documents( <<EOY
541
Time: 2001-11-23 15:01:42 -05:00
544
This is an error message
547
Time: 2001-11-23 15:02:31 -05:00
550
A slightly different error
553
Date: 2001-11-23 15:03:17 -05:00
556
Unknown variable "bar"
561
x = MoreObject("345\\n")
570
assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ),
571
'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } )
573
assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ),
574
'User' => 'ed', 'Warning' => "A slightly different error message.\n" } )
576
assert_equal( doc, { 'Date' => mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ),
577
'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n",
579
{ 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" },
580
{ 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } )
584
assert_equal( doc_ct, 3 )
587
def test_spec_root_fold
588
y = YAML::load( <<EOY
590
This YAML stream contains a single text value.
591
The next stream is a log file - a sequence of
592
log entries. Adding an entry to the log is a
593
simple matter of appending it at the end.
596
assert_equal( y, "This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end.\n" )
599
def test_spec_root_mapping
600
y = YAML::load( <<EOY
601
# This stream is an example of a top-level mapping.
607
assert_equal( y, { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), 'total' => 4443.52 } )
610
def test_spec_oneline_docs
612
YAML::load_documents( <<EOY
613
# The following is a sequence of three documents.
614
# The first contains an empty mapping, the second
615
# an empty sequence, and the last an empty string.
623
assert_equal( doc, {} )
625
assert_equal( doc, [] )
627
assert_equal( doc, '' )
631
assert_equal( doc_ct, 3 )
634
def test_spec_domain_prefix
635
customer_proc = proc { |type, val|
637
scheme, domain, type = type.split( ':', 3 )
638
val['type'] = "domain #{type}"
641
raise ArgumentError, "Not a Hash in domain.tld,2002/invoice: " + val.inspect
644
YAML.add_domain_type( "domain.tld,2002", 'invoice', &customer_proc )
645
YAML.add_domain_type( "domain.tld,2002", 'customer', &customer_proc )
646
assert_parse_only( { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }, <<EOY
647
# 'http://domain.tld,2002/invoice' is some type family.
648
invoice: !domain.tld,2002/^invoice
649
# 'seq' is shorthand for 'http://yaml.org/seq'.
650
# This does not effect '^customer' below
651
# because it is does not specify a prefix.
653
# '^customer' is shorthand for the full
654
# notation 'http://domain.tld,2002/customer'.
662
def test_spec_throwaway
664
{"this"=>"contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"}, <<EOY
665
### These are four throwaway comment ###
667
### lines (the second line is empty). ###
668
this: | # Comments may trail lines.
669
contains three lines of text.
670
The third one starts with a
671
# character. This isn't a comment.
673
# These are three throwaway comment
674
# lines (the first line is empty).
679
def test_spec_force_implicit
682
{ 'integer' => 12, 'also int' => 12, 'string' => '12' }, <<EOY
690
def test_spec_private_types
692
YAML::parse_documents( <<EOY
693
# Private types are per-document.
705
assert_equal( doc['pool'].type_id, 'x-private:ball' )
706
assert_equal( doc['pool'].transform.value, { 'number' => 8, 'color' => 'black' } )
708
assert_equal( doc['bearing'].type_id, 'x-private:ball' )
709
assert_equal( doc['bearing'].transform.value, { 'material' => 'steel' } )
713
assert_equal( doc_ct, 2 )
716
def test_spec_url_escaping
717
YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
720
YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
724
{ 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value' ] }, <<EOY
726
- !domain.tld,2002/type\\x30 value
727
- !domain.tld,2002/type0 value
728
different: # As far as the YAML parser is concerned
729
- !domain.tld,2002/type%30 value
734
def test_spec_override_anchor
736
a001 = "The alias node below is a repeated use of this value.\n"
738
{ 'anchor' => 'This scalar has an anchor.', 'override' => a001, 'alias' => a001 }, <<EOY
739
anchor : &A001 This scalar has an anchor.
741
The alias node below is a
742
repeated use of this value.
748
def test_spec_explicit_families
749
YAML.add_domain_type( "somewhere.com,2002", 'type' ) { |type, val|
753
{ 'not-date' => '2002-04-28', 'picture' => "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236i^\020' \202\n\001\000;", 'hmm' => "SOMEWHERE: family above is short for\nhttp://somewhere.com/type\n" }, <<EOY
754
not-date: !str 2002-04-28
756
R0lGODlhDAAMAIQAAP//9/X
757
17unp5WZmZgAAAOfn515eXv
758
Pz7Y6OjuDg4J+fn5OTk6enp
761
hmm: !somewhere.com,2002/type |
762
family above is short for
763
http://somewhere.com/type
768
def test_spec_application_family
769
# Testing the clarkevans.com graphs
770
YAML.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val|
772
val << "Shape Container"
775
raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
778
one_shape_proc = Proc.new { |type, val|
780
type = type.split( /:/ )
781
val['TYPE'] = "Shape: #{type[2]}"
784
raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
787
YAML.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc )
788
YAML.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc )
789
YAML.add_domain_type( "clarkevans.com,2002", 'graph/text', &one_shape_proc )
791
[[{"radius"=>7, "center"=>{"x"=>73, "y"=>129}, "TYPE"=>"Shape: graph/circle"}, {"finish"=>{"x"=>89, "y"=>102}, "TYPE"=>"Shape: graph/line", "start"=>{"x"=>73, "y"=>129}}, {"TYPE"=>"Shape: graph/text", "value"=>"Pretty vector drawing.", "start"=>{"x"=>73, "y"=>129}, "color"=>16772795}, "Shape Container"]], <<EOY
792
- !clarkevans.com,2002/graph/^shape
794
center: &ORIGIN {x: 73, y: 129}
796
- !^line # !clarkevans.com,2002/graph/line
798
finish: { x: 89, y: 102 }
802
value: Pretty vector drawing.
807
def test_spec_float_explicit
809
[ 10.0, 10.0, 10.0, 10.0 ], <<EOY
810
# All entries in the sequence
811
# have the same type and value.
814
- !yaml.org,2002/^float '10'
815
- !yaml.org,2002/float "\\
822
def test_spec_builtin_seq
823
# Assortment of sequences
825
{ 'empty' => [], 'in-line' => [ 'one', 'two', 'three', 'four', 'five' ],
826
'nested' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ],
827
"A multi-line sequence entry\n", 'Sixth item in top sequence' ] }, <<EOY
829
in-line: [ one, two, three # May span lines,
830
, four, # indentation is
831
five ] # mostly ignored.
833
- First item in top sequence
835
- Subordinate sequence entry
839
- Sixth item in top sequence
844
def test_spec_builtin_map
845
# Assortment of mappings
847
{ 'empty' => {}, 'in-line' => { 'one' => 1, 'two' => 2 },
848
'spanning' => { 'one' => 1, 'two' => 2 },
849
'nested' => { 'first' => 'First entry', 'second' =>
850
{ 'key' => 'Subordinate mapping' }, 'third' =>
851
[ 'Subordinate sequence', {}, 'Previous mapping is empty.',
852
{ 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' },
853
'The previous entry is equal to the following one.',
854
{ 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ],
855
12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.',
856
"\a" => 'This key had to be escaped.',
857
"This is a multi-line folded key\n" => "Whose value is also multi-line.\n",
858
[ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }, <<EOY
861
in-line: { one: 1, two: 2 }
867
key: Subordinate mapping
869
- Subordinate sequence
871
- Previous mapping is empty.
872
- A key: value pair in a sequence.
873
A second: key:value pair.
874
- The previous entry is equal to the following one.
876
A key: value pair in a sequence.
877
A second: key:value pair.
878
!float 12 : This key is a float.
881
: This key had to be protected.
882
"\\a" : This key had to be escaped.
894
- With a sequence value.
895
# The following parses correctly,
896
# but Ruby 1.6.* fails the comparison!
901
# with a: mapping value.
906
def test_spec_builtin_literal_blocks
907
# Assortment of literal scalar blocks
909
{"both are equal to"=>" This has no newline.", "is equal to"=>"The \\ ' \" characters may be\nfreely used. Leading white\n space is significant.\n\nLine breaks are significant.\nThus this value contains one\nempty line and ends with a\nsingle line break, but does\nnot start with one.\n", "also written as"=>" This has no newline.", "indented and chomped"=>" This has no newline.", "empty"=>"", "literal"=>"The \\ ' \" characters may be\nfreely used. Leading white\n space is significant.\n\nLine breaks are significant.\nThus this value contains one\nempty line and ends with a\nsingle line break, but does\nnot start with one.\n"}, <<EOY
913
The \\ ' " characters may be
914
freely used. Leading white
915
space is significant.
917
Line breaks are significant.
918
Thus this value contains one
919
empty line and ends with a
920
single line break, but does
923
is equal to: "The \\ ' \\" characters may \\
924
be\\nfreely used. Leading white\\n space \\
925
is significant.\\n\\nLine breaks are \\
926
significant.\\nThus this value contains \\
927
one\\nempty line and ends with a\\nsingle \\
928
line break, but does\\nnot start with one.\\n"
930
# Comments may follow a nested
931
# scalar value. They must be
934
# Modifiers may be combined in any order.
935
indented and chomped: |2-
941
both are equal to: " This has no newline."
945
str1 = "This has one newline.\n"
946
str2 = "This has no newline."
947
str3 = "This has two newlines.\n\n"
949
{ 'clipped' => str1, 'same as "clipped" above' => str1,
950
'stripped' => str2, 'same as "stripped" above' => str2,
951
'kept' => str3, 'same as "kept" above' => str3 }, <<EOY
953
This has one newline.
955
same as "clipped" above: "This has one newline.\\n"
960
same as "stripped" above: "This has no newline."
963
This has two newlines.
965
same as "kept" above: "This has two newlines.\\n\\n"
971
def test_spec_span_single_quote
972
assert_parse_only( {"third"=>"a single quote ' must be escaped.", "second"=>"! : \\ etc. can be used freely.", "is same as"=>"this contains six spaces\nand one line break", "empty"=>"", "span"=>"this contains six spaces\nand one line break"}, <<EOY
974
second: '! : \\ etc. can be used freely.'
975
third: 'a single quote '' must be escaped.'
981
is same as: "this contains six spaces\\nand one line break"
986
def test_spec_span_double_quote
987
assert_parse_only( {"is equal to"=>"this contains four spaces", "third"=>"a \" or a \\ must be escaped.", "second"=>"! : etc. can be used freely.", "empty"=>"", "fourth"=>"this value ends with an LF.\n", "span"=>"this contains four spaces"}, <<EOY
989
second: "! : etc. can be used freely."
990
third: "a \\\" or a \\\\ must be escaped."
991
fourth: "this value ends with an LF.\\n"
995
is equal to: "this contains four spaces"
1000
def test_spec_builtin_time
1003
{ "space separated" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ),
1004
"canonical" => mktime( 2001, 12, 15, 2, 59, 43, ".10" ),
1005
"date (noon UTC)" => Date.new( 2002, 12, 14),
1006
"valid iso8601" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ) }, <<EOY
1007
canonical: 2001-12-15T02:59:43.1Z
1008
valid iso8601: 2001-12-14t21:59:43.10-05:00
1009
space separated: 2001-12-14 21:59:43.10 -05:00
1010
date (noon UTC): 2002-12-14
1015
def test_spec_builtin_binary
1016
arrow_gif = "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236iiiccc\243\243\243\204\204\204\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371!\376\016Made with GIMP\000,\000\000\000\000\f\000\f\000\000\005, \216\2010\236\343@\024\350i\020\304\321\212\010\034\317\200M$z\357\3770\205p\270\2601f\r\e\316\001\303\001\036\020' \202\n\001\000;"
1018
{ 'canonical' => arrow_gif, 'base64' => arrow_gif,
1019
'description' => "The binary value above is a tiny arrow encoded as a gif image.\n" }, <<EOY
1020
canonical: !binary "\\
1021
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf\\
1022
n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW\\
1023
NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++\\
1024
f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg\\
1025
d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN\\
1026
AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww\\
1029
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf
1030
n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW
1031
NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++
1032
f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg
1033
d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN
1034
AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww
1037
The binary value above is a tiny arrow
1038
encoded as a gif image.
1042
def test_ruby_regexp
1043
# Test Ruby regular expressions
1045
{ 'simple' => /a.b/, 'complex' => %r'\A"((?:[^"]|\")+)"',
1046
'case-insensitive' => /George McFly/i }, <<EOY
1047
case-insensitive: !ruby/regexp "/George McFly/i"
1048
complex: !ruby/regexp "/\\\\A\\"((?:[^\\"]|\\\\\\")+)\\"/"
1049
simple: !ruby/regexp "/a.b/"
1060
assert_to_yaml( 1..3, <<EOY )
1061
--- !ruby/range 1..3
1065
assert_to_yaml( 'a'..'z', <<EOY )
1066
--- !ruby/range a..z
1070
assert_to_yaml( 10.5...30.3, <<EOY )
1071
--- !ruby/range 10.5...30.3
1076
def test_ruby_struct
1078
book_struct = Struct::new( "BookStruct", :author, :title, :year, :isbn )
1080
[ book_struct.new( "Yukihiro Matsumoto", "Ruby in a Nutshell", 2002, "0-596-00214-9" ),
1081
book_struct.new( [ 'Dave Thomas', 'Andy Hunt' ], "The Pickaxe", 2002,
1082
book_struct.new( "This should be the ISBN", "but I have another struct here", 2002, "None" )
1084
- !ruby/struct:BookStruct
1085
:author: Yukihiro Matsumoto
1086
:title: Ruby in a Nutshell
1088
:isbn: 0-596-00214-9
1089
- !ruby/struct:BookStruct
1095
:isbn: !ruby/struct:BookStruct
1096
:author: This should be the ISBN
1097
:title: but I have another struct here
1103
assert_to_yaml( YAML_Tests::StructTest.new( 123 ), <<EOY )
1104
--- !ruby/struct:YAML_Tests::StructTest
1110
def test_ruby_rational
1111
assert_to_yaml( Rational(1, 2), <<EOY )
1112
--- !ruby/object:Rational
1117
# Read YAML dumped by the ruby 1.8.3.
1118
assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
1119
assert_raise( ArgumentError ) { YAML.load("!ruby/object:Rational INVALID/RATIONAL\n") }
1122
def test_ruby_complex
1123
assert_to_yaml( Complex(3, 4), <<EOY )
1124
--- !ruby/object:Complex
1129
# Read YAML dumped by the ruby 1.8.3.
1130
assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
1131
assert_raise( ArgumentError ) { YAML.load("!ruby/object:Complex INVALID+COMPLEXi\n") }
1134
def test_emitting_indicators
1135
assert_to_yaml( "Hi, from Object 1. You passed: please, pretty please", <<EOY
1136
--- "Hi, from Object 1. You passed: please, pretty please"
1142
# Test the YAML::Stream class -- INACTIVE at the moment
1145
y = YAML::Stream.new( :Indent => 2, :UseVersion => 0 )
1147
{ 'hi' => 'hello', 'map' =>
1148
{ 'good' => 'two' },
1150
'try' => /^po(.*)$/,
1154
y.add( { 'po' => 'nil', 'oper' => 90 } )
1155
y.add( { 'hi' => 'wow!', 'bye' => 'wow!' } )
1156
y.add( { [ 'Red Socks', 'Boston' ] => [ 'One', 'Two', 'Three' ] } )
1157
y.add( [ true, false, false ] )
1161
# Test YPath choices parsing
1163
def test_ypath_parsing
1164
assert_path_segments( "/*/((one|three)/name|place)|//place",
1165
[ ["*", "one", "name"],
1166
["*", "three", "name"],
1173
# Tests from Tanaka Akira on [ruby-core]
1177
# Commas in plain scalars [ruby-core:1066]
1179
{"A"=>"A,","B"=>"B"}, <<EOY
1185
# Double-quoted keys [ruby-core:1069]
1187
{"1"=>2, "2"=>3}, <<EOY
1193
# Anchored mapping [ruby-core:1071]
1195
[{"a"=>"b"}] * 2, <<EOY
1202
# Stress test [ruby-core:1071]
1203
# a = []; 1000.times { a << {"a"=>"b", "c"=>"d"} }
1204
# YAML::load( a.to_yaml )
1209
# Test Time.now cycle
1211
def test_time_now_cycle
1213
# From Minero Aoki [ruby-core:2305]
1217
t = Time.at(t.tv_sec, t.tv_usec)
1226
def test_range_cycle
1228
# From Minero Aoki [ruby-core:02306]
1230
assert_cycle("a".."z")
1233
# From Nobu Nakada [ruby-core:02311]
1236
assert_cycle(1.0e20 .. 2.0e20)
1237
assert_cycle("0".."1")
1238
assert_cycle(".."..."...")
1239
assert_cycle(".rb"..".pl")
1240
assert_cycle(".rb"...".pl")
1241
assert_cycle('"'...".")
1242
assert_cycle("'"...".")
1246
# Circular references
1248
def test_circular_references
1249
a = []; a[0] = a; a[1] = a
1250
inspect_str = "[[...], [...]]"
1251
assert_equal( inspect_str, YAML::load( a.to_yaml ).inspect )
1257
def test_symbol_cycle
1259
# From Aaron Schrab [ruby-Bugs:2535]
1261
assert_cycle(:"^foo")
1265
# Test Numeric cycle
1267
class NumericTest < Numeric
1268
def initialize(value)
1272
@value == other.instance_eval{ @value }
1275
def test_numeric_cycle
1276
assert_cycle(1) # Fixnum
1277
assert_cycle(111111111111111111111111111111111) # Bignum
1278
assert_cycle(NumericTest.new(3)) # Subclass of Numeric
1282
# Test empty map/seq in map cycle
1284
def test_empty_map_key
1288
o = YAML.load({[]=>""}.to_yaml)
1289
assert_equal(Hash, o.class)
1290
assert_equal([[]], o.keys)
1295
o = YAML.load({{}=>""}.to_yaml)
1296
assert_equal(Hash, o.class)
1297
assert_equal([{}], o.keys)
1301
# contributed by riley lynch [ruby-Bugs-8548]
1303
def test_object_id_collision
1304
omap = YAML::Omap.new
1305
1000.times { |i| omap["key_#{i}"] = { "value" => i } }
1306
raise "id collision in ordered map" if omap.to_yaml =~ /id\d+/
1309
def test_date_out_of_range
1310
assert_nothing_raised{YAML::load('1900-01-01T00:00:00+00:00')}
1313
def test_normal_exit
1314
YAML.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
1315
# '[ruby-core:13735]'
1320
suite = Test::Unit::TestSuite.new('YAML')
1321
ObjectSpace.each_object(Class) do |klass|
1322
suite << klass.suite if (Test::Unit::TestCase > klass)
1324
require 'test/unit/ui/console/testrunner'
1325
Test::Unit::UI::Console::TestRunner.run(suite).passed?