Skip to content

Commit bfb1463

Browse files
committed
Port the rest of the owl
1 parent c370f19 commit bfb1463

9 files changed

Lines changed: 768 additions & 234 deletions

File tree

spec/System/TestCommon_spec.lua

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
describe("Common", function()
2+
describe("Class creation and use", function()
3+
it("produces error when parent constructors are not called", function()
4+
local ParentClass = newClass("ConstructorTestParentClass")
5+
function ParentClass:ConstructorTestParentClass()
6+
return self
7+
end
8+
local ChildClass = newClass("ConstructorTestProblemChildClass", "ConstructorTestParentClass")
9+
function ChildClass:ConstructorTestProblemChild()
10+
-- Intentionally does not call self:ConstructorTestParentClass()
11+
return self
12+
end
13+
common.classes.ConstructorTestParent = ParentClass
14+
common.classes.ConstructorTestProblemChild = ChildClass
15+
16+
assert.has_error(function()
17+
new("ConstructorTestProblemChild"):init()
18+
end, "Parent class 'ConstructorTestParentClass' of class 'ConstructorTestProblemChild' must be initialised")
19+
common.classes.ConstructorTestParent = nil
20+
common.classes.ConstructorTestProblemChild = nil
21+
end)
22+
it("produces an error if additional arguments are passed", function()
23+
local StupidClass = newClass("NewAbuse")
24+
function StupidClass:NewAbuse(someParam)
25+
return self
26+
end
27+
28+
common.classes.NewAbuse = StupidClass
29+
30+
assert.has_no.errors(function()
31+
local newObj = new("NewAbuse"):init("fish")
32+
end)
33+
assert.has_error(function()
34+
local newObj = new("NewAbuse", "look I'm using the old syntax")
35+
end)
36+
end)
37+
it("produces an error if it calls a parent class without giving it self", function()
38+
local ParentClass = newClass("ConstructorTestParentClass")
39+
function ParentClass:ConstructorTestParentClass()
40+
return self
41+
end
42+
43+
local ChildClass = newClass("ConstructorTestProblemChildClass", "ConstructorTestParentClass")
44+
function ChildClass:ConstructorTestProblemChild()
45+
self.ConstructorTestParentClass()
46+
return self
47+
end
48+
49+
common.classes.ConstructorTestParent = ParentClass
50+
common.classes.ConstructorTestProblemChild = ChildClass
51+
52+
assert.has_error(function()
53+
new("ConstructorTestProblemChild"):init()
54+
end)
55+
common.classes.ConstructorTestParent = nil
56+
common.classes.ConstructorTestProblemChild = nil
57+
end)
58+
it("produces an error if its constructor doesn't return the object", function()
59+
local StupidClass = newClass("StupidClass")
60+
function StupidClass:StupidClass()
61+
end
62+
63+
common.classes.StupidClass = StupidClass
64+
65+
assert.has_error(function()
66+
new("StupidClass"):init()
67+
end, "Class StupidClass constructor did not return a value")
68+
end)
69+
end)
70+
end)

spec/System/TestUtils_spec.lua

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
describe("Utils.stringify", function()
2+
local utils = require("Modules/Utils")
3+
4+
-- Parses stringify output back into a Lua value
5+
local function serializeAndLoad(value, allowNewlines)
6+
local str = utils.stringify(value, allowNewlines)
7+
local chunk, err = loadstring("return " .. str)
8+
assert.is_truthy(chunk)
9+
return chunk(), str
10+
end
11+
12+
describe("scalars", function()
13+
it("stringifies strings with quotes", function()
14+
assert.equal('"hello"', utils.stringify("hello"))
15+
end)
16+
17+
it("strips newlines from strings by default", function()
18+
assert.equal('"a b"', utils.stringify("a\nb"))
19+
end)
20+
21+
it("preserves newlines when allowed", function()
22+
local out = serializeAndLoad("a\nb", true)
23+
assert.equal("a\nb", out)
24+
end)
25+
26+
it("does not use long string form for newline-free strings", function()
27+
assert.equal('"ab"', utils.stringify("ab", true))
28+
end)
29+
30+
it("escapes quotes and backslashes", function()
31+
local input = 'a"b\\c'
32+
local out = serializeAndLoad(input, true)
33+
assert.equal(input, out)
34+
end)
35+
36+
it("preserves carriage returns and long-string delimiters when allowed", function()
37+
local input = "a\r\n]]b"
38+
local out = serializeAndLoad(input, true)
39+
assert.equal(input, out)
40+
end)
41+
42+
it("normalizes all newline forms when newlines are disabled", function()
43+
assert.equal('"a b c"', utils.stringify("a\r\nb\rc"))
44+
end)
45+
46+
it("stringifies numbers", function()
47+
assert.equal("42", utils.stringify(42))
48+
assert.equal("-3.5", utils.stringify(-3.5))
49+
end)
50+
51+
it("stringifies booleans", function()
52+
assert.equal("true", utils.stringify(true))
53+
assert.equal("false", utils.stringify(false))
54+
end)
55+
56+
it("stringifies nil", function()
57+
assert.equal("nil", utils.stringify(nil))
58+
end)
59+
60+
-- supposedly these are valid table keys, but like come on
61+
it("errors on disallowed types", function()
62+
assert.has_error(function() utils.stringify(function() end) end)
63+
assert.has_error(function() utils.stringify({ [function() end] = "hello" }) end)
64+
end)
65+
end)
66+
67+
describe("tables", function()
68+
it("serializes and loads an empty table", function()
69+
local out = serializeAndLoad({})
70+
assert.same({}, out)
71+
end)
72+
73+
it("serializes and loads an array using array syntax", function()
74+
local input = { 1, 2, 3 }
75+
local out, str = serializeAndLoad(input)
76+
assert.same(input, out)
77+
-- array entries should not include explicit keys
78+
assert.is_nil(str:find("%[1%]"))
79+
end)
80+
81+
it("serializes and loads a string-keyed map", function()
82+
local input = { foo = "bar", baz = 1 }
83+
local out = serializeAndLoad(input)
84+
assert.same(input, out)
85+
end)
86+
87+
it("serializes and loads nested tables (no mixed array/map levels)", function()
88+
local input = { a = { b = { c = { deep = true, value = 3 } } }, list = { "x", "y" } }
89+
local out = serializeAndLoad(input)
90+
assert.same(input, out)
91+
end)
92+
93+
it("sorts map keys deterministically", function()
94+
local str = utils.stringify({ c = 1, a = 1, b = 1 })
95+
local posA = str:find('%["a"%]')
96+
local posB = str:find('%["b"%]')
97+
local posC = str:find('%["c"%]')
98+
assert.is_truthy(posA < posB and posB < posC)
99+
end)
100+
101+
it("serializes and loads numeric (non-sequential) keys", function()
102+
local input = { [5] = "five", [10] = "ten" }
103+
local out = serializeAndLoad(input)
104+
assert.same(input, out)
105+
end)
106+
107+
it("serializes and loads multiline string values when allowed", function()
108+
local input = { text = "line1\nline2" }
109+
local out = serializeAndLoad(input, true)
110+
assert.same(input, out)
111+
end)
112+
113+
it("serializes and loads escaped multiline string keys", function()
114+
local input = { ['a"\\b\n]]c'] = true }
115+
local out = serializeAndLoad(input, true)
116+
assert.same(input, out)
117+
end)
118+
119+
it("serializes and loads mixed tables", function()
120+
local input = { "one", "two", six = 7, 3, 4, five = "six" }
121+
local str = utils.stringify(input, false, 1)
122+
assert.equal([[{
123+
"one",
124+
"two",
125+
3,
126+
4,
127+
["five"] = "six",
128+
["six"] = 7,
129+
}]], str)
130+
local out = serializeAndLoad(input)
131+
assert.same(input, out)
132+
end)
133+
end)
134+
end)

0 commit comments

Comments
 (0)