diff options
| -rw-r--r-- | lua_cjson.c | 14 | ||||
| -rw-r--r-- | tests/TestLua.pm | 70 | ||||
| -rw-r--r-- | tests/agentzh.t | 41 |
3 files changed, 124 insertions, 1 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index c14a1c5..97f2350 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #define DEFAULT_DECODE_INVALID_NUMBERS 1 | 68 | #define DEFAULT_DECODE_INVALID_NUMBERS 1 |
| 69 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 | 69 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 |
| 70 | #define DEFAULT_ENCODE_NUMBER_PRECISION 14 | 70 | #define DEFAULT_ENCODE_NUMBER_PRECISION 14 |
| 71 | #define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 1 | ||
| 71 | 72 | ||
| 72 | #ifdef DISABLE_INVALID_NUMBERS | 73 | #ifdef DISABLE_INVALID_NUMBERS |
| 73 | #undef DEFAULT_DECODE_INVALID_NUMBERS | 74 | #undef DEFAULT_DECODE_INVALID_NUMBERS |
| @@ -124,6 +125,7 @@ typedef struct { | |||
| 124 | int encode_invalid_numbers; /* 2 => Encode as "null" */ | 125 | int encode_invalid_numbers; /* 2 => Encode as "null" */ |
| 125 | int encode_number_precision; | 126 | int encode_number_precision; |
| 126 | int encode_keep_buffer; | 127 | int encode_keep_buffer; |
| 128 | int encode_empty_table_as_object; | ||
| 127 | 129 | ||
| 128 | int decode_invalid_numbers; | 130 | int decode_invalid_numbers; |
| 129 | int decode_max_depth; | 131 | int decode_max_depth; |
| @@ -300,6 +302,14 @@ static int json_cfg_encode_number_precision(lua_State *l) | |||
| 300 | return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14); | 302 | return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14); |
| 301 | } | 303 | } |
| 302 | 304 | ||
| 305 | /* Configures how to treat empty table when encode lua table */ | ||
| 306 | static int json_cfg_encode_empty_table_as_object(lua_State *l) | ||
| 307 | { | ||
| 308 | json_config_t *cfg = json_arg_init(l, 1); | ||
| 309 | |||
| 310 | return json_enum_option(l, 1, &cfg->encode_empty_table_as_object, NULL, 1); | ||
| 311 | } | ||
| 312 | |||
| 303 | /* Configures JSON encoding buffer persistence */ | 313 | /* Configures JSON encoding buffer persistence */ |
| 304 | static int json_cfg_encode_keep_buffer(lua_State *l) | 314 | static int json_cfg_encode_keep_buffer(lua_State *l) |
| 305 | { | 315 | { |
| @@ -390,6 +400,7 @@ static void json_create_config(lua_State *l) | |||
| 390 | cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS; | 400 | cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS; |
| 391 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; | 401 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; |
| 392 | cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION; | 402 | cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION; |
| 403 | cfg->encode_empty_table_as_object = DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT; | ||
| 393 | 404 | ||
| 394 | #if DEFAULT_ENCODE_KEEP_BUFFER > 0 | 405 | #if DEFAULT_ENCODE_KEEP_BUFFER > 0 |
| 395 | strbuf_init(&cfg->encode_buf, 0); | 406 | strbuf_init(&cfg->encode_buf, 0); |
| @@ -685,7 +696,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, | |||
| 685 | current_depth++; | 696 | current_depth++; |
| 686 | json_check_encode_depth(l, cfg, current_depth, json); | 697 | json_check_encode_depth(l, cfg, current_depth, json); |
| 687 | len = lua_array_length(l, cfg, json); | 698 | len = lua_array_length(l, cfg, json); |
| 688 | if (len > 0) | 699 | if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object)) |
| 689 | json_append_array(l, cfg, current_depth, json, len); | 700 | json_append_array(l, cfg, current_depth, json, len); |
| 690 | else | 701 | else |
| 691 | json_append_object(l, cfg, current_depth, json); | 702 | json_append_object(l, cfg, current_depth, json); |
| @@ -1352,6 +1363,7 @@ static int lua_cjson_new(lua_State *l) | |||
| 1352 | luaL_Reg reg[] = { | 1363 | luaL_Reg reg[] = { |
| 1353 | { "encode", json_encode }, | 1364 | { "encode", json_encode }, |
| 1354 | { "decode", json_decode }, | 1365 | { "decode", json_decode }, |
| 1366 | { "encode_empty_table_as_object", json_cfg_encode_empty_table_as_object }, | ||
| 1355 | { "encode_sparse_array", json_cfg_encode_sparse_array }, | 1367 | { "encode_sparse_array", json_cfg_encode_sparse_array }, |
| 1356 | { "encode_max_depth", json_cfg_encode_max_depth }, | 1368 | { "encode_max_depth", json_cfg_encode_max_depth }, |
| 1357 | { "decode_max_depth", json_cfg_decode_max_depth }, | 1369 | { "decode_max_depth", json_cfg_decode_max_depth }, |
diff --git a/tests/TestLua.pm b/tests/TestLua.pm new file mode 100644 index 0000000..cd22d83 --- /dev/null +++ b/tests/TestLua.pm | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | package TestLua; | ||
| 2 | |||
| 3 | use Test::Base -Base; | ||
| 4 | use IPC::Run3; | ||
| 5 | use Cwd; | ||
| 6 | |||
| 7 | use Test::LongString; | ||
| 8 | |||
| 9 | our @EXPORT = qw( run_tests ); | ||
| 10 | |||
| 11 | $ENV{LUA_CPATH} = "../?.so;;"; | ||
| 12 | $ENV{LUA_PATH} = "../lua/?.lua;;"; | ||
| 13 | #$ENV{LUA_PATH} = ($ENV{LUA_PATH} || "" ) . ';' . getcwd . "/runtime/?.lua" . ';;'; | ||
| 14 | |||
| 15 | sub run_test ($) { | ||
| 16 | my $block = shift; | ||
| 17 | #print $json_xs->pretty->encode(\@new_rows); | ||
| 18 | #my $res = #print $json_xs->pretty->encode($res); | ||
| 19 | my $name = $block->name; | ||
| 20 | |||
| 21 | my $lua = $block->lua or | ||
| 22 | die "No --- lua specified for test $name\n"; | ||
| 23 | |||
| 24 | my $luafile = "test_case.lua"; | ||
| 25 | |||
| 26 | open my $fh, ">$luafile" or | ||
| 27 | die "Cannot open $luafile for writing: $!\n"; | ||
| 28 | |||
| 29 | print $fh $lua; | ||
| 30 | close $fh; | ||
| 31 | |||
| 32 | my ($res, $err); | ||
| 33 | |||
| 34 | my @cmd; | ||
| 35 | |||
| 36 | if ($ENV{TEST_LUA_USE_VALGRIND}) { | ||
| 37 | @cmd = ('valgrind', '-q', '--leak-check=full', 'lua', 'test_case.lua'); | ||
| 38 | } else { | ||
| 39 | @cmd = ('lua', 'test_case.lua'); | ||
| 40 | } | ||
| 41 | |||
| 42 | run3 \@cmd, undef, \$res, \$err; | ||
| 43 | my $rc = $?; | ||
| 44 | |||
| 45 | #warn "res:$res\nerr:$err\n"; | ||
| 46 | |||
| 47 | if (defined $block->err) { | ||
| 48 | $err =~ /.*:.*:.*: (.*\s)?/; | ||
| 49 | $err = $1; | ||
| 50 | is $err, $block->err, "$name - err expected"; | ||
| 51 | |||
| 52 | } elsif ($rc) { | ||
| 53 | die "Failed to execute --- lua for test $name: $err\n"; | ||
| 54 | |||
| 55 | } else { | ||
| 56 | #is $res, $block->out, "$name - output ok"; | ||
| 57 | is $res, $block->out, "$name - output ok"; | ||
| 58 | } | ||
| 59 | |||
| 60 | is $rc, ($block->exit || 0), "$name - exit code ok"; | ||
| 61 | #unlink 'test_case.lua' or warn "could not delete \'test_case.lua\':$!"; | ||
| 62 | } | ||
| 63 | |||
| 64 | sub run_tests () { | ||
| 65 | for my $block (blocks()) { | ||
| 66 | run_test($block); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | 1; | ||
diff --git a/tests/agentzh.t b/tests/agentzh.t new file mode 100644 index 0000000..aeebd67 --- /dev/null +++ b/tests/agentzh.t | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | use TestLua; | ||
| 2 | |||
| 3 | plan tests => 2 * blocks(); | ||
| 4 | |||
| 5 | run_tests(); | ||
| 6 | |||
| 7 | __DATA__ | ||
| 8 | |||
| 9 | === TEST 1: empty tables as objects | ||
| 10 | --- lua | ||
| 11 | local cjson = require "cjson" | ||
| 12 | print(cjson.encode({})) | ||
| 13 | print(cjson.encode({dogs = {}})) | ||
| 14 | --- out | ||
| 15 | {} | ||
| 16 | {"dogs":{}} | ||
| 17 | |||
| 18 | |||
| 19 | |||
| 20 | === TEST 2: empty tables as arrays | ||
| 21 | --- lua | ||
| 22 | local cjson = require "cjson" | ||
| 23 | cjson.encode_empty_table_as_object(false) | ||
| 24 | print(cjson.encode({})) | ||
| 25 | print(cjson.encode({dogs = {}})) | ||
| 26 | --- out | ||
| 27 | [] | ||
| 28 | {"dogs":[]} | ||
| 29 | |||
| 30 | |||
| 31 | |||
| 32 | === TEST 3: empty tables as objects (explicit) | ||
| 33 | --- lua | ||
| 34 | local cjson = require "cjson" | ||
| 35 | cjson.encode_empty_table_as_object(true) | ||
| 36 | print(cjson.encode({})) | ||
| 37 | print(cjson.encode({dogs = {}})) | ||
| 38 | --- out | ||
| 39 | {} | ||
| 40 | {"dogs":{}} | ||
| 41 | |||
