Skip to content

Commit 4bd0a67

Browse files
authored
test: Rewrite tests to be table driven, with useful output (#5)
Signed-off-by: James Hillyerd <[email protected]>
1 parent 1b32545 commit 4bd0a67

File tree

1 file changed

+180
-71
lines changed

1 file changed

+180
-71
lines changed

json_test.go

Lines changed: 180 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,97 +2,195 @@ package json
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"testing"
67

7-
"github.com/yuin/gopher-lua"
8+
lua "github.com/yuin/gopher-lua"
89
)
910

10-
func TestSimple(t *testing.T) {
11-
const str = `
12-
local json = require("json")
13-
assert(type(json) == "table")
14-
assert(type(json.decode) == "function")
15-
assert(type(json.encode) == "function")
16-
17-
assert(json.encode(true) == "true")
18-
assert(json.encode(1) == "1")
19-
assert(json.encode(-10) == "-10")
20-
assert(json.encode(nil) == "null")
21-
assert(json.encode({}) == "[]")
22-
assert(json.encode({1, 2, 3}) == "[1,2,3]")
23-
24-
local _, err = json.encode({1, 2, [10] = 3})
25-
assert(string.find(err, "sparse array"))
26-
27-
local _, err = json.encode({1, 2, 3, name = "Tim"})
28-
assert(string.find(err, "mixed or invalid key types"))
29-
30-
local _, err = json.encode({name = "Tim", [false] = 123})
31-
assert(string.find(err, "mixed or invalid key types"))
32-
33-
local obj = {"a",1,"b",2,"c",3}
34-
local jsonStr = json.encode(obj)
35-
local jsonObj = json.decode(jsonStr)
36-
for i = 1, #obj do
37-
assert(obj[i] == jsonObj[i])
11+
// LuaInit holds globals available to callers of newLuaState().
12+
const LuaInit = `
13+
json = require("json")
14+
15+
-- Tests plain values and list-style tables.
16+
function assert_eq(got, want)
17+
if type(got) == "table" and type(want) == "table" then
18+
assert(#got == #want, string.format("got %d elements, wanted %d", #got, #want))
19+
20+
for i, gotv in ipairs(got) do
21+
local wantv = want[i]
22+
assert_eq(gotv, wantv, "got[%d] = %q, wanted %q", gotv, wantv)
23+
end
24+
25+
return
26+
end
27+
28+
assert(got == want, string.format("got %q, wanted %q", got, want))
3829
end
3930
40-
local obj = {name="Tim",number=12345}
41-
local jsonStr = json.encode(obj)
42-
local jsonObj = json.decode(jsonStr)
43-
assert(obj.name == jsonObj.name)
44-
assert(obj.number == jsonObj.number)
31+
function assert_contains(got, want)
32+
assert(string.find(got, want),
33+
string.format("got %q, wanted it to contain %q", got, want))
34+
end
35+
`
36+
37+
func TestRequire(t *testing.T) {
38+
const code = `
39+
local j = require("json")
40+
assert(type(j) == "table")
41+
assert(type(j.decode) == "function")
42+
assert(type(j.encode) == "function")
43+
`
4544

46-
assert(json.decode("null") == nil)
45+
ls := lua.NewState()
46+
defer ls.Close()
4747

48-
local status, err = pcall(function() json.decode() end)
49-
assert(err == "<string>:38: bad argument #1 to decode", err)
50-
local status, err = pcall(function() json.decode(1,2) end)
51-
assert(err == "<string>:40: bad argument #1 to decode", err)
52-
local status, err = pcall(function() json.encode() end)
53-
assert(err == "<string>:42: bad argument #1 to encode", err)
54-
local status, err = pcall(function() json.encode(1,2) end)
55-
assert(err == "<string>:44: bad argument #1 to encode", err)
48+
ls.PreloadModule("json", Loader)
49+
if err := ls.DoString(code); err != nil {
50+
t.Error(err)
51+
}
52+
}
5653

57-
assert(json.decode(json.encode({person={name = "tim",}})).person.name == "tim")
54+
func TestEncodeValues(t *testing.T) {
55+
tcs := map[string]struct {
56+
expr, want string
57+
}{
58+
"true": {"true", "true"},
59+
"false": {"false", "false"},
60+
"integer": {"42", "42"},
61+
"negative int": {"-10", "-10"},
62+
"float": {"1.234", "1.234"},
63+
"nil": {"nil", "null"},
64+
"empty list": {"{}", "[]"},
65+
"number list": {"{1, 2, 3}", "[1,2,3]"},
66+
"string list": {"{'a', 'b', 'c'}", `["a","b","c"]`},
67+
}
5868

59-
local obj = {
60-
abc = 123,
61-
def = nil,
69+
ls := newLuaState()
70+
defer ls.Close()
71+
72+
for name, tc := range tcs {
73+
tc := tc
74+
t.Run(name, func(t *testing.T) {
75+
code := fmt.Sprintf("assert_eq(json.encode(%s), %q)\n", tc.expr, tc.want)
76+
if err := ls.DoString(code); err != nil {
77+
t.Error(code, err)
78+
}
79+
})
6280
}
63-
local obj2 = {
64-
obj = obj,
81+
}
82+
83+
func TestEncodeErrors(t *testing.T) {
84+
const code = `
85+
local _, err = json.encode({1, 2, [10] = 3})
86+
assert_contains(err, "sparse array")
87+
88+
local _, err = json.encode({1, 2, 3, name = "Tim"})
89+
assert_contains(err, "mixed or invalid key types")
90+
91+
local _, err = json.encode({name = "Tim", [false] = 123})
92+
assert_contains(err, "mixed or invalid key types")
93+
`
94+
95+
ls := newLuaState()
96+
defer ls.Close()
97+
98+
if err := ls.DoString(code); err != nil {
99+
t.Error(code, err)
65100
}
66-
obj.obj2 = obj2
67-
assert(json.encode(obj) == nil)
101+
}
68102

69-
local a = {}
70-
for i=1, 5 do
71-
a[i] = i
72-
end
73-
assert(json.encode(a) == "[1,2,3,4,5]")
103+
func TestDecodeValues(t *testing.T) {
104+
tcs := map[string]struct {
105+
input, expr string
106+
}{
107+
"true": {"true", "true"},
108+
"false": {"false", "false"},
109+
"integer": {"42", "42"},
110+
"negative int": {"-10", "-10"},
111+
"float": {"1.234", "1.234"},
112+
"null": {"null", "nil"},
113+
"empty list": {"[]", "{}"},
114+
"number list": {"[1, 2, 3]", "{1, 2, 3}"},
115+
"string list": {`["a", "b", "c"]`, "{'a', 'b', 'c'}"},
116+
}
117+
118+
ls := newLuaState()
119+
defer ls.Close()
120+
121+
for name, tc := range tcs {
122+
tc := tc
123+
t.Run(name, func(t *testing.T) {
124+
code := fmt.Sprintf(`
125+
local got, err = json.decode(%q)
126+
if err ~= nil then error(err) end
127+
assert_eq(got, %s)
128+
`, tc.input, tc.expr)
129+
130+
if err := ls.DoString(code); err != nil {
131+
t.Error(code, err)
132+
}
133+
})
134+
}
135+
}
136+
137+
func TestIncorrectArgLens(t *testing.T) {
138+
const code = `
139+
local status, err = pcall(function() json.decode() end)
140+
assert_contains(err, "bad argument #1 to decode")
141+
142+
local status, err = pcall(function() json.decode(1,2) end)
143+
assert_contains(err, "bad argument #1 to decode")
144+
145+
local status, err = pcall(function() json.encode() end)
146+
assert_contains(err, "bad argument #1 to encode")
147+
148+
local status, err = pcall(function() json.encode(1,2) end)
149+
assert_contains(err, "bad argument #1 to encode")
74150
`
75-
s := lua.NewState()
76-
defer s.Close()
77151

78-
s.PreloadModule("json", Loader)
79-
if err := s.DoString(str); err != nil {
80-
t.Error(err)
152+
ls := newLuaState()
153+
defer ls.Close()
154+
155+
if err := ls.DoString(code); err != nil {
156+
t.Error(code, err)
81157
}
82158
}
83159

84-
func TestCustomRequire(t *testing.T) {
85-
const str = `
86-
local j = require("JSON")
87-
assert(type(j) == "table")
88-
assert(type(j.decode) == "function")
89-
assert(type(j.encode) == "function")
160+
func TestComplexCases(t *testing.T) {
161+
const code = `
162+
-- Table round-trip.
163+
local obj = {"a",1,"b",2,"c",3}
164+
local jsonStr = json.encode(obj)
165+
local jsonObj = json.decode(jsonStr)
166+
assert_eq(jsonObj, obj)
167+
168+
-- Table round-trip.
169+
local obj = {name="Tim",number=12345}
170+
local jsonStr = json.encode(obj)
171+
local jsonObj = json.decode(jsonStr)
172+
assert_eq(jsonObj.name, obj.name)
173+
assert_eq(jsonObj.number, obj.number)
174+
175+
-- Table round-trip.
176+
assert(json.decode(json.encode({person={name = "tim",}})).person.name == "tim")
177+
178+
-- Recursion.
179+
local obj = {
180+
abc = 123,
181+
def = nil,
182+
}
183+
local obj2 = {
184+
obj = obj,
185+
}
186+
obj.obj2 = obj2
187+
assert(json.encode(obj) == nil)
90188
`
91-
s := lua.NewState()
92-
defer s.Close()
93189

94-
s.PreloadModule("JSON", Loader)
95-
if err := s.DoString(str); err != nil {
190+
ls := newLuaState()
191+
defer ls.Close()
192+
193+
if err := ls.DoString(code); err != nil {
96194
t.Error(err)
97195
}
98196
}
@@ -106,3 +204,14 @@ func TestDecodeValue_jsonNumber(t *testing.T) {
106204
t.Fatalf("expecting LString, got %T", v)
107205
}
108206
}
207+
208+
func newLuaState() *lua.LState {
209+
// Initialize Lua.
210+
ls := lua.NewState()
211+
ls.PreloadModule("json", Loader)
212+
if err := ls.DoString(LuaInit); err != nil {
213+
panic(err)
214+
}
215+
216+
return ls
217+
}

0 commit comments

Comments
 (0)