aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/type/unit.lux
blob: 6835769baba6664cbba61f32206c8c637626363a (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
113
114
115
116
117
118
(.require
 [library
  [lux (.except)
   ["_" test (.only Test)]
   [abstract
    [monad (.only do)]
    [equivalence (.only Equivalence)]
    [\\specification
     ["$[0]" equivalence]
     ["$[0]" order]
     ["$[0]" enum]]]
   [math
    ["[0]" random (.only Random)]
    [number
     ["i" int]]]]]
 [\\library
  ["[0]" /]]
 ["[0]" /
  ["[1][0]" scale]])

(with_template [<name> <type> <unit>]
  [(def (<name> range)
     (-> Nat (Random (/.Qty Any <type>)))
     (|> random.int
         (at random.monad each (i.% (.int range)))
         (random.only (|>> (i.= +0) not))
         (at random.monad each (at <unit> in))))]

  [meter /.Meter /.meter]
  [second /.Second /.second]
  )

(def polymorphism
  Test
  (all _.and
       (_.for [/.equivalence]
              ($equivalence.spec /.equivalence (..meter 1,000)))
       (_.for [/.order]
              ($order.spec /.order (..meter 1,000)))
       (_.for [/.enum]
              ($enum.spec /.enum (..meter 1,000)))
       ))

(def what (/.unit []))
(def What (/.type what))

(def unit
  Test
  (do random.monad
    [expected random.int]
    (_.for [/.Unit]
           (`` (all _.and
                    (~~ (with_template [<type> <unit>]
                          [(_.coverage [<type> <unit>]
                             (|> expected
                                 (at <unit> in)
                                 (at <unit> out)
                                 (i.= expected)))]

                          [/.Gram /.gram]
                          [/.Meter /.meter]
                          [/.Litre /.litre]
                          [/.Second /.second]
                          ))
                    (_.coverage [/.quantity /.number]
                      (|> expected
                          /.quantity
                          /.number
                          (i.= expected)))
                    (_.coverage [/.unit /.type]
                      (|> expected
                          (at ..what in)
                          (is (/.Qty Any What))
                          (at ..what out)
                          (i.= expected)))
                    )))))

(def arithmetic
  Test
  (do random.monad
    [.let [zero (at /.meter in +0)
           (open "meter#[0]") (is (Equivalence (/.Qty Any /.Meter))
                                  /.equivalence)]
     left (random.only (|>> (meter#= zero) not) (..meter 1,000))
     right (..meter 1,000)
     extra (..second 1,000)]
    (`` (all _.and
             (~~ (with_template [<q> <i>]
                   [(_.coverage [<q>]
                      (i.= (<i> (at /.meter out left) (at /.meter out right))
                           (at /.meter out (<q> left right))))]

                   [/.+ i.+]
                   [/.- i.-]
                   ))
             (_.coverage [/.*]
               (let [expected (i.* (at /.meter out left) (at /.meter out right))
                     actual (/.number (is (/.Qty Any [/.Meter /.Meter])
                                          (/.* left right)))]
                 (i.= expected actual)))
             (_.coverage [/./]
               (|> right
                   (/.* left)
                   (/./ left)
                   (meter#= right)))
             ))))

(def .public test
  Test
  (<| (_.covering /._)
      (_.for [/.Qty])
      (all _.and
           ..polymorphism
           ..unit
           ..arithmetic

           /scale.test
           )))