local
	tableutil
= ...

testassert(tableutil.equal(1, 1))
testassert(not tableutil.equal(1, 2))

testassert(tableutil.equal("foo", "foo"))
testassert(not tableutil.equal("foo", "bar"))

testassert(tableutil.equal(true, true))
testassert(not tableutil.equal(true, false))

testassert(tableutil.equal(nil, nil))
testassert(not tableutil.equal(nil, false))

local a = { 1, 2 }
local b = { 1, 2 }

testassert(tableutil.equal(a, b))

local a1 = { 1, { 1, 2, 3 } }
local b1 = { 1, { 1, 2, 3 } }

testassert(tableutil.equal(a1, b1))

local a1x = { 1, { 1, 2, 4 } }
testassert(not tableutil.equal(a1x, b1))

local a2 = { "foo", "bar" }
local b2 = { "foo", "bar" }

testassert(tableutil.equal(a2, b2))

local a2x = { "foo", "baz" }
testassert(not tableutil.equal(a2x, b2))

local a3 =
{
	a = "foo",
	b = "bar",
	c = "baz",
	d = a,
	e = a1,
	f = a2
}

local b3 =
{
	a = "foo",
	b = "bar",
	c = "baz",
	d = b,
	e = b1,
	f = b2
}

testassert(tableutil.equal(a3, b3))

local a3x =
{
	a = "foo",
	b = "bar",
	c = "bar",
	d = a,
	e = a1,
	f = a2
}

testassert(not tableutil.equal(a3x, b3))

local a4 = {}

a4.p = a4

local b4 = {}

b4.p = b4

testassert(tableutil.equal(a4, b4))

local a5 =
{
	a = a3,
	b = a4
}

a5.p = a5.b
a5.n = a5

local b5 =
{
	a = b3,
	b = b4
}

b5.p = b5.b
b5.n = b5

testassert(tableutil.equal(a5, b5))

local a5x =
{
	a = a3,
	b = a4,
}

a5x.p = a5x.b
a5x.n = a5x
a5x.k = a4

testassert(not tableutil.equal(a5x, b5))

local a6 =
{
	a = a5,
	b = a4,
	c = a3
}

local b6 =
{
	a = b5,
	b = b4,
	c = b3
}

testassert(tableutil.equal(a6, b6))

local a6x =
{
	a = a5,
	b = a3,
	c = a4
}

testassert(not tableutil.equal(a6x, b6))

local a7 =
{
	[a1] = a3,
	[a2] = a4,
	[a3] = a5,
	[a4] = a6,
}

a7[a7] = a7

local b7 =
{
	[b1] = b3,
	[b2] = b4,
	[b3] = b5,
	[b4] = b6
}

b7[b7] = b7

testassert(tableutil.equal(a7, b7))

local a7x =
{
	[a1] = a3,
	[a2] = a4,
	[a3] = a3,
	[a4] = a6,
}

a7x[a7x] = a7x

testassert(not tableutil.equal(a7x, b7))

local ac = tableutil.clone(a)
testassert(not (a == ac))
testassert(tableutil.equal(a, ac))

local a1c = tableutil.clone(a1)
testassert(not (a1 == a1c))
testassert(tableutil.equal(a1, a1c))

local a2c = tableutil.clone(a2)
testassert(not (a2 == a2c))
testassert(tableutil.equal(a2, a2c))

local a3c = tableutil.clone(a3)
testassert(not (a3 == a3c))
testassert(tableutil.equal(a3, a3c))

local a4c = tableutil.clone(a4)
testassert(not (a4 == a4c))
testassert(tableutil.equal(a4, a4c))

local a5c = tableutil.clone(a5)
testassert(not (a5 == a5c))
testassert(tableutil.equal(a5, a5c))

local a6c = tableutil.clone(a6)
testassert(not (a6 == a6c))
testassert(tableutil.equal(a6, a6c))

local a7c = tableutil.clone(a7)
testassert(not (a7 == a7c))
testassert(tableutil.equal(a7, a7c))

local s1 =
{
	a = true,
	b = true,
	c = true,
	d = true
}

local s2 =
{
	a = true,
	d = true
}

local s3 =
{
	b = true,
	c = true
}

local s4 =
{
	c = true,
	d = true,
	e = true,
	f = true
}

local s5 =
{
	a = true,
	b = true
}

local s6 =
{
	e = true,
	f = true
}

testassert(tableutil.equal(s3, tableutil.complement(s2, s1)))
testassert(tableutil.equal({}, tableutil.complement(s1, s2)))
testassert(tableutil.equal(s2, tableutil.complement(s3, s1)))
testassert(tableutil.equal({}, tableutil.complement(s1, s3)))
testassert(tableutil.equal(s5, tableutil.complement(s4, s1)))
testassert(tableutil.equal(s6, tableutil.complement(s1, s4)))

setmetatable(a1, a2)
setmetatable(b1, b2)
testassert(tableutil.equal(a1, b1))

setmetatable(a2, a1)
setmetatable(b2, b1)
testassert(tableutil.equal(a2, b2))

setmetatable(a3, a2)
setmetatable(b3, b2)
testassert(tableutil.equal(a3, b3))

setmetatable(a4, a3)
setmetatable(b4, b3)
testassert(tableutil.equal(a4, b4))

setmetatable(a5, a4)
setmetatable(b5, b4)
testassert(tableutil.equal(a5, b5))

setmetatable(a6, a5)
setmetatable(b6, b5)
testassert(tableutil.equal(a6, b6))

testassert(tableutil.equal(a1, tableutil.clone(a1)))
testassert(tableutil.equal(a2, tableutil.clone(a2)))
testassert(tableutil.equal(a3, tableutil.clone(a3)))
testassert(tableutil.equal(a4, tableutil.clone(a4)))
testassert(tableutil.equal(a5, tableutil.clone(a5)))
testassert(tableutil.equal(a6, tableutil.clone(a6)))
