github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/testdata/lua-5.3.3-tests/sort.lua (about) 1 -- $Id: sort.lua,v 1.37 2016/03/07 19:27:51 roberto Exp $ 2 3 print "testing (parts of) table library" 4 5 print "testing unpack" 6 7 local unpack = table.unpack 8 9 local maxI = math.maxinteger 10 local minI = math.mininteger 11 12 13 local function checkerror (msg, f, ...) 14 local s, err = pcall(f, ...) 15 assert(not s and string.find(err, msg)) 16 end 17 18 19 checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4) 20 21 local x,y,z,a,n 22 a = {}; lim = _soft and 200 or 2000 23 for i=1, lim do a[i]=i end 24 assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim) 25 x = unpack(a) 26 assert(x == 1) 27 x = {unpack(a)} 28 assert(#x == lim and x[1] == 1 and x[lim] == lim) 29 x = {unpack(a, lim-2)} 30 assert(#x == 3 and x[1] == lim-2 and x[3] == lim) 31 x = {unpack(a, 10, 6)} 32 assert(next(x) == nil) -- no elements 33 x = {unpack(a, 11, 10)} 34 assert(next(x) == nil) -- no elements 35 x,y = unpack(a, 10, 10) 36 assert(x == 10 and y == nil) 37 x,y,z = unpack(a, 10, 11) 38 assert(x == 10 and y == 11 and z == nil) 39 a,x = unpack{1} 40 assert(a==1 and x==nil) 41 a,x = unpack({1,2}, 1, 1) 42 assert(a==1 and x==nil) 43 44 do 45 local maxi = (1 << 31) - 1 -- maximum value for an int (usually) 46 local mini = -(1 << 31) -- minimum value for an int (usually) 47 checkerror("too many results", unpack, {}, 0, maxi) 48 checkerror("too many results", unpack, {}, 1, maxi) 49 checkerror("too many results", unpack, {}, 0, maxI) 50 checkerror("too many results", unpack, {}, 1, maxI) 51 checkerror("too many results", unpack, {}, mini, maxi) 52 checkerror("too many results", unpack, {}, -maxi, maxi) 53 checkerror("too many results", unpack, {}, minI, maxI) 54 unpack({}, maxi, 0) 55 unpack({}, maxi, 1) 56 unpack({}, maxI, minI) 57 pcall(unpack, {}, 1, maxi + 1) 58 local a, b = unpack({[maxi] = 20}, maxi, maxi) 59 assert(a == 20 and b == nil) 60 a, b = unpack({[maxi] = 20}, maxi - 1, maxi) 61 assert(a == nil and b == 20) 62 local t = {[maxI - 1] = 12, [maxI] = 23} 63 a, b = unpack(t, maxI - 1, maxI); assert(a == 12 and b == 23) 64 a, b = unpack(t, maxI, maxI); assert(a == 23 and b == nil) 65 a, b = unpack(t, maxI, maxI - 1); assert(a == nil and b == nil) 66 t = {[minI] = 12.3, [minI + 1] = 23.5} 67 a, b = unpack(t, minI, minI + 1); assert(a == 12.3 and b == 23.5) 68 a, b = unpack(t, minI, minI); assert(a == 12.3 and b == nil) 69 a, b = unpack(t, minI + 1, minI); assert(a == nil and b == nil) 70 end 71 72 do -- length is not an integer 73 local t = setmetatable({}, {__len = function () return 'abc' end}) 74 assert(#t == 'abc') 75 checkerror("object length is not an integer", table.insert, t, 1) 76 end 77 78 print "testing pack" 79 80 a = table.pack() 81 assert(a[1] == nil and a.n == 0) 82 83 a = table.pack(table) 84 assert(a[1] == table and a.n == 1) 85 86 a = table.pack(nil, nil, nil, nil) 87 assert(a[1] == nil and a.n == 4) 88 89 90 -- testing move 91 do 92 93 checkerror("table expected", table.move, 1, 2, 3, 4) 94 95 local function eqT (a, b) 96 for k, v in pairs(a) do assert(b[k] == v) end 97 for k, v in pairs(b) do assert(a[k] == v) end 98 end 99 100 local a = table.move({10,20,30}, 1, 3, 2) -- move forward 101 eqT(a, {10,10,20,30}) 102 103 -- move forward with overlap of 1 104 a = table.move({10, 20, 30}, 1, 3, 3) 105 eqT(a, {10, 20, 10, 20, 30}) 106 107 -- moving to the same table (not being explicit about it) 108 a = {10, 20, 30, 40} 109 table.move(a, 1, 4, 2, a) 110 eqT(a, {10, 10, 20, 30, 40}) 111 112 a = table.move({10,20,30}, 2, 3, 1) -- move backward 113 eqT(a, {20,30,30}) 114 115 a = {} -- move to new table 116 assert(table.move({10,20,30}, 1, 3, 1, a) == a) 117 eqT(a, {10,20,30}) 118 119 a = {} 120 assert(table.move({10,20,30}, 1, 0, 3, a) == a) -- empty move (no move) 121 eqT(a, {}) 122 123 a = table.move({10,20,30}, 1, 10, 1) -- move to the same place 124 eqT(a, {10,20,30}) 125 126 -- moving on the fringes 127 a = table.move({[maxI - 2] = 1, [maxI - 1] = 2, [maxI] = 3}, 128 maxI - 2, maxI, -10, {}) 129 eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3}) 130 131 a = table.move({[minI] = 1, [minI + 1] = 2, [minI + 2] = 3}, 132 minI, minI + 2, -10, {}) 133 eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3}) 134 135 a = table.move({45}, 1, 1, maxI) 136 eqT(a, {45, [maxI] = 45}) 137 138 a = table.move({[maxI] = 100}, maxI, maxI, minI) 139 eqT(a, {[minI] = 100, [maxI] = 100}) 140 141 a = table.move({[minI] = 100}, minI, minI, maxI) 142 eqT(a, {[minI] = 100, [maxI] = 100}) 143 144 a = setmetatable({}, { 145 __index = function (_,k) return k * 10 end, 146 __newindex = error}) 147 local b = table.move(a, 1, 10, 3, {}) 148 eqT(a, {}) 149 eqT(b, {nil,nil,10,20,30,40,50,60,70,80,90,100}) 150 151 b = setmetatable({""}, { 152 __index = error, 153 __newindex = function (t,k,v) 154 t[1] = string.format("%s(%d,%d)", t[1], k, v) 155 end}) 156 table.move(a, 10, 13, 3, b) 157 assert(b[1] == "(3,100)(4,110)(5,120)(6,130)") 158 local stat, msg = pcall(table.move, b, 10, 13, 3, b) 159 assert(not stat and msg == b) 160 end 161 162 do 163 -- for very long moves, just check initial accesses and interrupt 164 -- move with an error 165 local function checkmove (f, e, t, x, y) 166 local pos1, pos2 167 local a = setmetatable({}, { 168 __index = function (_,k) pos1 = k end, 169 __newindex = function (_,k) pos2 = k; error() end, }) 170 local st, msg = pcall(table.move, a, f, e, t) 171 assert(not st and not msg and pos1 == x and pos2 == y) 172 end 173 -- TODO or spec 174 -- checkmove(1, maxI, 0, 1, 0) 175 -- checkmove(0, maxI - 1, 1, maxI - 1, maxI) 176 -- checkmove(minI, -2, -5, -2, maxI - 6) 177 -- checkmove(minI + 1, -1, -2, -1, maxI - 3) 178 -- checkmove(minI, -2, 0, minI, 0) -- non overlapping 179 -- checkmove(minI + 1, -1, 1, minI + 1, 1) -- non overlapping 180 end 181 182 checkerror("too many", table.move, {}, 0, maxI, 1) 183 checkerror("too many", table.move, {}, -1, maxI - 1, 1) 184 checkerror("too many", table.move, {}, minI, -1, 1) 185 checkerror("too many", table.move, {}, minI, maxI, 1) 186 -- TODO or spec 187 -- checkerror("wrap around", table.move, {}, 1, maxI, 2) 188 -- checkerror("wrap around", table.move, {}, 1, 2, maxI) 189 -- checkerror("wrap around", table.move, {}, minI, -2, 2) 190 191 192 print"testing sort" 193 194 195 -- strange lengths 196 local a = setmetatable({}, {__len = function () return -1 end}) 197 assert(#a == -1) 198 table.sort(a, error) -- should not compare anything 199 a = setmetatable({}, {__len = function () return maxI end}) 200 checkerror("too big", table.sort, a) 201 202 -- test checks for invalid order functions 203 local function check (t) 204 local function f(a, b) assert(a and b); return true end 205 checkerror("invalid order function", table.sort, t, f) 206 end 207 208 check{1,2,3,4} 209 check{1,2,3,4,5} 210 check{1,2,3,4,5,6} 211 212 213 function check (a, f) 214 f = f or function (x,y) return x<y end; 215 for n = #a, 2, -1 do 216 assert(not f(a[n], a[n-1])) 217 end 218 end 219 220 a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 221 "Oct", "Nov", "Dec"} 222 223 table.sort(a) 224 check(a) 225 226 function perm (s, n) 227 n = n or #s 228 if n == 1 then 229 local t = {unpack(s)} 230 table.sort(t) 231 check(t) 232 else 233 for i = 1, n do 234 s[i], s[n] = s[n], s[i] 235 perm(s, n - 1) 236 s[i], s[n] = s[n], s[i] 237 end 238 end 239 end 240 241 perm{} 242 perm{1} 243 perm{1,2} 244 perm{1,2,3} 245 perm{1,2,3,4} 246 perm{2,2,3,4} 247 perm{1,2,3,4,5} 248 perm{1,2,3,3,5} 249 perm{1,2,3,4,5,6} 250 perm{2,2,3,3,5,6} 251 252 function timesort (a, n, func, msg, pre) 253 local x = os.clock() 254 table.sort(a, func) 255 x = (os.clock() - x) * 1000 256 pre = pre or "" 257 print(string.format("%ssorting %d %s elements in %.2f msec.", pre, n, msg, x)) 258 check(a, func) 259 end 260 261 limit = 50000 262 if _soft then limit = 5000 end 263 264 a = {} 265 for i=1,limit do 266 a[i] = math.random() 267 end 268 269 timesort(a, limit, nil, "random") 270 271 timesort(a, limit, nil, "sorted", "re-") 272 273 a = {} 274 for i=1,limit do 275 a[i] = math.random() 276 end 277 278 x = os.clock(); i=0 279 table.sort(a, function(x,y) i=i+1; return y<x end) 280 x = (os.clock() - x) * 1000 281 print(string.format("Invert-sorting other %d elements in %.2f msec., with %i comparisons", 282 limit, x, i)) 283 check(a, function(x,y) return y<x end) 284 285 286 table.sort{} -- empty array 287 288 for i=1,limit do a[i] = false end 289 timesort(a, limit, function(x,y) return nil end, "equal") 290 291 for i,v in pairs(a) do assert(v == false) end 292 293 A = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"} 294 table.sort(A) 295 check(A) 296 297 table.sort(A, function (x, y) 298 load(string.format("A[%q] = ''", x), "")() 299 collectgarbage() 300 return x<y 301 end) 302 303 304 tt = {__lt = function (a,b) return a.val < b.val end} 305 a = {} 306 for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end 307 table.sort(a) 308 check(a, tt.__lt) 309 check(a) 310 311 print"OK"