Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpx/lua-cjson.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2011-05-07 20:53:57 +0400
committerMark Pulford <mark@kyne.com.au>2011-05-07 20:53:57 +0400
commit0d56e3bebecb7008f0baa7eaccf3dc9b2a39e360 (patch)
tree8c15c63f01afa79115f2b66b922bb27779df9b90
parent3d014d14bcf3dce3e5dbb9c193d689e46d333798 (diff)
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 @@
-- Simple JSON benchmark.
--
-- Your Mileage May Vary.
+--
+-- Mark Pulford <mark@kyne.com.au>
require "common"
local json = require "cjson"
---local json = require "json"
---local json = require "dkjson"
function bench_file(filename)
local data_json = file_load(filename)
@@ -28,12 +28,11 @@ function bench_file(filename)
return benchmark(tests, 5000, 5)
end
-i = 1
-while arg[i] do
- local results = {}
- results[arg[i]] = bench_file(arg[i])
- dump_value(results)
- i = i + 1
+for i = 1, #arg do
+ local results = bench_file(arg[i])
+ for k, v in pairs(results) do
+ print(string.format("%s: %s: %d", arg[i], k, v))
+ end
end
-- 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 @@
require "cjson"
require "posix"
-function dump_value(value, indent)
- if indent == nil then
- indent = ""
+-- Misc routines to assist with CJSON testing
+--
+-- Mark Pulford <mark@kyne.com.au>
+
+-- Determine with a Lua table can be treated as an array.
+-- Explicitly returns "not an array" for very sparse arrays.
+-- Returns:
+-- -1 Not an array
+-- 0 Empty table
+-- >0 Highest index in the array
+function is_array(table)
+ local max = 0
+ local count = 0
+ for k, v in pairs(table) do
+ if type(k) == "number" then
+ if k > max then max = k end
+ count = count + 1
+ else
+ return -1
+ end
+ end
+ if max > count * 2 then
+ return -1
end
- if value == cjson.null then
- value = "<cjson.null>"
+ return max
+end
+
+function serialise_table(value, indent)
+ local spacing, spacing2, indent2
+ if indent then
+ spacing = "\n" .. indent
+ spacing2 = spacing .. " "
+ indent2 = indent .. " "
+ else
+ spacing, spacing2, indent2 = " ", " ", false
end
- if type(value) == "string" or type(value) == "number" or
- type(value) == "boolean" then
- print(indent .. tostring(value))
- elseif type(value) == "table" then
- local count = 0
- for k, v in pairs(value) do
- dump_value(v, indent .. k .. ": ")
- count = count + 1
+ local max = is_array(value)
+
+ local comma = false
+ local fragment = { "{" .. spacing2 }
+ if max > 0 then
+ -- Serialise array
+ for i = 1, max do
+ if comma then
+ table.insert(fragment, "," .. spacing2)
+ end
+ table.insert(fragment, serialise_value(value[i], indent2))
+ comma = true
end
- if count == 0 then
- print(indent .. ": <empty>")
+ elseif max < 0 then
+ -- Serialise table
+ for k, v in pairs(value) do
+ if comma then
+ table.insert(fragment, "," .. spacing2)
+ end
+ table.insert(fragment, string.format(
+ "[%s] = %s", serialise_value(k, indent2),
+ serialise_value(v, indent2))
+ )
+ comma = true
end
+ end
+ table.insert(fragment, spacing .. "}")
+
+ return table.concat(fragment)
+end
+
+function serialise_value(value, indent)
+ if indent == nil then indent = "" end
+
+ if value == cjson.null then
+ return "cjson.null"
+ elseif type(value) == "string" then
+ return string.format("%q", value)
+ elseif type(value) == "nil" or type(value) == "number" or
+ type(value) == "boolean" then
+ return tostring(value)
+ elseif type(value) == "table" then
+ return serialise_table(value, indent)
else
- print(indent .. "<" .. type(value) .. ">")
+ return "\"<" .. type(value) .. ">\""
end
+end
+function dump_value(value)
+ print(serialise_value(value))
end
function file_load(filename)
@@ -39,6 +102,15 @@ function file_load(filename)
return data
end
+function file_save(filename, data)
+ local file, err = io.open(filename, "w")
+ if file == nil then
+ error("Unable to write " .. filename)
+ end
+ file:write(data)
+ file:close()
+end
+
function gettimeofday()
local tv_sec, tv_usec = posix.gettimeofday()
@@ -82,29 +154,83 @@ function compare_values(val1, val2)
if type1 ~= type2 then
return false
end
+
+ -- Check for NaN
+ if type1 == "number" and val1 ~= val1 and val2 ~= val2 then
+ return true
+ end
+
if type1 ~= "table" then
return val1 == val2
end
- local val1_keys = {}
- -- Note all the keys in val1 need to be checked
+
+ -- check_keys stores all the keys that must be checked in val2
+ local check_keys = {}
for k, _ in pairs(val1) do
check_keys[k] = true
end
+
for k, v in pairs(val2) do
if not check_keys[k] then
- -- Key didn't exist in val1
return false
end
- if not compare_value(val1[k], val2[k]) then
+
+ if not compare_values(val1[k], val2[k]) then
return false
end
+
check_keys[k] = nil
end
for k, _ in pairs(check_keys) do
- -- Not the same if any keys left to check
+ -- Not the same if any keys from val1 were not found in val2
return false
end
return true
end
+function run_test(testname, func, input, should_work, output)
+ local function status_line(name, status, value)
+ local statusmap = { [true] = ":success", [false] = ":error" }
+ if status ~= nil then
+ name = name .. statusmap[status]
+ end
+ print(string.format("[%s] %s", name, serialise_value(value, false)))
+ end
+
+ local result = { pcall(func, unpack(input)) }
+ local success = table.remove(result, 1)
+
+ local correct = false
+ if success == should_work and compare_values(result, output) then
+ correct = true
+ end
+
+ local teststatus = { [true] = "PASS", [false] = "FAIL" }
+ print("==> Test " .. testname .. ": " .. teststatus[correct])
+
+ status_line("Input", nil, input)
+ if not correct then
+ status_line("Expected", should_work, output)
+ end
+ status_line("Received", success, result)
+ print()
+
+ return correct, result
+end
+
+function run_test_group(testgroup, tests)
+ for k, v in ipairs(tests) do
+ if type(v) == "function" then
+ -- Useful for changing configuration during a batch
+ msg = v()
+ print(string.format("==> Config %s [%d]: %s", testgroup, k, msg))
+ print()
+ elseif type(v) == "table" then
+ run_test(testgroup .. " [" .. k .. "]", unpack(v))
+ else
+ error("Testgroup can only contain functions and tables")
+ end
+ end
+end
+
-- 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 @@
#!/usr/bin/env lua
+-- CJSON tests
+--
+-- Mark Pulford <mark@kyne.com.au>
+
require "common"
local json = require "cjson"