addon-sdk/source/test/traits/object-tests.js

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     5 "use strict";
     7 var Trait = require("sdk/deprecated/light-traits").Trait;
     8 var utils = require("./utils");
     9 var Data = utils.Data;
    10 var Method = utils.Method;
    11 var Accessor = utils.Accessor;
    12 var Required = utils.Required;
    13 var Conflict = utils.Conflict;
    15 function method() {}
    17 exports.Assert = require("./assert").Assert;
    19 exports["test empty trait"] = function (assert) {
    20   assert.equalTraits(Trait({}), {});
    21 };
    23 exports["test simple trait"] = function (assert) {
    24   var expected = {
    25     a: Data(0, true, true, true),
    26     b: Method(method, true, true, true)
    27   };
    29   assert.equalTraits(Trait({ a: 0, b: method }), expected);
    30 };
    32 exports["test simple trait with Trait.required property"] = function (assert) {
    33   var actual = Trait({ a: Trait.required, b: 1 });
    34   var expected = { a: Required("a"), b: Data(1) };
    36   assert.equalTraits(actual, expected);
    37 };
    39 exports["test ordering of trait properties is irrelevant"] = function (assert) {
    40   var actual = Trait({ a: 0, b: 1, c: Trait.required });
    41   var expected = Trait({ b: 1, c: Trait.required, a: 0 });
    43   assert.equalTraits(actual, expected);
    44 };
    46 exports["test trait with accessor property"] = function (assert) {
    47   var record = { get a() {}, set a(v) {} };
    48   var get = Object.getOwnPropertyDescriptor(record, "a").get;
    49   var set = Object.getOwnPropertyDescriptor(record, "a").set;
    51   assert.equalTraits(Trait(record), { a: Accessor(get, set) });
    52 };
    54 exports["test simple composition"] = function (assert) {
    55   var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method }));
    56   var expected = { a: Data(0), b: Data(1), c: Data(2), d: Method(method) };
    58   assert.equalTraits(actual, expected);
    59 };
    61 exports["test composition with conflict"] = function (assert) {
    62   var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 2, c: method }));
    63   var expected = { a: Conflict("a"), b: Data(1), c: Method(method) };
    65   assert.equalTraits(actual, expected);
    66 };
    68 exports["test composition of identical props does not cause conflict"] = function (assert) {
    69   var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 0, c: method }));
    71   assert.equalTraits(actual, { a: Data(0), b: Data(1), c: Method(method) });
    72 };
    74 exports["test composition with identical Trait.required props"] = function (assert) {
    75   var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }),
    76                              Trait({ a: Trait.required, c: method }));
    78   assert.equalTraits(actual, { a: Required(), b: Data(1), c: Method(method) });
    79 };
    81 exports["test composition satisfying a Trait.required prop"] = function (assert) {
    82   var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }),
    83                              Trait({ a: method }));
    85   assert.equalTraits(actual, { a: Method(method), b: Data(1) });
    86 };
    88 exports["test compose is neutral wrt conflicts"] = function (assert) {
    89   var actual = Trait.compose(Trait.compose(Trait({ a: 1 }), Trait({ a: 2 })),
    90                              Trait({ b: 0 }));
    92   assert.equalTraits(actual, { a: Conflict("a"), b: Data(0) });
    93 };
    95 exports["test conflicting prop overrides Trait.required prop"] = function (assert) {
    96   var actual = Trait.compose(Trait.compose(Trait({ a: 1 }),
    97                                            Trait({ a: 2 })),
    98                              Trait({ a: Trait.required }));
   100   assert.equalTraits(actual, { a: Conflict("a") });
   101 };
   103 exports["test compose is commutative"] = function (assert) {
   104   var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method }));
   105   var expected = Trait.compose(Trait({ c: 2, d: method }),
   106                                Trait({ a: 0, b: 1 }));
   108   assert.equalTraits(actual, expected);
   109 };
   111 exports["test compose is commutative, also for Trait.required/conflicting props"] = function (assert) {
   112   var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, e: Trait.required }),
   113                              Trait({ c: 2, d: method }));
   115   var expected = Trait.compose(Trait({ c: 2, d: method }),
   116                                Trait({ a: 0, b: 1, c: 3, e: Trait.required }));
   118   assert.equalTraits(actual, expected);
   119 };
   121 exports["test compose is associative"] = function (assert) {
   122   var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }),
   123                              Trait.compose(Trait({ c: 3, d: Trait.required }),
   124                                            Trait({ c: 2, d: method,
   125                                                     e: "foo" })));
   127   var expected = Trait.compose(
   128     Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }),
   129                   Trait({ c: 3, d: Trait.required })),
   130     Trait({ c: 2, d: method, e: "foo" }));
   132   assert.equalTraits(actual, expected);
   133 };
   135 exports["test diamond import of same prop does not generate conflict"] = function (assert) {
   136   var actual = Trait.compose(Trait.compose(Trait({ b: 2 }), Trait({ a: 1 })),
   137                              Trait.compose(Trait({ c: 3 }), Trait({ a: 1 })),
   138                              Trait({ d: 4 }));
   139   var expected = { a: Data(1), b: Data(2), c: Data(3), d: Data(4) };
   141   assert.equalTraits(actual, expected);
   142 };
   144 exports["test resolve with empty resolutions has no effect"] = function (assert) {
   145   assert.equalTraits(Trait({ a: 1, b: Trait.required, c: method }).resolve({}),
   146                     { a: Data(1), b: Required(), c: Method(method) });
   147 };
   149 exports["test resolve: renaming"] = function (assert) {
   150   var actual = Trait({ a: 1, b: Trait.required, c: method });
   152   assert.equalTraits(actual.resolve({ a: "A", c: "C" }),
   153                     { A: Data(1), b: Required(), C: Method(method),
   154                       a: Required(), c: Required() });
   155 };
   157 exports["test resolve: renaming to conflicting name causes conflict, order 1"] = function (assert) {
   158   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b" }),
   159                     { b: Conflict("b"), a: Required() });
   160 };
   162 exports["test resolve: renaming to conflicting name causes conflict, order 2"] = function (assert) {
   163   assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b" }),
   164                     { b: Conflict("b"), a: Required() });
   165 };
   167 exports["test resolve: simple exclusion"] = function (assert) {
   168   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined }),
   169                     { a: Required(), b: Data(2) });
   170 };
   172 exports["test resolve: exclusion to empty trait"] = function (assert) {
   173   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: null, b: undefined }),
   174                     { a: Required(), b: Required() });
   175 };
   177 exports["test resolve: exclusion and renaming of disjoint props"] = function (assert) {
   178   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "c" }),
   179                     { a: Required(), c: Data(2), b: Required() });
   180 };
   182 exports["test resolve: exclusion and renaming of overlapping props"] = function (assert) {
   183   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "a" }),
   184                      { a: Data(2), b: Required() });
   185 };
   187 exports["test resolve: renaming to a common alias causes conflict"] = function (assert) {
   188   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", b: "c" }),
   189                      { c: Conflict("c"), a: Required(), b: Required() });
   190 };
   192 exports["test resolve: renaming overrides Trait.required target"] = function (assert) {
   193   assert.equalTraits(Trait({ a: Trait.required, b: 2 }).resolve({ b: "a" }),
   194                      { a: Data(2), b: Required() });
   195 };
   197 exports["test resolve: renaming Trait.required properties has no effect"] = function (assert) {
   198   assert.equalTraits(Trait({ a: 2, b: Trait.required }).resolve({ b: "a" }),
   199                      { a: Data(2), b: Required() });
   200 };
   202 exports["test resolve: renaming of non-existent props has no effect"] = function (assert) {
   203   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", d: "c" }),
   204                      { c: Data(1), b: Data(2), a: Required() });
   205 };
   207 exports["test resolve: exclusion of non-existent props has no effect"] = function (assert) {
   208   assert.equalTraits(Trait({ a: 1 }).resolve({ b: undefined }), { a: Data(1) });
   209 };
   211 exports["test resolve is neutral w.r.t. Trait.required properties"] = function (assert) {
   212   var actual = Trait({ a: Trait.required, b: Trait.required, c: "foo", d: 1 });
   213   var expected = { a: Required(), b: Required(), c: Data("foo"), d: Data(1) };
   214   assert.equalTraits(actual.resolve({ a: "c", b: undefined }), expected);
   215 };
   217 exports["test resolve supports swapping of property names, ordering 1"] = function (assert) {
   218   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b", b: "a" }),
   219                      { a: Data(2), b: Data(1) });
   220 };
   222 exports["test resolve supports swapping of property names, ordering 2"] = function (assert) {
   223   assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ b: "a", a: "b" }),
   224                      { a: Data(2), b: Data(1) });
   225 };
   227 exports["test resolve supports swapping of property names, ordering 3"] = function (assert) {
   228   assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ b: "a", a: "b" }),
   229                      { a: Data(2), b: Data(1) });
   230 };
   232 exports["test resolve supports swapping of property names, ordering 4"] = function (assert) {
   233   assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b", b: "a" }),
   234                      { a: Data(2), b: Data(1) });
   235 };
   237 exports["test create simple"] = function (assert) {
   238   var o1 = Trait({
   239     a: 1,
   240     b: function () {
   241       return this.a;
   242     }
   243   }).create(Object.prototype);
   245   assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype");
   246   assert.equal(1, o1.a, "o1.a");
   247   assert.equal(1, o1.b(), "o1.b()");
   248   assert.equal(Object.keys(o1).length, 2, "Object.keys(o1).length === 2");
   249 };
   251 exports["test create with Array.prototype"] = function (assert) {
   252   var o2 = Trait({}).create(Array.prototype);
   253   assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype");
   254 };
   256 exports["test exception for incomplete required properties"] = function (assert) {
   257   assert.throws(function () {
   258     Trait({ foo: Trait.required }).create(Object.prototype);
   259   }, /Missing required property: `foo`/, "required prop error");
   260 };
   262 exports["test exception for unresolved conflicts"] = function (assert) {
   263   assert.throws(function () {
   264     Trait.compose(Trait({ a: 0 }), Trait({ a: 1 })).create({});
   265   }, /Remaining conflicting property: `a`/, "conflicting prop error");
   266 };
   268 exports["test verify that required properties are present but undefined"] = function (assert) {
   269   var o4 = Object.create(Object.prototype, Trait({ foo: Trait.required }));
   271   assert.ok("foo" in o4, "required property present");
   272   assert.throws(function () {
   273     o4.foo;
   274   }, /Missing required property: `foo`/, "required prop error");
   275 };
   277 exports["test verify that conflicting properties are present"] = function (assert) {
   278   var o5 = Object.create(Object.prototype, Trait.compose(Trait({ a: 0 }),
   279                                                          Trait({ a: 1 })));
   281   assert.ok("a" in o5, "conflicting property present");
   282   assert.throws(function () {
   283     o5.a;
   284   }, /Remaining conflicting property: `a`/, "conflicting prop access error");
   285 };
   287 exports["test diamond with conflicts"] = function (assert) {
   288   function makeT1(x) {
   289     return Trait({
   290       m: function () {
   291         return x
   292       }
   293     })
   294   };
   296   function makeT2(x) {
   297     return Trait.compose(Trait({
   298       t2: "foo"
   299     }), makeT1(x));
   300   };
   302   function makeT3(x) {
   303     return Trait.compose(Trait({
   304       t3: "bar"
   305     }), makeT1(x));
   306   };
   308   var T4 = Trait.compose(makeT2(5), makeT3(5));
   310   assert.throws(function () {
   311     T4.create(Object.prototype);
   312   }, /Remaining conflicting property: `m`/, "diamond prop conflict");
   313 };
   315 exports["test providing requirements through proto"] = function (assert) {
   316   var t = Trait({ required: Trait.required }).create({ required: "test" });
   317   assert.equal(t.required, "test", "property from proto is inherited");
   318 };
   320 if (module == require.main)
   321   require("test").run(exports);

mercurial