aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/data/format/xml.lux
blob: 221edba97457c3d24128c2d39cf9b8fcd651bcef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
(.module:
  [lux (#- char)
   data/text/format
   ["_" test (#+ Test)]
   [control
    pipe
    [monad (#+ Monad do)]
    ["p" parser]
    {[0 #test]
     [/
      ["$." equivalence]
      ["$." codec]]}]
   [data
    ["." name]
    ["E" error]
    ["." maybe]
    ["." text ("#@." equivalence)]
    [collection
     ["." dictionary]
     ["." list ("#@." functor)]]]
   [math
    ["r" random (#+ Random) ("#@." monad)]]]
  {1
   ["." / (#+ XML)]})

(def: char-range
  Text
  (format "_"
          "abcdefghijklmnopqrstuvwxyz"
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))

(def: char
  (Random Nat)
  (do r.monad
    [idx (|> r.nat (:: @ map (n/% (text.size char-range))))]
    (wrap (maybe.assume (text.nth idx char-range)))))

(def: (size bottom top)
  (-> Nat Nat (Random Nat))
  (let [constraint (|>> (n/% top) (n/max bottom))]
    (r@map constraint r.nat)))

(def: (text bottom top)
  (-> Nat Nat (Random Text))
  (do r.monad
    [size (..size bottom top)]
    (r.text ..char size)))

(def: xml-identifier^
  (Random Name)
  (r.and (..text 0 10)
         (..text 1 10)))

(def: #export xml
  (Random XML)
  (r.rec (function (_ xml)
           (r.or (..text 1 10)
                 (do r.monad
                   [size (..size 0 2)]
                   ($_ r.and
                       xml-identifier^
                       (r.dictionary name.hash size xml-identifier^ (..text 0 10))
                       (r.list size xml)))))))

(def: #export test
  Test
  (<| (_.context (%name (name-of /.XML)))
      ($_ _.and
          ($equivalence.spec /.equivalence ..xml)
          ($codec.spec /.equivalence /.codec ..xml)

          (do r.monad
            [text (..text 1 10)
             num-children (|> r.nat (:: @ map (n/% 5)))
             children (r.list num-children (..text 1 10))
             tag xml-identifier^
             attr xml-identifier^
             value (..text 1 10)
             #let [node (#/.Node tag
                                 (dictionary.put attr value /.attrs)
                                 (list@map (|>> #/.Text) children))]]
            ($_ _.and
                (_.test "Can parse text."
                        (E.default #0
                                   (do E.monad
                                     [output (/.run (#/.Text text)
                                                    /.text)]
                                     (wrap (text@= text output)))))
                (_.test "Can parse attributes."
                        (E.default #0
                                   (do E.monad
                                     [output (|> (/.attr attr)
                                                 (p.before /.ignore)
                                                 (/.run node))]
                                     (wrap (text@= value output)))))
                (_.test "Can parse nodes."
                        (E.default #0
                                   (do E.monad
                                     [_ (|> (/.node tag)
                                            (p.before /.ignore)
                                            (/.run node))]
                                     (wrap #1))))
                (_.test "Can parse children."
                        (E.default #0
                                   (do E.monad
                                     [outputs (|> (/.children (p.some /.text))
                                                  (/.run node))]
                                     (wrap (:: (list.equivalence text.equivalence) =
                                               children
                                               outputs)))))
                ))
          )))