aboutsummaryrefslogtreecommitdiff
path: root/stdlib/test/test/lux/data/coll/array.lux
blob: 236c2f915400bfa590bdb1723f80d9f8d9493852 (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
##  Copyright (c) Eduardo Julian. All rights reserved.
##  This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
##  If a copy of the MPL was not distributed with this file,
##  You can obtain one at http://mozilla.org/MPL/2.0/.

(;module:
  lux
  (lux (control [monad])
       [io]
       (data (coll ["&" array]
                   [list])
             [number])
       ["R" random]
       pipe)
  lux/test)

(def: bounded-size
  (R;Random Nat)
  (|> R;nat
      (:: R;Monad<Random> map (|>. (n.% +100) (n.+ +1)))))

(test: "Arrays and their copies"
  [size bounded-size
   original (R;array size R;nat)
   #let [clone (&;clone original)
         copy (: (&;Array Nat)
                 (&;new size))
         manual-copy (: (&;Array Nat)
                        (&;new size))]]
  ($_ seq
      (assert "Size function must correctly return size of array."
              (n.= size (&;size original)))
      (assert "Cloning an array should yield and identical array, but not the same one."
              (and (:: (&;Eq<Array> number;Eq<Nat>) = original clone)
                   (not (is original clone))))
      (assert "Full-range manual copies should give the same result as cloning."
              (exec (&;copy size +0 original +0 copy)
                (and (:: (&;Eq<Array> number;Eq<Nat>) = original copy)
                     (not (is original copy)))))
      (assert "Array folding should go over all values."
              (exec (:: &;Fold<Array> fold
                        (lambda [x idx]
                          (exec (&;put idx x manual-copy)
                            (n.inc idx)))
                        +0
                        original)
                (:: (&;Eq<Array> number;Eq<Nat>) = original manual-copy)))
      (assert "Transformations between (full) arrays and lists shouldn't cause lose or change any values."
              (|> original
                  &;to-list &;from-list
                  (:: (&;Eq<Array> number;Eq<Nat>) = original)))
      ))

(test: "Array mutation"
  [size bounded-size
   idx (:: @ map (n.% size) R;nat)
   array (|> (R;array size R;nat)
             (R;filter (|>. &;to-list (list;any? n.odd?))))
   #let [value (default (undefined)
                 (&;get idx array))]]
  ($_ seq
      (assert "Shouldn't be able to find a value in an unoccupied cell."
              (case (&;get idx (&;remove idx array))
                (#;Some _) false
                #;None     true))
      (assert "You should be able to access values put into the array."
              (case (&;get idx (&;put idx value array))
                (#;Some value') (n.= value' value)
                #;None          false))
      (assert "All cells should be occupied on a full array."
              (and (n.= size (&;occupied array))
                   (n.= +0 (&;vacant array))))
      (assert "Filtering mutates the array to remove invalid values."
              (exec (&;filter n.even? array)
                (and (n.< size (&;occupied array))
                     (n.> +0 (&;vacant array))
                     (n.= size (n.+ (&;occupied array)
                                    (&;vacant array))))))
      ))

(test: "Finding values."
  [size bounded-size
   array (|> (R;array size R;nat)
             (R;filter (|>. &;to-list (list;any? n.even?))))]
  ($_ seq
      (assert "Can find values inside arrays."
              (|> (&;find n.even? array)
                  (case> (#;Some _) true
                         #;None     false)))
      (assert "Can find values inside arrays (with access to indices)."
              (|> (&;find+ (lambda [idx n]
                             (and (n.even? n)
                                  (n.< size idx)))
                           array)
                  (case> (#;Some _) true
                         #;None     false)))))

(test: "Functor"
  [size bounded-size
   array (R;array size R;nat)]
  (let [(^open) &;Functor<Array>
        (^open) (&;Eq<Array> number;Eq<Nat>)]
    ($_ seq
        (assert "Functor shouldn't alter original array."
                (let [copy (map id array)]
                  (and (= array copy)
                       (not (is array copy)))))
        (assert "Functor should go over all available array elements."
                (let [there (map n.inc array)
                      back-again (map n.dec there)]
                  (and (not (= array there))
                       (= array back-again)))))))

(test: "Monoid"
  [sizeL bounded-size
   sizeR bounded-size
   left (R;array sizeL R;nat)
   right (R;array sizeR R;nat)
   #let [(^open) &;Monoid<Array>
         (^open) (&;Eq<Array> number;Eq<Nat>)
         fusion (append left right)]]
  ($_ seq
      (assert "Appending two arrays should produce a new one twice as large."
              (n.= (n.+ sizeL sizeR) (&;size fusion)))
      (assert "First elements of fused array should equal the first array."
              (|> (: (&;Array Nat)
                     (&;new sizeL))
                  (&;copy sizeL +0 fusion +0)
                  (= left)))
      (assert "Last elements of fused array should equal the second array."
              (|> (: (&;Array Nat)
                     (&;new sizeR))
                  (&;copy sizeR sizeL fusion +0)
                  (= right)))
      ))