1#
2# rb.test:  test samples for the yaml library.
3# http://yaml4r.sourceforge.net/cookbook/
4#
5
6if {[lsearch [namespace children] ::tcltest] == -1} {
7    # single test
8    set selfrun 1
9    lappend auto_path [pwd]
10    package require tcltest
11    namespace import ::tcltest::*
12    puts [source huddle.tcl]
13    puts [source yaml.tcl]
14
15} else {
16    # all.tcl
17    source [file join \
18        [file dirname [file dirname [file join [pwd] [info script]]]] \
19        devtools testutilities.tcl]
20
21    testsNeedTcl     8.3
22    testsNeedTcltest 1.0
23
24    if {$::tcl_version < 8.5} {
25        if {[catch {package require dict}]} {
26            puts "    Aborting the tests found in \"[file tail [info script]]\""
27            puts "    Requiring dict package, not found."
28            return
29        }
30    }
31
32    testing {
33        useLocal yaml.tcl yaml
34    }
35}
36
37proc dictsort {dict} {
38    array set a $dict
39    set out [list]
40    foreach key [lsort [array names a]] {
41        lappend out $key $a($key)
42    }
43    return $out
44}
45
46proc dictsort2 {dict {pattern d}} {
47    set cur  [lindex $pattern 0]
48    set subs [lrange $pattern 1 end]
49    foreach {tag sw} $cur break
50    set out {}
51    if {$sw ne ""} {array set msubs $sw}
52    if {$tag eq "l"} { ; # list
53        set i 0
54        foreach {node} $dict {
55            set subs1 $subs
56            if {$sw ne "" && [info exists msubs($i)]} {
57                set subs1 $msubs($i)
58            }
59            if {$subs1 ne ""} {
60                set node [dictsort2 $node $subs1]
61            }
62            lappend out $node
63            incr i
64        }
65        return $out
66    }
67    if {$tag eq "d"} { ; # dict
68        array set map $dict
69        foreach key [lsort [array names map]] {
70            set node $map($key)
71            set subs1 $subs
72            if {$sw ne "" && [info exists msubs($key)]} {
73                set subs1 $msubs($key)
74            }
75            if {$subs1 ne ""} {
76                set node [dictsort2 $node $subs1]
77            }
78            lappend out $key $node
79        }
80        return $out
81    }
82    error
83}
84
85test yaml.rb-1 "Simple Sequence" -body {
86    set data {
87---
88- apple 
89- banana 
90- carrot 
91}
92    yaml::yaml2dict $data
93} -result {apple banana carrot}
94
95test yaml.rb-2 "Nested Sequences" -body {
96    set data {
97---
98- 
99 - foo 
100 - bar 
101 - baz 
102}
103    yaml::yaml2dict $data
104} -result {{foo bar baz}}
105
106test yaml.rb-3 "Mixed Sequences" -body {
107    set data {
108---
109-
110 - fo o 
111- 
112 - x1 23 
113- bana na
114- carr ot
115}
116    yaml::yaml2dict $data
117} -result {{{fo o}} {{x1 23}} {bana na} {carr ot}}
118
119test yaml.rb-4 "Deeply Nested Sequences" -body {
120    set data {
121---
122- 
123 - 
124  - uno 
125  - dos 
126}
127    yaml::yaml2dict $data
128} -result {{{uno dos}}}
129
130test yaml.rb-5 "Simple Mapping" -body {
131    set data {
132---
133foo: whatever 
134bar: stuff 
135}
136    yaml::yaml2dict $data
137} -result {foo whatever bar stuff}
138
139test yaml.rb-6 "Sequence in a Mapping" -body {
140    set data {
141---
142foo: whatever 
143bar: 
144 - uno 
145 - dos 
146}
147    yaml::yaml2dict $data
148} -result {foo whatever bar {uno dos}}
149
150test yaml.rb-7 "Nested Mappings" -body {
151    set data {
152---
153foo: whatever 
154bar: 
155 fruit: apple 
156 name: steve 
157 sport: baseball 
158}
159    yaml::yaml2dict $data
160} -result [dict create foo whatever bar [dict create fruit apple name steve sport baseball]]
161
162test yaml.rb-8 "Mixed Mapping" -body {
163    set data {
164---
165foo: whatever 
166bar: 
167 - 
168   fruit: apple 
169   name: steve 
170   sport: baseball 
171 - more 
172 - 
173   python: rocks 
174   perl: papers 
175   ruby: scissorses 
176}
177    yaml::yaml2dict $data
178} -result [dict create foo whatever bar [list [dict create fruit apple name steve sport baseball] more [dict create python rocks perl papers ruby scissorses]]]
179
180test yaml.rb-9 "Mapping-in-Sequence Shortcut" -body {
181    set data {
182---
183- work on YAML.py: 
184   - work on Store
185}
186    yaml::yaml2dict $data
187} -result {{{work on YAML.py} {{work on Store}}}}
188
189test yaml.rb-10 "Sequence-in-Mapping Shortcut" -body {
190    set data {
191---
192allow:
193- 'localhost'
194- '%.sourceforge.net'
195- '%.freepan.org'
196}
197    yaml::yaml2dict $data
198} -result {allow {localhost %.sourceforge.net %.freepan.org}}
199
200test yaml.rb-11 "Merge key" -body {
201    set data {
202---
203mapping:
204  name: Joe
205  job: Accountant
206  <<:
207    age: 38
208}
209    dictsort2 [yaml::yaml2dict $data] {d d}
210} -result [dictsort2 {mapping {name Joe job Accountant age 38}} {d d}]
211
212test yaml.rb-12 "Simple Inline Array" -body {
213    set data {
214---  
215seq: [ a, b, c ] 
216}
217    yaml::yaml2dict $data
218} -result {seq {a b c}}
219
220test yaml.rb-13 "Simple Inline Hash" -body {
221    set data {
222---  
223hash: { name: Steve, foo: bar }
224}
225    dictsort2 [yaml::yaml2dict $data] {d d}
226} -result [dictsort2 {hash {name Steve foo bar}} {d d}]
227
228test yaml.rb-14 "Multi-line Inline Collections" -body {
229    set data {
230---  
231languages: [ Ruby, 
232             Perl, 
233             Python ] 
234websites: { YAML: yaml.org, 
235            Ruby: ruby-lang.org, 
236            Python: python.org, 
237            Perl: use.perl.org }
238}
239    dictsort2 [yaml::yaml2dict $data] {{d {websites d}}}
240} -result [dictsort2 {languages {Ruby Perl Python} websites {YAML yaml.org Ruby ruby-lang.org Python python.org Perl use.perl.org}} \
241{{d {websites d}}} ]
242
243test yaml.rb-15 "Commas in Values" -body {
244    set data {
245---  
246attendances: [ 45,123, 70,000, 17,222 ]
247}
248    yaml::yaml2dict $data
249} -result {attendances {45 123 70 000 17 222}}
250
251test yaml.rb-16 "Strings" -body {
252    set data {
253--- String
254}
255    yaml::yaml2dict $data
256} -result {String}
257
258test yaml.rb-17 "String characters" -body {
259    set data {
260---
261- What's Yaml? 
262- It's for writing data structures in plain text. 
263- And? 
264- And what? That's not good enough for you? 
265- No, I mean, "And what about Yaml?" 
266- Oh, oh yeah. Uh.. Yaml for Ruby. 
267}
268    yaml::yaml2dict $data
269} -result {{What's Yaml?} {It's for writing data structures in plain text.} And? {And what? That's not good enough for you?} {No, I mean, "And what about Yaml?"} {Oh, oh yeah. Uh.. Yaml for Ruby.}}
270
271test yaml.rb-18 "Indicators in Strings" -body {
272    set data {
273---  
274the colon followed by space is an indicator: but is a string:right here 
275same for the pound sign: here we have it#in a string 
276the comma can, honestly, be used in most cases: [ but not in, inline collections ]
277}
278    yaml::yaml2dict $data
279} -result [dict create {the colon followed by space is an indicator} {but is a string:right here} {same for the pound sign} {here we have it#in a string} {the comma can, honestly, be used in most cases} {{but not in} {inline collections}}]
280
281test yaml.rb-19 "Forcing Strings" -body {
282    set data {
283---  
284date string: !!str 2001-08-01 
285number string: !!str 192 
286}
287    yaml::yaml2dict $data
288} -result [dict create {date string} 2001-08-01 {number string} 192]
289
290test yaml.rb-20 "Single-quoted Strings" -body {
291    set data {
292---  
293all my favorite symbols: '#:!/%.)' 
294a few i hate: '&(*' 
295why do i hate them?: 'it''s very hard to explain' 
296}
297    yaml::yaml2dict $data
298} -result {{all my favorite symbols} #:!/%.) {a few i hate} &(* {why do i hate them?} {it's very hard to explain}}
299
300test yaml.rb-21 "Double-quoted Strings" -body {
301    set data {
302---  
303i know where i want my line breaks: "one here\nand another here\n" 
304}
305    yaml::yaml2dict $data
306} -result {{i know where i want my line breaks} {one here
307and another here
308}}
309
310test yaml.rb-22 "Multi-line Quoted Strings" -body {
311    set data {
312---  
313i want a long string: "so i'm going to
314  let it go on and on to other lines
315  until i end it with a quote."
316}
317    yaml::yaml2dict $data
318} -result {{i want a long string} {so i'm going to let it go on and on to other lines until i end it with a quote.}}
319
320test yaml.rb-23 "Plain scalars" -body {
321    set data {
322---  
323- My little toe is broken in two places;
324- I'm crazy to have skied this way;
325- I'm not the craziest he's seen, since there was always the German guy
326  who skied for 3 hours on a broken shin bone (just below the kneecap);
327- Nevertheless, second place is respectable, and he doesn't
328  recommend going for the record;
329- He's going to put my foot in plaster for a month;
330- This would impair my skiing ability somewhat for the
331  duration, as can be imagined.
332}
333    yaml::yaml2dict $data
334} -result {{My little toe is broken in two places;} {I'm crazy to have skied this way;} {I'm not the craziest he's seen, since there was always the German guy who skied for 3 hours on a broken shin bone (just below the kneecap);} {Nevertheless, second place is respectable, and he doesn't recommend going for the record;} {He's going to put my foot in plaster for a month;} {This would impair my skiing ability somewhat for the duration, as can be imagined.}}
335
336test yaml.rb-24 "Null" -body {
337    set data {
338---  
339name: Mr. Show 
340hosted by: Bob and David 
341date of next season: ~ 
342}
343    yaml::yaml2dict $data
344} -result {name {Mr. Show} {hosted by} {Bob and David} {date of next season} {}}
345
346test yaml.rb-25 "Boolean" -body {
347    set data {
348---  
349Is Gus a Liar?: true
350Do I rely on Gus for Sustenance?: false 
351}
352    yaml::yaml2dict $data
353} -result [dict create {Is Gus a Liar?} 1 {Do I rely on Gus for Sustenance?} 0]
354
355test yaml.rb-26 "Integers" -body {
356    set data {
357---  
358zero: 0 
359simple: 12 
360one-thousand: 1,000 
361negative one-thousand: -1,000 
362}
363    yaml::yaml2dict $data
364} -result [dict create zero 0 simple 12 one-thousand 1000 {negative one-thousand} -1000]
365
366test yaml.rb-27 "Integers as Map Keys" -body {
367    set data {
368---  
3691: one 
3702: two 
3713: three 
372}
373    yaml::yaml2dict $data
374} -result {1 one 2 two 3 three}
375
376test yaml.rb-28 "Floats" -body {
377    set data {
378---  
379a simple float: 2.00 
380larger float: 1,000.09 
381scientific notation: 1.00009e+3 
382}
383    yaml::yaml2dict $data
384} -result [dict create {a simple float} 2.00 {larger float} 1000.09 {scientific notation} 1.00009e+3]
385
386
387if {$::tcl_version < 8.5} {
388    test yaml.rb-29 "Time" -body {
389        set data {
390---  
391iso8601: 2001-12-14t21:59:43.10-05:00 
392space seperated: 2001-12-14 21:59:43.10 -05:00 
393}
394        yaml::yaml2dict $data
395    } -result [eval dict create [string map \
396                 [list TIMESTAMP1 [clock scan "+5 hours" -base [clock scan "2001-12-14 21:59:43" -gmt 1]] \
397                       TIMESTAMP2 [clock scan "+5 hours" -base [clock scan "2001-12-14 21:59:43" -gmt 1]]] \
398                 {iso8601 TIMESTAMP1 {space seperated} TIMESTAMP2}]]
399} else {
400    test yaml.rb-29 "Time" -body {
401        set data {
402---  
403iso8601: 2001-12-14t21:59:43.10-05:00 
404space seperated: 2001-12-14 21:59:43.10 -05:00 
405}
406        yaml::yaml2dict $data
407    } -result [string map [list TIMESTAMP1 [clock scan "2001-12-14 21:59:43 -05:00" -format {%Y-%m-%d %k:%M:%S %Z}] \
408                                    TIMESTAMP2 [clock scan "2001-12-14 21:59:43 -05:00" -format {%Y-%m-%d %k:%M:%S %Z}]] \
409                     {iso8601 TIMESTAMP1 {space seperated} TIMESTAMP2}]
410}
411
412test yaml.rb-30 "Date" -body {
413    set data {
414--- 1976-07-31
415}
416    yaml::yaml2dict $data
417} -result [clock scan "1976-07-31"]
418
419test yaml.rb-31 "Blocks" -body {
420    set data {
421---
422this: |
423    Foo
424    Bar
425}
426    yaml::yaml2dict $data
427} -result {this {Foo
428Bar
429}}
430
431test yaml.rb-32 "The '+' indicator" -body {
432    set data {
433---
434normal: |
435  extra new lines not kept
436
437preserving: |+
438  extra new lines are kept
439
440
441dummy: value
442}
443    dictsort [yaml::yaml2dict $data]
444} -result [dictsort {normal {extra new lines not kept
445} preserving {extra new lines are kept
446
447
448} dummy value}]
449
450test yaml.rb-33 "Three trailing newlines in literals" -body {
451    set data {
452---
453clipped: |
454    This has one newline.
455
456
457
458same as "clipped" above: "This has one newline.\n"
459
460stripped: |-
461    This has no newline.
462
463
464
465same as "stripped" above: "This has no newline."
466
467kept: |+
468    This has four newlines.
469
470
471
472same as "kept" above: "This has four newlines.\n\n\n\n"
473}
474    dictsort [yaml::yaml2dict $data]
475} -result [dictsort {clipped {This has one newline.
476} {same as "clipped" above} {This has one newline.
477} stripped {This has no newline.} {same as "stripped" above} {This has no newline.} kept {This has four newlines.
478
479
480
481} {same as "kept" above} {This has four newlines.
482
483
484
485}}]
486
487test yaml.rb-34 "Extra trailing newlines with spaces" -body {
488    set data {
489---
490this: |
491    Foo
492
493
494kept: |+
495    Foo
496}
497    yaml::yaml2dict $data
498} -result [dict create this {Foo
499} kept {Foo
500}]
501
502test yaml.rb-35 "Folded Block in a Sequence" -body {
503    set data {
504---
505- apple
506- banana
507- >
508    can't you see
509    the beauty of yaml?
510    hmm
511- dog
512}
513    yaml::yaml2dict $data
514} -result {apple banana {can't you see the beauty of yaml? hmm
515} dog}
516
517test yaml.rb-36 "Folded Block as a Mapping Value" -body {
518    set data {
519---
520quote: >
521    Mark McGwire's
522    year was crippled
523    by a knee injury.
524source: espn
525}
526    yaml::yaml2dict $data
527} -result [dict create quote {Mark McGwire's year was crippled by a knee injury.
528} source espn]
529
530test yaml.rb-37 "Three trailing newlines in folded blocks" -body {
531    set data {
532---
533clipped: >
534    This has one newline.
535
536
537
538same as "clipped" above: "This has one newline.\n" 
539
540stripped: >-
541    This has no newline.
542
543
544
545same as "stripped" above: "This has no newline."
546
547kept: >+
548    This has four newlines.
549
550
551
552same as "kept" above: "This has four newlines.\n\n\n\n"
553}
554    dictsort [yaml::yaml2dict $data]
555} -result [dictsort {clipped {This has one newline.
556} {same as "clipped" above} {This has one newline.
557} stripped {This has no newline.} {same as "stripped" above} {This has no newline.} kept {This has four newlines.
558
559
560} {same as "kept" above} {This has four newlines.
561
562
563
564}}]
565
566test yaml.rb-38 "Extra trailing newlines with spaces" -body {
567    set data {
568---
569- &showell Steve 
570- Clark 
571- Brian 
572- Oren 
573- *showell
574}
575    yaml::yaml2dict $data
576} -result {Steve Clark Brian Oren Steve}
577
578test yaml.rb-39 "Alias of a Mapping" -body {
579    set data {
580---
581- &hello 
582    Meat: pork 
583    Starch: potato 
584- banana 
585- *hello 
586}
587    yaml::yaml2dict $data
588} -result [list [dict create Meat pork Starch potato] banana [dict create Meat pork Starch potato]]
589
590#test yaml.rb-40 "Trailing Document Separator" -body {
591#    set data {
592#- foo: 1
593#  bar: 2
594#---
595#more: stuff
596#}
597#    yaml::yaml2dict $data
598#} -result {Steve Clark Brian Oren Steve}
599
600test yaml.rb-41 "Alias of a Mapping" -body {
601    set data {
602--- %YAML:1.0 
603foo: 1 
604bar: 2 
605}
606    yaml::yaml2dict $data
607} -result {foo 1 bar 2}
608
609test yaml.rb-42 "Red Herring Document Separator" -body {
610    set data {
611---
612foo: |
613    ---
614}
615    yaml::yaml2dict $data
616} -result {foo {---
617}}
618
619test yaml.rb-43 "Multiple Document Separators in Block" -body {
620    set data {
621---
622foo: | 
623    ---
624    foo: bar
625    ---
626    yo: baz
627bar: | 
628    fooness
629}
630    yaml::yaml2dict $data
631} -result {foo {---
632foo: bar
633---
634yo: baz
635} bar {fooness
636}}
637
638# YAML For Ruby
639# (ignored)
640
641
642
643
644
645# ... Tests of addStrings ...
646#     (Requires introspection of parser state)
647
648
649if [info exists selfrun] {
650    tcltest::cleanupTests
651} else {
652    testsuiteCleanup
653}
654
655
656