aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2011-05-08 02:23:57 +0930
committerMark Pulford <mark@kyne.com.au>2011-05-08 02:23:57 +0930
commit0d56e3bebecb7008f0baa7eaccf3dc9b2a39e360 (patch)
tree8c15c63f01afa79115f2b66b922bb27779df9b90
parent3d014d14bcf3dce3e5dbb9c193d689e46d333798 (diff)
downloadlua-cjson-0d56e3bebecb7008f0baa7eaccf3dc9b2a39e360.tar.gz
lua-cjson-0d56e3bebecb7008f0baa7eaccf3dc9b2a39e360.tar.bz2
lua-cjson-0d56e3bebecb7008f0baa7eaccf3dc9b2a39e360.zip
Implement data driven test framework
- Add run_test(): Test a function and verify its output - Add run_test_group(): Execute a test batch - Add serialise_value(): Serialise a Lua value into the Lua syntax - Add file_save() helper function - Add NaN comparison support to compare_values()
-rwxr-xr-xtests/bench.lua15
-rw-r--r--tests/common.lua168
-rwxr-xr-xtests/test.lua4
3 files changed, 158 insertions, 29 deletions
diff --git a/tests/bench.lua b/tests/bench.lua
index b5b1a77..847365b 100755
--- a/tests/bench.lua
+++ b/tests/bench.lua
@@ -3,11 +3,11 @@
3-- Simple JSON benchmark. 3-- Simple JSON benchmark.
4-- 4--
5-- Your Mileage May Vary. 5-- Your Mileage May Vary.
6--
7-- Mark Pulford <mark@kyne.com.au>
6 8
7require "common" 9require "common"
8local json = require "cjson" 10local json = require "cjson"
9--local json = require "json"
10--local json = require "dkjson"
11 11
12function bench_file(filename) 12function bench_file(filename)
13 local data_json = file_load(filename) 13 local data_json = file_load(filename)
@@ -28,12 +28,11 @@ function bench_file(filename)
28 return benchmark(tests, 5000, 5) 28 return benchmark(tests, 5000, 5)
29end 29end
30 30
31i = 1 31for i = 1, #arg do
32while arg[i] do 32 local results = bench_file(arg[i])
33 local results = {} 33 for k, v in pairs(results) do
34 results[arg[i]] = bench_file(arg[i]) 34 print(string.format("%s: %s: %d", arg[i], k, v))
35 dump_value(results) 35 end
36 i = i + 1
37end 36end
38 37
39-- vi:ai et sw=4 ts=4: 38-- vi:ai et sw=4 ts=4:
diff --git a/tests/common.lua b/tests/common.lua
index 219de3f..9a7ed19 100644
--- a/tests/common.lua
+++ b/tests/common.lua
@@ -1,31 +1,94 @@
1require "cjson" 1require "cjson"
2require "posix" 2require "posix"
3 3
4function dump_value(value, indent) 4-- Misc routines to assist with CJSON testing
5 if indent == nil then 5--
6 indent = "" 6-- Mark Pulford <mark@kyne.com.au>
7
8-- Determine with a Lua table can be treated as an array.
9-- Explicitly returns "not an array" for very sparse arrays.
10-- Returns:
11-- -1 Not an array
12-- 0 Empty table
13-- >0 Highest index in the array
14function is_array(table)
15 local max = 0
16 local count = 0
17 for k, v in pairs(table) do
18 if type(k) == "number" then
19 if k > max then max = k end
20 count = count + 1
21 else
22 return -1
23 end
24 end
25 if max > count * 2 then
26 return -1
7 end 27 end
8 28
9 if value == cjson.null then 29 return max
10 value = "<cjson.null>" 30end
31
32function serialise_table(value, indent)
33 local spacing, spacing2, indent2
34 if indent then
35 spacing = "\n" .. indent
36 spacing2 = spacing .. " "
37 indent2 = indent .. " "
38 else
39 spacing, spacing2, indent2 = " ", " ", false
11 end 40 end
12 41
13 if type(value) == "string" or type(value) == "number" or 42 local max = is_array(value)
14 type(value) == "boolean" then 43
15 print(indent .. tostring(value)) 44 local comma = false
16 elseif type(value) == "table" then 45 local fragment = { "{" .. spacing2 }
17 local count = 0 46 if max > 0 then
18 for k, v in pairs(value) do 47 -- Serialise array
19 dump_value(v, indent .. k .. ": ") 48 for i = 1, max do
20 count = count + 1 49 if comma then
50 table.insert(fragment, "," .. spacing2)
51 end
52 table.insert(fragment, serialise_value(value[i], indent2))
53 comma = true
21 end 54 end
22 if count == 0 then 55 elseif max < 0 then
23 print(indent .. ": <empty>") 56 -- Serialise table
57 for k, v in pairs(value) do
58 if comma then
59 table.insert(fragment, "," .. spacing2)
60 end
61 table.insert(fragment, string.format(
62 "[%s] = %s", serialise_value(k, indent2),
63 serialise_value(v, indent2))
64 )
65 comma = true
24 end 66 end
67 end
68 table.insert(fragment, spacing .. "}")
69
70 return table.concat(fragment)
71end
72
73function serialise_value(value, indent)
74 if indent == nil then indent = "" end
75
76 if value == cjson.null then
77 return "cjson.null"
78 elseif type(value) == "string" then
79 return string.format("%q", value)
80 elseif type(value) == "nil" or type(value) == "number" or
81 type(value) == "boolean" then
82 return tostring(value)
83 elseif type(value) == "table" then
84 return serialise_table(value, indent)
25 else 85 else
26 print(indent .. "<" .. type(value) .. ">") 86 return "\"<" .. type(value) .. ">\""
27 end 87 end
88end
28 89
90function dump_value(value)
91 print(serialise_value(value))
29end 92end
30 93
31function file_load(filename) 94function file_load(filename)
@@ -39,6 +102,15 @@ function file_load(filename)
39 return data 102 return data
40end 103end
41 104
105function file_save(filename, data)
106 local file, err = io.open(filename, "w")
107 if file == nil then
108 error("Unable to write " .. filename)
109 end
110 file:write(data)
111 file:close()
112end
113
42function gettimeofday() 114function gettimeofday()
43 local tv_sec, tv_usec = posix.gettimeofday() 115 local tv_sec, tv_usec = posix.gettimeofday()
44 116
@@ -82,29 +154,83 @@ function compare_values(val1, val2)
82 if type1 ~= type2 then 154 if type1 ~= type2 then
83 return false 155 return false
84 end 156 end
157
158 -- Check for NaN
159 if type1 == "number" and val1 ~= val1 and val2 ~= val2 then
160 return true
161 end
162
85 if type1 ~= "table" then 163 if type1 ~= "table" then
86 return val1 == val2 164 return val1 == val2
87 end 165 end
88 local val1_keys = {} 166
89 -- Note all the keys in val1 need to be checked 167 -- check_keys stores all the keys that must be checked in val2
168 local check_keys = {}
90 for k, _ in pairs(val1) do 169 for k, _ in pairs(val1) do
91 check_keys[k] = true 170 check_keys[k] = true
92 end 171 end
172
93 for k, v in pairs(val2) do 173 for k, v in pairs(val2) do
94 if not check_keys[k] then 174 if not check_keys[k] then
95 -- Key didn't exist in val1
96 return false 175 return false
97 end 176 end
98 if not compare_value(val1[k], val2[k]) then 177
178 if not compare_values(val1[k], val2[k]) then
99 return false 179 return false
100 end 180 end
181
101 check_keys[k] = nil 182 check_keys[k] = nil
102 end 183 end
103 for k, _ in pairs(check_keys) do 184 for k, _ in pairs(check_keys) do
104 -- Not the same if any keys left to check 185 -- Not the same if any keys from val1 were not found in val2
105 return false 186 return false
106 end 187 end
107 return true 188 return true
108end 189end
109 190
191function run_test(testname, func, input, should_work, output)
192 local function status_line(name, status, value)
193 local statusmap = { [true] = ":success", [false] = ":error" }
194 if status ~= nil then
195 name = name .. statusmap[status]
196 end
197 print(string.format("[%s] %s", name, serialise_value(value, false)))
198 end
199
200 local result = { pcall(func, unpack(input)) }
201 local success = table.remove(result, 1)
202
203 local correct = false
204 if success == should_work and compare_values(result, output) then
205 correct = true
206 end
207
208 local teststatus = { [true] = "PASS", [false] = "FAIL" }
209 print("==> Test " .. testname .. ": " .. teststatus[correct])
210
211 status_line("Input", nil, input)
212 if not correct then
213 status_line("Expected", should_work, output)
214 end
215 status_line("Received", success, result)
216 print()
217
218 return correct, result
219end
220
221function run_test_group(testgroup, tests)
222 for k, v in ipairs(tests) do
223 if type(v) == "function" then
224 -- Useful for changing configuration during a batch
225 msg = v()
226 print(string.format("==> Config %s [%d]: %s", testgroup, k, msg))
227 print()
228 elseif type(v) == "table" then
229 run_test(testgroup .. " [" .. k .. "]", unpack(v))
230 else
231 error("Testgroup can only contain functions and tables")
232 end
233 end
234end
235
110-- vi:ai et sw=4 ts=4: 236-- vi:ai et sw=4 ts=4:
diff --git a/tests/test.lua b/tests/test.lua
index 3c8c404..51f29c4 100755
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -1,5 +1,9 @@
1#!/usr/bin/env lua 1#!/usr/bin/env lua
2 2
3-- CJSON tests
4--
5-- Mark Pulford <mark@kyne.com.au>
6
3require "common" 7require "common"
4local json = require "cjson" 8local json = require "cjson"
5 9