diff options
Diffstat (limited to 't')
59 files changed, 2598 insertions, 0 deletions
diff --git a/t/00_load.t b/t/00_load.t new file mode 100644 index 0000000..916c826 --- /dev/null +++ b/t/00_load.t @@ -0,0 +1,15 @@ +use Test::More; +use strict; +BEGIN { plan tests => 5 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use_ok('JSON'); +} + +ok( exists $INC{ 'JSON/backportPP.pm' }, 'load backportPP' ); +ok( ! exists $INC{ 'JSON/PP.pm' }, q/didn't load PP/ ); + +is( JSON->backend, 'JSON::PP' ); +ok( JSON->backend->is_pp ); diff --git a/t/00_pod.t b/t/00_pod.t new file mode 100644 index 0000000..e8e3082 --- /dev/null +++ b/t/00_pod.t @@ -0,0 +1,8 @@ +use strict; +$^W = 1; + +use Test::More; + +eval "use Test::Pod 1.00"; +plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; +all_pod_files_ok (); diff --git a/t/01_utf8.t b/t/01_utf8.t new file mode 100644 index 0000000..442fc40 --- /dev/null +++ b/t/01_utf8.t @@ -0,0 +1,36 @@ +# copied over from JSON::XS and modified to use JSON + +use strict; +use Test::More; +BEGIN { plan tests => 9 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + + +use utf8; +use JSON; + + +ok (JSON->new->allow_nonref (1)->utf8 (1)->encode ("ü") eq "\"\xc3\xbc\""); +ok (JSON->new->allow_nonref (1)->encode ("ü") eq "\"ü\""); + +SKIP: { + skip "UNICODE handling is disabale.", 7 unless $JSON::can_handle_UTF16_and_utf8; + +ok (JSON->new->allow_nonref (1)->ascii (1)->utf8 (1)->encode (chr 0x8000) eq '"\u8000"'); +ok (JSON->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402) eq "\"\\ud801\\udc02\"\n"); + +eval { JSON->new->allow_nonref (1)->utf8 (1)->decode ('"ü"') }; +ok $@ =~ /malformed UTF-8/; + +ok (JSON->new->allow_nonref (1)->decode ('"ü"') eq "ü"); +ok (JSON->new->allow_nonref (1)->decode ('"\u00fc"') eq "ü"); +ok (JSON->new->allow_nonref (1)->decode ('"\ud801\udc02' . "\x{10204}\"") eq "\x{10402}\x{10204}"); +ok (JSON->new->allow_nonref (1)->decode ('"\"\n\\\\\r\t\f\b"') eq "\"\012\\\015\011\014\010"); + +} diff --git a/t/02_error.t b/t/02_error.t new file mode 100644 index 0000000..0c757d3 --- /dev/null +++ b/t/02_error.t @@ -0,0 +1,51 @@ +# copied over from JSON::XS and modified to use JSON + +use strict; +use Test::More; +BEGIN { plan tests => 31 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +use utf8; +use JSON; + + +eval { JSON->new->encode ([\-1]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\undef]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\2]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\{}]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\[]]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\\1]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->allow_nonref (1)->decode ('"\u1234\udc00"') }; ok $@ =~ /missing high /; +eval { JSON->new->allow_nonref->decode ('"\ud800"') }; ok $@ =~ /missing low /; +eval { JSON->new->allow_nonref (1)->decode ('"\ud800\u1234"') }; ok $@ =~ /surrogate pair /; +eval { JSON->new->decode ('null') }; ok $@ =~ /allow_nonref/; +eval { JSON->new->allow_nonref (1)->decode ('+0') }; ok $@ =~ /malformed/; +eval { JSON->new->allow_nonref->decode ('.2') }; ok $@ =~ /malformed/; +eval { JSON->new->allow_nonref (1)->decode ('bare') }; ok $@ =~ /malformed/; +eval { JSON->new->allow_nonref->decode ('naughty') }; ok $@ =~ /null/; +eval { JSON->new->allow_nonref (1)->decode ('01') }; ok $@ =~ /leading zero/; +eval { JSON->new->allow_nonref->decode ('00') }; ok $@ =~ /leading zero/; +eval { JSON->new->allow_nonref (1)->decode ('-0.') }; ok $@ =~ /decimal point/; +eval { JSON->new->allow_nonref->decode ('-0e') }; ok $@ =~ /exp sign/; +eval { JSON->new->allow_nonref (1)->decode ('-e+1') }; ok $@ =~ /initial minus/; +eval { JSON->new->allow_nonref->decode ("\"\n\"") }; ok $@ =~ /invalid character/; +eval { JSON->new->allow_nonref (1)->decode ("\"\x01\"") }; ok $@ =~ /invalid character/; +eval { JSON->new->decode ('[5') }; ok $@ =~ /parsing array/; +eval { JSON->new->decode ('{"5"') }; ok $@ =~ /':' expected/; +eval { JSON->new->decode ('{"5":null') }; ok $@ =~ /parsing object/; + +eval { JSON->new->decode (undef) }; ok $@ =~ /malformed/; +eval { JSON->new->decode (\5) }; ok !!$@; # Can't coerce readonly +eval { JSON->new->decode ([]) }; ok $@ =~ /malformed/; +eval { JSON->new->decode (\*STDERR) }; ok $@ =~ /malformed/; +eval { JSON->new->decode (*STDERR) }; ok !!$@; # cannot coerce GLOB + +eval { decode_json ("\"\xa0") }; ok $@ =~ /malformed.*character/; +eval { decode_json ("\"\xa0\"") }; ok $@ =~ /malformed.*character/; + diff --git a/t/03_types.t b/t/03_types.t new file mode 100644 index 0000000..f22c09b --- /dev/null +++ b/t/03_types.t @@ -0,0 +1,60 @@ +# copied over from JSON::XS and modified to use JSON +use strict; +use Test::More; + +BEGIN { plan tests => 76 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + + +ok (!defined JSON->new->allow_nonref (1)->decode ('null')); +ok (JSON->new->allow_nonref (1)->decode ('true') == 1); +ok (JSON->new->allow_nonref (1)->decode ('false') == 0); + +my $true = JSON->new->allow_nonref (1)->decode ('true'); +ok ($true eq 1); +ok (JSON::is_bool $true); +my $false = JSON->new->allow_nonref (1)->decode ('false'); +ok ($false == !$true); +ok (JSON::is_bool $false); +ok (++$false == 1); +ok (!JSON::is_bool $false); + +ok (JSON->new->allow_nonref (1)->decode ('5') == 5); +ok (JSON->new->allow_nonref (1)->decode ('-5') == -5); +ok (JSON->new->allow_nonref (1)->decode ('5e1') == 50); +ok (JSON->new->allow_nonref (1)->decode ('-333e+0') == -333); +ok (JSON->new->allow_nonref (1)->decode ('2.5') == 2.5); + +ok (JSON->new->allow_nonref (1)->decode ('""') eq ""); +ok ('[1,2,3,4]' eq encode_json decode_json ('[1,2, 3,4]')); +ok ('[{},[],[],{}]' eq encode_json decode_json ('[{},[], [ ] ,{ }]')); +ok ('[{"1":[5]}]' eq encode_json [{1 => [5]}]); +ok ('{"1":2,"3":4}' eq JSON->new->canonical (1)->encode (decode_json '{ "1" : 2, "3" : 4 }')); +ok ('{"1":2,"3":1.2}' eq JSON->new->canonical (1)->encode (decode_json '{ "1" : 2, "3" : 1.2 }')); + +ok ('[true]' eq encode_json [JSON::true]); +ok ('[false]' eq encode_json [JSON::false]); +ok ('[true]' eq encode_json [\1]); +ok ('[false]' eq encode_json [\0]); +ok ('[null]' eq encode_json [undef]); +ok ('[true]' eq encode_json [JSON::true]); +ok ('[false]' eq encode_json [JSON::false]); + +for my $v (1, 2, 3, 5, -1, -2, -3, -4, 100, 1000, 10000, -999, -88, -7, 7, 88, 999, -1e5, 1e6, 1e7, 1e8) { + ok ($v == ((decode_json "[$v]")->[0])); + ok ($v == ((decode_json encode_json [$v])->[0])); +} + +ok (30123 == ((decode_json encode_json [30123])->[0])); +ok (32123 == ((decode_json encode_json [32123])->[0])); +ok (32456 == ((decode_json encode_json [32456])->[0])); +ok (32789 == ((decode_json encode_json [32789])->[0])); +ok (32767 == ((decode_json encode_json [32767])->[0])); +ok (32768 == ((decode_json encode_json [32768])->[0])); + +my @sparse; @sparse[0,3] = (1, 4); +ok ("[1,null,null,4]" eq encode_json \@sparse); + diff --git a/t/06_pc_pretty.t b/t/06_pc_pretty.t new file mode 100644 index 0000000..c910f3a --- /dev/null +++ b/t/06_pc_pretty.t @@ -0,0 +1,69 @@ +#! perl + +# copied over from JSON::PC and modified to use JSON +# copied over from JSON::XS and modified to use JSON + +use strict; +use Test::More; +BEGIN { plan tests => 9 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +my ($js,$obj,$json); +my $pc = new JSON; + +$obj = {foo => "bar"}; +$js = $pc->encode($obj); +is($js,q|{"foo":"bar"}|); + +$obj = [10, "hoge", {foo => "bar"}]; +$pc->pretty (1); +$js = $pc->encode($obj); +is($js,q|[ + 10, + "hoge", + { + "foo" : "bar" + } +] +|); + +$obj = { foo => [ {a=>"b"}, 0, 1, 2 ] }; +$pc->pretty(0); +$js = $pc->encode($obj); +is($js,q|{"foo":[{"a":"b"},0,1,2]}|); + + +$obj = { foo => [ {a=>"b"}, 0, 1, 2 ] }; +$pc->pretty(1); +$js = $pc->encode($obj); +is($js,q|{ + "foo" : [ + { + "a" : "b" + }, + 0, + 1, + 2 + ] +} +|); + +$obj = { foo => [ {a=>"b"}, 0, 1, 2 ] }; +$pc->pretty(0); +$js = $pc->encode($obj); +is($js,q|{"foo":[{"a":"b"},0,1,2]}|); + + +$obj = {foo => "bar"}; +$pc->indent(3); # original -- $pc->indent(1); +is($pc->encode($obj), qq|{\n "foo":"bar"\n}\n|, "nospace"); +$pc->space_after(1); +is($pc->encode($obj), qq|{\n "foo": "bar"\n}\n|, "after"); +$pc->space_before(1); +is($pc->encode($obj), qq|{\n "foo" : "bar"\n}\n|, "both"); +$pc->space_after(0); +is($pc->encode($obj), qq|{\n "foo" :"bar"\n}\n|, "before"); + diff --git a/t/07_pc_esc.t b/t/07_pc_esc.t new file mode 100644 index 0000000..e6153b8 --- /dev/null +++ b/t/07_pc_esc.t @@ -0,0 +1,93 @@ +#
+# このファイルのエンコーディングはUTF-8
+#
+
+# copied over from JSON::PC and modified to use JSON
+# copied over from JSON::XS and modified to use JSON
+
+use Test::More;
+use strict;
+
+BEGIN { plan tests => 17 };
+
+BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; }
+
+BEGIN {
+ use lib qw(t);
+ use _unicode_handling;
+}
+
+
+use utf8;
+use JSON;
+
+#########################
+my ($js,$obj,$str);
+
+my $pc = new JSON;
+
+$obj = {test => qq|abc"def|};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\"def"}|);
+
+$obj = {qq|te"st| => qq|abc"def|};
+$str = $pc->encode($obj);
+is($str,q|{"te\"st":"abc\"def"}|);
+
+$obj = {test => qq|abc/def|}; # / => \/
+$str = $pc->encode($obj); # but since version 0.99
+is($str,q|{"test":"abc/def"}|); # this handling is deleted.
+$obj = $pc->decode($str);
+is($obj->{test},q|abc/def|);
+
+$obj = {test => q|abc\def|};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\\\\def"}|);
+
+$obj = {test => "abc\bdef"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\bdef"}|);
+
+$obj = {test => "abc\fdef"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\fdef"}|);
+
+$obj = {test => "abc\ndef"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\ndef"}|);
+
+$obj = {test => "abc\rdef"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\rdef"}|);
+
+$obj = {test => "abc-def"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc-def"}|);
+
+$obj = {test => "abc(def"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc(def"}|);
+
+$obj = {test => "abc\\def"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"abc\\\\def"}|);
+
+
+$obj = {test => "あいうえお"};
+$str = $pc->encode($obj);
+is($str,q|{"test":"あいうえお"}|);
+
+$obj = {"あいうえお" => "かきくけこ"};
+$str = $pc->encode($obj);
+is($str,q|{"あいうえお":"かきくけこ"}|);
+
+
+$obj = $pc->decode(q|{"id":"abc\ndef"}|);
+is($obj->{id},"abc\ndef",q|{"id":"abc\ndef"}|);
+
+$obj = $pc->decode(q|{"id":"abc\\\ndef"}|);
+is($obj->{id},"abc\\ndef",q|{"id":"abc\\\ndef"}|);
+
+$obj = $pc->decode(q|{"id":"abc\\\\\ndef"}|);
+is($obj->{id},"abc\\\ndef",q|{"id":"abc\\\\\ndef"}|);
+
diff --git a/t/08_pc_base.t b/t/08_pc_base.t new file mode 100644 index 0000000..ca06092 --- /dev/null +++ b/t/08_pc_base.t @@ -0,0 +1,99 @@ +use Test::More; + +# copied over from JSON::PC and modified to use JSON +# copied over from JSON::XS and modified to use JSON + +use strict; +BEGIN { plan tests => 20 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +my ($js,$obj); + +my $pc = new JSON; + +$js = q|{}|; + +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,'{}', '{}'); + +$js = q|[]|; +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,'[]', '[]'); + + +$js = q|{"foo":"bar"}|; +$obj = $pc->decode($js); +is($obj->{foo},'bar'); +$js = $pc->encode($obj); +is($js,'{"foo":"bar"}', '{"foo":"bar"}'); + +$js = q|{"foo":""}|; +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,'{"foo":""}', '{"foo":""}'); + +$js = q|{"foo":" "}|; +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,'{"foo":" "}' ,'{"foo":" "}'); + +$js = q|{"foo":"0"}|; +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,'{"foo":"0"}',q|{"foo":"0"} - autoencode (default)|); + + +$js = q|{"foo":"0 0"}|; +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,'{"foo":"0 0"}','{"foo":"0 0"}'); + +$js = q|[1,2,3]|; +$obj = $pc->decode($js); +is($obj->[1],2); +$js = $pc->encode($obj); +is($js,'[1,2,3]'); + +$js = q|{"foo":{"bar":"hoge"}}|; +$obj = $pc->decode($js); +is($obj->{foo}->{bar},'hoge'); +$js = $pc->encode($obj); +is($js,q|{"foo":{"bar":"hoge"}}|); + +$js = q|[{"foo":[1,2,3]},-0.12,{"a":"b"}]|; +$obj = $pc->decode($js); +$js = $pc->encode($obj); +is($js,q|[{"foo":[1,2,3]},-0.12,{"a":"b"}]|); + + +$obj = ["\x01"]; +is($js = $pc->encode($obj),'["\\u0001"]'); +$obj = $pc->decode($js); +is($obj->[0],"\x01"); + +$obj = ["\e"]; +is($js = $pc->encode($obj),'["\\u001b"]'); +$obj = $pc->decode($js); +is($obj->[0],"\e"); + +$js = '{"id":"}'; +eval q{ $pc->decode($js) }; +like($@, qr/unexpected end/i); + +$obj = { foo => sub { "bar" } }; +eval q{ $js = $pc->encode($obj) }; +like($@, qr/JSON can only/i, 'invalid value (coderef)'); + +#$obj = { foo => bless {}, "Hoge" }; +#eval q{ $js = $pc->encode($obj) }; +#like($@, qr/JSON can only/i, 'invalid value (blessd object)'); + +$obj = { foo => \$js }; +eval q{ $js = $pc->encode($obj) }; +like($@, qr/cannot encode reference/i, 'invalid value (ref)'); + diff --git a/t/09_pc_extra_number.t b/t/09_pc_extra_number.t new file mode 100644 index 0000000..ce60ee5 --- /dev/null +++ b/t/09_pc_extra_number.t @@ -0,0 +1,39 @@ +# copied over from JSON::PC and modified to use JSON +# copied over from JSON::XS and modified to use JSON + +use Test::More; +use strict; +BEGIN { plan tests => 6 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + + +######################### +my ($js,$obj); +my $pc = new JSON; + +$js = '{"foo":0}'; +$obj = $pc->decode($js); +is($obj->{foo}, 0, "normal 0"); + +$js = '{"foo":0.1}'; +$obj = $pc->decode($js); +is($obj->{foo}, 0.1, "normal 0.1"); + + +$js = '{"foo":10}'; +$obj = $pc->decode($js); +is($obj->{foo}, 10, "normal 10"); + +$js = '{"foo":-10}'; +$obj = $pc->decode($js); +is($obj->{foo}, -10, "normal -10"); + + +$js = '{"foo":0, "bar":0.1}'; +$obj = $pc->decode($js); +is($obj->{foo},0, "normal 0"); +is($obj->{bar},0.1,"normal 0.1"); + diff --git a/t/10_pc_keysort.t b/t/10_pc_keysort.t new file mode 100644 index 0000000..823e5a6 --- /dev/null +++ b/t/10_pc_keysort.t @@ -0,0 +1,20 @@ +# copied over from JSON::PC and modified to use JSON +# copied over from JSON::XS and modified to use JSON + +use Test::More; +use strict; +BEGIN { plan tests => 1 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; +######################### + +my ($js,$obj); +my $pc = JSON->new->canonical(1); + +$obj = {a=>1, b=>2, c=>3, d=>4, e=>5, f=>6, g=>7, h=>8, i=>9}; + +$js = $pc->encode($obj); +is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|); + diff --git a/t/11_pc_expo.t b/t/11_pc_expo.t new file mode 100644 index 0000000..5e587d8 --- /dev/null +++ b/t/11_pc_expo.t @@ -0,0 +1,47 @@ +# copied over from JSON::PC and modified to use JSON +# copied over from JSON::XS and modified to use JSON + +use Test::More; +use strict; +BEGIN { plan tests => 8 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +######################### +my ($js,$obj); +my $pc = new JSON; + +$js = q|[-12.34]|; +$obj = $pc->decode($js); +is($obj->[0], -12.34, 'digit -12.34'); +$js = $pc->encode($obj); +is($js,'[-12.34]', 'digit -12.34'); + +$js = q|[-1.234e5]|; +$obj = $pc->decode($js); +is($obj->[0], -123400, 'digit -1.234e5'); +$js = $pc->encode($obj); +is($js,'[-123400]', 'digit -1.234e5'); + +$js = q|[1.23E-4]|; +$obj = $pc->decode($js); +is($obj->[0], 0.000123, 'digit 1.23E-4'); +$js = $pc->encode($obj); + +if ( $js =~ /\[1/ ) { # for 5.6.2 on Darwin 8.10.0 + like($js, qr/[1.23[eE]-04]/, 'digit 1.23E-4'); +} +else { + is($js,'[0.000123]', 'digit 1.23E-4'); +} + + + +$js = q|[1.01e+67]|; # 30 -> 67 ... patched by H.Merijn Brand +$obj = $pc->decode($js); +is($obj->[0], 1.01e+67, 'digit 1.01e+67'); +$js = $pc->encode($obj); +like($js,qr/\[1.01[Ee]\+0?67\]/, 'digit 1.01e+67'); + diff --git a/t/12_blessed.t b/t/12_blessed.t new file mode 100644 index 0000000..ddd7907 --- /dev/null +++ b/t/12_blessed.t @@ -0,0 +1,53 @@ +# copied over from JSON::XS and modified to use JSON + +use strict; +use Test::More; +BEGIN { plan tests => 16 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + + +my $o1 = bless { a => 3 }, "XX"; +my $o2 = bless \(my $dummy = 1), "YY"; + +sub XX::TO_JSON { + {'__',""} +} + +my $js = JSON->new; + +eval { $js->encode ($o1) }; ok ($@ =~ /allow_blessed/); +eval { $js->encode ($o2) }; ok ($@ =~ /allow_blessed/); +$js->allow_blessed; +ok ($js->encode ($o1) eq "null"); +ok ($js->encode ($o2) eq "null"); +$js->convert_blessed; +ok ($js->encode ($o1) eq '{"__":""}'); + +ok ($js->encode ($o2) eq "null"); + +$js->filter_json_object (sub { 5 }); +$js->filter_json_single_key_object (a => sub { shift }); +$js->filter_json_single_key_object (b => sub { 7 }); + +ok ("ARRAY" eq ref $js->decode ("[]")); +ok (5 eq join ":", @{ $js->decode ('[{}]') }); +ok (6 eq join ":", @{ $js->decode ('[{"a":6}]') }); +ok (5 eq join ":", @{ $js->decode ('[{"a":4,"b":7}]') }); + +$js->filter_json_object; +ok (7 == $js->decode ('[{"a":4,"b":7}]')->[0]{b}); +ok (3 eq join ":", @{ $js->decode ('[{"a":3}]') }); + +$js->filter_json_object (sub { }); +ok (7 == $js->decode ('[{"a":4,"b":7}]')->[0]{b}); +ok (9 eq join ":", @{ $js->decode ('[{"a":9}]') }); + +$js->filter_json_single_key_object ("a"); +ok (4 == $js->decode ('[{"a":4}]')->[0]{a}); + +#$js->filter_json_single_key_object (a => sub {}); +$js->filter_json_single_key_object (a => sub { return; }); # sub {} is not suitable for Perl 5.6 +ok (4 == $js->decode ('[{"a":4}]')->[0]{a}); diff --git a/t/13_limit.t b/t/13_limit.t new file mode 100644 index 0000000..4ca8b0c --- /dev/null +++ b/t/13_limit.t @@ -0,0 +1,34 @@ +use strict; +use Test::More; + +BEGIN { plan tests => 11 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + + +my $def = 512; + +my $js = JSON->new; + +{ + local $^W = undef; # avoid for warning 'Deep recursion on subroutin' + +ok (!eval { $js->decode (("[" x ($def + 1)) . ("]" x ($def + 1))) }); +ok (ref $js->decode (("[" x $def) . ("]" x $def))); +ok (ref $js->decode (("{\"\":" x ($def - 1)) . "[]" . ("}" x ($def - 1)))); +ok (!eval { $js->decode (("{\"\":" x $def) . "[]" . ("}" x $def)) }); + +ok (ref $js->max_depth (32)->decode (("[" x 32) . ("]" x 32))); + +ok ($js->max_depth(1)->encode ([])); +ok (!eval { $js->encode ([[]]), 1 }); + +ok ($js->max_depth(2)->encode ([{}])); +ok (!eval { $js->encode ([[{}]]), 1 }); + +ok (eval { ref $js->max_size (8)->decode ("[ ]") }); +eval { $js->max_size (8)->decode ("[ ]") }; ok ($@ =~ /max_size/); + +} diff --git a/t/14_latin1.t b/t/14_latin1.t new file mode 100644 index 0000000..238a88b --- /dev/null +++ b/t/14_latin1.t @@ -0,0 +1,27 @@ +# copied over from JSON::XS and modified to use JSON + +use Test::More; +use strict; +BEGIN { plan tests => 4 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +use JSON; + +SKIP: { + skip "UNICODE handling is disabale.", 4 unless $JSON::can_handle_UTF16_and_utf8; + +my $xs = JSON->new->latin1->allow_nonref; + +ok $xs->encode ("\x{12}\x{89} ") eq "\"\\u0012\x{89} \""; +ok $xs->encode ("\x{12}\x{89}\x{abc}") eq "\"\\u0012\x{89}\\u0abc\""; + +ok $xs->decode ("\"\\u0012\x{89}\"" ) eq "\x{12}\x{89}"; +ok $xs->decode ("\"\\u0012\x{89}\\u0abc\"") eq "\x{12}\x{89}\x{abc}"; + +} diff --git a/t/15_prefix.t b/t/15_prefix.t new file mode 100644 index 0000000..3071be2 --- /dev/null +++ b/t/15_prefix.t @@ -0,0 +1,16 @@ +# copied over from JSON::XS and modified to use JSON + +BEGIN { $| = 1; print "1..4\n"; } +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +my $xs = JSON->new->allow_nonref; + +eval { $xs->decode ("[] ") }; +print $@ ? "not " : "", "ok 1\n"; +eval { $xs->decode ("[] x") }; +print $@ ? "" : "not ", "ok 2\n"; +print 2 == ($xs->decode_prefix ("[][]"))[1] ? "" : "not ", "ok 3\n"; +print 3 == ($xs->decode_prefix ("[1] t"))[1] ? "" : "not ", "ok 4\n"; + diff --git a/t/16_tied.t b/t/16_tied.t new file mode 100644 index 0000000..50d7272 --- /dev/null +++ b/t/16_tied.t @@ -0,0 +1,23 @@ +# copied over from JSON::XS and modified to use JSON + +use strict; +use Test::More; +BEGIN { plan tests => 2 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; +use Tie::Hash; +use Tie::Array; + +my $js = JSON->new; + +tie my %h, 'Tie::StdHash'; +%h = (a => 1); + +ok ($js->encode (\%h) eq '{"a":1}'); + +tie my @a, 'Tie::StdArray'; +@a = (1, 2); + +ok ($js->encode (\@a) eq '[1,2]'); diff --git a/t/17_relaxed.t b/t/17_relaxed.t new file mode 100644 index 0000000..e87a966 --- /dev/null +++ b/t/17_relaxed.t @@ -0,0 +1,30 @@ +# copied over from JSON::XS and modified to use JSON + +use Test::More; +use strict; + +BEGIN { plan tests => 8 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +use utf8; +use JSON; + + +my $json = JSON->new->relaxed; + +ok ('[1,2,3]' eq encode_json $json->decode (' [1,2, 3]')); +ok ('[1,2,4]' eq encode_json $json->decode ('[1,2, 4 , ]')); +ok (!eval { $json->decode ('[1,2, 3,4,,]') }); +ok (!eval { $json->decode ('[,1]') }); + +ok ('{"1":2}' eq encode_json $json->decode (' {"1":2}')); +ok ('{"1":2}' eq encode_json $json->decode ('{"1":2,}')); +ok (!eval { $json->decode ('{,}') }); + +ok ('[1,2]' eq encode_json $json->decode ("[1#,2\n ,2,# ] \n\t]")); diff --git a/t/18_json_checker.t b/t/18_json_checker.t new file mode 100644 index 0000000..fd1b3f0 --- /dev/null +++ b/t/18_json_checker.t @@ -0,0 +1,175 @@ +#! perl + +# use the testsuite from http://www.json.org/JSON_checker/ +# except for fail18.json, as we do not support a depth of 20 (but 16 and 32). + +# copied over from JSON::XS and modified to use JSON + +use strict; +#no warnings; +local $^W = undef; +use Test::More; +BEGIN { plan tests => 39 }; +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +my $json = JSON->new->utf8->max_depth(32)->canonical; + +binmode DATA; +my $num = 1; +for (;;) { + + $/ = "\n# "; + chomp (my $test = <DATA>) + or last; + $/ = "\n"; + my $name = <DATA>; + if (my $perl = eval { $json->decode ($test) }) { + ok ($name =~ /^pass/, $name); +#print $json->encode ($perl), "\n"; + is ($json->encode ($json->decode ($json->encode ($perl))), $json->encode ($perl)); + } else { + ok ($name =~ /^fail/, "$name ($@)"); + } + +} + +__DATA__ +"A JSON payload should be an object or array, not a string." +# fail1.json +{"Extra value after close": true} "misplaced quoted value" +# fail10.json +{"Illegal expression": 1 + 2} +# fail11.json +{"Illegal invocation": alert()} +# fail12.json +{"Numbers cannot have leading zeroes": 013} +# fail13.json +{"Numbers cannot be hex": 0x14} +# fail14.json +["Illegal backslash escape: \x15"] +# fail15.json +[\naked] +# fail16.json +["Illegal backslash escape: \017"] +# fail17.json +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +# fail18.json +{"Missing colon" null} +# fail19.json +["Unclosed array" +# fail2.json +{"Double colon":: null} +# fail20.json +{"Comma instead of colon", null} +# fail21.json +["Colon instead of comma": false] +# fail22.json +["Bad value", truth] +# fail23.json +['single quote'] +# fail24.json +[" tab character in string "] +# fail25.json +["tab\ character\ in\ string\ "] +# fail26.json +["line +break"] +# fail27.json +["line\ +break"] +# fail28.json +[0e] +# fail29.json +{unquoted_key: "keys must be quoted"} +# fail3.json +[0e+] +# fail30.json +[0e+-1] +# fail31.json +{"Comma instead if closing brace": true, +# fail32.json +["mismatch"} +# fail33.json +["extra comma",] +# fail4.json +["double extra comma",,] +# fail5.json +[ , "<-- missing value"] +# fail6.json +["Comma after the close"], +# fail7.json +["Extra close"]] +# fail8.json +{"Extra comma": true,} +# fail9.json +[ + "JSON Test Pattern pass1", + {"object with 1 member":["array with 1 element"]}, + {}, + [], + -42, + true, + false, + null, + { + "integer": 1234567890, + "real": -9876.543210, + "e": 0.123456789e-12, + "E": 1.234567890E+34, + "": 23456789012E66, + "zero": 0, + "one": 1, + "space": " ", + "quote": "\"", + "backslash": "\\", + "controls": "\b\f\n\r\t", + "slash": "/ & \/", + "alpha": "abcdefghijklmnopqrstuvwyz", + "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", + "digit": "0123456789", + "0123456789": "digit", + "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?", + "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", + "true": true, + "false": false, + "null": null, + "array":[ ], + "object":{ }, + "address": "50 St. James Street", + "url": "http://www.JSON.org/", + "comment": "// /* <!-- --", + "# -- --> */": " ", + " s p a c e d " :[1,2 , 3 + +, + +4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], + "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", + "quotes": "" \u0022 %22 0x22 034 "", + "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" +: "A key can be any string" + }, + 0.5 ,98.6 +, +99.44 +, + +1066, +1e1, +0.1e1, +1e-1, +1e00,2e+00,2e-00 +,"rosebud"] +# pass1.json +[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] +# pass2.json +{ + "JSON Test Pattern pass3": { + "The outermost value": "must be an object or array.", + "In this test": "It is an object." + } +} + +# pass3.json diff --git a/t/19_incr.t b/t/19_incr.t new file mode 100644 index 0000000..f77096c --- /dev/null +++ b/t/19_incr.t @@ -0,0 +1,183 @@ +#!/usr/bin/perl -w + +# copied over from JSON::XS and modified to use JSON + +use strict; + +use Test::More; +BEGIN { plan tests => 697 }; +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + + +use JSON; + +if ( $] >= 5.006 ) { + +eval <<'TEST' or die "Failed to eval test code for version $]: $@"; + +sub splitter { + my ($coder, $text) = @_; + + $coder->canonical(1) if $] >= 5.017009; + + for (0 .. length $text) { + my $a = substr $text, 0, $_; + my $b = substr $text, $_; + + $coder->incr_parse ($a); + $coder->incr_parse ($b); + + my $data = $coder->incr_parse; + ok ($data); + is ($coder->encode ($data), $coder->encode ($coder->decode ($text)), "data"); + ok ($coder->incr_text =~ /^\s*$/, "tailws"); + } +} + + + +splitter +JSON->new , ' ["x\\"","\\u1000\\\\n\\nx",1,{"\\\\" :5 , "": "x"}]'; +splitter +JSON->new , '[ "x\\"","\\u1000\\\\n\\nx" , 1,{"\\\\ " :5 , "": " x"} ] '; +splitter +JSON->new->allow_nonref, '"test"'; +splitter +JSON->new->allow_nonref, ' "5" '; + + + +{ + my $text = '[5],{"":1} , [ 1,2, 3], {"3":null}'; + my $coder = new JSON; + for (0 .. length $text) { + my $a = substr $text, 0, $_; + my $b = substr $text, $_; + + $coder->incr_parse ($a); + $coder->incr_parse ($b); + + my $j1 = $coder->incr_parse; ok ($coder->incr_text =~ s/^\s*,//, "cskip1"); + my $j2 = $coder->incr_parse; ok ($coder->incr_text =~ s/^\s*,//, "cskip2"); + my $j3 = $coder->incr_parse; ok ($coder->incr_text =~ s/^\s*,//, "cskip3"); + my $j4 = $coder->incr_parse; ok ($coder->incr_text !~ s/^\s*,//, "cskip4"); + my $j5 = $coder->incr_parse; ok ($coder->incr_text !~ s/^\s*,//, "cskip5"); + + ok ('[5]' eq encode_json $j1, "cjson1"); + ok ('{"":1}' eq encode_json $j2, "cjson2"); + ok ('[1,2,3]' eq encode_json $j3, "cjson3"); + ok ('{"3":null}' eq encode_json $j4, "cjson4"); + ok (!defined $j5, "cjson5"); + } +} + +{ + my $text = '[x][5]'; + my $coder = new JSON; + $coder->incr_parse ($text); + ok (!eval { $coder->incr_parse }, "sparse1"); + ok (!eval { $coder->incr_parse }, "sparse2"); + $coder->incr_skip; + ok ('[5]' eq $coder->encode (scalar $coder->incr_parse), "sparse3"); +} + + +TEST + + +} +else { + + +eval <<'TEST' or die "Failed to eval test code for version $]: $@"; + +my $incr_text; + +sub splitter { + my ($coder, $text) = @_; + + for (0 .. length $text) { + my $a = substr $text, 0, $_; + my $b = substr $text, $_; + + $coder->incr_parse ($a); + $coder->incr_parse ($b); + + my $data = $coder->incr_parse; + ok ($data); + ok ($coder->encode ($data) eq $coder->encode ($coder->decode ($text)), "data"); + ok (($incr_text = $coder->incr_text) =~ /^\s*$/, "tailws"); + } +} + +splitter +JSON->new , ' ["x\\"","\\u1000\\\\n\\nx",1,{"\\\\" :5 , "": "x"}]'; +splitter +JSON->new , '[ "x\\"","\\u1000\\\\n\\nx" , 1,{"\\\\ " :5 , "": " x"} ] '; +splitter +JSON->new->allow_nonref, '"test"'; +splitter +JSON->new->allow_nonref, ' "5" '; + + +{ + my $text = '[5],{"":1} , [ 1,2, 3], {"3":null}'; + my $coder = new JSON; + for (0 .. length $text) { + my $a = substr $text, 0, $_; + my $b = substr $text, $_; + + $coder->incr_parse ($a); + $coder->incr_parse ($b); + + my $j1 = $coder->incr_parse; ok ( $coder->incr_text( ($incr_text = $coder->incr_text) =~ s/^\s*,// and $incr_text ), "cskip1"); + my $j2 = $coder->incr_parse; ok ( $coder->incr_text( ($incr_text = $coder->incr_text) =~ s/^\s*,// and $incr_text ), "cskip2"); + my $j3 = $coder->incr_parse; ok ( $coder->incr_text( ($incr_text = $coder->incr_text) =~ s/^\s*,// and $incr_text ), "cskip3"); + my $j4 = $coder->incr_parse; ok (($incr_text = $coder->incr_text) !~ s/^\s*,//, "cskip4"); + my $j5 = $coder->incr_parse; ok (($incr_text = $coder->incr_text) !~ s/^\s*,//, "cskip5"); + + ok ('[5]' eq encode_json $j1, "cjson1"); + ok ('{"":1}' eq encode_json $j2, "cjson2"); + ok ('[1,2,3]' eq encode_json $j3, "cjson3"); + ok ('{"3":null}' eq encode_json $j4, "cjson4"); + ok (!defined $j5, "cjson5"); + } +} + +{ + my $text = '[x][5]'; + my $coder = new JSON; + $coder->incr_parse ($text); + ok (!eval { $coder->incr_parse }, "sparse1"); + ok (!eval { $coder->incr_parse }, "sparse2"); + $coder->incr_skip; + ok ('[5]' eq $coder->encode (scalar $coder->incr_parse), "sparse3"); +} + + +TEST + +} # for 5.005 + + + + +{ + my $coder = JSON->new->max_size (5); + ok (!$coder->incr_parse ("[ "), "incsize1"); + eval q{ !$coder->incr_parse ("] ") }; ok ($@ =~ /6 bytes/, "incsize2 $@"); +} + +{ + my $coder = JSON->new->max_depth (3); + ok (!$coder->incr_parse ("[[["), "incdepth1"); + eval q{ !$coder->incr_parse (" [] ") }; ok ($@ =~ /maximum nesting/, "incdepth2 $@"); +} + +{ + my $coder = JSON->new; + + my $res = eval { $coder->incr_parse("]") }; + my $e = $@; # test more clobbers $@, we need it twice + + ok(!$res, "unbalanced bracket" ); + ok($e, "got error"); + like( $e, qr/malformed/, "malformed json string error" ); + + $coder->incr_skip; + + is_deeply(eval { $coder->incr_parse("[42]") }, [42], "valid data after incr_skip"); +} + diff --git a/t/20_unknown.t b/t/20_unknown.t new file mode 100644 index 0000000..8bc81cb --- /dev/null +++ b/t/20_unknown.t @@ -0,0 +1,55 @@ +#!/usr/bin/perl -w + +use strict; + +use Test::More; +BEGIN { plan tests => 10 }; +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + + +use strict; +use JSON; + +my $json = JSON->new; + +eval q| $json->encode( [ sub {} ] ) |; +ok( $@ =~ /encountered CODE/, $@ ); + +eval q| $json->encode( [ \-1 ] ) |; +ok( $@ =~ /cannot encode reference to scalar/, $@ ); + +eval q| $json->encode( [ \undef ] ) |; +ok( $@ =~ /cannot encode reference to scalar/, $@ ); + +eval q| $json->encode( [ \{} ] ) |; +ok( $@ =~ /cannot encode reference to scalar/, $@ ); + +$json->allow_unknown; + +is( $json->encode( [ sub {} ] ), '[null]' ); +is( $json->encode( [ \-1 ] ), '[null]' ); +is( $json->encode( [ \undef ] ), '[null]' ); +is( $json->encode( [ \{} ] ), '[null]' ); + + +SKIP: { + + skip "this test is for Perl 5.8 or later", 2 if( $] < 5.008 ); + +$json->allow_unknown(0); + +my $fh; +open( $fh, '>hoge.txt' ) or die $!; + +eval q| $json->encode( [ $fh ] ) |; +ok( $@ =~ /encountered GLOB/, $@ ); + +$json->allow_unknown(1); + +is( $json->encode( [ $fh ] ), '[null]' ); + +close $fh; + +unlink('hoge.txt'); + +} diff --git a/t/21_evans_bugrep.t b/t/21_evans_bugrep.t new file mode 100644 index 0000000..2e6200d --- /dev/null +++ b/t/21_evans_bugrep.t @@ -0,0 +1,50 @@ +use strict; +use Test::More; + +BEGIN { plan tests => 6 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + + +use JSON; + +print JSON->backend, "\t", JSON->backend->VERSION, "\n"; + +my $data = ["\x{3042}\x{3044}\x{3046}\x{3048}\x{304a}", + "\x{304b}\x{304d}\x{304f}\x{3051}\x{3053}"]; + +my $j = new JSON; +my $js = $j->encode($data); +$j = undef; + +my @parts = (substr($js, 0, int(length($js) / 2)), + substr($js, int(length($js) / 2))); +$j = JSON->new; +my $object = $j->incr_parse($parts[0]); + +ok( !defined $object ); + +eval { + $j->incr_text; +}; + +like( $@, qr/incr_text can not be called when the incremental parser already started parsing/ ); + +$object = $j->incr_parse($parts[1]); + +ok( defined $object ); + +is( $object->[0], $data->[0] ); +is( $object->[1], $data->[1] ); + +eval { + $j->incr_text; +}; + +ok( !$@ ); + diff --git a/t/22_comment_at_eof.t b/t/22_comment_at_eof.t new file mode 100644 index 0000000..a388a78 --- /dev/null +++ b/t/22_comment_at_eof.t @@ -0,0 +1,47 @@ +# the oritinal test case was provided by IKEGAMI@cpan.org + +use strict; + +use Test::More tests => 13; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +use Data::Dumper qw( Dumper ); + +sub decoder { + my ($str) = @_; + + my $json = JSON->new->relaxed; + + $json->incr_parse($_[0]); + + my $rv; + if (!eval { $rv = $json->incr_parse(); 1 }) { + $rv = "died with $@"; + } + + local $Data::Dumper::Useqq = 1; + local $Data::Dumper::Terse = 1; + local $Data::Dumper::Indent = 0; + + return Dumper($rv); +} + + +is( decoder( "[]" ), '[]', 'array baseline' ); +is( decoder( " []" ), '[]', 'space ignored before array' ); +is( decoder( "\n[]" ), '[]', 'newline ignored before array' ); +is( decoder( "# foo\n[]" ), '[]', 'comment ignored before array' ); +is( decoder( "# fo[o\n[]"), '[]', 'comment ignored before array' ); +is( decoder( "# fo]o\n[]"), '[]', 'comment ignored before array' ); +is( decoder( "[# fo]o\n]"), '[]', 'comment ignored inside array' ); + +is( decoder( "" ), 'undef', 'eof baseline' ); +is( decoder( " " ), 'undef', 'space ignored before eof' ); +is( decoder( "\n" ), 'undef', 'newline ignored before eof' ); +is( decoder( "#,foo\n" ), 'undef', 'comment ignored before eof' ); +is( decoder( "# []o\n" ), 'undef', 'comment ignored before eof' ); + +is( decoder( qq/#\n[#foo\n"#\\n"#\n]/), '["#\n"]', 'array and string in multiple lines' ); diff --git a/t/99_binary.t b/t/99_binary.t new file mode 100644 index 0000000..254b08e --- /dev/null +++ b/t/99_binary.t @@ -0,0 +1,53 @@ +# copied over from JSON::XS and modified to use JSON + +use Test::More; +use strict; +BEGIN { plan tests => 2432 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +use JSON; + +SKIP: { + skip "UNICODE handling is disabale.", 2432 unless $JSON::can_handle_UTF16_and_utf8; + +sub test($) { + my $js; + + $js = JSON->new->allow_nonref(0)->utf8->ascii->shrink->encode ([$_[0]]); + ok ($_[0] eq ((decode_json $js)->[0])); + $js = JSON->new->allow_nonref(0)->utf8->ascii->encode ([$_[0]]); + ok ($_[0] eq (JSON->new->utf8->shrink->decode($js))->[0]); + + $js = JSON->new->allow_nonref(0)->utf8->shrink->encode ([$_[0]]); + ok ($_[0] eq ((decode_json $js)->[0])); + $js = JSON->new->allow_nonref(1)->utf8->encode ([$_[0]]); + ok ($_[0] eq (JSON->new->utf8->shrink->decode($js))->[0]); + + $js = JSON->new->allow_nonref(1)->ascii->encode ([$_[0]]); + ok ($_[0] eq JSON->new->decode ($js)->[0]); + $js = JSON->new->allow_nonref(0)->ascii->encode ([$_[0]]); + ok ($_[0] eq JSON->new->shrink->decode ($js)->[0]); + + $js = JSON->new->allow_nonref(1)->shrink->encode ([$_[0]]); + ok ($_[0] eq JSON->new->decode ($js)->[0]); + $js = JSON->new->allow_nonref(0)->encode ([$_[0]]); + ok ($_[0] eq JSON->new->shrink->decode ($js)->[0]); +} + +srand 0; # doesn't help too much, but its at least more deterministic + +#for (1..768) { +for (1..64, 125..129, 255..257, 512, 704, 736, 768) { + test join "", map chr ($_ & 255), 0..$_; + test join "", map chr rand 255, 0..$_; + test join "", map chr ($_ * 97 & ~0x4000), 0..$_; + test join "", map chr (rand (2**20) & ~0x800), 0..$_; +} + +} diff --git a/t/_unicode_handling.pm b/t/_unicode_handling.pm new file mode 100644 index 0000000..ea60d29 --- /dev/null +++ b/t/_unicode_handling.pm @@ -0,0 +1,28 @@ +#package utf8;
+package _unicode_handling;
+
+# this is a dummy pragma for 5.005.
+
+ if ($] < 5.006) {
+ $INC{'utf8.pm'} = './utf8.pm';
+
+ eval q|
+ sub utf8::import { }
+ sub utf8::unimport { }
+ |;
+
+ $JSON::can_handle_UTF16_and_utf8 = 0;
+ }
+ else {
+ $JSON::can_handle_UTF16_and_utf8 = 1;
+
+ if ($] > 5.007 and $] < 5.008003) {
+# $JSON::can_handle_UTF16_and_utf8 = 0;
+ }
+
+ }
+
+
+
+
+1;
diff --git a/t/e00_func.t b/t/e00_func.t new file mode 100644 index 0000000..ddb57ce --- /dev/null +++ b/t/e00_func.t @@ -0,0 +1,17 @@ +
+use Test::More;
+use strict;
+BEGIN { plan tests => 2 };
+BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; }
+use JSON;
+#########################
+
+my $json = JSON->new;
+
+my $js = 'abc';
+
+
+is(to_json($js, {allow_nonref => 1}), '"abc"');
+
+is(from_json('"abc"', {allow_nonref => 1}), 'abc');
+
diff --git a/t/e01_property.t b/t/e01_property.t new file mode 100644 index 0000000..2418ff3 --- /dev/null +++ b/t/e01_property.t @@ -0,0 +1,67 @@ + +use Test::More; +use strict; + +BEGIN { plan tests => 90 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +use JSON; + +my @simples = + qw/utf8 indent canonical space_before space_after allow_nonref shrink allow_blessed + convert_blessed relaxed + /; + +if ($JSON::can_handle_UTF16_and_utf8) { + unshift @simples, 'ascii'; + unshift @simples, 'latin1'; +} + +SKIP: { + skip "UNICODE handling is disabale.", 14 unless $JSON::can_handle_UTF16_and_utf8; +} + +my $json = new JSON; + +for my $name (@simples) { + my $method = 'get_' . $name; + ok(! $json->$method(), $method . ' default'); + $json->$name(); + ok($json->$method(), $method . ' set true'); + $json->$name(0); + ok(! $json->$method(), $method . ' set false'); + $json->$name(); + ok($json->$method(), $method . ' set true again'); +} + + +ok($json->get_max_depth == 512, 'get_max_depth default'); +$json->max_depth(7); +ok($json->get_max_depth == 7, 'get_max_depth set 7 => 7'); +$json->max_depth(); +ok($json->get_max_depth != 0, 'get_max_depth no arg'); + + +ok($json->get_max_size == 0, 'get_max_size default'); +$json->max_size(7); +ok($json->get_max_size == 7, 'get_max_size set 7 => 7'); +$json->max_size(); +ok($json->get_max_size == 0, 'get_max_size no arg'); + + +for my $name (@simples) { + $json->$name(); + ok($json->property($name), $name); + $json->$name(0); + ok(! $json->property($name), $name); + $json->$name(); + ok($json->property($name), $name); +} + + diff --git a/t/e02_bool.t b/t/e02_bool.t new file mode 100644 index 0000000..bbf9408 --- /dev/null +++ b/t/e02_bool.t @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +use strict; + +use Test::More; +use strict; + +BEGIN { plan tests => 8 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +my $json = new JSON; + + +is($json->encode([!1]), '[""]'); +is($json->encode([!!2]), '["1"]'); + +is($json->encode([ 'a' eq 'b' ]), '[""]'); +is($json->encode([ 'a' eq 'a' ]), '["1"]'); + +is($json->encode([ ('a' eq 'b') + 1 ]), '[1]'); +is($json->encode([ ('a' eq 'a') + 1 ]), '[2]'); + +# discard overload hack for JSON::XS 3.0 boolean class +#ok(JSON::true eq 'true'); +#ok(JSON::true eq '1'); +ok(JSON::true == 1); +isa_ok(JSON::true, 'JSON::PP::Boolean'); +#isa_ok(JSON::true, 'JSON::Boolean'); + + + diff --git a/t/e03_bool2.t b/t/e03_bool2.t new file mode 100644 index 0000000..998cd79 --- /dev/null +++ b/t/e03_bool2.t @@ -0,0 +1,43 @@ +use Test::More; + +BEGIN { plan tests => 16 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } +use JSON; + +is(to_json([JSON::true]), q|[true]|); +is(to_json([JSON::false]), q|[false]|); +is(to_json([JSON::null]), q|[null]|); + +my $jsontext = q|[true,false,null]|; +my $obj = from_json($jsontext); +#push @JSON::backportPP::Boolean::ISA, 'JSON::Boolean'; +isa_ok($obj->[0], 'JSON::PP::Boolean'); +isa_ok($obj->[1], 'JSON::PP::Boolean'); +ok(!defined $obj->[2], 'null is undef'); + +ok($obj->[0] == 1); +ok($obj->[0] != 0); +ok($obj->[1] == 0); +ok($obj->[1] != 1); +# discard overload hack for JSON::XS 3.0 boolean class +#ok($obj->[0] eq 'true', 'eq true'); +#ok($obj->[0] ne 'false', 'ne false'); +#ok($obj->[1] eq 'false', 'eq false'); +#ok($obj->[1] ne 'true', 'ne true'); + +ok($obj->[0] eq $obj->[0]); +ok($obj->[0] ne $obj->[1]); + +#ok(JSON::true eq 'true'); +#ok(JSON::true ne 'false'); +#ok(JSON::true ne 'null'); +#ok(JSON::false eq 'false'); +#ok(JSON::false ne 'true'); +#ok(JSON::false ne 'null'); +ok(!defined JSON::null); + +is(from_json('[true]' )->[0], JSON::true); +is(from_json('[false]')->[0], JSON::false); +is(from_json('[null]' )->[0], JSON::null); + diff --git a/t/e04_sortby.t b/t/e04_sortby.t new file mode 100644 index 0000000..69bc08f --- /dev/null +++ b/t/e04_sortby.t @@ -0,0 +1,24 @@ +
+use Test::More;
+use strict;
+BEGIN { plan tests => 3 };
+BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; }
+use JSON;
+#########################
+
+my ($js,$obj);
+my $pc = JSON->new;
+
+$obj = {a=>1, b=>2, c=>3, d=>4, e=>5, f=>6, g=>7, h=>8, i=>9};
+
+$js = $pc->sort_by(1)->encode($obj);
+is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|);
+
+
+$js = $pc->sort_by(sub { $JSON::PP::a cmp $JSON::PP::b })->encode($obj);
+is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|);
+
+$js = $pc->sort_by('hoge')->encode($obj);
+is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|);
+
+sub JSON::PP::hoge { $JSON::PP::a cmp $JSON::PP::b }
diff --git a/t/e05_esc_slash.t b/t/e05_esc_slash.t new file mode 100644 index 0000000..9be12cf --- /dev/null +++ b/t/e05_esc_slash.t @@ -0,0 +1,15 @@ +
+use Test::More;
+use strict;
+BEGIN { plan tests => 2 };
+BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; }
+use JSON;
+#########################
+
+my $json = JSON->new->allow_nonref;
+
+my $js = '/';
+
+is($json->encode($js), '"/"');
+is($json->escape_slash->encode($js), '"\/"');
+
diff --git a/t/e06_allow_barekey.t b/t/e06_allow_barekey.t new file mode 100644 index 0000000..eac42e6 --- /dev/null +++ b/t/e06_allow_barekey.t @@ -0,0 +1,19 @@ +
+use Test::More;
+use strict;
+BEGIN { plan tests => 2 };
+BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; }
+use JSON;
+#########################
+
+my $json = JSON->new->allow_nonref;
+
+eval q| $json->decode('{foo:"bar"}') |;
+
+ok($@); # in XS and PP, the error message differs.
+
+$json->allow_barekey;
+
+is($json->decode('{foo:"bar"}')->{foo}, 'bar');
+
+
diff --git a/t/e07_allow_singlequote.t b/t/e07_allow_singlequote.t new file mode 100644 index 0000000..0e35e3f --- /dev/null +++ b/t/e07_allow_singlequote.t @@ -0,0 +1,20 @@ +
+use Test::More;
+use strict;
+BEGIN { plan tests => 4 };
+BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; }
+use JSON;
+#########################
+
+my $json = JSON->new->allow_nonref;
+
+eval q| $json->decode("{'foo':'bar'}") |;
+
+ok($@); # in XS and PP, the error message differs.
+
+$json->allow_singlequote;
+
+is($json->decode(q|{'foo':"bar"}|)->{foo}, 'bar');
+is($json->decode(q|{'foo':'bar'}|)->{foo}, 'bar');
+is($json->allow_barekey->decode(q|{foo:'bar'}|)->{foo}, 'bar');
+
diff --git a/t/e08_decode.t b/t/e08_decode.t new file mode 100644 index 0000000..3782dfd --- /dev/null +++ b/t/e08_decode.t @@ -0,0 +1,41 @@ +# +# decode on Perl 5.005, 5.6, 5.8 or later +# +use strict; +use Test::More; + +BEGIN { plan tests => 6 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +no utf8; + +my $json = JSON->new->allow_nonref; + + +is($json->decode(q|"ü"|), "ü"); # utf8 +is($json->decode(q|"\u00fc"|), "\xfc"); # latin1 +is($json->decode(q|"\u00c3\u00bc"|), "\xc3\xbc"); # utf8 + +my $str = 'あ'; # Japanese 'a' in utf8 + +is($json->decode(q|"\u00e3\u0081\u0082"|), $str); + +utf8::decode($str); # usually UTF-8 flagged on, but no-op for 5.005. + +is($json->decode(q|"\u3042"|), $str); + + +my $utf8 = $json->decode(q|"\ud808\udf45"|); # chr 12345 + +utf8::encode($utf8); # UTf-8 flaged off + +is($utf8, "\xf0\x92\x8d\x85"); + diff --git a/t/e09_encode.t b/t/e09_encode.t new file mode 100644 index 0000000..05acb15 --- /dev/null +++ b/t/e09_encode.t @@ -0,0 +1,39 @@ +# +# decode on Perl 5.005, 5.6, 5.8 or later +# +use strict; +use Test::More; + +BEGIN { plan tests => 7 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +no utf8; + +my $json = JSON->new->allow_nonref; + +is($json->encode("ü"), q|"ü"|); # as is + +$json->ascii; + +is($json->encode("\xfc"), q|"\u00fc"|); # latin1 +is($json->encode("\xc3\xbc"), q|"\u00c3\u00bc"|); # utf8 +is($json->encode("ü"), q|"\u00c3\u00bc"|); # utf8 +is($json->encode('あ'), q|"\u00e3\u0081\u0082"|); + +if ($] >= 5.006) { + is($json->encode(chr hex 3042 ), q|"\u3042"|); + is($json->encode(chr hex 12345 ), q|"\ud808\udf45"|); +} +else { + is($json->encode(chr hex 3042 ), $json->encode(chr 66)); + is($json->encode(chr hex 12345 ), $json->encode(chr 69)); +} + diff --git a/t/e10_bignum.t b/t/e10_bignum.t new file mode 100644 index 0000000..5774f7d --- /dev/null +++ b/t/e10_bignum.t @@ -0,0 +1,41 @@ + +use strict; +use Test::More; +BEGIN { plan tests => 6 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON -support_by_pp; + +eval q| require Math::BigInt |; + +SKIP: { + skip "Can't load Math::BigInt.", 6 if ($@); + + my $v = Math::BigInt->VERSION; + $v =~ s/_.+$// if $v; + +my $fix = !$v ? '+' + : $v < 1.6 ? '+' + : ''; + + +my $json = new JSON; + +$json->allow_nonref->allow_bignum(1); +$json->convert_blessed->allow_blessed; + +my $num = $json->decode(q|100000000000000000000000000000000000000|); + +isa_ok($num, 'Math::BigInt'); +is("$num", $fix . '100000000000000000000000000000000000000'); +is($json->encode($num), $fix . '100000000000000000000000000000000000000'); + +$num = $json->decode(q|2.0000000000000000001|); + +isa_ok($num, 'Math::BigFloat'); +is("$num", '2.0000000000000000001'); +is($json->encode($num), '2.0000000000000000001'); + + +} diff --git a/t/e11_conv_blessed_univ.t b/t/e11_conv_blessed_univ.t new file mode 100644 index 0000000..18d09d4 --- /dev/null +++ b/t/e11_conv_blessed_univ.t @@ -0,0 +1,45 @@ + +use strict; +use Test::More; +BEGIN { plan tests => 3 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON -convert_blessed_universally; + + +my $obj = Test->new( [ 1, 2, {foo => 'bar'} ] ); + +$obj->[3] = Test2->new( { a => 'b' } ); + +my $json = JSON->new->allow_blessed->convert_blessed; + +is( $json->encode( $obj ), '[1,2,{"foo":"bar"},"hoge"]' ); + +$json->convert_blessed(0); + +is( $json->encode( $obj ), 'null' ); + +$json->allow_blessed(0)->convert_blessed(1); + +is( $json->encode( $obj ), '[1,2,{"foo":"bar"},"hoge"]' ); + + +package Test; + +sub new { + bless $_[1], $_[0]; +} + + + +package Test2; + +sub new { + bless $_[1], $_[0]; +} + +sub TO_JSON { + "hoge"; +} + diff --git a/t/e12_upgrade.t b/t/e12_upgrade.t new file mode 100644 index 0000000..820eed8 --- /dev/null +++ b/t/e12_upgrade.t @@ -0,0 +1,32 @@ +use strict; +use Test::More; + +BEGIN { plan tests => 3 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +my $json = JSON->new->allow_nonref->utf8; +my $str = '\\u00c8'; + +my $value = $json->decode( '"\\u00c8"' ); + +#use Devel::Peek; +#Dump( $value ); + +is( $value, chr 0xc8 ); + +SKIP: { + skip "UNICODE handling is disabale.", 1 unless $JSON::can_handle_UTF16_and_utf8; + ok( utf8::is_utf8( $value ) ); +} + +eval { $json->decode( '"' . chr(0xc8) . '"' ) }; +ok( $@ =~ /malformed UTF-8 character in JSON string/ ); + diff --git a/t/e13_overloaded_eq.t b/t/e13_overloaded_eq.t new file mode 100644 index 0000000..4418c20 --- /dev/null +++ b/t/e13_overloaded_eq.t @@ -0,0 +1,66 @@ +#!/usr/bin/perl + +use strict; +use Test::More tests => 4; + +BEGIN { + $ENV{ PERL_JSON_BACKEND } = "JSON::backportPP"; +} + +use JSON; + +my $json = JSON->new->convert_blessed; + +my $obj = OverloadedObject->new( 'foo' ); +ok( $obj eq 'foo' ); +is( $json->encode( [ $obj ] ), q{["foo"]} ); + +# rt.cpan.org #64783 +my $foo = bless {}, 'Foo'; +my $bar = bless {}, 'Bar'; + +eval q{ $json->encode( $foo ) }; +ok($@); +eval q{ $json->encode( $bar ) }; +ok(!$@); + + +package Foo; + +use strict; +use overload ( + 'eq' => sub { 0 }, + '""' => sub { $_[0] }, + fallback => 1, +); + +sub TO_JSON { + return $_[0]; +} + +package Bar; + +use strict; +use overload ( + 'eq' => sub { 0 }, + '""' => sub { $_[0] }, + fallback => 1, +); + +sub TO_JSON { + return overload::StrVal($_[0]); +} + + +package OverloadedObject; + +use overload 'eq' => sub { $_[0]->{v} eq $_[1] }, '""' => sub { $_[0]->{v} }, fallback => 1; + + +sub new { + bless { v => $_[1] }, $_[0]; +} + + +sub TO_JSON { "$_[0]"; } + diff --git a/t/e14_decode_prefix.t b/t/e14_decode_prefix.t new file mode 100644 index 0000000..3a2f2ef --- /dev/null +++ b/t/e14_decode_prefix.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +use strict; +use Test::More tests => 8; + +BEGIN { + $ENV{ PERL_JSON_BACKEND } = "JSON::backportPP"; +} + +use JSON; + +my $json = JSON->new; + +my $complete_text = qq/{"foo":"bar"}/; +my $garbaged_text = qq/{"foo":"bar"}\n/; +my $garbaged_text2 = qq/{"foo":"bar"}\n\n/; +my $garbaged_text3 = qq/{"foo":"bar"}\n----/; + +is( ( $json->decode_prefix( $complete_text ) ) [1], 13 ); +is( ( $json->decode_prefix( $garbaged_text ) ) [1], 13 ); +is( ( $json->decode_prefix( $garbaged_text2 ) ) [1], 13 ); +is( ( $json->decode_prefix( $garbaged_text3 ) ) [1], 13 ); + +eval { $json->decode( "\n" ) }; ok( $@ =~ /malformed JSON/ ); +eval { $json->decode('null') }; ok $@ =~ /allow_nonref/; + +eval { $json->decode_prefix( "\n" ) }; ok( $@ =~ /malformed JSON/ ); +eval { $json->decode_prefix('null') }; ok $@ =~ /allow_nonref/; + diff --git a/t/e15_tie_ixhash.t b/t/e15_tie_ixhash.t new file mode 100644 index 0000000..9e8991d --- /dev/null +++ b/t/e15_tie_ixhash.t @@ -0,0 +1,44 @@ + +use strict; +use Test::More; +BEGIN { plan tests => 2 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = "JSON::backportPP"; } + +use JSON; + +# from https://rt.cpan.org/Ticket/Display.html?id=25162 + +SKIP: { + eval {require Tie::IxHash}; + skip "Can't load Tie::IxHash.", 2 if ($@); + + my %columns; + tie %columns, 'Tie::IxHash'; + + %columns = ( + id => 'int', + 1 => 'a', + 2 => 'b', + 3 => 'c', + 4 => 'd', + 5 => 'e', + ); + + my $js = to_json(\%columns); + is( $js, q/{"id":"int","1":"a","2":"b","3":"c","4":"d","5":"e"}/ ); + + $js = to_json(\%columns, {pretty => 1}); + is( $js, <<'STR' ); +{ + "id" : "int", + "1" : "a", + "2" : "b", + "3" : "c", + "4" : "d", + "5" : "e" +} +STR + +} + diff --git a/t/e16_incr_parse_fixed.t b/t/e16_incr_parse_fixed.t new file mode 100644 index 0000000..9dff6d5 --- /dev/null +++ b/t/e16_incr_parse_fixed.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +BEGIN { + $ENV{ PERL_JSON_BACKEND } = $ARGV[0] || 'JSON::backportPP'; +} + +use strict; +use Test::More tests => 4; + +use JSON; + +my $json = JSON->new->allow_nonref(); + +my @vs = $json->incr_parse('"a\"bc'); + +ok( not scalar(@vs) ); + +@vs = $json->incr_parse('"'); + +is( $vs[0], "a\"bc" ); + + +$json = JSON->new; + +@vs = $json->incr_parse('"a\"bc'); +ok( not scalar(@vs) ); +@vs = eval { $json->incr_parse('"') }; +ok($@ =~ qr/JSON text must be an object or array/); + diff --git a/t/e90_misc.t b/t/e90_misc.t new file mode 100644 index 0000000..39d7e8d --- /dev/null +++ b/t/e90_misc.t @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +use strict; +use Test::More tests => 4; + +BEGIN { + $ENV{ PERL_JSON_BACKEND } = $ARGV[0] || 'JSON::backportPP'; +} + +use JSON; + +# reported by https://rt.cpan.org/Public/Bug/Display.html?id=68359 + +eval { JSON->to_json( 5, { allow_nonref => 1 } ) }; +ok($@); + +is( q{"5"}, JSON::to_json( "5", { allow_nonref => 1 } ) ); +is( q{5}, JSON::to_json( 5, { allow_nonref => 1 } ) ); +is( q{"JSON"}, JSON::to_json( 'JSON', { allow_nonref => 1 } ) ); diff --git a/t/x00_load.t b/t/x00_load.t new file mode 100644 index 0000000..e220874 --- /dev/null +++ b/t/x00_load.t @@ -0,0 +1,15 @@ + +use strict; +use Test::More; +BEGIN { plan tests => 1 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON; + +SKIP: { + skip "can't use JSON::XS.", 1, unless( JSON->backend->is_xs ); + diag("load JSON::XS v." . JSON->backend->VERSION ); + ok(1, "load JSON::XS v." . JSON->backend->VERSION ); +} + diff --git a/t/x02_error.t b/t/x02_error.t new file mode 100644 index 0000000..b4f9a80 --- /dev/null +++ b/t/x02_error.t @@ -0,0 +1,61 @@ +use strict; +use Test::More; +BEGIN { plan tests => 31 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +local $^W; + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +use utf8; +use JSON; + +SKIP: { + skip "can't use JSON::XS.", 31, unless( JSON->backend->is_xs ); + +eval { JSON->new->encode ([\-1]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\undef]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\2]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\{}]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\[]]) }; ok $@ =~ /cannot encode reference/; +eval { JSON->new->encode ([\\1]) }; ok $@ =~ /cannot encode reference/; + +eval { JSON->new->allow_nonref (1)->decode ('"\u1234\udc00"') }; ok $@ =~ /missing high /; +eval { JSON->new->allow_nonref->decode ('"\ud800"') }; ok $@ =~ /missing low /; +eval { JSON->new->allow_nonref (1)->decode ('"\ud800\u1234"') }; ok $@ =~ /surrogate pair /; + +eval { JSON->new->decode ('null') }; ok $@ =~ /allow_nonref/; +eval { JSON->new->allow_nonref (1)->decode ('+0') }; ok $@ =~ /malformed/; +eval { JSON->new->allow_nonref->decode ('.2') }; ok $@ =~ /malformed/; +eval { JSON->new->allow_nonref (1)->decode ('bare') }; ok $@ =~ /malformed/; +eval { JSON->new->allow_nonref->decode ('naughty') }; ok $@ =~ /null/; +eval { JSON->new->allow_nonref (1)->decode ('01') }; ok $@ =~ /leading zero/; +eval { JSON->new->allow_nonref->decode ('00') }; ok $@ =~ /leading zero/; +eval { JSON->new->allow_nonref (1)->decode ('-0.') }; ok $@ =~ /decimal point/; +eval { JSON->new->allow_nonref->decode ('-0e') }; ok $@ =~ /exp sign/; +eval { JSON->new->allow_nonref (1)->decode ('-e+1') }; ok $@ =~ /initial minus/; +eval { JSON->new->allow_nonref->decode ("\"\n\"") }; ok $@ =~ /invalid character/; +eval { JSON->new->allow_nonref (1)->decode ("\"\x01\"") }; ok $@ =~ /invalid character/; +eval { JSON->new->decode ('[5') }; ok $@ =~ /parsing array/; +eval { JSON->new->decode ('{"5"') }; ok $@ =~ /':' expected/; +eval { JSON->new->decode ('{"5":null') }; ok $@ =~ /parsing object/; + +eval { JSON->new->decode (undef) }; ok $@ =~ /malformed/; +eval { JSON->new->decode (\5) }; ok !!$@; # Can't coerce readonly +eval { JSON->new->decode ([]) }; ok $@ =~ /malformed/; +eval { JSON->new->decode (\*STDERR) }; ok $@ =~ /malformed/; +eval { JSON->new->decode (*STDERR) }; ok !!$@; # cannot coerce GLOB + +# differences between JSON::XS and JSON::PP + +eval { decode_json ("\"\xa0") }; ok $@ =~ /malformed.*character/; +eval { decode_json ("\"\xa0\"") }; ok $@ =~ /malformed.*character/; + +#eval { decode_json ("\"\xa0") }; ok $@ =~ /JSON text must be an object or array/; +#eval { decode_json ("\"\xa0\"") }; ok $@ =~ /JSON text must be an object or array/; + +} diff --git a/t/x12_blessed.t b/t/x12_blessed.t new file mode 100644 index 0000000..b6df13a --- /dev/null +++ b/t/x12_blessed.t @@ -0,0 +1,54 @@ +use strict; +use Test::More; +BEGIN { plan tests => 16 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON; + +SKIP: { + skip "can't use JSON::XS.", 16, unless( JSON->backend->is_xs ); + +my $o1 = bless { a => 3 }, "XX"; +my $o2 = bless \(my $dummy = 1), "YY"; + +sub XX::TO_JSON { + {'__',""} +} + +my $js = JSON->new; + +eval { $js->encode ($o1) }; ok ($@ =~ /allow_blessed/); +eval { $js->encode ($o2) }; ok ($@ =~ /allow_blessed/); +$js->allow_blessed; +ok ($js->encode ($o1) eq "null"); +ok ($js->encode ($o2) eq "null"); +$js->convert_blessed; +ok ($js->encode ($o1) eq '{"__":""}'); + +ok ($js->encode ($o2) eq "null"); + +$js->filter_json_object (sub { 5 }); +$js->filter_json_single_key_object (a => sub { shift }); +$js->filter_json_single_key_object (b => sub { 7 }); + +ok ("ARRAY" eq ref $js->decode ("[]")); +ok (5 eq join ":", @{ $js->decode ('[{}]') }); +ok (6 eq join ":", @{ $js->decode ('[{"a":6}]') }); +ok (5 eq join ":", @{ $js->decode ('[{"a":4,"b":7}]') }); + +$js->filter_json_object; +ok (7 == $js->decode ('[{"a":4,"b":7}]')->[0]{b}); +ok (3 eq join ":", @{ $js->decode ('[{"a":3}]') }); + +$js->filter_json_object (sub { }); +ok (7 == $js->decode ('[{"a":4,"b":7}]')->[0]{b}); +ok (9 eq join ":", @{ $js->decode ('[{"a":9}]') }); + +$js->filter_json_single_key_object ("a"); +ok (4 == $js->decode ('[{"a":4}]')->[0]{a}); + +$js->filter_json_single_key_object (a => sub {}); +ok (4 == $js->decode ('[{"a":4}]')->[0]{a}); + +} diff --git a/t/x16_tied.t b/t/x16_tied.t new file mode 100644 index 0000000..f219fc2 --- /dev/null +++ b/t/x16_tied.t @@ -0,0 +1,26 @@ +use strict; +use Test::More; +BEGIN { plan tests => 2 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON; +use Tie::Hash; +use Tie::Array; + +SKIP: { + skip "can't use JSON::XS.", 2, unless( JSON->backend->is_xs ); + +my $js = JSON->new; + +tie my %h, 'Tie::StdHash'; +%h = (a => 1); + +ok ($js->encode (\%h) eq '{"a":1}'); + +tie my @a, 'Tie::StdArray'; +@a = (1, 2); + +ok ($js->encode (\@a) eq '[1,2]'); + +} diff --git a/t/x17_strange_overload.t b/t/x17_strange_overload.t new file mode 100644 index 0000000..5ba85be --- /dev/null +++ b/t/x17_strange_overload.t @@ -0,0 +1,22 @@ +use strict; +use Test::More; +BEGIN { plan tests => 2 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +SKIP: { + skip "for JSON::XS 3.x. cimpatible. Please see to Changes.", 2; + + eval q{ + use JSON::XS; + use JSON (); + }; + + skip "can't use JSON::XS.", 2, if $@; + skip "JSON::XS version < " . JSON->require_xs_version, 2 + if JSON::XS->VERSION < JSON->require_xs_version; + + is("" . JSON::XS::true(), 'true'); + is("" . JSON::true(), 'true'); +} + diff --git a/t/xe01_property.t b/t/xe01_property.t new file mode 100644 index 0000000..6b894cd --- /dev/null +++ b/t/xe01_property.t @@ -0,0 +1,56 @@ + +use Test::More; +use strict; + +BEGIN { plan tests => 90 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + + +use JSON; + +SKIP: { + skip "can't use JSON::XS.", 90, unless( JSON->backend->is_xs ); + +my @simples = + qw/ascii latin1 utf8 indent canonical space_before space_after allow_nonref shrink allow_blessed + convert_blessed relaxed + /; + +my $json = new JSON; + +for my $name (@simples) { + my $method = 'get_' . $name; + ok(! $json->$method(), $method . ' default'); + $json->$name(); + ok($json->$method(), $method . ' set true'); + $json->$name(0); + ok(! $json->$method(), $method . ' set false'); + $json->$name(); + ok($json->$method(), $method . ' set true again'); +} + + +ok($json->get_max_depth == 512, 'get_max_depth default'); +$json->max_depth(7); +ok($json->get_max_depth == 7, 'get_max_depth set 7 => 7'); +$json->max_depth(); +ok($json->get_max_depth != 0, 'get_max_depth no arg'); + +ok($json->get_max_size == 0, 'get_max_size default'); +$json->max_size(7); +ok($json->get_max_size == 7, 'get_max_size set 7 => 7'); +$json->max_size(); +ok($json->get_max_size == 0, 'get_max_size no arg'); + + +for my $name (@simples) { + $json->$name(); + ok($json->property($name), $name); + $json->$name(0); + ok(! $json->property($name), $name); + $json->$name(); + ok($json->property($name), $name); +} + +} diff --git a/t/xe02_bool.t b/t/xe02_bool.t new file mode 100644 index 0000000..784fdf3 --- /dev/null +++ b/t/xe02_bool.t @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +use strict; + +use Test::More; +use strict; + +BEGIN { plan tests => 8 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON; + +SKIP: { + skip "can't use JSON::XS.", 8, unless( JSON->backend->is_xs ); + +my $json = new JSON; + +is($json->encode([!1]), '[""]'); +is($json->encode([!!2]), '["1"]'); + +is($json->encode([ 'a' eq 'b' ]), '[""]'); +is($json->encode([ 'a' eq 'a' ]), '["1"]'); + +is($json->encode([ ('a' eq 'b') + 1 ]), '[1]'); +is($json->encode([ ('a' eq 'a') + 1 ]), '[2]'); + +# discard overload hack for JSON::XS 3.0 boolean class +#ok(JSON::true eq 'true'); +#ok(JSON::true eq '1'); +ok(JSON::true == 1); +isa_ok(JSON::true, 'JSON::PP::Boolean'); + +} diff --git a/t/xe03_bool2.t b/t/xe03_bool2.t new file mode 100644 index 0000000..4175ffe --- /dev/null +++ b/t/xe03_bool2.t @@ -0,0 +1,47 @@ +use Test::More; + +BEGIN { plan tests => 16 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } +use JSON; + +SKIP: { + skip "can't use JSON::XS.", 16, unless( JSON->backend->is_xs ); + +is(to_json([JSON::true]), q|[true]|); +is(to_json([JSON::false]), q|[false]|); +is(to_json([JSON::null]), q|[null]|); + +my $jsontext = q|[true,false,null]|; +my $obj = from_json($jsontext); + +isa_ok($obj->[0], 'JSON::PP::Boolean'); +isa_ok($obj->[1], 'JSON::PP::Boolean'); +ok(!defined $obj->[2], 'null is undef'); + +ok($obj->[0] == 1); +ok($obj->[0] != 0); +ok($obj->[1] == 0); +ok($obj->[1] != 1); + +#ok($obj->[0] eq 'true', 'eq true'); +#ok($obj->[0] ne 'false', 'ne false'); +#ok($obj->[1] eq 'false', 'eq false'); +#ok($obj->[1] ne 'true', 'ne true'); + +ok($obj->[0] eq $obj->[0]); +ok($obj->[0] ne $obj->[1]); + +#ok(JSON::true eq 'true'); +#ok(JSON::true ne 'false'); +#ok(JSON::true ne 'null'); +#ok(JSON::false eq 'false'); +#ok(JSON::false ne 'true'); +#ok(JSON::false ne 'null'); +ok(!defined JSON::null); + +is(from_json('[true]' )->[0], JSON::true); +is(from_json('[false]')->[0], JSON::false); +is(from_json('[null]' )->[0], JSON::null); + +} diff --git a/t/xe04support_by_pp.t b/t/xe04support_by_pp.t new file mode 100644 index 0000000..f8c8873 --- /dev/null +++ b/t/xe04support_by_pp.t @@ -0,0 +1,22 @@ +use strict; +use Test::More; +BEGIN { plan tests => 3 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON -support_by_pp; + +SKIP: { + skip "can't use JSON::XS.", 3, unless( JSON->backend->is_xs ); + +my $json = new JSON; + + +is($json->escape_slash(0)->allow_nonref->encode("/"), '"/"'); +is($json->escape_slash(1)->allow_nonref->encode("/"), '"\/"'); +is($json->escape_slash(0)->allow_nonref->encode("/"), '"/"'); + + +} +__END__ + diff --git a/t/xe05_indent_length.t b/t/xe05_indent_length.t new file mode 100644 index 0000000..fc28fa3 --- /dev/null +++ b/t/xe05_indent_length.t @@ -0,0 +1,76 @@ +use strict; +use Test::More; +BEGIN { plan tests => 7 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON -support_by_pp; + +SKIP: { + skip "can't use JSON::XS.", 7, unless( JSON->backend->is_xs ); + +my $json = new JSON; + + +is($json->indent_length(2)->encode([1,{foo => 'bar'}, "1", "/"]), qq|[1,{"foo":"bar"},"1","/"]|); + +is($json->indent->encode([1,{foo => 'bar'}, "1", "/"]), qq|[ + 1, + { + "foo":"bar" + }, + "1", + "/" +] +|); + + +is($json->escape_slash(1)->pretty->indent_length(2)->encode([1,{foo => 'bar'}, "1", "/"]), qq|[ + 1, + { + "foo" : "bar" + }, + "1", + "\\/" +] +|); + + +is($json->escape_slash(1)->pretty->indent_length(3)->encode([1,{foo => 'bar'}, "1", "/"]), qq|[ + 1, + { + "foo" : "bar" + }, + "1", + "\\/" +] +|); + +is($json->escape_slash(1)->pretty->indent_length(15)->encode([1,{foo => 'bar'}, "1", "/"]), qq|[ + 1, + { + "foo" : "bar" + }, + "1", + "\\/" +] +|); + + +is($json->indent_length(0)->encode([1,{foo => 'bar'}, "1", "/"]), qq|[ +1, +{ +"foo" : "bar" +}, +"1", +"\\/" +] +|); + +is($json->indent(0)->space_before(0)->space_after(0)->escape_slash(0) + ->encode([1,{foo => 'bar'}, "1", "/"]), qq|[1,{"foo":"bar"},"1","/"]|); + + +} + + diff --git a/t/xe08_decode.t b/t/xe08_decode.t new file mode 100644 index 0000000..ed78fbb --- /dev/null +++ b/t/xe08_decode.t @@ -0,0 +1,45 @@ +# +# decode on Perl 5.005, 5.6, 5.8 or later +# +use strict; +use Test::More; + +BEGIN { plan tests => 6 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON; + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + +no utf8; + +SKIP: { + skip "can't use JSON::XS.", 6, unless( JSON->backend->is_xs ); + +my $json = JSON->new->allow_nonref; + + +is($json->decode(q|"ü"|), "ü"); # utf8 +is($json->decode(q|"\u00fc"|), "\xfc"); # latin1 +is($json->decode(q|"\u00c3\u00bc"|), "\xc3\xbc"); # utf8 + +my $str = 'あ'; # Japanese 'a' in utf8 + +is($json->decode(q|"\u00e3\u0081\u0082"|), $str); + +utf8::decode($str); # usually UTF-8 flagged on, but no-op for 5.005. + +is($json->decode(q|"\u3042"|), $str); + + +my $utf8 = $json->decode(q|"\ud808\udf45"|); # chr 12345 + +utf8::encode($utf8); # UTf-8 flaged off + +is($utf8, "\xf0\x92\x8d\x85"); + +} diff --git a/t/xe10_bignum.t b/t/xe10_bignum.t new file mode 100644 index 0000000..d72b8ad --- /dev/null +++ b/t/xe10_bignum.t @@ -0,0 +1,36 @@ + +use strict; +use Test::More; +BEGIN { plan tests => 6 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON -support_by_pp; + +eval q| require Math::BigInt |; + + +SKIP: { + skip "can't use JSON::XS.", 6, unless( JSON->backend->is_xs ); + skip "Can't load Math::BigInt.", 6 if ($@); + +my $json = new JSON; +print $json->backend, "\n"; + +$json->allow_nonref->allow_bignum(1); +$json->convert_blessed->allow_blessed; + +my $num = $json->decode(q|100000000000000000000000000000000000000|); + +isa_ok($num, 'Math::BigInt'); +is($num, '100000000000000000000000000000000000000'); +is($json->encode($num), '100000000000000000000000000000000000000'); + +$num = $json->decode(q|2.0000000000000000001|); + +isa_ok($num, 'Math::BigFloat'); +is($num, '2.0000000000000000001'); +is($json->encode($num), '2.0000000000000000001'); + + +} diff --git a/t/xe11_conv_blessed_univ.t b/t/xe11_conv_blessed_univ.t new file mode 100644 index 0000000..8ccc0c1 --- /dev/null +++ b/t/xe11_conv_blessed_univ.t @@ -0,0 +1,48 @@ + +use strict; +use Test::More; +BEGIN { plan tests => 3 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON -convert_blessed_universally; + +SKIP: { + skip "can't use JSON::XS.", 3, unless( JSON->backend->is_xs ); + +my $obj = Test->new( [ 1, 2, {foo => 'bar'} ] ); + +$obj->[3] = Test2->new( { a => 'b' } ); + +my $json = JSON->new->allow_blessed->convert_blessed; + +is( $json->encode( $obj ), '[1,2,{"foo":"bar"},"hoge"]' ); + +$json->convert_blessed(0); + +is( $json->encode( $obj ), 'null' ); + +$json->allow_blessed(0)->convert_blessed(1); + +is( $json->encode( $obj ), '[1,2,{"foo":"bar"},"hoge"]' ); + +} + +package Test; + +sub new { + bless $_[1], $_[0]; +} + + + +package Test2; + +sub new { + bless $_[1], $_[0]; +} + +sub TO_JSON { + "hoge"; +} + diff --git a/t/xe12_boolean.t b/t/xe12_boolean.t new file mode 100644 index 0000000..9a1292c --- /dev/null +++ b/t/xe12_boolean.t @@ -0,0 +1,35 @@ + +use strict; +use Test::More; + +BEGIN { plan tests => 4 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON -support_by_pp; + +BEGIN { + use lib qw(t); + use _unicode_handling; +} + + +SKIP: { + skip "can't use JSON::XS.", 4, unless( JSON->backend->is_xs ); + +my $json = new JSON; +my $bool = $json->allow_nonref->decode('true'); + +# it's normal +isa_ok( $bool, 'JSON::PP::Boolean' ); +is( $json->encode([ JSON::true ]), '[true]' ); + +# make XS non support flag enable! +$bool = $json->allow_singlequote->decode('true'); + +isa_ok( $bool, 'JSON::PP::Boolean' ); +is( $json->encode([ JSON::true ]), '[true]' ); + +} + +__END__ diff --git a/t/xe19_xs_and_suportbypp.t b/t/xe19_xs_and_suportbypp.t new file mode 100644 index 0000000..f8ed824 --- /dev/null +++ b/t/xe19_xs_and_suportbypp.t @@ -0,0 +1,34 @@ +#! perl + +# https://rt.cpan.org/Public/Bug/Display.html?id=52847 + +use strict; +use Test::More; + +BEGIN { plan tests => 2 }; +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON -support_by_pp; + +SKIP: { + skip "can't use JSON::XS.", 2, unless( JSON->backend->is_xs ); + + my $json = JSON->new->allow_barekey; + + for (1..2) { + is_deeply( test($json, q!{foo:"foo"}! ), {foo=>'foo'} ); + JSON->new->allow_singlequote(0); + } +} + + +sub test { + my ($coder, $str) = @_; + my $rv; + return $rv if eval { $rv = $coder->decode($str); 1 }; + chomp( my $e = $@ ); + return "died with \"$e\""; +}; + + + diff --git a/t/xe20_croak_message.t b/t/xe20_croak_message.t new file mode 100644 index 0000000..07ea8e6 --- /dev/null +++ b/t/xe20_croak_message.t @@ -0,0 +1,22 @@ +#! perl + +# https://rt.cpan.org/Public/Bug/Display.html?id=61708 + +use strict; +use Test::More; + +BEGIN { plan tests => 1 }; +BEGIN { $ENV{PERL_JSON_BACKEND} = 1; } + +use JSON; # currently it can't pass with -support_by_pp; + + +SKIP: { + skip "can't use JSON::XS.", 1, unless( JSON->backend->is_xs ); + + my $json = JSON->new; + + eval q{ $json->encode( undef ) }; + like( $@, qr/line 1\./ ); +} + diff --git a/t/xe21_is_pp.t b/t/xe21_is_pp.t new file mode 100644 index 0000000..33f53dc --- /dev/null +++ b/t/xe21_is_pp.t @@ -0,0 +1,30 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More; + +BEGIN { plan tests => 5 }; + +BEGIN { + $ENV{PERL_JSON_BACKEND} = 1; +} + +use JSON; + +my $json = JSON->new(); + +ok( $json->backend, 'backend is ' . $json->backend ); + +if ( $json->backend->is_xs ) { + ok (!JSON->is_pp(), 'JSON->is_pp()'); + ok ( JSON->is_xs(), 'JSON->is_xs()'); + ok (!$json->is_pp(), '$json->is_pp()'); + ok ( $json->is_xs(), '$json->is_xs()'); +} +else { + ok ( JSON->is_pp(), 'JSON->is_pp()'); + ok (!JSON->is_xs(), 'JSON->is_xs()'); + ok ( $json->is_pp(), '$json->is_pp()'); + ok (!$json->is_xs(), '$json->is_xs()'); +} + |