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