Browse Source

reorganize JSON test cases, add some new tests

pull/1/head
Sami Vaarala 12 years ago
parent
commit
a7dced5e93
  1. 40
      testcases/test-builtin-json-codepoints.js
  2. 0
      testcases/test-builtin-json-cyclic.js
  3. 27
      testcases/test-builtin-json-object.js
  4. 77
      testcases/test-builtin-json-proplist.js
  5. 85
      testcases/test-builtin-json-replacer.js
  6. 72
      testcases/test-builtin-json-tojson.js
  7. 66
      testcases/test-builtin-json-toplevel.js
  8. 0
      testcases/test-builtin-json-types.js
  9. 39
      testcases/test-builtin-json-wrapper.js
  10. 15
      testcases/test-builtin-json.js
  11. 34
      testcases/test-dev-json-wrapper.js

40
testcases/test-builtin-json-codepoints.js

@ -0,0 +1,40 @@
/*===
codepoint test (no output)
===*/
/* Test that all codepoint escapes can be parsed. */
function codepointTest() {
var i;
var str;
var t;
var nybbles = "0123456789abcdef";
for (i = 0; i < 65536; i++) {
str = '"\\u' +
nybbles.charAt((i >> 12) & 0x0f) +
nybbles.charAt((i >> 8) & 0x0f) +
nybbles.charAt((i >> 4) & 0x0f) +
nybbles.charAt((i >> 0) & 0x0f) +
'"';
t = JSON.parse(str);
if (typeof t !== 'string') {
throw new Error('result not string, codepoint: ' + i);
}
if (t.length !== 1) {
throw new Error('result string length not 1, codepoint: ' + i);
}
if (t.charCodeAt(0) !== i) {
throw new Error('result codepoint incorrect, codepoint: ' + i);
}
}
}
print('codepoint test (no output)');
try {
codepointTest();
} catch (e) {
print(e.name);
}

0
testcases/test-dev-json-cyclic.js → testcases/test-builtin-json-cyclic.js

27
testcases/test-builtin-json-object.js

@ -0,0 +1,27 @@
/*===
[object JSON]
true
TypeError
TypeError
===*/
/* [[Class]] is "JSON" */
print(Object.prototype.toString.call(JSON));
/* extensible */
print(Object.isExtensible(JSON));
try {
// not constructable -> TypeError
new JSON();
} catch (e) {
print(e.name);
}
try {
// not callable -> TypeError
new JSON();
} catch (e) {
print(e.name);
}

77
testcases/test-builtin-json-proplist.js

@ -0,0 +1,77 @@
print=console.log;
/*===
{"foo":1,"bar":2,"baz":4}
{"baz":4,"foo":1,"bar":2,"baz":4,"baz":4}
{"foo":1,"bar":2,"baz":4}
{"baz":4,"foo":1,"bar":2,"baz":4,"baz":4}
===*/
/* If the 2nd argument to stringify() is an array, it becomes the
* PropertyList of the serialization algorithm and affects the JO()
* algorithm concretely.
*
* The specification requires that serialization of properties will:
*
* (1) allow serialization of non-enumerable properties
* (2) will follow PropertyList order, not the object's enumeration order
* (order of properties in Object.keys())
* (3) allows the same property to be serialized multiple times
*/
function stringifyPropertyListTest1() {
var obj = {
"foo": 1,
"bar": 2,
"quux": 3
};
Object.defineProperties(obj, {
baz: { value: 4, enumerable: false, configurable: true, writable: true }
});
// baz is non-enumerable
var txt = JSON.stringify(obj, [ 'foo', 'bar', 'baz' ]);
print(txt);
// different order, 'baz' appears multiple times
var txt = JSON.stringify(obj, [ 'baz', 'foo', 'bar', 'baz', 'baz' ]);
print(txt);
}
function stringifyPropertyListTest2() {
// test that inherited properties are also correctly enumerated
// when using a PropertyList
var proto = {};
function F() {
// quux and baz are inherited
this.foo = 1;
this.bar = 2;
}
F.prototype = proto;
var obj;
Object.defineProperties(proto, {
quux: { value: 3, enumerable: true, writable: true, configurable: true },
baz: { value: 4, enumerable: false, writable: true, configurable: true },
});
obj = new F();
var txt = JSON.stringify(obj, [ 'foo', 'bar', 'baz' ]);
print(txt);
var txt = JSON.stringify(obj, [ 'baz', 'foo', 'bar', 'baz', 'baz' ]);
print(txt);
}
try {
stringifyPropertyListTest1();
stringifyPropertyListTest2();
} catch (e) {
print(e.name);
}

85
testcases/test-builtin-json-replacer.js

@ -0,0 +1,85 @@
print=console.log
/*===
identity replacer
replacer: [object Object] string object [object Object]
replacer: [object Object] string foo number 1
replacer: [object Object] string bar string bar
{"foo":1,"bar":"bar"}
replace top level with foo
"foo"
replace non-empty primitive values
{"foo":"foo","bar":"foo","quux":{"key1":"foo","key2":"foo"},"quuux":["foo","foo","foo"]}
===*/
function replacerTest1() {
var obj = {
foo: 1,
bar: 'bar'
};
function repl(k, v) {
print('replacer:', this, typeof k, k, typeof v, v);
return v;
}
// Replacer will be called first for the specification mandated
// holder object and an empty string key.
print(JSON.stringify(obj, repl));
}
function replacerTest2() {
var obj = {
foo: 1,
bar: 'bar'
};
function repl(k, v) {
return 'foo';
}
// When the replacer is called for the top-level holder, return
// 'foo', thus serializing only that string.
print(JSON.stringify(obj, repl));
}
function replacerTest3() {
var obj = {
foo: 1,
bar: 'bar',
quux: {
key1: 'val1', key2: 'val2'
},
quuux: [
'arr1', 'arr2', 'arr3'
]
};
function repl(k, v) {
if (k.length > 0 && typeof v !== 'object') {
return 'foo';
} else {
return v;
}
}
// Replace every non-object value with a non-empty key with 'foo'.
//
// Note that this also affects the array serialization.
// Rhino seems to skip replacer for the array.
print(JSON.stringify(obj, repl));
}
try {
print('identity replacer');
replacerTest1();
print('replace top level with foo');
replacerTest2();
print('replace non-empty primitive values')
replacerTest3();
} catch (e) {
print(e.name);
}

72
testcases/test-builtin-json-tojson.js

@ -0,0 +1,72 @@
/*===
{"foo":1,"bar":"bar/toJSON"}
{"foo":1,"bar":"bar/toJSON","quux":{"toJSON":123}}
Error quuux/toJSON error
{"foo":1,"bar":"bar/toJSON","quux":{"toJSON":123},"quuux":"2012-01-02T03:04:05.006Z"}
===*/
/* Any Object values with a callable toJSON() property will get called,
* and the return value of toJSON() replaces the value to be serialized.
*
* If toJSON property exists but is not callable, it is ignored.
* If toJSON() throws an error, serialization stops with the error.
*/
function toJsonPropertyTest1() {
var obj = {
foo: 1,
bar: { toJSON: function() { return 'bar/toJSON'; } }
};
print(JSON.stringify(obj));
}
function toJsonPropertyTest2() {
var obj = {
foo: 1,
bar: { toJSON: function() { return 'bar/toJSON'; } },
quux: { toJSON: 123 }
};
print(JSON.stringify(obj));
}
function toJsonPropertyTest3() {
var obj = {
foo: 1,
bar: { toJSON: function() { return 'bar/toJSON'; } },
quux: { toJSON: 123 },
quuux: { toJSON: function() { throw new Error('quuux/toJSON error'); } }
};
try {
print(JSON.stringify(obj));
} catch (e) {
// FIXME: here we assume that message is intact
print(e.name, e.message);
}
}
function toJsonPropertyTest4() {
var obj = {
foo: 1,
bar: { toJSON: function() { return 'bar/toJSON'; } },
quux: { toJSON: 123 },
quuux: new Date(Date.parse('2012-01-02T03:04:05.006Z'))
};
// Date.prototype.toJSON() ultimately calls Date.prototype.toISOString()
// which has an exact output format
print(JSON.stringify(obj));
}
try {
toJsonPropertyTest1();
toJsonPropertyTest2();
toJsonPropertyTest3();
toJsonPropertyTest4();
} catch (e) {
print(e.name);
}

66
testcases/test-builtin-json-toplevel.js

@ -0,0 +1,66 @@
/*===
undefined undefined
string null
string true
string false
string 123
string null
string null
string null
string "text"
string {"foo":"bar"}
string ["foo","bar"]
===*/
/* JSON top level value can be any type, not just an object or an array. */
function testStringify(x) {
var t = JSON.stringify(x);
print(typeof t, t);
}
try {
testStringify(undefined); // this returns 'undefined', not a string
testStringify(null);
testStringify(true);
testStringify(false);
testStringify(123.0);
testStringify(Number.NaN);
testStringify(Number.POSITIVE_INFINITY);
testStringify(Number.NEGATIVE_INFINITY);
testStringify('text');
testStringify({foo:'bar'});
testStringify(['foo','bar']);
} catch (e) {
print(e.name);
}
/*===
object
boolean
boolean
number
string
object
object
===*/
/* Test parsing of arbitrary top-level value. */
function testParse(x) {
var t = JSON.parse(x);
print(typeof t);
}
try {
testParse('null'); // note: typeof null -> 'object'
testParse('true');
testParse('false');
testParse('123.0');
testParse('"text"');
testParse('{"foo":"bar"}');
testParse('["foo","bar"]');
} catch (e) {
print(e.name);
}

0
testcases/test-dev-json-types.js → testcases/test-builtin-json-types.js

39
testcases/test-builtin-json-wrapper.js

@ -0,0 +1,39 @@
/* When encoding any value (val) using JSON.stringigy(), encoding begins
* with a dummy wrapper object:
*
* { "": val }
*
* This seems to be a purely internal matter but is not: the wrapper
* object is accessible to a replacement function.
*/
var val;
var t;
/*===
replacer
object
foo
foo
===*/
// Here the wrapper object is: { "": "foo" }
try {
val = "foo";
t = JSON.stringify(val, function(k, v) {
// this binding: holder object, i.e. the wrapper
// k: key
// v: value
print("replacer");
print(typeof this);
print(this['']); // access the empty string key of the wrapper!
print(k); // empty string
print(v); // 'foo'
});
} catch (e) {
print(e.name);
}

15
testcases/test-builtin-json.js

@ -1,15 +0,0 @@
/*
* JSON object (E5 Section 15.12).
*
* There are detailed JSON tests elsewhere. Here we test the basic
* functionality.
*/
/*---
{
"skip": true
}
---*/
/* FIXME */

34
testcases/test-dev-json-wrapper.js

@ -1,34 +0,0 @@
/* When encoding any value (val) using JSON.stringigy(), encoding begins
* with a dummy wrapper object:
*
* { "": val }
*
* This seems to be a purely internal matter but is not: the wrapper
* object is accessible to a replacement function.
*/
var val;
var t;
/*===
replacer
object
foo
foo
===*/
// Here the wrapper object is: { "": "foo" }
val = "foo";
t = JSON.stringify(val, function(k, v) {
// this binding: holder object, i.e. the wrapper
// k: key
// v: value
print("replacer");
print(typeof this);
print(this['']); // access the empty string key of the wrapper!
print(k); // empty string
print(v); // 'foo'
});
Loading…
Cancel
Save