@@ -2,97 +2,195 @@ package json
2
2
3
3
import (
4
4
"encoding/json"
5
+ "fmt"
5
6
"testing"
6
7
7
- "github.com/yuin/gopher-lua"
8
+ lua "github.com/yuin/gopher-lua"
8
9
)
9
10
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))
38
29
end
39
30
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
+ `
45
44
46
- assert(json.decode("null") == nil)
45
+ ls := lua .NewState ()
46
+ defer ls .Close ()
47
47
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
+ }
56
53
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
+ }
58
68
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
+ })
62
80
}
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 )
65
100
}
66
- obj.obj2 = obj2
67
- assert(json.encode(obj) == nil)
101
+ }
68
102
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")
74
150
`
75
- s := lua .NewState ()
76
- defer s .Close ()
77
151
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 )
81
157
}
82
158
}
83
159
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)
90
188
`
91
- s := lua .NewState ()
92
- defer s .Close ()
93
189
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 {
96
194
t .Error (err )
97
195
}
98
196
}
@@ -106,3 +204,14 @@ func TestDecodeValue_jsonNumber(t *testing.T) {
106
204
t .Fatalf ("expecting LString, got %T" , v )
107
205
}
108
206
}
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