toolkit/modules/tests/xpcshell/test_dict.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/modules/tests/xpcshell/test_dict.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,304 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +Components.utils.import("resource://gre/modules/Dict.jsm");
     1.9 +
    1.10 +/**
    1.11 + * Test that a few basic get, set, has and del operations work.
    1.12 + */
    1.13 +function test_get_set_has_del() {
    1.14 +  let dict = new Dict({foo: "bar"});
    1.15 +  dict.set("baz", 200);
    1.16 +  do_check_eq(dict.get("foo"), "bar");
    1.17 +  do_check_eq(dict.get("baz"), 200);
    1.18 +  do_check_true(dict.has("foo"));
    1.19 +  do_check_true(dict.has("baz"));
    1.20 +  // Now delete the entries
    1.21 +  do_check_true(dict.del("foo"));
    1.22 +  do_check_true(dict.del("baz"));
    1.23 +  do_check_false(dict.has("foo"));
    1.24 +  do_check_false(dict.has("baz"));
    1.25 +  // and make sure del returns false
    1.26 +  do_check_false(dict.del("foo"));
    1.27 +  do_check_false(dict.del("baz"));
    1.28 +}
    1.29 +
    1.30 +/**
    1.31 + * Test that the second parameter of get (default value) works.
    1.32 + */
    1.33 +function test_get_default() {
    1.34 +  let dict = new Dict();
    1.35 +  do_check_true(dict.get("foo") === undefined);
    1.36 +  do_check_eq(dict.get("foo", "bar"), "bar");
    1.37 +}
    1.38 +
    1.39 +/**
    1.40 + * Test that there are no collisions with builtins.
    1.41 + */
    1.42 +function test_collisions_with_builtins() {
    1.43 +  let dict = new Dict();
    1.44 +  // First check that a new dictionary doesn't already have builtins.
    1.45 +  do_check_false(dict.has("toString"));
    1.46 +  do_check_false(dict.has("watch"));
    1.47 +  do_check_false(dict.has("__proto__"));
    1.48 +
    1.49 +  // Add elements in an attempt to collide with builtins.
    1.50 +  dict.set("toString", "toString");
    1.51 +  dict.set("watch", "watch");
    1.52 +  // This is a little evil. We set __proto__ to an object to try to make it look
    1.53 +  // up the prototype chain.
    1.54 +  dict.set("__proto__", {prototest: "prototest"});
    1.55 +
    1.56 +  // Now check that the entries exist.
    1.57 +  do_check_true(dict.has("toString"));
    1.58 +  do_check_true(dict.has("watch"));
    1.59 +  do_check_true(dict.has("__proto__"));
    1.60 +  // ...and that we aren't looking up the prototype chain.
    1.61 +  do_check_false(dict.has("prototest"));
    1.62 +}
    1.63 +
    1.64 +/**
    1.65 + * Test that the "count" property works as expected.
    1.66 + */
    1.67 +function test_count() {
    1.68 +  let dict = new Dict({foo: "bar"});
    1.69 +  do_check_eq(dict.count, 1);
    1.70 +  dict.set("baz", "quux");
    1.71 +  do_check_eq(dict.count, 2);
    1.72 +  // This shouldn't change the count
    1.73 +  dict.set("baz", "quux2");
    1.74 +  do_check_eq(dict.count, 2);
    1.75 +
    1.76 +  do_check_true(dict.del("baz"));
    1.77 +  do_check_eq(dict.count, 1);
    1.78 +  // This shouldn't change the count either
    1.79 +  do_check_false(dict.del("not"));
    1.80 +  do_check_eq(dict.count, 1);
    1.81 +  do_check_true(dict.del("foo"));
    1.82 +  do_check_eq(dict.count, 0);
    1.83 +}
    1.84 +
    1.85 +/**
    1.86 + * Test that the copy function works as expected.
    1.87 + */
    1.88 +function test_copy() {
    1.89 +  let obj = {};
    1.90 +  let dict1 = new Dict({foo: "bar", baz: obj});
    1.91 +  let dict2 = dict1.copy();
    1.92 +  do_check_eq(dict2.get("foo"), "bar");
    1.93 +  do_check_eq(dict2.get("baz"), obj);
    1.94 +  // Make sure the two update independent of each other.
    1.95 +  dict1.del("foo");
    1.96 +  do_check_false(dict1.has("foo"));
    1.97 +  do_check_true(dict2.has("foo"));
    1.98 +  dict2.set("test", 400);
    1.99 +  do_check_true(dict2.has("test"));
   1.100 +  do_check_false(dict1.has("test"));
   1.101 +
   1.102 +  // Check that the copy is shallow and not deep.
   1.103 +  dict1.get("baz").prop = "proptest";
   1.104 +  do_check_eq(dict2.get("baz").prop, "proptest");
   1.105 +}
   1.106 +
   1.107 +// This is used by both test_listers and test_iterators.
   1.108 +function _check_lists(keys, values, items) {
   1.109 +  do_check_eq(keys.length, 2);
   1.110 +  do_check_true(keys.indexOf("x") != -1);
   1.111 +  do_check_true(keys.indexOf("y") != -1);
   1.112 +
   1.113 +  do_check_eq(values.length, 2);
   1.114 +  do_check_true(values.indexOf("a") != -1);
   1.115 +  do_check_true(values.indexOf("b") != -1);
   1.116 +
   1.117 +  // This is a little more tricky -- we need to check that one of the two
   1.118 +  // entries is ["x", "a"] and the other is ["y", "b"].
   1.119 +  do_check_eq(items.length, 2);
   1.120 +  do_check_eq(items[0].length, 2);
   1.121 +  do_check_eq(items[1].length, 2);
   1.122 +  let ix = (items[0][0] == "x") ? 0 : 1;
   1.123 +  let iy = (ix == 0) ? 1 : 0;
   1.124 +  do_check_eq(items[ix][0], "x");
   1.125 +  do_check_eq(items[ix][1], "a");
   1.126 +  do_check_eq(items[iy][0], "y");
   1.127 +  do_check_eq(items[iy][1], "b");
   1.128 +}
   1.129 +
   1.130 +/**
   1.131 + * Test the list functions.
   1.132 + */
   1.133 +function test_listers() {
   1.134 +  let dict = new Dict({"x": "a", "y": "b"});
   1.135 +  let keys = dict.listkeys();
   1.136 +  let values = dict.listvalues();
   1.137 +  let items = dict.listitems();
   1.138 +  _check_lists(keys, values, items);
   1.139 +}
   1.140 +
   1.141 +/**
   1.142 + * Test the iterator functions.
   1.143 + */
   1.144 +function test_iterators() {
   1.145 +  let dict = new Dict({"x": "a", "y": "b"});
   1.146 +  // Convert the generators to lists
   1.147 +  let keys = [x for (x in dict.keys)];
   1.148 +  let values = [x for (x in dict.values)];
   1.149 +  let items = [x for (x in dict.items)];
   1.150 +  _check_lists(keys, values, items);
   1.151 +}
   1.152 +
   1.153 +/**
   1.154 + * Test that setting a property throws an exception in strict mode.
   1.155 + */
   1.156 +function test_set_property_strict() {
   1.157 +  "use strict";
   1.158 +  var dict = new Dict();
   1.159 +  var thrown = false;
   1.160 +  try {
   1.161 +    dict.foo = "bar";
   1.162 +  }
   1.163 +  catch (ex) {
   1.164 +    thrown = true;
   1.165 +  }
   1.166 +  do_check_true(thrown);
   1.167 +}
   1.168 +
   1.169 +/**
   1.170 + * Test that setting a property has no effect in non-strict mode.
   1.171 + */
   1.172 +function test_set_property_non_strict() {
   1.173 +  let dict = new Dict();
   1.174 +  dict.foo = "bar";
   1.175 +  do_check_false("foo" in dict);
   1.176 +  let realget = dict.get;
   1.177 +  dict.get = "baz";
   1.178 +  do_check_eq(dict.get, realget);
   1.179 +}
   1.180 +
   1.181 +/**
   1.182 + * Tests setting a property by a lazy getter.
   1.183 + */
   1.184 +function test_set_property_lazy_getter() {
   1.185 +  let thunkCalled = false;
   1.186 +
   1.187 +  let setThunk = function(dict) {
   1.188 +    thunkCalled = false;
   1.189 +    dict.setAsLazyGetter("foo", function() {
   1.190 +      thunkCalled = true;
   1.191 +      return "bar";
   1.192 +    });
   1.193 +  };
   1.194 +
   1.195 +  let (dict = new Dict()) {
   1.196 +    setThunk(dict);
   1.197 +
   1.198 +    // Test that checking for the key existence does not invoke
   1.199 +    // the getter function.
   1.200 +    do_check_true(dict.has("foo"));
   1.201 +    do_check_false(thunkCalled);
   1.202 +    do_check_true(dict.isLazyGetter("foo"));
   1.203 +
   1.204 +    // Calling get the first time should invoke the getter function
   1.205 +    // and unmark the key as a lazy getter.
   1.206 +    do_check_eq(dict.get("foo"), "bar");
   1.207 +    do_check_true(thunkCalled);
   1.208 +    do_check_false(dict.isLazyGetter("foo"));
   1.209 +
   1.210 +    // Calling get again should not invoke the getter function
   1.211 +    thunkCalled = false;
   1.212 +    do_check_eq(dict.get("foo"), "bar");
   1.213 +    do_check_false(thunkCalled);
   1.214 +    do_check_false(dict.isLazyGetter("foo"));
   1.215 +  }
   1.216 +
   1.217 +  // Test that listvalues works for lazy keys.
   1.218 +  let (dict = new Dict()) {
   1.219 +    setThunk(dict);
   1.220 +    do_check_true(dict.isLazyGetter("foo"));
   1.221 +
   1.222 +    let (listvalues = dict.listvalues()) {
   1.223 +      do_check_false(dict.isLazyGetter("foo"));
   1.224 +      do_check_true(thunkCalled);
   1.225 +      do_check_true(listvalues.length, 1);
   1.226 +      do_check_eq(listvalues[0], "bar");
   1.227 +    }
   1.228 +
   1.229 +    thunkCalled = false;
   1.230 +
   1.231 +    // Retrieving the list again shouldn't invoke our getter.
   1.232 +    let (listvalues = dict.listvalues()) {
   1.233 +      do_check_false(dict.isLazyGetter("foo"));
   1.234 +      do_check_false(thunkCalled);
   1.235 +      do_check_true(listvalues.length, 1);
   1.236 +      do_check_eq(listvalues[0], "bar");
   1.237 +    }
   1.238 +  }
   1.239 +
   1.240 +  // Test that the values iterator also works as expected.
   1.241 +  let (dict = new Dict()) {
   1.242 +    setThunk(dict);
   1.243 +    let values = dict.values;
   1.244 +
   1.245 +    // Our getter shouldn't be called before the iterator reaches it.
   1.246 +    do_check_true(dict.isLazyGetter("foo"));
   1.247 +    do_check_false(thunkCalled);
   1.248 +    do_check_eq(values.next(), "bar");
   1.249 +    do_check_true(thunkCalled);
   1.250 +
   1.251 +    thunkCalled = false;
   1.252 +    do_check_false(dict.isLazyGetter("foo"));
   1.253 +    do_check_eq(dict.get("foo"), "bar");
   1.254 +    do_check_false(thunkCalled);
   1.255 +  }
   1.256 +}
   1.257 +
   1.258 +// This is used by both test_construct_dict_from_json_string and test_serialize_dict_to_json_string
   1.259 +function _sort_comp_arr(arr1,arr2){
   1.260 +  arr1.sort();
   1.261 +  arr2.sort();
   1.262 +  do_check_eq(arr1.toString(),arr2.toString());
   1.263 +}
   1.264 +
   1.265 +/**
   1.266 + * Tests constructing a dictionary from a JSON string.
   1.267 + */
   1.268 +function test_construct_dict_from_json_string() {
   1.269 +  let d1 = new Dict({a:1, b:2, c:"foobar"});
   1.270 +  let d2 = new Dict(JSON.stringify(({a:1, b:2, c:"foobar"})));
   1.271 +  _sort_comp_arr(d1.listkeys(),d2.listkeys());
   1.272 +  do_check_eq(d1.get("a"), d2.get("a"));
   1.273 +  do_check_eq(d1.get("b"), d2.get("b"));
   1.274 +  do_check_eq(d1.get("c"), d2.get("c"));
   1.275 +}
   1.276 +
   1.277 +/**
   1.278 + * Tests serializing a dictionary to a JSON string.
   1.279 + */
   1.280 +function test_serialize_dict_to_json_string() {
   1.281 +  let d1 = new Dict({a:1, b:2, c:"foobar"});
   1.282 +  let d2 = new Dict(d1.toJSON());
   1.283 +  _sort_comp_arr(d1.listkeys(),d2.listkeys());
   1.284 +  do_check_eq(d1.get("a"), d2.get("a"));
   1.285 +  do_check_eq(d1.get("b"), d2.get("b"));
   1.286 +  do_check_eq(d1.get("c"), d2.get("c"));
   1.287 +}
   1.288 +
   1.289 +var tests = [
   1.290 +  test_get_set_has_del,
   1.291 +  test_get_default,
   1.292 +  test_collisions_with_builtins,
   1.293 +  test_count,
   1.294 +  test_copy,
   1.295 +  test_listers,
   1.296 +  test_iterators,
   1.297 +  test_set_property_strict,
   1.298 +  test_set_property_non_strict,
   1.299 +  test_set_property_lazy_getter,
   1.300 +  test_construct_dict_from_json_string,
   1.301 +  test_serialize_dict_to_json_string
   1.302 +];
   1.303 +
   1.304 +function run_test() {
   1.305 +  for (let [, test] in Iterator(tests))
   1.306 +    test();
   1.307 +}

mercurial