km-psych 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/README.rdoc +129 -0
  2. data/ext/psych/emitter.c +488 -0
  3. data/ext/psych/emitter.h +8 -0
  4. data/ext/psych/extconf.rb +22 -0
  5. data/ext/psych/parser.c +349 -0
  6. data/ext/psych/parser.h +6 -0
  7. data/ext/psych/psych.c +34 -0
  8. data/ext/psych/psych.h +20 -0
  9. data/ext/psych/to_ruby.c +41 -0
  10. data/ext/psych/to_ruby.h +8 -0
  11. data/ext/psych/yaml_tree.c +24 -0
  12. data/ext/psych/yaml_tree.h +8 -0
  13. data/lib/km-psych.rb +244 -0
  14. data/lib/psych/coder.rb +86 -0
  15. data/lib/psych/core_ext.rb +38 -0
  16. data/lib/psych/deprecated.rb +82 -0
  17. data/lib/psych/handler.rb +221 -0
  18. data/lib/psych/json.rb +6 -0
  19. data/lib/psych/json/stream.rb +32 -0
  20. data/lib/psych/json/tree_builder.rb +32 -0
  21. data/lib/psych/nodes.rb +77 -0
  22. data/lib/psych/nodes/alias.rb +18 -0
  23. data/lib/psych/nodes/document.rb +60 -0
  24. data/lib/psych/nodes/mapping.rb +56 -0
  25. data/lib/psych/nodes/node.rb +42 -0
  26. data/lib/psych/nodes/scalar.rb +67 -0
  27. data/lib/psych/nodes/sequence.rb +81 -0
  28. data/lib/psych/nodes/stream.rb +37 -0
  29. data/lib/psych/omap.rb +4 -0
  30. data/lib/psych/parser.rb +44 -0
  31. data/lib/psych/scalar_scanner.rb +105 -0
  32. data/lib/psych/set.rb +4 -0
  33. data/lib/psych/stream.rb +53 -0
  34. data/lib/psych/tree_builder.rb +94 -0
  35. data/lib/psych/visitors.rb +5 -0
  36. data/lib/psych/visitors/emitter.rb +41 -0
  37. data/lib/psych/visitors/json_tree.rb +14 -0
  38. data/lib/psych/visitors/to_ruby.rb +263 -0
  39. data/lib/psych/visitors/visitor.rb +27 -0
  40. data/lib/psych/visitors/yaml_tree.rb +342 -0
  41. data/test/psych/helper.rb +63 -0
  42. data/test/psych/json/test_stream.rb +75 -0
  43. data/test/psych/test_alias_and_anchor.rb +26 -0
  44. data/test/psych/test_array.rb +19 -0
  45. data/test/psych/test_boolean.rb +36 -0
  46. data/test/psych/test_class.rb +17 -0
  47. data/test/psych/test_coder.rb +169 -0
  48. data/test/psych/test_date_time.rb +17 -0
  49. data/test/psych/test_deprecated.rb +210 -0
  50. data/test/psych/test_document.rb +46 -0
  51. data/test/psych/test_emitter.rb +88 -0
  52. data/test/psych/test_encoding.rb +179 -0
  53. data/test/psych/test_engine_manager.rb +57 -0
  54. data/test/psych/test_exception.rb +39 -0
  55. data/test/psych/test_hash.rb +30 -0
  56. data/test/psych/test_json_tree.rb +43 -0
  57. data/test/psych/test_null.rb +19 -0
  58. data/test/psych/test_object.rb +27 -0
  59. data/test/psych/test_omap.rb +68 -0
  60. data/test/psych/test_parser.rb +216 -0
  61. data/test/psych/test_psych.rb +133 -0
  62. data/test/psych/test_scalar.rb +11 -0
  63. data/test/psych/test_scalar_scanner.rb +70 -0
  64. data/test/psych/test_serialize_subclasses.rb +38 -0
  65. data/test/psych/test_set.rb +49 -0
  66. data/test/psych/test_stream.rb +49 -0
  67. data/test/psych/test_string.rb +49 -0
  68. data/test/psych/test_struct.rb +51 -0
  69. data/test/psych/test_symbol.rb +17 -0
  70. data/test/psych/test_to_yaml_properties.rb +63 -0
  71. data/test/psych/test_tree_builder.rb +79 -0
  72. data/test/psych/test_yaml.rb +1251 -0
  73. data/test/psych/visitors/test_emitter.rb +124 -0
  74. data/test/psych/visitors/test_to_ruby.rb +325 -0
  75. data/test/psych/visitors/test_yaml_tree.rb +149 -0
  76. metadata +187 -0
@@ -0,0 +1,1251 @@
1
+ # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*-
2
+ # vim:sw=4:ts=4
3
+ # $Id$
4
+ #
5
+ require_relative 'helper'
6
+
7
+ # [ruby-core:01946]
8
+ module Psych_Tests
9
+ StructTest = Struct::new( :c )
10
+ end
11
+
12
+ class Psych_Unit_Tests < Psych::TestCase
13
+ def teardown
14
+ Psych.domain_types.clear
15
+ end
16
+ #
17
+ # Tests modified from 00basic.t in Psych.pm
18
+ #
19
+ def test_basic_map
20
+ # Simple map
21
+ assert_parse_only(
22
+ { 'one' => 'foo', 'three' => 'baz', 'two' => 'bar' }, <<EOY
23
+ one: foo
24
+ two: bar
25
+ three: baz
26
+ EOY
27
+ )
28
+ end
29
+
30
+ def test_basic_strings
31
+ # Common string types
32
+ assert_cycle("x")
33
+ assert_cycle(":x")
34
+ assert_cycle(":")
35
+ assert_parse_only(
36
+ { 1 => 'simple string', 2 => 42, 3 => '1 Single Quoted String',
37
+ 4 => 'Psych\'s Double "Quoted" String', 5 => "A block\n with several\n lines.\n",
38
+ 6 => "A \"chomped\" block", 7 => "A folded\n string\n", 8 => ": started string" },
39
+ <<EOY
40
+ 1: simple string
41
+ 2: 42
42
+ 3: '1 Single Quoted String'
43
+ 4: "Psych's Double \\\"Quoted\\\" String"
44
+ 5: |
45
+ A block
46
+ with several
47
+ lines.
48
+ 6: |-
49
+ A "chomped" block
50
+ 7: >
51
+ A
52
+ folded
53
+ string
54
+ 8: ": started string"
55
+ EOY
56
+ )
57
+ end
58
+
59
+ #
60
+ # Test the specification examples
61
+ # - Many examples have been changes because of whitespace problems that
62
+ # caused the two to be inequivalent, or keys to be sorted wrong
63
+ #
64
+
65
+ def test_spec_simple_implicit_sequence
66
+ # Simple implicit sequence
67
+ assert_to_yaml(
68
+ [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ], <<EOY
69
+ - Mark McGwire
70
+ - Sammy Sosa
71
+ - Ken Griffey
72
+ EOY
73
+ )
74
+ end
75
+
76
+ def test_spec_simple_implicit_map
77
+ # Simple implicit map
78
+ assert_to_yaml(
79
+ { 'hr' => 65, 'avg' => 0.278, 'rbi' => 147 }, <<EOY
80
+ avg: 0.278
81
+ hr: 65
82
+ rbi: 147
83
+ EOY
84
+ )
85
+ end
86
+
87
+ def test_spec_simple_map_with_nested_sequences
88
+ # Simple mapping with nested sequences
89
+ assert_to_yaml(
90
+ { 'american' =>
91
+ [ 'Boston Red Sox', 'Detroit Tigers', 'New York Yankees' ],
92
+ 'national' =>
93
+ [ 'New York Mets', 'Chicago Cubs', 'Atlanta Braves' ] }, <<EOY
94
+ american:
95
+ - Boston Red Sox
96
+ - Detroit Tigers
97
+ - New York Yankees
98
+ national:
99
+ - New York Mets
100
+ - Chicago Cubs
101
+ - Atlanta Braves
102
+ EOY
103
+ )
104
+ end
105
+
106
+ def test_spec_simple_sequence_with_nested_map
107
+ # Simple sequence with nested map
108
+ assert_to_yaml(
109
+ [
110
+ {'name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278},
111
+ {'name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288}
112
+ ], <<EOY
113
+ -
114
+ avg: 0.278
115
+ hr: 65
116
+ name: Mark McGwire
117
+ -
118
+ avg: 0.288
119
+ hr: 63
120
+ name: Sammy Sosa
121
+ EOY
122
+ )
123
+ end
124
+
125
+ def test_spec_sequence_of_sequences
126
+ # Simple sequence with inline sequences
127
+ assert_parse_only(
128
+ [
129
+ [ 'name', 'hr', 'avg' ],
130
+ [ 'Mark McGwire', 65, 0.278 ],
131
+ [ 'Sammy Sosa', 63, 0.288 ]
132
+ ], <<EOY
133
+ - [ name , hr , avg ]
134
+ - [ Mark McGwire , 65 , 0.278 ]
135
+ - [ Sammy Sosa , 63 , 0.288 ]
136
+ EOY
137
+ )
138
+ end
139
+
140
+ def test_spec_mapping_of_mappings
141
+ # Simple map with inline maps
142
+ assert_parse_only(
143
+ { 'Mark McGwire' =>
144
+ { 'hr' => 65, 'avg' => 0.278 },
145
+ 'Sammy Sosa' =>
146
+ { 'hr' => 63, 'avg' => 0.288 }
147
+ }, <<EOY
148
+ Mark McGwire: {hr: 65, avg: 0.278}
149
+ Sammy Sosa: {hr: 63,
150
+ avg: 0.288}
151
+ EOY
152
+ )
153
+ end
154
+
155
+ def test_ambiguous_comments
156
+ # [ruby-talk:88012]
157
+ assert_to_yaml( "Call the method #dave", <<EOY )
158
+ --- "Call the method #dave"
159
+ EOY
160
+ end
161
+
162
+ def test_spec_nested_comments
163
+ # Map and sequences with comments
164
+ assert_parse_only(
165
+ { 'hr' => [ 'Mark McGwire', 'Sammy Sosa' ],
166
+ 'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
167
+ hr: # 1998 hr ranking
168
+ - Mark McGwire
169
+ - Sammy Sosa
170
+ rbi:
171
+ # 1998 rbi ranking
172
+ - Sammy Sosa
173
+ - Ken Griffey
174
+ EOY
175
+ )
176
+ end
177
+
178
+ def test_spec_anchors_and_aliases
179
+ # Anchors and aliases
180
+ assert_parse_only(
181
+ { 'hr' =>
182
+ [ 'Mark McGwire', 'Sammy Sosa' ],
183
+ 'rbi' =>
184
+ [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
185
+ hr:
186
+ - Mark McGwire
187
+ # Name "Sammy Sosa" scalar SS
188
+ - &SS Sammy Sosa
189
+ rbi:
190
+ # So it can be referenced later.
191
+ - *SS
192
+ - Ken Griffey
193
+ EOY
194
+ )
195
+
196
+ assert_to_yaml(
197
+ [{"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
198
+ -
199
+ &F fareref: DOGMA
200
+ &C currency: GBP
201
+ &D departure: LAX
202
+ &A arrival: EDI
203
+ - { *F: MADF, *C: AUD, *D: SYD, *A: MEL }
204
+ - { *F: DFSF, *C: USD, *D: JFK, *A: MCO }
205
+ EOY
206
+ )
207
+
208
+ assert_to_yaml(
209
+ {"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
210
+ ---
211
+ ALIASES: [&f fareref, &c currency, &d departure, &a arrival]
212
+ FARES:
213
+ - *f: DOGMA
214
+ *c: GBP
215
+ *d: LAX
216
+ *a: EDI
217
+
218
+ - *f: MADF
219
+ *c: AUD
220
+ *d: SYD
221
+ *a: MEL
222
+
223
+ - *f: DFSF
224
+ *c: USD
225
+ *d: JFK
226
+ *a: MCO
227
+
228
+ EOY
229
+ )
230
+
231
+ end
232
+
233
+ def test_spec_mapping_between_sequences
234
+ # Complex key #1
235
+ dj = Date.new( 2001, 7, 23 )
236
+ assert_parse_only(
237
+ { [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
238
+ [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ] }, <<EOY
239
+ ? # PLAY SCHEDULE
240
+ - Detroit Tigers
241
+ - Chicago Cubs
242
+ :
243
+ - 2001-07-23
244
+
245
+ ? [ New York Yankees,
246
+ Atlanta Braves ]
247
+ : [ 2001-07-02, 2001-08-12,
248
+ 2001-08-14 ]
249
+ EOY
250
+ )
251
+
252
+ # Complex key #2
253
+ assert_parse_only(
254
+ { [ 'New York Yankees', 'Atlanta Braves' ] =>
255
+ [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ),
256
+ Date.new( 2001, 8, 14 ) ],
257
+ [ 'Detroit Tigers', 'Chicago Cubs' ] =>
258
+ [ Date.new( 2001, 7, 23 ) ]
259
+ }, <<EOY
260
+ ?
261
+ - New York Yankees
262
+ - Atlanta Braves
263
+ :
264
+ - 2001-07-02
265
+ - 2001-08-12
266
+ - 2001-08-14
267
+ ?
268
+ - Detroit Tigers
269
+ - Chicago Cubs
270
+ :
271
+ - 2001-07-23
272
+ EOY
273
+ )
274
+ end
275
+
276
+ def test_spec_sequence_key_shortcut
277
+ # Shortcut sequence map
278
+ assert_parse_only(
279
+ { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
280
+ 'bill-to' => 'Chris Dumars', 'product' =>
281
+ [ { 'item' => 'Super Hoop', 'quantity' => 1 },
282
+ { 'item' => 'Basketball', 'quantity' => 4 },
283
+ { 'item' => 'Big Shoes', 'quantity' => 1 } ] }, <<EOY
284
+ invoice: 34843
285
+ date : 2001-01-23
286
+ bill-to: Chris Dumars
287
+ product:
288
+ - item : Super Hoop
289
+ quantity: 1
290
+ - item : Basketball
291
+ quantity: 4
292
+ - item : Big Shoes
293
+ quantity: 1
294
+ EOY
295
+ )
296
+ end
297
+
298
+ def test_spec_sequence_in_sequence_shortcut
299
+ # Seq-in-seq
300
+ assert_parse_only( [ [ [ 'one', 'two', 'three' ] ] ], <<EOY )
301
+ - - - one
302
+ - two
303
+ - three
304
+ EOY
305
+ end
306
+
307
+ def test_spec_sequence_shortcuts
308
+ # Sequence shortcuts combined
309
+ assert_parse_only(
310
+ [
311
+ [
312
+ [ [ 'one' ] ],
313
+ [ 'two', 'three' ],
314
+ { 'four' => nil },
315
+ [ { 'five' => [ 'six' ] } ],
316
+ [ 'seven' ]
317
+ ],
318
+ [ 'eight', 'nine' ]
319
+ ], <<EOY )
320
+ - - - - one
321
+ - - two
322
+ - three
323
+ - four:
324
+ - - five:
325
+ - six
326
+ - - seven
327
+ - - eight
328
+ - nine
329
+ EOY
330
+ end
331
+
332
+ def test_spec_single_literal
333
+ # Literal scalar block
334
+ assert_parse_only( [ "\\/|\\/|\n/ | |_\n" ], <<EOY )
335
+ - |
336
+ \\/|\\/|
337
+ / | |_
338
+ EOY
339
+ end
340
+
341
+ def test_spec_single_folded
342
+ # Folded scalar block
343
+ assert_parse_only(
344
+ [ "Mark McGwire's year was crippled by a knee injury.\n" ], <<EOY
345
+ - >
346
+ Mark McGwire\'s
347
+ year was crippled
348
+ by a knee injury.
349
+ EOY
350
+ )
351
+ end
352
+
353
+ def test_spec_preserve_indent
354
+ # Preserve indented spaces
355
+ assert_parse_only(
356
+ "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
357
+ --- >
358
+ Sammy Sosa completed another
359
+ fine season with great stats.
360
+
361
+ 63 Home Runs
362
+ 0.288 Batting Average
363
+
364
+ What a year!
365
+ EOY
366
+ )
367
+ end
368
+
369
+ def test_spec_indentation_determines_scope
370
+ assert_parse_only(
371
+ { 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n",
372
+ 'stats' => "65 Home Runs\n0.278 Batting Average\n" }, <<EOY
373
+ name: Mark McGwire
374
+ accomplishment: >
375
+ Mark set a major league
376
+ home run record in 1998.
377
+ stats: |
378
+ 65 Home Runs
379
+ 0.278 Batting Average
380
+ EOY
381
+ )
382
+ end
383
+
384
+ def test_spec_multiline_scalars
385
+ # Multiline flow scalars
386
+ assert_parse_only(
387
+ { 'plain' => 'This unquoted scalar spans many lines.',
388
+ 'quoted' => "So does this quoted scalar.\n" }, <<EOY
389
+ plain: This unquoted
390
+ scalar spans
391
+ many lines.
392
+ quoted: "\\
393
+ So does this quoted
394
+ scalar.\\n"
395
+ EOY
396
+ )
397
+ end
398
+
399
+ def test_spec_type_int
400
+ assert_parse_only(
401
+ { 'canonical' => 12345, 'decimal' => 12345, 'octal' => '014'.oct, 'hexadecimal' => '0xC'.hex }, <<EOY
402
+ canonical: 12345
403
+ decimal: +12,345
404
+ octal: 014
405
+ hexadecimal: 0xC
406
+ EOY
407
+ )
408
+ assert_parse_only(
409
+ { 'canonical' => 685230, 'decimal' => 685230, 'octal' => 02472256, 'hexadecimal' => 0x0A74AE, 'sexagesimal' => 685230 }, <<EOY)
410
+ canonical: 685230
411
+ decimal: +685,230
412
+ octal: 02472256
413
+ hexadecimal: 0x0A,74,AE
414
+ sexagesimal: 190:20:30
415
+ EOY
416
+ end
417
+
418
+ def test_spec_type_float
419
+ assert_parse_only(
420
+ { 'canonical' => 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15,
421
+ 'negative infinity' => -1.0/0.0 }, <<EOY)
422
+ canonical: 1.23015e+3
423
+ exponential: 12.3015e+02
424
+ fixed: 1,230.15
425
+ negative infinity: -.inf
426
+ EOY
427
+ nan = Psych::load( <<EOY )
428
+ not a number: .NaN
429
+ EOY
430
+ assert( nan['not a number'].nan? )
431
+ end
432
+
433
+ def test_spec_type_misc
434
+ assert_parse_only(
435
+ { nil => nil, true => true, false => false, 'string' => '12345' }, <<EOY
436
+ null: ~
437
+ true: yes
438
+ false: no
439
+ string: '12345'
440
+ EOY
441
+ )
442
+ end
443
+
444
+ def test_spec_complex_invoice
445
+ # Complex invoice type
446
+ id001 = { 'given' => 'Chris', 'family' => 'Dumars', 'address' =>
447
+ { 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak',
448
+ 'state' => 'MI', 'postal' => 48046 } }
449
+ assert_parse_only(
450
+ { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
451
+ 'bill-to' => id001, 'ship-to' => id001, 'product' =>
452
+ [ { 'sku' => 'BL394D', 'quantity' => 4,
453
+ 'description' => 'Basketball', 'price' => 450.00 },
454
+ { 'sku' => 'BL4438H', 'quantity' => 1,
455
+ 'description' => 'Super Hoop', 'price' => 2392.00 } ],
456
+ 'tax' => 251.42, 'total' => 4443.52,
457
+ 'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" }, <<EOY
458
+ invoice: 34843
459
+ date : 2001-01-23
460
+ bill-to: &id001
461
+ given : Chris
462
+ family : !str Dumars
463
+ address:
464
+ lines: |
465
+ 458 Walkman Dr.
466
+ Suite #292
467
+ city : Royal Oak
468
+ state : MI
469
+ postal : 48046
470
+ ship-to: *id001
471
+ product:
472
+ - !map
473
+ sku : BL394D
474
+ quantity : 4
475
+ description : Basketball
476
+ price : 450.00
477
+ - sku : BL4438H
478
+ quantity : 1
479
+ description : Super Hoop
480
+ price : 2392.00
481
+ tax : 251.42
482
+ total: 4443.52
483
+ comments: >
484
+ Late afternoon is best.
485
+ Backup contact is Nancy
486
+ Billsmer @ 338-4338.
487
+ EOY
488
+ )
489
+ end
490
+
491
+ def test_spec_log_file
492
+ doc_ct = 0
493
+ Psych::load_documents( <<EOY
494
+ ---
495
+ Time: 2001-11-23 15:01:42 -05:00
496
+ User: ed
497
+ Warning: >
498
+ This is an error message
499
+ for the log file
500
+ ---
501
+ Time: 2001-11-23 15:02:31 -05:00
502
+ User: ed
503
+ Warning: >
504
+ A slightly different error
505
+ message.
506
+ ---
507
+ Date: 2001-11-23 15:03:17 -05:00
508
+ User: ed
509
+ Fatal: >
510
+ Unknown variable "bar"
511
+ Stack:
512
+ - file: TopClass.py
513
+ line: 23
514
+ code: |
515
+ x = MoreObject("345\\n")
516
+ - file: MoreClass.py
517
+ line: 58
518
+ code: |-
519
+ foo = bar
520
+ EOY
521
+ ) { |doc|
522
+ case doc_ct
523
+ when 0
524
+ assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ),
525
+ 'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } )
526
+ when 1
527
+ assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ),
528
+ 'User' => 'ed', 'Warning' => "A slightly different error message.\n" } )
529
+ when 2
530
+ assert_equal( doc, { 'Date' => mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ),
531
+ 'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n",
532
+ 'Stack' => [
533
+ { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" },
534
+ { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } )
535
+ end
536
+ doc_ct += 1
537
+ }
538
+ assert_equal( doc_ct, 3 )
539
+ end
540
+
541
+ def test_spec_root_fold
542
+ y = Psych::load( <<EOY
543
+ ---
544
+ This Psych stream contains a single text value.
545
+ The next stream is a log file - a sequence of
546
+ log entries. Adding an entry to the log is a
547
+ simple matter of appending it at the end.
548
+ EOY
549
+ )
550
+ assert_equal( y, "This Psych 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." )
551
+ end
552
+
553
+ def test_spec_root_mapping
554
+ y = Psych::load( <<EOY
555
+ # This stream is an example of a top-level mapping.
556
+ invoice : 34843
557
+ date : 2001-01-23
558
+ total : 4443.52
559
+ EOY
560
+ )
561
+ assert_equal( y, { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), 'total' => 4443.52 } )
562
+ end
563
+
564
+ def test_spec_oneline_docs
565
+ doc_ct = 0
566
+ Psych::load_documents( <<EOY
567
+ # The following is a sequence of three documents.
568
+ # The first contains an empty mapping, the second
569
+ # an empty sequence, and the last an empty string.
570
+ --- {}
571
+ --- [ ]
572
+ --- ''
573
+ EOY
574
+ ) { |doc|
575
+ case doc_ct
576
+ when 0
577
+ assert_equal( doc, {} )
578
+ when 1
579
+ assert_equal( doc, [] )
580
+ when 2
581
+ assert_equal( doc, '' )
582
+ end
583
+ doc_ct += 1
584
+ }
585
+ assert_equal( doc_ct, 3 )
586
+ end
587
+
588
+ def test_spec_domain_prefix
589
+ customer_proc = proc { |type, val|
590
+ if Hash === val
591
+ scheme, domain, type = type.split( ':', 3 )
592
+ val['type'] = "domain #{type}"
593
+ val
594
+ else
595
+ raise ArgumentError, "Not a Hash in domain.tld,2002/invoice: " + val.inspect
596
+ end
597
+ }
598
+ Psych.add_domain_type( "domain.tld,2002", 'invoice', &customer_proc )
599
+ Psych.add_domain_type( "domain.tld,2002", 'customer', &customer_proc )
600
+ assert_parse_only( { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }, <<EOY
601
+ # 'http://domain.tld,2002/invoice' is some type family.
602
+ invoice: !domain.tld,2002/invoice
603
+ # 'seq' is shorthand for 'http://yaml.org/seq'.
604
+ # This does not effect '^customer' below
605
+ # because it is does not specify a prefix.
606
+ customers: !seq
607
+ # '^customer' is shorthand for the full
608
+ # notation 'http://domain.tld,2002/customer'.
609
+ - !customer
610
+ given : Chris
611
+ family : Dumars
612
+ EOY
613
+ )
614
+ end
615
+
616
+ def test_spec_throwaway
617
+ assert_parse_only(
618
+ {"this"=>"contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"}, <<EOY
619
+ ### These are four throwaway comment ###
620
+
621
+ ### lines (the second line is empty). ###
622
+ this: | # Comments may trail lines.
623
+ contains three lines of text.
624
+ The third one starts with a
625
+ # character. This isn't a comment.
626
+
627
+ # These are three throwaway comment
628
+ # lines (the first line is empty).
629
+ EOY
630
+ )
631
+ end
632
+
633
+ def test_spec_force_implicit
634
+ # Force implicit
635
+ assert_parse_only(
636
+ { 'integer' => 12, 'also int' => 12, 'string' => '12' }, <<EOY
637
+ integer: 12
638
+ also int: ! "12"
639
+ string: !str 12
640
+ EOY
641
+ )
642
+ end
643
+
644
+ ###
645
+ # Commenting out this test. This line:
646
+ #
647
+ # - !domain.tld,2002/type\\x30 value
648
+ #
649
+ # Is invalid according to the YAML spec:
650
+ #
651
+ # http://yaml.org/spec/1.1/#id896876
652
+ #
653
+ # def test_spec_url_escaping
654
+ # Psych.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
655
+ # "ONE: #{val}"
656
+ # }
657
+ # Psych.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
658
+ # "TWO: #{val}"
659
+ # }
660
+ # assert_parse_only(
661
+ # { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value' ] }, <<EOY
662
+ #same:
663
+ # - !domain.tld,2002/type\\x30 value
664
+ # - !domain.tld,2002/type0 value
665
+ #different: # As far as the Psych parser is concerned
666
+ # - !domain.tld,2002/type%30 value
667
+ #EOY
668
+ # )
669
+ # end
670
+
671
+ def test_spec_override_anchor
672
+ # Override anchor
673
+ a001 = "The alias node below is a repeated use of this value.\n"
674
+ assert_parse_only(
675
+ { 'anchor' => 'This scalar has an anchor.', 'override' => a001, 'alias' => a001 }, <<EOY
676
+ anchor : &A001 This scalar has an anchor.
677
+ override : &A001 >
678
+ The alias node below is a
679
+ repeated use of this value.
680
+ alias : *A001
681
+ EOY
682
+ )
683
+ end
684
+
685
+ def test_spec_explicit_families
686
+ Psych.add_domain_type( "somewhere.com,2002", 'type' ) { |type, val|
687
+ "SOMEWHERE: #{val}"
688
+ }
689
+ assert_parse_only(
690
+ { '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
691
+ not-date: !str 2002-04-28
692
+ picture: !binary |
693
+ R0lGODlhDAAMAIQAAP//9/X
694
+ 17unp5WZmZgAAAOfn515eXv
695
+ Pz7Y6OjuDg4J+fn5OTk6enp
696
+ 56enmleECcgggoBADs=
697
+
698
+ hmm: !somewhere.com,2002/type |
699
+ family above is short for
700
+ http://somewhere.com/type
701
+ EOY
702
+ )
703
+ end
704
+
705
+ def test_spec_application_family
706
+ # Testing the clarkevans.com graphs
707
+ Psych.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val|
708
+ if Array === val
709
+ val << "Shape Container"
710
+ val
711
+ else
712
+ raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
713
+ end
714
+ }
715
+ one_shape_proc = Proc.new { |type, val|
716
+ if Hash === val
717
+ type = type.split( /:/ )
718
+ val['TYPE'] = "Shape: #{type[2]}"
719
+ val
720
+ else
721
+ raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
722
+ end
723
+ }
724
+ Psych.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc )
725
+ Psych.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc )
726
+ Psych.add_domain_type( "clarkevans.com,2002", 'graph/text', &one_shape_proc )
727
+ # MODIFIED to remove invalid Psych
728
+ assert_parse_only(
729
+ [[{"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
730
+ - !clarkevans.com,2002/graph/shape
731
+ - !/graph/circle
732
+ center: &ORIGIN {x: 73, y: 129}
733
+ radius: 7
734
+ - !/graph/line # !clarkevans.com,2002/graph/line
735
+ start: *ORIGIN
736
+ finish: { x: 89, y: 102 }
737
+ - !/graph/text
738
+ start: *ORIGIN
739
+ color: 0xFFEEBB
740
+ value: Pretty vector drawing.
741
+ EOY
742
+ )
743
+ end
744
+
745
+ def test_spec_float_explicit
746
+ assert_parse_only(
747
+ [ 10.0, 10.0, 10.0, 10.0 ], <<EOY
748
+ # All entries in the sequence
749
+ # have the same type and value.
750
+ - 10.0
751
+ - !float 10
752
+ - !yaml.org,2002/float '10'
753
+ - !yaml.org,2002/float "\\
754
+ 1\\
755
+ 0"
756
+ EOY
757
+ )
758
+ end
759
+
760
+ def test_spec_builtin_seq
761
+ # Assortment of sequences
762
+ assert_parse_only(
763
+ { 'empty' => [], 'in-line' => [ 'one', 'two', 'three', 'four', 'five' ],
764
+ 'nested' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ],
765
+ "A multi-line sequence entry\n", 'Sixth item in top sequence' ] }, <<EOY
766
+ empty: []
767
+ in-line: [ one, two, three # May span lines,
768
+ , four, # indentation is
769
+ five ] # mostly ignored.
770
+ nested:
771
+ - First item in top sequence
772
+ -
773
+ - Subordinate sequence entry
774
+ - >
775
+ A multi-line
776
+ sequence entry
777
+ - Sixth item in top sequence
778
+ EOY
779
+ )
780
+ end
781
+
782
+ def test_spec_builtin_map
783
+ # Assortment of mappings
784
+ assert_parse_only(
785
+ { 'empty' => {}, 'in-line' => { 'one' => 1, 'two' => 2 },
786
+ 'spanning' => { 'one' => 1, 'two' => 2 },
787
+ 'nested' => { 'first' => 'First entry', 'second' =>
788
+ { 'key' => 'Subordinate mapping' }, 'third' =>
789
+ [ 'Subordinate sequence', {}, 'Previous mapping is empty.',
790
+ { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' },
791
+ 'The previous entry is equal to the following one.',
792
+ { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ],
793
+ 12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.',
794
+ "\a" => 'This key had to be escaped.',
795
+ "This is a multi-line folded key\n" => "Whose value is also multi-line.\n",
796
+ [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }, <<EOY
797
+
798
+ empty: {}
799
+ in-line: { one: 1, two: 2 }
800
+ spanning: { one: 1,
801
+ two: 2 }
802
+ nested:
803
+ first : First entry
804
+ second:
805
+ key: Subordinate mapping
806
+ third:
807
+ - Subordinate sequence
808
+ - { }
809
+ - Previous mapping is empty.
810
+ - A key: value pair in a sequence.
811
+ A second: key:value pair.
812
+ - The previous entry is equal to the following one.
813
+ -
814
+ A key: value pair in a sequence.
815
+ A second: key:value pair.
816
+ !float 12 : This key is a float.
817
+ ? >
818
+ ?
819
+ : This key had to be protected.
820
+ "\\a" : This key had to be escaped.
821
+ ? >
822
+ This is a
823
+ multi-line
824
+ folded key
825
+ : >
826
+ Whose value is
827
+ also multi-line.
828
+ ?
829
+ - This key
830
+ - is a sequence
831
+ :
832
+ - With a sequence value.
833
+ # The following parses correctly,
834
+ # but Ruby 1.6.* fails the comparison!
835
+ # ?
836
+ # This: key
837
+ # is a: mapping
838
+ # :
839
+ # with a: mapping value.
840
+ EOY
841
+ )
842
+ end
843
+
844
+ def test_spec_builtin_literal_blocks
845
+ # Assortment of literal scalar blocks
846
+ assert_parse_only(
847
+ {"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
848
+ empty: |
849
+
850
+ literal: |
851
+ The \\\ ' " characters may be
852
+ freely used. Leading white
853
+ space is significant.
854
+
855
+ Line breaks are significant.
856
+ Thus this value contains one
857
+ empty line and ends with a
858
+ single line break, but does
859
+ not start with one.
860
+
861
+ is equal to: "The \\\\ ' \\" characters may \\
862
+ be\\nfreely used. Leading white\\n space \\
863
+ is significant.\\n\\nLine breaks are \\
864
+ significant.\\nThus this value contains \\
865
+ one\\nempty line and ends with a\\nsingle \\
866
+ line break, but does\\nnot start with one.\\n"
867
+
868
+ # Comments may follow a nested
869
+ # scalar value. They must be
870
+ # less indented.
871
+
872
+ # Modifiers may be combined in any order.
873
+ indented and chomped: |2-
874
+ This has no newline.
875
+
876
+ also written as: |-2
877
+ This has no newline.
878
+
879
+ both are equal to: " This has no newline."
880
+ EOY
881
+ )
882
+
883
+ str1 = "This has one newline.\n"
884
+ str2 = "This has no newline."
885
+ str3 = "This has two newlines.\n\n"
886
+ assert_parse_only(
887
+ { 'clipped' => str1, 'same as "clipped" above' => str1,
888
+ 'stripped' => str2, 'same as "stripped" above' => str2,
889
+ 'kept' => str3, 'same as "kept" above' => str3 }, <<EOY
890
+ clipped: |
891
+ This has one newline.
892
+
893
+ same as "clipped" above: "This has one newline.\\n"
894
+
895
+ stripped: |-
896
+ This has no newline.
897
+
898
+ same as "stripped" above: "This has no newline."
899
+
900
+ kept: |+
901
+ This has two newlines.
902
+
903
+ same as "kept" above: "This has two newlines.\\n\\n"
904
+
905
+ EOY
906
+ )
907
+ end
908
+
909
+ def test_spec_span_single_quote
910
+ 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
911
+ empty: ''
912
+ second: '! : \\ etc. can be used freely.'
913
+ third: 'a single quote '' must be escaped.'
914
+ span: 'this contains
915
+ six spaces
916
+
917
+ and one
918
+ line break'
919
+ is same as: "this contains six spaces\\nand one line break"
920
+ EOY
921
+ )
922
+ end
923
+
924
+ def test_spec_span_double_quote
925
+ 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
926
+ empty: ""
927
+ second: "! : etc. can be used freely."
928
+ third: "a \\\" or a \\\\ must be escaped."
929
+ fourth: "this value ends with an LF.\\n"
930
+ span: "this contains
931
+ four \\
932
+ spaces"
933
+ is equal to: "this contains four spaces"
934
+ EOY
935
+ )
936
+ end
937
+
938
+ def test_spec_builtin_time
939
+ # Time
940
+ assert_parse_only(
941
+ { "space separated" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ),
942
+ "canonical" => mktime( 2001, 12, 15, 2, 59, 43, ".10" ),
943
+ "date (noon UTC)" => Date.new( 2002, 12, 14),
944
+ "valid iso8601" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ) }, <<EOY
945
+ canonical: 2001-12-15T02:59:43.1Z
946
+ valid iso8601: 2001-12-14t21:59:43.10-05:00
947
+ space separated: 2001-12-14 21:59:43.10 -05:00
948
+ date (noon UTC): 2002-12-14
949
+ EOY
950
+ )
951
+ end
952
+
953
+ def test_spec_builtin_binary
954
+ 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;"
955
+ assert_parse_only(
956
+ { 'canonical' => arrow_gif, 'base64' => arrow_gif,
957
+ 'description' => "The binary value above is a tiny arrow encoded as a gif image.\n" }, <<EOY
958
+ canonical: !binary "\\
959
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf\\
960
+ n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW\\
961
+ NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++\\
962
+ f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg\\
963
+ d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN\\
964
+ AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww\\
965
+ EeECcgggoBADs="
966
+ base64: !binary |
967
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf
968
+ n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW
969
+ NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++
970
+ f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg
971
+ d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN
972
+ AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww
973
+ EeECcgggoBADs=
974
+ description: >
975
+ The binary value above is a tiny arrow
976
+ encoded as a gif image.
977
+ EOY
978
+ )
979
+ end
980
+ def test_ruby_regexp
981
+ # Test Ruby regular expressions
982
+ assert_to_yaml(
983
+ { 'simple' => /a.b/, 'complex' => %r'\A"((?:[^"]|\")+)"',
984
+ 'case-insensitive' => /George McFly/i }, <<EOY
985
+ case-insensitive: !ruby/regexp "/George McFly/i"
986
+ complex: !ruby/regexp "/\\\\A\\"((?:[^\\"]|\\\\\\")+)\\"/"
987
+ simple: !ruby/regexp "/a.b/"
988
+ EOY
989
+ )
990
+ end
991
+
992
+ #
993
+ # Test of Ranges
994
+ #
995
+ def test_ranges
996
+
997
+ # Simple numeric
998
+ assert_to_yaml( 1..3, <<EOY )
999
+ --- !ruby/range 1..3
1000
+ EOY
1001
+
1002
+ # Simple alphabetic
1003
+ assert_to_yaml( 'a'..'z', <<EOY )
1004
+ --- !ruby/range a..z
1005
+ EOY
1006
+
1007
+ # Float
1008
+ assert_to_yaml( 10.5...30.3, <<EOY )
1009
+ --- !ruby/range 10.5...30.3
1010
+ EOY
1011
+
1012
+ end
1013
+
1014
+ def test_ruby_struct
1015
+ # Ruby structures
1016
+ book_struct = Struct::new( "MyBookStruct", :author, :title, :year, :isbn )
1017
+ assert_to_yaml(
1018
+ [ book_struct.new( "Yukihiro Matsumoto", "Ruby in a Nutshell", 2002, "0-596-00214-9" ),
1019
+ book_struct.new( [ 'Dave Thomas', 'Andy Hunt' ], "The Pickaxe", 2002,
1020
+ book_struct.new( "This should be the ISBN", "but I have another struct here", 2002, "None" )
1021
+ ) ], <<EOY
1022
+ - !ruby/struct:MyBookStruct
1023
+ author: Yukihiro Matsumoto
1024
+ title: Ruby in a Nutshell
1025
+ year: 2002
1026
+ isbn: 0-596-00214-9
1027
+ - !ruby/struct:MyBookStruct
1028
+ author:
1029
+ - Dave Thomas
1030
+ - Andy Hunt
1031
+ title: The Pickaxe
1032
+ year: 2002
1033
+ isbn: !ruby/struct:MyBookStruct
1034
+ author: This should be the ISBN
1035
+ title: but I have another struct here
1036
+ year: 2002
1037
+ isbn: None
1038
+ EOY
1039
+ )
1040
+
1041
+ assert_to_yaml( Psych_Tests::StructTest.new( 123 ), <<EOY )
1042
+ --- !ruby/struct:Psych_Tests::StructTest
1043
+ c: 123
1044
+ EOY
1045
+
1046
+ end
1047
+
1048
+ def test_ruby_rational
1049
+ assert_to_yaml( Rational(1, 2), <<EOY )
1050
+ --- !ruby/object:Rational
1051
+ numerator: 1
1052
+ denominator: 2
1053
+ EOY
1054
+
1055
+ # Read Psych dumped by the ruby 1.8.3.
1056
+ assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
1057
+ assert_raises( ArgumentError ) { Psych.load("!ruby/object:Rational INVALID/RATIONAL\n") }
1058
+ end
1059
+
1060
+ def test_ruby_complex
1061
+ assert_to_yaml( Complex(3, 4), <<EOY )
1062
+ --- !ruby/object:Complex
1063
+ image: 4
1064
+ real: 3
1065
+ EOY
1066
+
1067
+ # Read Psych dumped by the ruby 1.8.3.
1068
+ assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
1069
+ assert_raises( ArgumentError ) { Psych.load("!ruby/object:Complex INVALID+COMPLEXi\n") }
1070
+ end
1071
+
1072
+ def test_emitting_indicators
1073
+ assert_to_yaml( "Hi, from Object 1. You passed: please, pretty please", <<EOY
1074
+ --- "Hi, from Object 1. You passed: please, pretty please"
1075
+ EOY
1076
+ )
1077
+ end
1078
+
1079
+ ##
1080
+ ## Test the Psych::Stream class -- INACTIVE at the moment
1081
+ ##
1082
+ #def test_document
1083
+ # y = Psych::Stream.new( :Indent => 2, :UseVersion => 0 )
1084
+ # y.add(
1085
+ # { 'hi' => 'hello', 'map' =>
1086
+ # { 'good' => 'two' },
1087
+ # 'time' => Time.now,
1088
+ # 'try' => /^po(.*)$/,
1089
+ # 'bye' => 'goodbye'
1090
+ # }
1091
+ # )
1092
+ # y.add( { 'po' => 'nil', 'oper' => 90 } )
1093
+ # y.add( { 'hi' => 'wow!', 'bye' => 'wow!' } )
1094
+ # y.add( { [ 'Red Socks', 'Boston' ] => [ 'One', 'Two', 'Three' ] } )
1095
+ # y.add( [ true, false, false ] )
1096
+ #end
1097
+
1098
+ #
1099
+ # Test YPath choices parsing
1100
+ #
1101
+ #def test_ypath_parsing
1102
+ # assert_path_segments( "/*/((one|three)/name|place)|//place",
1103
+ # [ ["*", "one", "name"],
1104
+ # ["*", "three", "name"],
1105
+ # ["*", "place"],
1106
+ # ["/", "place"] ]
1107
+ # )
1108
+ #end
1109
+
1110
+ #
1111
+ # Tests from Tanaka Akira on [ruby-core]
1112
+ #
1113
+ def test_akira
1114
+
1115
+ # Commas in plain scalars [ruby-core:1066]
1116
+ assert_to_yaml(
1117
+ {"A"=>"A,","B"=>"B"}, <<EOY
1118
+ A: "A,"
1119
+ B: B
1120
+ EOY
1121
+ )
1122
+
1123
+ # Double-quoted keys [ruby-core:1069]
1124
+ assert_to_yaml(
1125
+ {"1"=>2, "2"=>3}, <<EOY
1126
+ '1': 2
1127
+ "2": 3
1128
+ EOY
1129
+ )
1130
+
1131
+ # Anchored mapping [ruby-core:1071]
1132
+ assert_to_yaml(
1133
+ [{"a"=>"b"}] * 2, <<EOY
1134
+ - &id001
1135
+ a: b
1136
+ - *id001
1137
+ EOY
1138
+ )
1139
+
1140
+ # Stress test [ruby-core:1071]
1141
+ # a = []; 1000.times { a << {"a"=>"b", "c"=>"d"} }
1142
+ # Psych::load( a.to_yaml )
1143
+
1144
+ end
1145
+
1146
+ #
1147
+ # Test Time.now cycle
1148
+ #
1149
+ def test_time_now_cycle
1150
+ #
1151
+ # From Minero Aoki [ruby-core:2305]
1152
+ #
1153
+ #require 'yaml'
1154
+ t = Time.now
1155
+ t = Time.at(t.tv_sec, t.tv_usec)
1156
+ 5.times do
1157
+ assert_cycle(t)
1158
+ end
1159
+ end
1160
+
1161
+ #
1162
+ # Test Range cycle
1163
+ #
1164
+ def test_range_cycle
1165
+ #
1166
+ # From Minero Aoki [ruby-core:02306]
1167
+ #
1168
+ assert_cycle("a".."z")
1169
+
1170
+ #
1171
+ # From Nobu Nakada [ruby-core:02311]
1172
+ #
1173
+ assert_cycle(0..1)
1174
+ assert_cycle(1.0e20 .. 2.0e20)
1175
+ assert_cycle("0".."1")
1176
+ assert_cycle(".."..."...")
1177
+ assert_cycle(".rb"..".pl")
1178
+ assert_cycle(".rb"...".pl")
1179
+ assert_cycle('"'...".")
1180
+ assert_cycle("'"...".")
1181
+ end
1182
+
1183
+ #
1184
+ # Circular references
1185
+ #
1186
+ def test_circular_references
1187
+ a = []; a[0] = a; a[1] = a
1188
+ inspect_str = "[[...], [...]]"
1189
+ assert_equal( inspect_str, Psych::load(Psych.dump(a)).inspect )
1190
+ end
1191
+
1192
+ #
1193
+ # Test Symbol cycle
1194
+ #
1195
+ def test_symbol_cycle
1196
+ #
1197
+ # From Aaron Schrab [ruby-Bugs:2535]
1198
+ #
1199
+ assert_cycle(:"^foo")
1200
+ end
1201
+
1202
+ #
1203
+ # Test Numeric cycle
1204
+ #
1205
+ class NumericTest < Numeric
1206
+ def initialize(value)
1207
+ @value = value
1208
+ end
1209
+ def ==(other)
1210
+ @value == other.instance_eval{ @value }
1211
+ end
1212
+ end
1213
+ def test_numeric_cycle
1214
+ assert_cycle(1) # Fixnum
1215
+ assert_cycle(111111111111111111111111111111111) # Bignum
1216
+ assert_cycle(NumericTest.new(3)) # Subclass of Numeric
1217
+ end
1218
+
1219
+ #
1220
+ # Test empty map/seq in map cycle
1221
+ #
1222
+ def test_empty_map_key
1223
+ #
1224
+ # empty seq as key
1225
+ #
1226
+ assert_cycle({[]=>""})
1227
+
1228
+ #
1229
+ # empty map as key
1230
+ #
1231
+ assert_cycle({{}=>""})
1232
+ end
1233
+
1234
+ #
1235
+ # contributed by riley lynch [ruby-Bugs-8548]
1236
+ #
1237
+ def test_object_id_collision
1238
+ omap = Psych::Omap.new
1239
+ 1000.times { |i| omap["key_#{i}"] = { "value" => i } }
1240
+ raise "id collision in ordered map" if Psych.dump(omap) =~ /id\d+/
1241
+ end
1242
+
1243
+ def test_date_out_of_range
1244
+ Psych::load('1900-01-01T00:00:00+00:00')
1245
+ end
1246
+
1247
+ def test_normal_exit
1248
+ Psych.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
1249
+ # '[ruby-core:13735]'
1250
+ end
1251
+ end