---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.4-tests/sort.lua
---
print("testing (parts of) table library");
print("testing unpack");
local unpack = table.unpack
local maxI = math.maxinteger
local minI = math.mininteger
local fn checkerror(msg, f, ...) {
local s, err = pcall(f, ...)
assert(!s && string.find(err, msg));
}
checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4);
local x, y, z, a, n
a = {}
lim = _soft && 200 || 2000
for i = 1, lim {
a[(i)] = i
}
assert(select(lim, unpack(a)) == lim && select('#', unpack(a)) == lim);
x = unpack(a)
assert(x == 1);
x = {
unpack(a)
}
assert(#x == lim && x[(1)] == 1 && x[(lim)] == lim);
x = {
unpack(a, lim - 2)
}
assert(#x == 3 && x[(1)] == lim - 2 && x[(3)] == lim);
x = {
unpack(a, 10, 6)
}
assert(next(x) == nil);
x = {
unpack(a, 11, 10)
}
assert(next(x) == nil);
x, y = unpack(a, 10, 10)
assert(x == 10 && y == nil);
x, y, z = unpack(a, 10, 11)
assert(x == 10 && y == 11 && z == nil);
a, x = unpack({
1
})
assert(a == 1 && x == nil);
a, x = unpack({
1,
2
}, 1, 1)
assert(a == 1 && x == nil);
{
local maxi = (1 << 31) - 1
local mini = -(1 << 31)
checkerror("too many results", unpack, {}, 0, maxi);
checkerror("too many results", unpack, {}, 1, maxi);
checkerror("too many results", unpack, {}, 0, maxI);
checkerror("too many results", unpack, {}, 1, maxI);
checkerror("too many results", unpack, {}, mini, maxi);
checkerror("too many results", unpack, {}, -maxi, maxi);
checkerror("too many results", unpack, {}, minI, maxI);
unpack({}, maxi, 0);
unpack({}, maxi, 1);
unpack({}, maxI, minI);
pcall(unpack, {}, 1, maxi + 1);
local a, b = unpack({
maxi = 20
}, maxi, maxi)
assert(a == 20 && b == nil);
a, b = unpack({
maxi = 20
}, maxi - 1, maxi)
assert(a == nil && b == 20);
local t = {
maxI - 1 = 12,
maxI = 23
}
a, b = unpack(t, maxI - 1, maxI)
assert(a == 12 && b == 23);
a, b = unpack(t, maxI, maxI)
assert(a == 23 && b == nil);
a, b = unpack(t, maxI, maxI - 1)
assert(a == nil && b == nil);
t = {
minI = 12.3,
minI + 1 = 23.5
}
a, b = unpack(t, minI, minI + 1)
assert(a == 12.3 && b == 23.5);
a, b = unpack(t, minI, minI)
assert(a == 12.3 && b == nil);
a, b = unpack(t, minI + 1, minI)
assert(a == nil && b == nil);
}
{
local t = setmetatable({}, {
__len = fn () {
return 'abc'
}
})
assert(#t == 'abc');
checkerror("object length is not an integer", table.insert, t, 1);
}
print("testing pack");
a = table.pack()
assert(a[(1)] == undef && a.n == 0);
a = table.pack(table)
assert(a[(1)] == table && a.n == 1);
a = table.pack(nil, nil, nil, nil)
assert(a[(1)] == nil && a.n == 4);
{
checkerror("table expected", table.move, 1, 2, 3, 4);
local fn eqT(a, b) {
for k, v with pairs(a) {
assert(b[(k)] == v);
}
for k, v with pairs(b) {
assert(a[(k)] == v);
}
}
local a = table.move({
10,
20,
30
}, 1, 3, 2)
eqT(a, {
10,
10,
20,
30
});
a = table.move({
10,
20,
30
}, 1, 3, 3)
eqT(a, {
10,
20,
10,
20,
30
});
a = {
10,
20,
30,
40
}
table.move(a, 1, 4, 2, a);
eqT(a, {
10,
10,
20,
30,
40
});
a = table.move({
10,
20,
30
}, 2, 3, 1)
eqT(a, {
20,
30,
30
});
a = {}
assert(table.move({
10,
20,
30
}, 1, 3, 1, a) == a);
eqT(a, {
10,
20,
30
});
a = {}
assert(table.move({
10,
20,
30
}, 1, 0, 3, a) == a);
eqT(a, {});
a = table.move({
10,
20,
30
}, 1, 10, 1)
eqT(a, {
10,
20,
30
});
a = table.move({
maxI - 2 = 1,
maxI - 1 = 2,
maxI = 3
}, maxI - 2, maxI, -10, {})
eqT(a, {
-10 = 1,
-9 = 2,
-8 = 3
});
a = table.move({
minI = 1,
minI + 1 = 2,
minI + 2 = 3
}, minI, minI + 2, -10, {})
eqT(a, {
-10 = 1,
-9 = 2,
-8 = 3
});
a = table.move({
45
}, 1, 1, maxI)
eqT(a, {
45,
maxI = 45
});
a = table.move({
maxI = 100
}, maxI, maxI, minI)
eqT(a, {
minI = 100,
maxI = 100
});
a = table.move({
minI = 100
}, minI, minI, maxI)
eqT(a, {
minI = 100,
maxI = 100
});
a = setmetatable({}, {
__index = fn (_, k) {
return k * 10
},
__newindex = error
})
local b = table.move(a, 1, 10, 3, {})
eqT(a, {});
eqT(b, {
nil,
nil,
10,
20,
30,
40,
50,
60,
70,
80,
90,
100
});
b = setmetatable({
""
}, {
__index = error,
__newindex = fn (t, k, v) {
t[(1)] = string.format("%s(%d,%d)", t[(1)], k, v)
}
})
table.move(a, 10, 13, 3, b);
assert(b[(1)] == "(3,100)(4,110)(5,120)(6,130)");
local stat, msg = pcall(table.move, b, 10, 13, 3, b)
assert(!stat && msg == b);
}
{
local fn checkmove(f, e, t, x, y) {
local pos1, pos2
local a = setmetatable({}, {
__index = fn (_, k) {
pos1 = k
},
__newindex = fn (_, k) {
pos2 = k
error();
}
})
local st, msg = pcall(table.move, a, f, e, t)
assert(!st && !msg && pos1 == x && pos2 == y);
}
checkmove(1, maxI, 0, 1, 0);
checkmove(0, maxI - 1, 1, maxI - 1, maxI);
checkmove(minI, -2, -5, -2, maxI - 6);
checkmove(minI + 1, -1, -2, -1, maxI - 3);
checkmove(minI, -2, 0, minI, 0);
checkmove(minI + 1, -1, 1, minI + 1, 1);
}
checkerror("too many", table.move, {}, 0, maxI, 1);
checkerror("too many", table.move, {}, -1, maxI - 1, 1);
checkerror("too many", table.move, {}, minI, -1, 1);
checkerror("too many", table.move, {}, minI, maxI, 1);
checkerror("wrap around", table.move, {}, 1, maxI, 2);
checkerror("wrap around", table.move, {}, 1, 2, maxI);
checkerror("wrap around", table.move, {}, minI, -2, 2);
print("testing sort");
local a = setmetatable({}, {
__len = fn () {
return -1
}
})
assert(#a == -1);
table.sort(a, error);
a = setmetatable({}, {
__len = fn () {
return maxI
}
})
checkerror("too big", table.sort, a);
local fn check(t) {
local fn f(a, b) {
assert(a && b);
return true
}
checkerror("invalid order function", table.sort, t, f);
}
check({
1,
2,
3,
4
});
check({
1,
2,
3,
4,
5
});
check({
1,
2,
3,
4,
5,
6
});
global fn check(a, f) {
f = f || fn (x, y) {
return x < y
}
for n = #a, 2, -1 {
assert(!f(a[(n)], a[(n - 1)]));
}
}
a = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
}
table.sort(a);
check(a);
global fn perm(s, n) {
n = n || #s
if n == 1 {
local t = {
unpack(s)
}
table.sort(t);
check(t);
} else {
for i = 1, n {
s[(i)], s[(n)] = s[(n)], s[(i)]
perm(s, n - 1);
s[(i)], s[(n)] = s[(n)], s[(i)]
}
}
}
perm({});
perm({
1
});
perm({
1,
2
});
perm({
1,
2,
3
});
perm({
1,
2,
3,
4
});
perm({
2,
2,
3,
4
});
perm({
1,
2,
3,
4,
5
});
perm({
1,
2,
3,
3,
5
});
perm({
1,
2,
3,
4,
5,
6
});
perm({
2,
2,
3,
3,
5,
6
});
global fn timesort(a, n, func, msg, pre) {
local x = os.clock()
table.sort(a, func);
x = (os.clock() - x) * 1000
pre = pre || ""
print(string.format("%ssorting %d %s elements in %.2f msec.", pre, n, msg, x));
check(a, func);
}
limit = 50000
if _soft {
limit = 5000
}
a = {}
for i = 1, limit {
a[(i)] = math.random()
}
timesort(a, limit, nil, "random");
timesort(a, limit, nil, "sorted", "re-");
a = {}
for i = 1, limit {
a[(i)] = math.random()
}
x = os.clock()
i = 0
table.sort(a, fn (x, y) {
i = i + 1
return y < x
});
x = (os.clock() - x) * 1000
print(string.format("Invert-sorting other %d elements in %.2f msec., with %i comparisons", limit, x, i));
check(a, fn (x, y) {
return y < x
});
table.sort({});
for i = 1, limit {
a[(i)] = false
}
timesort(a, limit, fn (x, y) {
return nil
}, "equal");
for i, v with pairs(a) {
assert(v == false);
}
A = {
"álo",
"\0first :-)",
"alo",
"then this one",
"45",
"and a new"
}
table.sort(A);
check(A);
table.sort(A, fn (x, y) {
load(string.format("A[%q] = ''", x), "")();
collectgarbage();
return x < y
});
tt = {
__lt = fn (a, b) {
return a.val < b.val
}
}
a = {}
for i = 1, 10 {
a[(i)] = {
val = math.random(100)
}
setmetatable(a[(i)], tt);
}
table.sort(a);
check(a, tt.__lt);
check(a);
print("OK");