| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #library('json_tests'); | 5 #library('json_tests'); |
| 6 | 6 |
| 7 #import('dart:json'); | 7 #import('dart:json'); |
| 8 #import('dart:html'); | 8 #import('dart:html'); |
| 9 #import('../../lib/unittest/unittest.dart'); | 9 #import('../../lib/unittest/unittest.dart'); |
| 10 #import('../../lib/unittest/html_config.dart'); | 10 #import('../../lib/unittest/html_config.dart'); |
| 11 | 11 |
| 12 main() { | 12 main() { |
| 13 useHtmlConfiguration(); | 13 useHtmlConfiguration(); |
| 14 test('Parse', () { | 14 test('Parse', () { |
| 15 // Scalars. | 15 // Scalars. |
| 16 expect(JSON.parse(' 5 ')).equals(5); | 16 expect(JSON.parse(' 5 '), equals(5)); |
| 17 expect(JSON.parse(' -42 ')).equals(-42); | 17 expect(JSON.parse(' -42 '), equals(-42)); |
| 18 expect(JSON.parse(' 3e0 ')).equals(3); | 18 expect(JSON.parse(' 3e0 '), equals(3)); |
| 19 expect(JSON.parse(' 3.14 ')).equals(3.14); | 19 expect(JSON.parse(' 3.14 '), equals(3.14)); |
| 20 expect(JSON.parse('true ')).equals(true); | 20 expect(JSON.parse('true '), isTrue); |
| 21 expect(JSON.parse(' false')).equals(false); | 21 expect(JSON.parse(' false'), isFalse); |
| 22 expect(JSON.parse(' null ')).equals(null); | 22 expect(JSON.parse(' null '), isNull); |
| 23 expect(JSON.parse('\n\rnull\t')).equals(null); | 23 expect(JSON.parse('\n\rnull\t'), isNull); |
| 24 expect(JSON.parse(' "hi there\\" bob" ')).equals('hi there" bob'); | 24 expect(JSON.parse(' "hi there\\" bob" '), equals('hi there" bob')); |
| 25 expect(JSON.parse(' "" ')).equals(''); | 25 expect(JSON.parse(' "" '), isEmpty); |
| 26 | 26 |
| 27 // Lists. | 27 // Lists. |
| 28 expectValueEquals([], JSON.parse(' [] ')); | 28 expect(JSON.parse(' [] '), isEmpty); |
| 29 expectValueEquals([], JSON.parse('[ ]')); | 29 expect(JSON.parse('[ ]'), isEmpty); |
| 30 expectValueEquals([3, -4.5, true, 'hi', false], | 30 expect(JSON.parse(' [3, -4.5, true, "hi", false] '), |
| 31 JSON.parse(' [3, -4.5, true, "hi", false] ')); | 31 orderedEquals([3, -4.5, true, 'hi', false])); |
| 32 // Nulls are tricky. | 32 // Nulls are tricky. |
| 33 expectValueEquals([null], JSON.parse('[null]')); | 33 expect(JSON.parse('[null]'), orderedEquals([null])); |
| 34 expectValueEquals([3, -4.5, null, true, 'hi', false], | 34 expect(JSON.parse(' [3, -4.5, null, true, "hi", false] '), |
| 35 JSON.parse(' [3, -4.5, null, true, "hi", false] ')); | 35 orderedEquals([3, -4.5, null, true, 'hi', false])); |
| 36 expectValueEquals([[null]], JSON.parse('[[null]]')); | 36 expect(JSON.parse('[[null]]'), |
| 37 expectValueEquals([[3], [], [null], ['hi', true]], | 37 recursivelyMatches([[null]])); |
| 38 JSON.parse(' [ [3], [], [null], ["hi", true]] ')); | 38 expect(JSON.parse(' [ [3], [], [null], ["hi", true]] '), |
| 39 recursivelyMatches([[3], [], [null], ['hi', true]])); |
| 39 | 40 |
| 40 // Maps. | 41 // Maps. |
| 41 expectValueEquals({}, JSON.parse(' {} ')); | 42 expect(JSON.parse(' {} '), isEmpty); |
| 42 expectValueEquals({}, JSON.parse('{ }')); | 43 expect(JSON.parse('{ }'), isEmpty); |
| 43 | 44 |
| 44 expectValueEquals( | 45 expect(JSON.parse( |
| 45 {'x':3, 'y':-4.5, 'z':'hi', 'u':true, 'v':false}, | 46 ' {"x":3, "y": -4.5, "z" : "hi","u" : true, "v": false } '), |
| 46 JSON.parse(' {"x":3, "y": -4.5, "z" : "hi","u" : true, "v": false } ')); | 47 recursivelyMatches({"x":3, "y": -4.5, "z" : "hi", |
| 47 expectValueEquals({"x":3, "y":-4.5, "z":'hi'}, | 48 "u" : true, "v": false })); |
| 48 JSON.parse(' {"x":3, "y": -4.5, "z" : "hi" } ')); | |
| 49 expectValueEquals({"z":'hi', "x":3, "y":-4.5}, | |
| 50 JSON.parse(' {"y": -4.5, "z" : "hi" ,"x":3 } ')); | |
| 51 | 49 |
| 52 expectValueEquals({' hi bob ':3, '':4.5}, | 50 expect(JSON.parse(' {"x":3, "y": -4.5, "z" : "hi" } '), |
| 53 JSON.parse('{ " hi bob " :3, "": 4.5}')); | 51 recursivelyMatches({"x":3, "y": -4.5, "z" : "hi" })); |
| 54 | 52 |
| 55 expectValueEquals({'x':{}}, JSON.parse(' { "x" : { } } ')); | 53 expect(JSON.parse(' {"y": -4.5, "z" : "hi" ,"x":3 } '), |
| 56 expectValueEquals({'x':{}}, JSON.parse('{"x":{}}')); | 54 recursivelyMatches({"y": -4.5, "z" : "hi" ,"x":3 })); |
| 55 |
| 56 expect(JSON.parse('{ " hi bob " :3, "": 4.5}'), |
| 57 recursivelyMatches({ " hi bob " :3, "": 4.5})); |
| 58 |
| 59 expect(JSON.parse(' { "x" : { } } '), |
| 60 recursivelyMatches({ 'x' : {}})); |
| 61 expect(JSON.parse('{"x":{}}'), |
| 62 recursivelyMatches({ 'x' : {}})); |
| 57 | 63 |
| 58 // Nulls are tricky. | 64 // Nulls are tricky. |
| 59 expectValueEquals({'w':null}, JSON.parse('{"w":null}')); | 65 expect(JSON.parse('{"w":null}'), |
| 60 expectValueEquals({'x':{'w':null}}, JSON.parse('{"x":{"w":null}}')); | 66 recursivelyMatches({ 'w' : null})); |
| 61 expectValueEquals( | 67 |
| 62 {'x':3, 'y':-4.5, 'z':'hi', 'w':null, 'u':true, 'v':false}, | 68 expect(JSON.parse('{"x":{"w":null}}'), |
| 63 JSON.parse(' {"x":3, "y": -4.5, "z" : "hi",' | 69 recursivelyMatches({"x":{"w":null}})); |
| 64 '"w":null, "u" : true, "v": false } ')); | 70 |
| 65 expectValueEquals( | 71 expect(JSON.parse(' {"x":3, "y": -4.5, "z" : "hi",' |
| 66 {'x':{'a':3, 'b':-4.5}, 'y':[{}], 'z':'hi', 'w':{'c':null, 'd':true}, | 72 '"w":null, "u" : true, "v": false } '), |
| 67 'v':null}, | 73 recursivelyMatches({"x":3, "y": -4.5, "z" : "hi", |
| 68 JSON.parse('{"x": {"a":3, "b": -4.5}, "y":[{}], ' | 74 "w":null, "u" : true, "v": false })); |
| 69 '"z":"hi","w":{"c":null,"d":true}, "v":null}')); | 75 |
| 70 }); | 76 expect(JSON.parse('{"x": {"a":3, "b": -4.5}, "y":[{}], ' |
| 77 '"z":"hi","w":{"c":null,"d":true}, "v":null}'), |
| 78 recursivelyMatches({"x": {"a":3, "b": -4.5}, "y":[{}], |
| 79 "z":"hi","w":{"c":null,"d":true}, "v":null})); |
| 71 | 80 |
| 72 test('stringify', () { | 81 test('stringify', () { |
| 73 // Scalars. | 82 // Scalars. |
| 74 expect(JSON.stringify(5)).equals('5'); | 83 expect(JSON.stringify(5), equals('5')); |
| 75 expect(JSON.stringify(-42)).equals('-42'); | 84 expect(JSON.stringify(-42), equals('-42')); |
| 76 // Dart does not guarantee a formatting for doubles, | 85 // Dart does not guarantee a formatting for doubles, |
| 77 // so reparse and compare to the original. | 86 // so reparse and compare to the original. |
| 78 validateRoundTrip(3.14); | 87 validateRoundTrip(3.14); |
| 79 expect(JSON.stringify(true)).equals('true'); | 88 expect(JSON.stringify(true), equals('true')); |
| 80 expect(JSON.stringify(false)).equals('false'); | 89 expect(JSON.stringify(false), equals('false')); |
| 81 expect(JSON.stringify(null)).equals('null'); | 90 expect(JSON.stringify(null), equals('null')); |
| 82 expect(JSON.stringify(' hi there" bob ')).equals('" hi there\\" bob "'); | 91 expect(JSON.stringify(' hi there" bob '), equals('" hi there\\" bob "')); |
| 83 expect(JSON.stringify('hi\\there')).equals('"hi\\\\there"'); | 92 expect(JSON.stringify('hi\\there'), equals('"hi\\\\there"')); |
| 84 // TODO(devoncarew): these tests break the dartium build | 93 // TODO(devoncarew): these tests break the dartium build |
| 85 //expect(JSON.stringify('hi\nthere')).equals('"hi\\nthere"'); | 94 //expect(JSON.stringify('hi\nthere'), equals('"hi\\nthere"')); |
| 86 //expect(JSON.stringify('hi\r\nthere')).equals('"hi\\r\\nthere"'); | 95 //expect(JSON.stringify('hi\r\nthere'), equals('"hi\\r\\nthere"')); |
| 87 expect(JSON.stringify('')).equals('""'); | 96 expect(JSON.stringify(''), equals('""')); |
| 88 | 97 |
| 89 // Lists. | 98 // Lists. |
| 90 expect(JSON.stringify([])).equals('[]'); | 99 expect(JSON.stringify([]), equals('[]')); |
| 91 expect(JSON.stringify(new List(0))).equals('[]'); | 100 expect(JSON.stringify(new List(0)), equals('[]')); |
| 92 expect(JSON.stringify(new List(3))).equals('[null,null,null]'); | 101 expect(JSON.stringify(new List(3)), equals('[null,null,null]')); |
| 93 validateRoundTrip([3, -4.5, null, true, 'hi', false]); | 102 validateRoundTrip([3, -4.5, null, true, 'hi', false]); |
| 94 Expect.equals('[[3],[],[null],["hi",true]]', | 103 expect(JSON.stringify([[3], [], [null], ['hi', true]]), |
| 95 JSON.stringify([[3], [], [null], ['hi', true]])); | 104 equals('[[3],[],[null],["hi",true]]')); |
| 96 | 105 |
| 97 // Maps. | 106 // Maps. |
| 98 expect(JSON.stringify({})).equals('{}'); | 107 expect(JSON.stringify({}), equals('{}')); |
| 99 expect(JSON.stringify(new Map())).equals('{}'); | 108 expect(JSON.stringify(new Map()), equals('{}')); |
| 100 expect(JSON.stringify({'x':{}})).equals('{"x":{}}'); | 109 expect(JSON.stringify({'x':{}}), equals('{"x":{}}')); |
| 101 expect(JSON.stringify({'x':{'a':3}})).equals('{"x":{"a":3}}'); | 110 expect(JSON.stringify({'x':{'a':3}}), equals('{"x":{"a":3}}')); |
| 102 | 111 |
| 103 // Dart does not guarantee an order on the keys | 112 // Dart does not guarantee an order on the keys |
| 104 // of a map literal, so reparse and compare to the original Map. | 113 // of a map literal, so reparse and compare to the original Map. |
| 105 validateRoundTrip( | 114 validateRoundTrip( |
| 106 {'x':3, 'y':-4.5, 'z':'hi', 'w':null, 'u':true, 'v':false}); | 115 {'x':3, 'y':-4.5, 'z':'hi', 'w':null, 'u':true, 'v':false}); |
| 107 validateRoundTrip({"x":3, "y":-4.5, "z":'hi'}); | 116 validateRoundTrip({"x":3, "y":-4.5, "z":'hi'}); |
| 108 validateRoundTrip({' hi bob ':3, '':4.5}); | 117 validateRoundTrip({' hi bob ':3, '':4.5}); |
| 109 validateRoundTrip( | 118 validateRoundTrip( |
| 110 {'x':{'a':3, 'b':-4.5}, 'y':[{}], 'z':'hi', 'w':{'c':null, 'd':true}, | 119 {'x':{'a':3, 'b':-4.5}, 'y':[{}], 'z':'hi', 'w':{'c':null, 'd':true}, |
| 111 'v':null}); | 120 'v':null}); |
| 112 }); | 121 }); |
| 113 | 122 |
| 114 test('stringify throws if argument cannot be converted', () { | 123 test('stringify throws if argument cannot be converted', () { |
| 115 /** | 124 /** |
| 116 * Checks that we get an exception (rather than silently returning null) if | 125 * Checks that we get an exception (rather than silently returning null) if |
| 117 * we try to stringify something that cannot be converted to json. | 126 * we try to stringify something that cannot be converted to json. |
| 118 */ | 127 */ |
| 119 expectThrow(() { | 128 expect(() => JSON.stringify(new TestClass()), throws); |
| 120 JSON.stringify(new TestClass()); | |
| 121 }); | 129 }); |
| 122 }); | 130 }); |
| 123 } | 131 } |
| 124 | 132 |
| 125 class TestClass { | 133 class TestClass { |
| 126 int x; | 134 int x; |
| 127 String y; | 135 String y; |
| 128 | 136 |
| 129 TestClass() : x = 3, y = 'joe' { } | 137 TestClass() : x = 3, y = 'joe' { } |
| 130 } | 138 } |
| 131 | 139 |
| 132 /** | 140 /** |
| 133 * Checks that the argument can be converted to a JSON string and | 141 * Checks that the argument can be converted to a JSON string and |
| 134 * back, and produce something equivalent to the argument. | 142 * back, and produce something equivalent to the argument. |
| 135 */ | 143 */ |
| 136 validateRoundTrip(expected) { | 144 validateRoundTrip(expected) { |
| 137 expectValueEquals(expected, JSON.parse(JSON.stringify(expected))); | 145 expect(JSON.parse(JSON.stringify(expected)), recursivelyMatches(expected)); |
| 138 } | 146 } |
| 139 | 147 |
| 140 /** | |
| 141 * Checks that expected value-equals actual, where value-equals is | |
| 142 * the same as == except for Lists and Maps where it's recursive | |
| 143 * value-equals. | |
| 144 */ | |
| 145 // TODO(chambers): Move into Expect class. | |
| 146 expectValueEquals(expected, actual, [String message = '']) { | |
| 147 if (expected is List && actual is List) { | |
| 148 int n = Math.min(expected.length, actual.length); | |
| 149 for (int i = 0; i < n; i++) { | |
| 150 expectValueEquals(expected[i], actual[i], 'at index ${i} ${message}'); | |
| 151 } | |
| 152 // We check on length at the end in order to provide better error | |
| 153 // messages when an unexpected item is inserted in a list. | |
| 154 expect(actual.length).equals(expected.length); | |
| 155 } else if (expected is Map && actual is Map) { | |
| 156 expectIsContained(expected, actual, 'in actual ${message}'); | |
| 157 expectIsContained(actual, expected, 'in expected ${message}', false); | |
| 158 } else { | |
| 159 expect(actual).equals(expected); | |
| 160 } | |
| 161 } | |
| 162 | 148 |
| 163 expectIsContained(Map expected, Map actual, | |
| 164 [String message = '', bool checkValues = true]) { | |
| 165 for (final key in expected.getKeys()) { | |
| 166 expect(actual.containsKey(key)).equals(true); | |
| 167 if (checkValues) { | |
| 168 expectValueEquals(expected[key], actual[key],'at key ${key} ${message}'); | |
| 169 } | |
| 170 } | |
| 171 } | |
| OLD | NEW |