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"