1specify table_ext:
2- before:
3    unextended = require "table_ext"
4- "describe table.clone ()":
5  - before:
6      subject = { k1 = {"v1"}, k2 = {"v2"}, k3 = {"v3"} }
7      f       = table.clone
8  - it does not just return the subject:
9      expect (f (subject)).should_not_be (subject)
10  - it does copy the subject:
11      expect (f (subject)).should_equal (subject)
12  - it only makes a shallow copy:
13      expect (f (subject).k1).should_be (subject.k1)
14  - the original subject is not perturbed:
15      target = { k1 = subject.k1, k2 = subject.k2, k3 = subject.k3 }
16      copy   = f (subject)
17      expect (subject).should_equal (target)
18      expect (subject).should_be (subject)
19  - "it diagnoses non-table arguments":
20      expect ("table expected").should_error (f, nil)
21      expect ("table expected").should_error (f, "foo")
22
23
24- "describe table.clone_rename()":
25  - before:
26      subject = { k1 = {"v1"}, k2 = {"v2"}, k3 = {"v3"} }
27      f       = table.clone_rename
28  - it does not just return the subject:
29      expect (f ({}, subject)).should_not_be (subject)
30  - it copies the subject:
31      expect (f ({}, subject)).should_equal (subject)
32  - it only makes a shallow copy:
33      expect (f ({}, subject).k2).should_be (subject.k2)
34
35  - context when renaming some keys:
36    - before:
37        target = { newkey = subject.k1, k2 = subject.k2, k3 = subject.k3 }
38    - it renames during cloning:
39        expect (f ({k1 = "newkey"}, subject)).should_equal (target)
40    - it does not perturb the value in the renamed key field:
41        expect (f ({k1 = "newkey"}, subject).newkey).should_be (subject.k1)
42
43  - "it diagnoses non-table arguments":
44      expect ("table expected").should_error (f, {}, nil)
45      expect ("table expected").should_error (f, {}, "foo")
46
47
48- "describe table.empty ()":
49  - before:
50      f = table.empty
51  - it returns true for an empty table:
52      expect (f {}).should_be (true)
53      expect (f {nil}).should_be (true)
54  - "it returns false for a non-empty table":
55      expect (f {"stuff"}).should_be (false)
56      expect (f {{}}).should_be (false)
57      expect (f {false}).should_be (false)
58  - "it diagnoses non-table arguments":
59      expect ("table expected").should_error (f, nil)
60      expect ("table expected").should_error (f, "foo")
61
62
63- "describe table.invert ()":
64  - before:
65      subject = { k1 = 1, k2 = 2, k3 = 3 }
66      f       = table.invert
67  - it returns a new table:
68      expect (f (subject)).should_not_be (subject)
69  - it inverts keys and values in the returned table:
70      expect (f (subject)).should_equal { "k1", "k2", "k3" }
71  - it is reversible:
72      expect (f (f (subject))).should_equal (subject)
73  - "it seems to copy a list of 1..n numbers":
74      subject = { 1, 2, 3 }
75      expect (f (subject)).should_equal (subject)
76      expect (f (subject)).should_not_be (subject)
77  - "it diagnoses non-table arguments":
78      expect ("table expected").should_error (f, nil)
79      expect ("table expected").should_error (f, "foo")
80
81
82- "describe table.keys ()":
83  - before:
84      subject = { k1 = 1, k2 = 2, k3 = 3 }
85      f       = table.keys
86  - it returns an empty list when subject is empty:
87      expect (f {}).should_equal {}
88  - it makes a list of table keys:
89      cmp = function (a, b) return a < b end
90      expect (table.sort (f (subject), cmp)).should_equal {"k1", "k2", "k3"}
91  - it does not guarantee stable ordering:
92      subject = {}
93      -- is this a good test? there is a vanishingly small possibility the
94      -- returned table will have all 10000 keys in the same order...
95      for i = 10000, 1, -1 do table.insert (subject, i) end
96      expect (f (subject)).should_not_equal (subject)
97  - "it diagnoses non-table arguments":
98      expect ("table expected").should_error (f, nil)
99      expect ("table expected").should_error (f, "foo")
100
101
102- "describe table.merge ()":
103  - before: |
104      -- Additional merge keys which are moderately unusual
105      t1 = { k1 = {"v1"}, k2 = "if", k3 = {"?"} }
106      t2 = { ["if"] = true, [{"?"}] = false, _ = "underscore", k3 = t1.k1 }
107      f  = table.merge
108
109      target = {}
110      for k, v in pairs (t1) do target[k] = v end
111      for k, v in pairs (t2) do target[k] = v end
112  - it does not create a whole new table:
113      expect (f (t1, t2)).should_be (t1)
114  - it does not change t1 when t2 is empty:
115      expect (f (t1, {})).should_be (t1)
116  - it copies t2 when t1 is empty:
117      expect (f ({}, t1)).should_not_be (t1)
118      expect (f ({}, t1)).should_equal (t1)
119  - it merges keys from t2 into t1:
120      expect (f (t1, t2)).should_equal (target)
121  - it gives precedence to values from t2:
122      original = table.clone (t1)
123      m = f (t1, t2)      -- Merge is destructive, do it once only.
124      expect (m.k3).should_be (t2.k3)
125      expect (m.k3).should_not_be (original.k3)
126  - "it diagnoses non-table arguments":
127      expect ("table expected").should_error (f, nil, nil)
128      expect ("table expected").should_error (f, "foo", "bar")
129
130
131- "describe table.new ()":
132  - before:
133      f = table.new
134
135  - context when not setting a default:
136    - before: default = nil
137    - it returns a new table when nil is passed:
138        expect (f (default, nil)).should_equal {}
139    - it returns any table passed in:
140        t = { "unique table" }
141        expect (f (default, t)).should_be (t)
142
143  - context when setting a default:
144    - before:
145        default = "default"
146    - it returns a new table when nil is passed:
147        expect (f (default, nil)).should_equal {}
148    - it returns any table passed in:
149        t = { "unique table" }
150        expect (f (default, t)).should_be (t)
151
152  - it returns the stored value for existing keys:
153      t = f ("default")
154      v = { "unique value" }
155      t[1] = v
156      expect (t[1]).should_be (v)
157  - it returns the constructor default for unset keys:
158      t = f ("default")
159      expect (t[1]).should_be "default"
160  - it returns the actual default object:
161      default = { "unique object" }
162      t = f (default)
163      expect (t[1]).should_be (default)
164  - "it diagnoses non-tables/non-nil in the second argument":
165      expect ("table expected").should_error (f, nil, "foo")
166
167
168- "describe table.size ()":
169  - before: |
170      --          - 1 -  --------- 2 ----------  -- 3 --
171      subject = { "one", { { "two" }, "three" }, four = 5 }
172      f = table.size
173  - it counts the number of keys in a table:
174      expect (f (subject)).should_be (3)
175  - it counts no keys in an empty table:
176      expect (f {}).should_be (0)
177  - "it diagnoses non-table arguments":
178      expect ("table expected").should_error (f, nil)
179      expect ("table expected").should_error (f, "foo")
180
181
182- "describe table.sort ()":
183  - before:
184      subject = { 5, 2, 4, 1, 0, 3 }
185      target  = { 0, 1, 2, 3, 4, 5 }
186      cmp     = function (a, b) return a < b end
187      f       = table.sort
188  - it sorts elements in place:
189      f (subject, cmp)
190      expect (subject).should_equal (target)
191  - it returns the sorted table:
192      expect (f (subject, cmp)).should_equal (target)
193  - "it diagnoses non-table arguments":
194      expect ("table expected").should_error (f, nil)
195      expect ("table expected").should_error (f, nil)
196
197
198- "describe table.values ()":
199  - before:
200      subject = { k1 = {1}, k2 = {2}, k3 = {3} }
201      f       = table.values
202  - it returns an empty list when subject is empty:
203      expect (f {}).should_equal {}
204  - it makes a list of table values:
205      cmp = function (a, b) return a[1] < b[1] end
206      expect (table.sort (f (subject), cmp)).should_equal {{1}, {2}, {3}}
207  - it does guarantee stable ordering:
208      subject = {}
209      -- is this a good test? or just requiring an implementation quirk?
210      for i = 10000, 1, -1 do table.insert (subject, i) end
211      expect (f (subject)).should_equal (subject)
212  - "it diagnoses non-table arguments":
213      expect ("table expected").should_error (f, nil)
214      expect ("table expected").should_error (f, "foo")
215
216
217- context when requiring the module:
218  - before:
219      extensions = { "clone", "clone_rename", "empty", "invert", "keys",
220                     "merge", "new", "size", "sort", "values" }
221  - it returns the unextended module table:
222      for _, api in ipairs (extensions) do
223        if api ~= "sort" then
224          expect (unextended[api]).should_be (nil)
225        end
226      end
227  - it injects an enhanced sort function:
228      expect (unextended.sort).should_not_be (table.sort)
229  - it does not override any other module access points:
230      for api in pairs (unextended) do
231        if api ~= "sort" then
232          expect (table[api]).should_be (unextended[api])
233        end
234      end
235