toolkit/modules/tests/xpcshell/test_dict.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:645281a09bf5
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 Components.utils.import("resource://gre/modules/Dict.jsm");
6
7 /**
8 * Test that a few basic get, set, has and del operations work.
9 */
10 function test_get_set_has_del() {
11 let dict = new Dict({foo: "bar"});
12 dict.set("baz", 200);
13 do_check_eq(dict.get("foo"), "bar");
14 do_check_eq(dict.get("baz"), 200);
15 do_check_true(dict.has("foo"));
16 do_check_true(dict.has("baz"));
17 // Now delete the entries
18 do_check_true(dict.del("foo"));
19 do_check_true(dict.del("baz"));
20 do_check_false(dict.has("foo"));
21 do_check_false(dict.has("baz"));
22 // and make sure del returns false
23 do_check_false(dict.del("foo"));
24 do_check_false(dict.del("baz"));
25 }
26
27 /**
28 * Test that the second parameter of get (default value) works.
29 */
30 function test_get_default() {
31 let dict = new Dict();
32 do_check_true(dict.get("foo") === undefined);
33 do_check_eq(dict.get("foo", "bar"), "bar");
34 }
35
36 /**
37 * Test that there are no collisions with builtins.
38 */
39 function test_collisions_with_builtins() {
40 let dict = new Dict();
41 // First check that a new dictionary doesn't already have builtins.
42 do_check_false(dict.has("toString"));
43 do_check_false(dict.has("watch"));
44 do_check_false(dict.has("__proto__"));
45
46 // Add elements in an attempt to collide with builtins.
47 dict.set("toString", "toString");
48 dict.set("watch", "watch");
49 // This is a little evil. We set __proto__ to an object to try to make it look
50 // up the prototype chain.
51 dict.set("__proto__", {prototest: "prototest"});
52
53 // Now check that the entries exist.
54 do_check_true(dict.has("toString"));
55 do_check_true(dict.has("watch"));
56 do_check_true(dict.has("__proto__"));
57 // ...and that we aren't looking up the prototype chain.
58 do_check_false(dict.has("prototest"));
59 }
60
61 /**
62 * Test that the "count" property works as expected.
63 */
64 function test_count() {
65 let dict = new Dict({foo: "bar"});
66 do_check_eq(dict.count, 1);
67 dict.set("baz", "quux");
68 do_check_eq(dict.count, 2);
69 // This shouldn't change the count
70 dict.set("baz", "quux2");
71 do_check_eq(dict.count, 2);
72
73 do_check_true(dict.del("baz"));
74 do_check_eq(dict.count, 1);
75 // This shouldn't change the count either
76 do_check_false(dict.del("not"));
77 do_check_eq(dict.count, 1);
78 do_check_true(dict.del("foo"));
79 do_check_eq(dict.count, 0);
80 }
81
82 /**
83 * Test that the copy function works as expected.
84 */
85 function test_copy() {
86 let obj = {};
87 let dict1 = new Dict({foo: "bar", baz: obj});
88 let dict2 = dict1.copy();
89 do_check_eq(dict2.get("foo"), "bar");
90 do_check_eq(dict2.get("baz"), obj);
91 // Make sure the two update independent of each other.
92 dict1.del("foo");
93 do_check_false(dict1.has("foo"));
94 do_check_true(dict2.has("foo"));
95 dict2.set("test", 400);
96 do_check_true(dict2.has("test"));
97 do_check_false(dict1.has("test"));
98
99 // Check that the copy is shallow and not deep.
100 dict1.get("baz").prop = "proptest";
101 do_check_eq(dict2.get("baz").prop, "proptest");
102 }
103
104 // This is used by both test_listers and test_iterators.
105 function _check_lists(keys, values, items) {
106 do_check_eq(keys.length, 2);
107 do_check_true(keys.indexOf("x") != -1);
108 do_check_true(keys.indexOf("y") != -1);
109
110 do_check_eq(values.length, 2);
111 do_check_true(values.indexOf("a") != -1);
112 do_check_true(values.indexOf("b") != -1);
113
114 // This is a little more tricky -- we need to check that one of the two
115 // entries is ["x", "a"] and the other is ["y", "b"].
116 do_check_eq(items.length, 2);
117 do_check_eq(items[0].length, 2);
118 do_check_eq(items[1].length, 2);
119 let ix = (items[0][0] == "x") ? 0 : 1;
120 let iy = (ix == 0) ? 1 : 0;
121 do_check_eq(items[ix][0], "x");
122 do_check_eq(items[ix][1], "a");
123 do_check_eq(items[iy][0], "y");
124 do_check_eq(items[iy][1], "b");
125 }
126
127 /**
128 * Test the list functions.
129 */
130 function test_listers() {
131 let dict = new Dict({"x": "a", "y": "b"});
132 let keys = dict.listkeys();
133 let values = dict.listvalues();
134 let items = dict.listitems();
135 _check_lists(keys, values, items);
136 }
137
138 /**
139 * Test the iterator functions.
140 */
141 function test_iterators() {
142 let dict = new Dict({"x": "a", "y": "b"});
143 // Convert the generators to lists
144 let keys = [x for (x in dict.keys)];
145 let values = [x for (x in dict.values)];
146 let items = [x for (x in dict.items)];
147 _check_lists(keys, values, items);
148 }
149
150 /**
151 * Test that setting a property throws an exception in strict mode.
152 */
153 function test_set_property_strict() {
154 "use strict";
155 var dict = new Dict();
156 var thrown = false;
157 try {
158 dict.foo = "bar";
159 }
160 catch (ex) {
161 thrown = true;
162 }
163 do_check_true(thrown);
164 }
165
166 /**
167 * Test that setting a property has no effect in non-strict mode.
168 */
169 function test_set_property_non_strict() {
170 let dict = new Dict();
171 dict.foo = "bar";
172 do_check_false("foo" in dict);
173 let realget = dict.get;
174 dict.get = "baz";
175 do_check_eq(dict.get, realget);
176 }
177
178 /**
179 * Tests setting a property by a lazy getter.
180 */
181 function test_set_property_lazy_getter() {
182 let thunkCalled = false;
183
184 let setThunk = function(dict) {
185 thunkCalled = false;
186 dict.setAsLazyGetter("foo", function() {
187 thunkCalled = true;
188 return "bar";
189 });
190 };
191
192 let (dict = new Dict()) {
193 setThunk(dict);
194
195 // Test that checking for the key existence does not invoke
196 // the getter function.
197 do_check_true(dict.has("foo"));
198 do_check_false(thunkCalled);
199 do_check_true(dict.isLazyGetter("foo"));
200
201 // Calling get the first time should invoke the getter function
202 // and unmark the key as a lazy getter.
203 do_check_eq(dict.get("foo"), "bar");
204 do_check_true(thunkCalled);
205 do_check_false(dict.isLazyGetter("foo"));
206
207 // Calling get again should not invoke the getter function
208 thunkCalled = false;
209 do_check_eq(dict.get("foo"), "bar");
210 do_check_false(thunkCalled);
211 do_check_false(dict.isLazyGetter("foo"));
212 }
213
214 // Test that listvalues works for lazy keys.
215 let (dict = new Dict()) {
216 setThunk(dict);
217 do_check_true(dict.isLazyGetter("foo"));
218
219 let (listvalues = dict.listvalues()) {
220 do_check_false(dict.isLazyGetter("foo"));
221 do_check_true(thunkCalled);
222 do_check_true(listvalues.length, 1);
223 do_check_eq(listvalues[0], "bar");
224 }
225
226 thunkCalled = false;
227
228 // Retrieving the list again shouldn't invoke our getter.
229 let (listvalues = dict.listvalues()) {
230 do_check_false(dict.isLazyGetter("foo"));
231 do_check_false(thunkCalled);
232 do_check_true(listvalues.length, 1);
233 do_check_eq(listvalues[0], "bar");
234 }
235 }
236
237 // Test that the values iterator also works as expected.
238 let (dict = new Dict()) {
239 setThunk(dict);
240 let values = dict.values;
241
242 // Our getter shouldn't be called before the iterator reaches it.
243 do_check_true(dict.isLazyGetter("foo"));
244 do_check_false(thunkCalled);
245 do_check_eq(values.next(), "bar");
246 do_check_true(thunkCalled);
247
248 thunkCalled = false;
249 do_check_false(dict.isLazyGetter("foo"));
250 do_check_eq(dict.get("foo"), "bar");
251 do_check_false(thunkCalled);
252 }
253 }
254
255 // This is used by both test_construct_dict_from_json_string and test_serialize_dict_to_json_string
256 function _sort_comp_arr(arr1,arr2){
257 arr1.sort();
258 arr2.sort();
259 do_check_eq(arr1.toString(),arr2.toString());
260 }
261
262 /**
263 * Tests constructing a dictionary from a JSON string.
264 */
265 function test_construct_dict_from_json_string() {
266 let d1 = new Dict({a:1, b:2, c:"foobar"});
267 let d2 = new Dict(JSON.stringify(({a:1, b:2, c:"foobar"})));
268 _sort_comp_arr(d1.listkeys(),d2.listkeys());
269 do_check_eq(d1.get("a"), d2.get("a"));
270 do_check_eq(d1.get("b"), d2.get("b"));
271 do_check_eq(d1.get("c"), d2.get("c"));
272 }
273
274 /**
275 * Tests serializing a dictionary to a JSON string.
276 */
277 function test_serialize_dict_to_json_string() {
278 let d1 = new Dict({a:1, b:2, c:"foobar"});
279 let d2 = new Dict(d1.toJSON());
280 _sort_comp_arr(d1.listkeys(),d2.listkeys());
281 do_check_eq(d1.get("a"), d2.get("a"));
282 do_check_eq(d1.get("b"), d2.get("b"));
283 do_check_eq(d1.get("c"), d2.get("c"));
284 }
285
286 var tests = [
287 test_get_set_has_del,
288 test_get_default,
289 test_collisions_with_builtins,
290 test_count,
291 test_copy,
292 test_listers,
293 test_iterators,
294 test_set_property_strict,
295 test_set_property_non_strict,
296 test_set_property_lazy_getter,
297 test_construct_dict_from_json_string,
298 test_serialize_dict_to_json_string
299 ];
300
301 function run_test() {
302 for (let [, test] in Iterator(tests))
303 test();
304 }

mercurial