aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.3/packages/api-utils/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tools/addon-sdk-1.3/packages/api-utils/tests')
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/commonjs-test-adapter/asserts.js50
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-client.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-e10s-adapter.js11
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-e10s-adapter.js17
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-main.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module-client.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/hello-world.js11
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-client.js7
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-e10s-adapter.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/syntax-error.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/thrown-exception.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/fixtures/es5.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/README.txt4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/ORACLE54
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/b.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/program.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/submodule/a.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/a.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/b.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/program.js10
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/program.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/a.js8
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/b.js2
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/a.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/b.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/program.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/hasOwnProperty.js0
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/program.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/toString.js0
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/a.js12
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/program.js8
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/program.js9
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/a.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/b.js0
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/program.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/a/b/c/d.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/program.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/a.js2
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/program.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/program.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/a.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/b.js2
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/a.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/b.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/c.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/program.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/test.js13
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/add.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/async1.js10
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/async2.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/badExportAndReturn.js6
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/badFirst.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/badSecond.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/blue.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/castor.js6
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/cheetah.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/color.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupe.js11
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeNested.js11
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeSetExports.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/exportsEquals.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/green.js6
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/lion.js3
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/orange.js6
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/pollux.js6
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/red.js12
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/setExports.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/subtract.js5
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/tiger.js4
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional1.js8
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional2.js2
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/modules/types/cat.js1
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-api-utils.js274
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-app-strings.js58
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-array.js36
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-byte-streams.js202
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-collection.js160
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-commonjs-test-adapter.js7
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-content-loader.js223
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-content-proxy.js406
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-content-symbiont.js153
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-content-worker.js347
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-cortex.js118
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-cuddlefish.js40
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-dom.js84
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s-porting.js73
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s.js268
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-errors.js66
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-events.js182
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-file.js276
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-function-utils.js23
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-globals.js12
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-hidden-frame.js47
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-observer.js31
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-utils.js58
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-light-traits.js7
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-list.js203
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-match-pattern.js161
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-memory.js15
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-modules.js131
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-observer-service.js73
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-passwords-utils.js138
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-plain-text-console.js64
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-preferences-service.js87
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-registry.js76
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-require.js25
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-securable-module.js382
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-self.js34
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-set-exports.js28
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-browser.js525
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-observer.js35
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-tab.js106
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-text-streams.js189
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-timer.js126
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-traceback.js114
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-traits-core.js834
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-traits.js394
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-type.js88
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-unit-test.js218
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-unload.js195
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-url.js157
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-window-loader.js152
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-window-observer.js42
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-window-utils.js276
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-xhr.js67
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-xpcom.js106
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/test-xul-app.js41
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/traits/assert.js94
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/traits/descriptor-tests.js331
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/traits/inheritance-tests.js100
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/traits/object-tests.js317
-rw-r--r--tools/addon-sdk-1.3/packages/api-utils/tests/traits/utils.js52
146 files changed, 9737 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/commonjs-test-adapter/asserts.js b/tools/addon-sdk-1.3/packages/api-utils/tests/commonjs-test-adapter/asserts.js
new file mode 100644
index 0000000..83abd23
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/commonjs-test-adapter/asserts.js
@@ -0,0 +1,50 @@
+"use strict";
+
+const AssertBase = require("test/assert").Assert;
+
+/**
+ * Generates custom assertion constructors that may be bundled with a test
+ * suite.
+ * @params {String}
+ * names of assertion function to be added to the generated Assert.
+ */
+function Assert() {
+ let assertDescriptor = {};
+ Array.forEach(arguments, function(name) {
+ assertDescriptor[name] = { value: function(message) {
+ this.pass(message);
+ }}
+ });
+
+ return function Assert() {
+ return Object.create(AssertBase.apply(null, arguments), assertDescriptor);
+ };
+}
+
+exports["test suite"] = {
+ Assert: Assert("foo"),
+ "test that custom assertor is passed to test function": function(assert) {
+ assert.ok("foo" in assert, "custom assertion function `foo` is defined");
+ assert.foo("custom assertion function `foo` is called");
+ },
+ "test sub suite": {
+ "test that `Assert` is inherited by sub suits": function(assert) {
+ assert.ok("foo" in assert, "assertion function `foo` is not defined");
+ },
+ "test sub sub suite": {
+ Assert: Assert("bar"),
+ "test that custom assertor is passed to test function": function(assert) {
+ assert.ok("bar" in assert,
+ "custom assertion function `bar` is defined");
+ assert.bar("custom assertion function `bar` is called");
+ },
+ "test that `Assert` is not inherited by sub sub suits": function(assert) {
+ assert.ok(!("foo" in assert),
+ "assertion function `foo` is not defined");
+ }
+ }
+ }
+};
+
+if (module == require.main)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-client.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-client.js
new file mode 100644
index 0000000..7725897
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-client.js
@@ -0,0 +1,4 @@
+exports.main = function(options, callbacks) {
+ console.log(require("e10s-samples/adapter-only").use(1, 5));
+ callbacks.quit();
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-e10s-adapter.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-e10s-adapter.js
new file mode 100644
index 0000000..cfbfc92
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/adapter-only-e10s-adapter.js
@@ -0,0 +1,11 @@
+if (this.chrome) {
+ exports.use = function(a, b) {
+ return chrome.call("superpower", a, b);
+ };
+} else {
+ exports.register = function(addon) {
+ addon.registerCall("superpower", function(name, a, b) {
+ return "hello " + a + " " + b;
+ });
+ };
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-e10s-adapter.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-e10s-adapter.js
new file mode 100644
index 0000000..78534ef
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-e10s-adapter.js
@@ -0,0 +1,17 @@
+if (this.chrome) {
+ // TODO: register receiver for async msg.
+ chrome.on("asyncy", function() {
+ console.log("i am an async message from firefox");
+ });
+ exports.go = function() {
+ console.log("about to send sync message to firefox");
+ chrome.call("superpower");
+ console.log("returned from sync message to firefox");
+ };
+} else {
+ exports.register = function(addon) {
+ addon.registerCall("superpower", function(name) {
+ addon.send("asyncy");
+ });
+ };
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-main.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-main.js
new file mode 100644
index 0000000..46f6578
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499-main.js
@@ -0,0 +1,4 @@
+exports.main = function(options, callbacks) {
+ require("e10s-samples/bug-617499").go();
+ callbacks.quit();
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499.js
new file mode 100644
index 0000000..a6a4d63
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/bug-617499.js
@@ -0,0 +1 @@
+throw new Error("This code should never be loaded in the Firefox process!");
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module-client.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module-client.js
new file mode 100644
index 0000000..e082bda
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module-client.js
@@ -0,0 +1,3 @@
+exports.main = function() {
+ require("e10s-samples/chrome-only-module");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module.js
new file mode 100644
index 0000000..94cdddd
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/chrome-only-module.js
@@ -0,0 +1,5 @@
+var chrome = require("chrome");
+
+exports.notAccessibleFromAddons = function() {
+ throw new Error("This function should never be called from addons.");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/hello-world.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/hello-world.js
new file mode 100644
index 0000000..a59912e
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/hello-world.js
@@ -0,0 +1,11 @@
+exports.main = function(options, callbacks) {
+ console.log("hello", "world");
+ console.info("sup", "dogg");
+ console.warn("how", "r", "u");
+ console.debug("gud");
+ console.error("NO U");
+ console.exception(new Error("o snap"));
+ console.log({toString: function() { throw new Error(); }});
+ console.trace();
+ callbacks.quit();
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-client.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-client.js
new file mode 100644
index 0000000..d58b0cd
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-client.js
@@ -0,0 +1,7 @@
+var superpower = require("e10s-samples/superpower");
+
+exports.main = function(options, callbacks) {
+ console.log("superpower.use returned",
+ superpower.use("hello", "there"));
+ callbacks.quit();
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-e10s-adapter.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-e10s-adapter.js
new file mode 100644
index 0000000..9294d84
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower-e10s-adapter.js
@@ -0,0 +1,13 @@
+if (this.chrome) {
+ exports.use = function(a, b) {
+ return chrome.call("superpower", a, b);
+ };
+} else {
+ var superpower = require("e10s-samples/superpower");
+
+ exports.register = function(addon) {
+ addon.registerCall("superpower", function(name, a, b) {
+ return superpower.use(a, b);
+ });
+ };
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower.js
new file mode 100644
index 0000000..9c8bc96
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/superpower.js
@@ -0,0 +1,13 @@
+var chrome = require("chrome");
+
+var gDelegate = null;
+
+exports.setDelegate = function(delegate) {
+ gDelegate = delegate;
+};
+
+exports.use = function(a, b) {
+ if (gDelegate)
+ return gDelegate(a, b);
+ return null;
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/syntax-error.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/syntax-error.js
new file mode 100644
index 0000000..4effa19
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/syntax-error.js
@@ -0,0 +1 @@
+hello!
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/thrown-exception.js b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/thrown-exception.js
new file mode 100644
index 0000000..52cd676
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/e10s-samples/thrown-exception.js
@@ -0,0 +1,3 @@
+exports.main = function() {
+ throw new Error("alas");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/fixtures/es5.js b/tools/addon-sdk-1.3/packages/api-utils/tests/fixtures/es5.js
new file mode 100644
index 0000000..6e5b1ea
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/fixtures/es5.js
@@ -0,0 +1,4 @@
+"use strict";
+exports.frozen = Object.freeze({});
+exports.sealed = Object.seal({});
+exports.inextensible = Object.preventExtensions({});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/README.txt b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/README.txt
new file mode 100644
index 0000000..d1a6fec
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/README.txt
@@ -0,0 +1,4 @@
+This is an svn export of just the 'compliance' directory of the
+interoperablejs project on Google Code:
+
+ http://code.google.com/p/interoperablejs/
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/ORACLE b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/ORACLE
new file mode 100644
index 0000000..b5c7646
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/ORACLE
@@ -0,0 +1,54 @@
+ORACLE
+
+absolute
+PASS require works with absolute identifiers pass
+DONE info
+
+cyclic
+PASS a exists pass
+PASS b exists pass
+PASS a gets b pass
+PASS b gets a pass
+DONE info
+
+determinism
+PASS require does not fall back to relative modules when absolutes are not available. pass
+DONE info
+
+exactExports
+PASS exact exports pass
+DONE info
+
+hasOwnProperty
+DONE info
+
+method
+PASS calling a module member pass
+PASS members not implicitly bound pass
+PASS get and set pass
+DONE info
+
+missing
+PASS require throws error when module missing pass
+DONE info
+
+monkeys
+PASS monkeys permitted pass
+DONE info
+
+nested
+PASS nested module identifier pass
+DONE info
+
+reflexive
+PASS reflexive import pass
+DONE info
+
+relative
+PASS a and b share foo through a relative require pass
+DONE info
+
+transitive
+PASS transitive pass
+DONE info
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/b.js
new file mode 100644
index 0000000..da5bf4f
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/b.js
@@ -0,0 +1 @@
+exports.foo = function() {};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/program.js
new file mode 100644
index 0000000..7980ecf
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/program.js
@@ -0,0 +1,5 @@
+var test = require('test');
+var a = require('submodule/a');
+var b = require('b');
+test.assert(a.foo().foo === b.foo, 'require works with absolute identifiers');
+test.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/submodule/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/submodule/a.js
new file mode 100644
index 0000000..bc138b8
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/submodule/a.js
@@ -0,0 +1,3 @@
+exports.foo = function () {
+ return require('b');
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/absolute/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/a.js
new file mode 100644
index 0000000..e0188fa
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/a.js
@@ -0,0 +1,4 @@
+exports.a = function () {
+ return b;
+};
+var b = require('b');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/b.js
new file mode 100644
index 0000000..873a305
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/b.js
@@ -0,0 +1,4 @@
+var a = require('a');
+exports.b = function () {
+ return a;
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/program.js
new file mode 100644
index 0000000..2ee4758
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/program.js
@@ -0,0 +1,10 @@
+var test = require('test');
+var a = require('a');
+var b = require('b');
+
+test.assert(a.a, 'a exists');
+test.assert(b.b, 'b exists')
+test.assert(a.a().b === b.b, 'a gets b');
+test.assert(b.b().a === a.a, 'b gets a');
+
+test.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/cyclic/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/program.js
new file mode 100644
index 0000000..7c0e50b
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/program.js
@@ -0,0 +1,3 @@
+var test = require('test');
+require('submodule/a');
+test.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/a.js
new file mode 100644
index 0000000..0221574
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/a.js
@@ -0,0 +1,8 @@
+var pass = false;
+var test = require('test');
+try {
+ require('a');
+} catch (exception) {
+ pass = true;
+}
+test.assert(pass, 'require does not fall back to relative modules when absolutes are not available.')
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/b.js
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/submodule/b.js
@@ -0,0 +1,2 @@
+
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/determinism/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/a.js
new file mode 100644
index 0000000..d9f20c9
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/a.js
@@ -0,0 +1,3 @@
+exports.b = function () {
+ return require('b');
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/b.js
new file mode 100644
index 0000000..d324e31
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/b.js
@@ -0,0 +1,3 @@
+var test = require('test');
+var a = require('a');
+test.assert(a.b() === exports, 'exact exports');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/program.js
new file mode 100644
index 0000000..d9fa578
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/program.js
@@ -0,0 +1,3 @@
+var test = require('test');
+var b = require('b');
+test.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/exactExports/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/hasOwnProperty.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/hasOwnProperty.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/hasOwnProperty.js
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/program.js
new file mode 100644
index 0000000..4914d9d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/program.js
@@ -0,0 +1,4 @@
+var print = sys.print;
+var hasOwnProperty = require('hasOwnProperty');
+var toString = require('toString');
+print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/toString.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/toString.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/hasOwnProperty/toString.js
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/a.js
new file mode 100644
index 0000000..69c48af
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/a.js
@@ -0,0 +1,12 @@
+exports.foo = function () {
+ return this;
+};
+exports.set = function (x) {
+ this.x = x;
+};
+exports.get = function () {
+ return this.x;
+};
+exports.getClosed = function () {
+ return exports.x;
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/program.js
new file mode 100644
index 0000000..f222c51
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/program.js
@@ -0,0 +1,8 @@
+var test = require('test');
+var a = require('a');
+var foo = a.foo;
+test.assert(a.foo() == a, 'calling a module member');
+test.assert(foo() != a, 'members not implicitly bound');
+a.set(10);
+test.assert(a.get() != 10, 'get and set')
+sys.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/method/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/program.js
new file mode 100644
index 0000000..f6e8b4f
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/program.js
@@ -0,0 +1,9 @@
+var test = require('test');
+var print = sys.print;
+try {
+ require('bogus');
+ print('FAIL require throws error when module missing', 'fail');
+} catch (exception) {
+ print('PASS require throws error when module missing', 'pass');
+}
+print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/missing/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/a.js
new file mode 100644
index 0000000..18d3d8b
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/a.js
@@ -0,0 +1 @@
+require('b').monkey = 10;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/b.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/b.js
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/program.js
new file mode 100644
index 0000000..4a41c2b
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/program.js
@@ -0,0 +1,5 @@
+var b = require('b');
+var a = require('a');
+var test = require('test');
+test.assert(b.monkey != 10, 'monkeys not permitted on exports');
+test.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/monkeys/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/a/b/c/d.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/a/b/c/d.js
new file mode 100644
index 0000000..69fd282
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/a/b/c/d.js
@@ -0,0 +1,3 @@
+exports.foo = function () {
+ return 1;
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/program.js
new file mode 100644
index 0000000..d91e604
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/program.js
@@ -0,0 +1,3 @@
+var test = require('test');
+test.assert(require('a/b/c/d').foo() == 1, 'nested module identifier');
+sys.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/nested/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/a.js
new file mode 100644
index 0000000..27532cc
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/a.js
@@ -0,0 +1,2 @@
+var test = require('test');
+test.assert(require('a') === exports, 'reflexive import');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/program.js
new file mode 100644
index 0000000..4722023
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/program.js
@@ -0,0 +1,3 @@
+var test = require('test');
+require('a');
+test.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/reflexive/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/program.js
new file mode 100644
index 0000000..d18e57c
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/program.js
@@ -0,0 +1,5 @@
+var test = require('test');
+var a = require('submodule/a');
+var b = require('submodule/b');
+test.assert(a.foo == b.foo, 'a and b share foo through a relative require');
+sys.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/a.js
new file mode 100644
index 0000000..42e4ca0
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/a.js
@@ -0,0 +1 @@
+exports.foo = require('./b').foo;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/b.js
new file mode 100644
index 0000000..9042c16
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/submodule/b.js
@@ -0,0 +1,2 @@
+exports.foo = function () {
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/relative/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/a.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/a.js
new file mode 100644
index 0000000..4df7bb8
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/a.js
@@ -0,0 +1 @@
+exports.foo = require('b').foo;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/b.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/b.js
new file mode 100644
index 0000000..30ea70d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/b.js
@@ -0,0 +1 @@
+exports.foo = require('c').foo;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/c.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/c.js
new file mode 100644
index 0000000..69fd282
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/c.js
@@ -0,0 +1,3 @@
+exports.foo = function () {
+ return 1;
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/program.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/program.js
new file mode 100644
index 0000000..9f3978a
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/program.js
@@ -0,0 +1,3 @@
+var test = require('test');
+test.assert(require('a').foo() == 1, 'transitive');
+sys.print('DONE', 'info');
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/test.js
new file mode 100644
index 0000000..cd8a523
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/interoperablejs-read-only/compliance/transitive/test.js
@@ -0,0 +1,13 @@
+
+exports.print = function () {
+ sys.print.apply(undefined, arguments);
+};
+
+exports.assert = function (guard, message) {
+ if (guard) {
+ exports.print('PASS ' + message, 'pass');
+ } else {
+ exports.print('FAIL ' + message, 'fail');
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/add.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/add.js
new file mode 100644
index 0000000..5825e08
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/add.js
@@ -0,0 +1,5 @@
+define('modules/add', function () {
+ return function (a, b) {
+ return a + b;
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/async1.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/async1.js
new file mode 100644
index 0000000..cb51500
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/async1.js
@@ -0,0 +1,10 @@
+define(['./traditional2', './async2'], function () {
+ var traditional2 = require('./traditional2');
+ return {
+ name: 'async1',
+ traditional1Name: traditional2.traditional1Name,
+ traditional2Name: traditional2.name,
+ async2Name: require('./async2').name,
+ async2Traditional2Name: require('./async2').traditional2Name
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/async2.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/async2.js
new file mode 100644
index 0000000..c0281e5
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/async2.js
@@ -0,0 +1,4 @@
+define(['./traditional2', 'exports'], function (traditional2, exports) {
+ exports.name = 'async2';
+ exports.traditional2Name = traditional2.name;
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badExportAndReturn.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badExportAndReturn.js
new file mode 100644
index 0000000..0844be1
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badExportAndReturn.js
@@ -0,0 +1,6 @@
+// This is a bad module, it asks for exports but also returns a value from
+// the define defintion function.
+define(['exports'], function (exports) {
+ return 'badExportAndReturn';
+});
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badFirst.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badFirst.js
new file mode 100644
index 0000000..c3e4c36
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badFirst.js
@@ -0,0 +1,5 @@
+define(['./badSecond'], function (badSecond) {
+ return {
+ name: 'badFirst'
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badSecond.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badSecond.js
new file mode 100644
index 0000000..213c7b8
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/badSecond.js
@@ -0,0 +1,4 @@
+var first = require('./badFirst');
+
+exports.name = 'badSecond';
+exports.badFirstName = first.name;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/blue.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/blue.js
new file mode 100644
index 0000000..af3a193
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/blue.js
@@ -0,0 +1,5 @@
+define(function () {
+ return {
+ name: 'blue'
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/castor.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/castor.js
new file mode 100644
index 0000000..c2d40b7
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/castor.js
@@ -0,0 +1,6 @@
+define(['exports', './pollux'], function(exports, pollux) {
+ exports.name = 'castor';
+ exports.getPolluxName = function () {
+ return pollux.name;
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/cheetah.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/cheetah.js
new file mode 100644
index 0000000..ad24e3a
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/cheetah.js
@@ -0,0 +1,5 @@
+define(function () {
+ return function () {
+ return 'cheetah';
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/color.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/color.js
new file mode 100644
index 0000000..e1fe374
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/color.js
@@ -0,0 +1,3 @@
+define({
+ type: 'color'
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupe.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupe.js
new file mode 100644
index 0000000..f5ce8c9
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupe.js
@@ -0,0 +1,11 @@
+define({
+ name: 'dupe'
+});
+
+// This is wrong and should not be allowed. Only one call to
+// define per file.
+define([], function () {
+ return {
+ name: 'dupe2'
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeNested.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeNested.js
new file mode 100644
index 0000000..85ecb8d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeNested.js
@@ -0,0 +1,11 @@
+
+define(function () {
+ // This is wrong and should not be allowed.
+ define('dupeNested2', {
+ name: 'dupeNested2'
+ });
+
+ return {
+ name: 'dupeNested'
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeSetExports.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeSetExports.js
new file mode 100644
index 0000000..8ad3417
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/dupeSetExports.js
@@ -0,0 +1,4 @@
+define({name: "dupeSetExports"});
+
+// so this should cause a failure
+module.setExports("no no no");
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/exportsEquals.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/exportsEquals.js
new file mode 100644
index 0000000..a9bbdd8
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/exportsEquals.js
@@ -0,0 +1 @@
+module.exports = 4;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/green.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/green.js
new file mode 100644
index 0000000..8bca33c
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/green.js
@@ -0,0 +1,6 @@
+define('modules/green', ['./color'], function (color) {
+ return {
+ name: 'green',
+ parentType: color.type
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/lion.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/lion.js
new file mode 100644
index 0000000..f3962c1
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/lion.js
@@ -0,0 +1,3 @@
+define(function(require) {
+ return 'lion';
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/orange.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/orange.js
new file mode 100644
index 0000000..d983a35
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/orange.js
@@ -0,0 +1,6 @@
+define(['./color'], function (color) {
+ return {
+ name: 'orange',
+ parentType: color.type
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/pollux.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/pollux.js
new file mode 100644
index 0000000..e49370b
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/pollux.js
@@ -0,0 +1,6 @@
+define(['exports', './castor'], function(exports, castor) {
+ exports.name = 'pollux';
+ exports.getCastorName = function () {
+ return castor.name;
+ };
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/red.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/red.js
new file mode 100644
index 0000000..eb58660
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/red.js
@@ -0,0 +1,12 @@
+define(function (require) {
+ // comment fake-outs for require finding.
+ // require('bad1');
+ return {
+ name: 'red',
+ parentType: require('./color').type
+ };
+
+ /*
+ require('bad2');
+ */
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/setExports.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/setExports.js
new file mode 100644
index 0000000..290a3cb
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/setExports.js
@@ -0,0 +1 @@
+module.setExports(5);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/subtract.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/subtract.js
new file mode 100644
index 0000000..2743132
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/subtract.js
@@ -0,0 +1,5 @@
+define(function () {
+ return function (a, b) {
+ return a - b;
+ }
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/tiger.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/tiger.js
new file mode 100644
index 0000000..9a98b76
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/tiger.js
@@ -0,0 +1,4 @@
+define(function (require, exports) {
+ exports.name = 'tiger';
+ exports.type = require('modules/types/cat').type;
+});
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional1.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional1.js
new file mode 100644
index 0000000..d2e720d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional1.js
@@ -0,0 +1,8 @@
+exports.name = 'traditional1'
+
+var async1 = require('./async1');
+
+exports.traditional2Name = async1.traditional2Name;
+exports.traditional1Name = async1.traditional1Name;
+exports.async2Name = async1.async2Name;
+exports.async2Traditional2Name = async1.async2Traditional2Name;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional2.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional2.js
new file mode 100644
index 0000000..8363404
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/traditional2.js
@@ -0,0 +1,2 @@
+exports.name = 'traditional2';
+exports.traditional1Name = require('./traditional1').name;
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/modules/types/cat.js b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/types/cat.js
new file mode 100644
index 0000000..24a1c59
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/modules/types/cat.js
@@ -0,0 +1 @@
+exports.type = 'cat';
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-api-utils.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-api-utils.js
new file mode 100644
index 0000000..57dd8cd
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-api-utils.js
@@ -0,0 +1,274 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Drew Willcoxon <adw@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const apiUtils = require("api-utils");
+
+exports.testPublicConstructor = function (test) {
+ function PrivateCtor() {}
+ PrivateCtor.prototype = {};
+
+ let PublicCtor = apiUtils.publicConstructor(PrivateCtor);
+ test.assert(
+ PrivateCtor.prototype.isPrototypeOf(PublicCtor.prototype),
+ "PrivateCtor.prototype should be prototype of PublicCtor.prototype"
+ );
+
+ function testObj(useNew) {
+ let obj = useNew ? new PublicCtor() : PublicCtor();
+ test.assert(obj instanceof PublicCtor,
+ "Object should be instance of PublicCtor");
+ test.assert(obj instanceof PrivateCtor,
+ "Object should be instance of PrivateCtor");
+ test.assert(PublicCtor.prototype.isPrototypeOf(obj),
+ "PublicCtor's prototype should be prototype of object");
+ test.assertEqual(obj.constructor, PublicCtor,
+ "Object constructor should be PublicCtor");
+ }
+ testObj(true);
+ testObj(false);
+};
+
+exports.testValidateOptionsEmpty = function (test) {
+ let val = apiUtils.validateOptions(null, {});
+ assertObjsEqual(test, val, {});
+
+ val = apiUtils.validateOptions(null, { foo: {} });
+ assertObjsEqual(test, val, {});
+
+ val = apiUtils.validateOptions({}, {});
+ assertObjsEqual(test, val, {});
+
+ val = apiUtils.validateOptions({}, { foo: {} });
+ assertObjsEqual(test, val, {});
+};
+
+exports.testValidateOptionsNonempty = function (test) {
+ let val = apiUtils.validateOptions({ foo: 123 }, {});
+ assertObjsEqual(test, val, {});
+
+ val = apiUtils.validateOptions({ foo: 123, bar: 456 },
+ { foo: {}, bar: {}, baz: {} });
+ assertObjsEqual(test, val, { foo: 123, bar: 456 });
+};
+
+exports.testValidateOptionsMap = function (test) {
+ let val = apiUtils.validateOptions({ foo: 3, bar: 2 }, {
+ foo: { map: function (v) v * v },
+ bar: { map: function (v) undefined }
+ });
+ assertObjsEqual(test, val, { foo: 9, bar: undefined });
+};
+
+exports.testValidateOptionsMapException = function (test) {
+ let val = apiUtils.validateOptions({ foo: 3 }, {
+ foo: { map: function () { throw new Error(); }}
+ });
+ assertObjsEqual(test, val, { foo: 3 });
+};
+
+exports.testValidateOptionsOk = function (test) {
+ let val = apiUtils.validateOptions({ foo: 3, bar: 2, baz: 1 }, {
+ foo: { ok: function (v) v },
+ bar: { ok: function (v) v }
+ });
+ assertObjsEqual(test, val, { foo: 3, bar: 2 });
+
+ test.assertRaises(
+ function () apiUtils.validateOptions({ foo: 2, bar: 2 }, {
+ bar: { ok: function (v) v > 2 }
+ }),
+ 'The option "bar" is invalid.',
+ "ok should raise exception on invalid option"
+ );
+
+ test.assertRaises(
+ function () apiUtils.validateOptions(null, { foo: { ok: function (v) v }}),
+ 'The option "foo" is invalid.',
+ "ok should raise exception on invalid option"
+ );
+};
+
+exports.testValidateOptionsIs = function (test) {
+ let opts = {
+ array: [],
+ boolean: true,
+ func: function () {},
+ nul: null,
+ number: 1337,
+ object: {},
+ string: "foo",
+ undef1: undefined
+ };
+ let requirements = {
+ array: { is: ["array"] },
+ boolean: { is: ["boolean"] },
+ func: { is: ["function"] },
+ nul: { is: ["null"] },
+ number: { is: ["number"] },
+ object: { is: ["object"] },
+ string: { is: ["string"] },
+ undef1: { is: ["undefined"] },
+ undef2: { is: ["undefined"] }
+ };
+ let val = apiUtils.validateOptions(opts, requirements);
+ assertObjsEqual(test, val, opts);
+
+ test.assertRaises(
+ function () apiUtils.validateOptions(null, {
+ foo: { is: ["object", "number"] }
+ }),
+ 'The option "foo" must be one of the following types: object, number',
+ "Invalid type should raise exception"
+ );
+};
+
+exports.testValidateOptionsMapIsOk = function (test) {
+ let [map, is, ok] = [false, false, false];
+ let val = apiUtils.validateOptions({ foo: 1337 }, {
+ foo: {
+ map: function (v) v.toString(),
+ is: ["string"],
+ ok: function (v) v.length > 0
+ }
+ });
+ assertObjsEqual(test, val, { foo: "1337" });
+
+ let requirements = {
+ foo: {
+ is: ["object"],
+ ok: function () test.fail("is should have caused us to throw by now")
+ }
+ };
+ test.assertRaises(
+ function () apiUtils.validateOptions(null, requirements),
+ 'The option "foo" must be one of the following types: object',
+ "is should be used before ok is called"
+ );
+};
+
+exports.testValidateOptionsErrorMsg = function (test) {
+ test.assertRaises(
+ function () apiUtils.validateOptions(null, {
+ foo: { ok: function (v) v, msg: "foo!" }
+ }),
+ "foo!",
+ "ok should raise exception with customized message"
+ );
+};
+
+exports.testValidateMapWithMissingKey = function (test) {
+ let val = apiUtils.validateOptions({ }, {
+ foo: {
+ map: function (v) v || "bar"
+ }
+ });
+ assertObjsEqual(test, val, { foo: "bar" });
+
+ val = apiUtils.validateOptions({ }, {
+ foo: {
+ map: function (v) { throw "bar" }
+ }
+ });
+ assertObjsEqual(test, val, { });
+};
+
+exports.testAddIterator = function testAddIterator(test) {
+ let obj = {};
+ let keys = ["foo", "bar", "baz"];
+ let vals = [1, 2, 3];
+ let keysVals = [["foo", 1], ["bar", 2], ["baz", 3]];
+ apiUtils.addIterator(
+ obj,
+ function keysValsGen() {
+ for each (let keyVal in keysVals)
+ yield keyVal;
+ }
+ );
+
+ let keysItr = [];
+ for (let key in obj)
+ keysItr.push(key);
+ test.assertEqual(keysItr.length, keys.length,
+ "the keys iterator returns the correct number of items");
+ for (let i = 0; i < keys.length; i++)
+ test.assertEqual(keysItr[i], keys[i], "the key is correct");
+
+ let valsItr = [];
+ for each (let val in obj)
+ valsItr.push(val);
+ test.assertEqual(valsItr.length, vals.length,
+ "the vals iterator returns the correct number of items");
+ for (let i = 0; i < vals.length; i++)
+ test.assertEqual(valsItr[i], vals[i], "the val is correct");
+
+ let keysValsItr = [];
+ for (let keyVal in Iterator(obj))
+ keysValsItr.push(keyVal);
+ test.assertEqual(keysValsItr.length, keysVals.length, "the keys/vals " +
+ "iterator returns the correct number of items");
+ for (let i = 0; i < keysVals.length; i++) {
+ test.assertEqual(keysValsItr[i][0], keysVals[i][0], "the key is correct");
+ test.assertEqual(keysValsItr[i][1], keysVals[i][1], "the val is correct");
+ }
+
+ let keysOnlyItr = [];
+ for (let key in Iterator(obj, true /* keysonly */))
+ keysOnlyItr.push(key);
+ test.assertEqual(keysOnlyItr.length, keysVals.length, "the keys only " +
+ "iterator returns the correct number of items");
+ for (let i = 0; i < keysVals.length; i++)
+ test.assertEqual(keysOnlyItr[i], keysVals[i][0], "the key is correct");
+};
+
+function assertObjsEqual(test, obj1, obj2) {
+ var items = 0;
+ for (let [key, val] in Iterator(obj1)) {
+ items++;
+ test.assert(key in obj2, "obj1 key should be present in obj2");
+ test.assertEqual(obj2[key], val, "obj1 value should match obj2 value");
+ }
+ for (let [key, val] in Iterator(obj2)) {
+ items++;
+ test.assert(key in obj1, "obj2 key should be present in obj1");
+ test.assertEqual(obj1[key], val, "obj2 value should match obj1 value");
+ }
+ if (!items)
+ test.assertEqual(JSON.stringify(obj1), JSON.stringify(obj2),
+ "obj1 should have same JSON representation as obj2");
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-app-strings.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-app-strings.js
new file mode 100644
index 0000000..ac72724
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-app-strings.js
@@ -0,0 +1,58 @@
+const {Cc,Ci} = require("chrome");
+
+let StringBundle = require("app-strings").StringBundle;
+exports.testStringBundle = function(test) {
+ let url = "chrome://global/locale/security/caps.properties";
+
+ let strings = StringBundle(url);
+
+ test.assertEqual(strings.url, url,
+ "'url' property contains correct URL of string bundle");
+
+ let appLocale = Cc["@mozilla.org/intl/nslocaleservice;1"].
+ getService(Ci.nsILocaleService).
+ getApplicationLocale();
+
+ let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].
+ getService(Ci.nsIStringBundleService).
+ createBundle(url, appLocale);
+
+ let (name = "Yes") {
+ test.assertEqual(strings.get(name), stringBundle.GetStringFromName(name),
+ "getting a string returns the string");
+ }
+
+ let (name = "ExtensionCapability", args = ["foo"]) {
+ test.assertEqual(strings.get(name, args),
+ stringBundle.formatStringFromName(name, args, args.length),
+ "getting a formatted string returns the formatted string");
+ }
+
+ test.assertRaises(function () strings.get("nonexistentString"),
+ "String 'nonexistentString' could not be retrieved from " +
+ "the bundle due to an unknown error (it doesn't exist?).",
+ "retrieving a nonexistent string throws an exception");
+
+ let a = [], b = [];
+ let enumerator = stringBundle.getSimpleEnumeration();
+ while (enumerator.hasMoreElements()) {
+ let elem = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
+ a.push([elem.key, elem.value]);
+ }
+ for (let keyVal in Iterator(strings))
+ b.push(keyVal);
+
+ // Sort the arrays, because we don't assume enumeration has a set order.
+ // Sort compares [key, val] as string "key,val", which sorts the way we want
+ // it to, so there is no need to provide a custom compare function.
+ a.sort();
+ b.sort();
+
+ test.assertEqual(a.length, b.length,
+ "the iterator returns the correct number of items");
+ for (let i = 0; i < a.length; i++) {
+ test.assertEqual(a[i][0], b[i][0], "the iterated string's name is correct");
+ test.assertEqual(a[i][1], b[i][1],
+ "the iterated string's value is correct");
+ }
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-array.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-array.js
new file mode 100644
index 0000000..88aed24
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-array.js
@@ -0,0 +1,36 @@
+var array = require("array");
+
+exports.testHas = function(test) {
+ var testAry = [1, 2, 3];
+ test.assertEqual(array.has([1, 2, 3], 1), true);
+ test.assertEqual(testAry.length, 3);
+ test.assertEqual(testAry[0], 1);
+ test.assertEqual(testAry[1], 2);
+ test.assertEqual(testAry[2], 3);
+ test.assertEqual(array.has(testAry, 2), true);
+ test.assertEqual(array.has(testAry, 3), true);
+ test.assertEqual(array.has(testAry, 4), false);
+ test.assertEqual(array.has(testAry, "1"), false);
+};
+
+exports.testAdd = function(test) {
+ var testAry = [1];
+ test.assertEqual(array.add(testAry, 1), false);
+ test.assertEqual(testAry.length, 1);
+ test.assertEqual(testAry[0], 1);
+ test.assertEqual(array.add(testAry, 2), true);
+ test.assertEqual(testAry.length, 2);
+ test.assertEqual(testAry[0], 1);
+ test.assertEqual(testAry[1], 2);
+};
+
+exports.testRemove = function(test) {
+ var testAry = [1, 2];
+ test.assertEqual(array.remove(testAry, 3), false);
+ test.assertEqual(testAry.length, 2);
+ test.assertEqual(testAry[0], 1);
+ test.assertEqual(testAry[1], 2);
+ test.assertEqual(array.remove(testAry, 2), true);
+ test.assertEqual(testAry.length, 1);
+ test.assertEqual(testAry[0], 1);
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-byte-streams.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-byte-streams.js
new file mode 100644
index 0000000..c66a9ba
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-byte-streams.js
@@ -0,0 +1,202 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim:set ts=2 sw=2 sts=2 et filetype=javascript
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Drew Willcoxon <adw@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const byteStreams = require("byte-streams");
+const file = require("file");
+const url = require("url");
+
+const STREAM_CLOSED_ERROR = "The stream is closed and cannot be used.";
+
+// This should match the constant of the same name in byte-streams.js.
+const BUFFER_BYTE_LEN = 0x8000;
+
+exports.testWriteRead = function (test) {
+ let fname = dataFileFilename();
+
+ // Write a small string less than the stream's buffer size...
+ let str = "exports.testWriteRead data!";
+ let stream = open(test, fname, true);
+ test.assert(!stream.closed, "stream.closed after open should be false");
+ stream.write(str);
+ stream.close();
+ test.assert(stream.closed, "Stream should be closed after stream.close");
+ test.assertRaises(function () stream.write("This shouldn't be written!"),
+ STREAM_CLOSED_ERROR,
+ "stream.write after close should raise error");
+
+ // ... and read it.
+ stream = open(test, fname);
+ test.assertEqual(stream.read(), str,
+ "stream.read should return string written");
+ test.assertEqual(stream.read(), "",
+ "stream.read at EOS should return empty string");
+ stream.close();
+ test.assert(stream.closed, "Stream should be closed after stream.close");
+ test.assertRaises(function () stream.read(),
+ STREAM_CLOSED_ERROR,
+ "stream.read after close should raise error");
+
+ file.remove(fname);
+};
+
+// Write a big string many times the size of the stream's buffer and read it.
+exports.testWriteReadBig = function (test) {
+ let str = "";
+ let bufLen = BUFFER_BYTE_LEN;
+ let fileSize = bufLen * 10;
+ for (let i = 0; i < fileSize; i++)
+ str += i % 10;
+ let fname = dataFileFilename();
+ let stream = open(test, fname, true);
+ stream.write(str);
+ stream.close();
+ stream = open(test, fname);
+ test.assertEqual(stream.read(), str,
+ "stream.read should return string written");
+ stream.close();
+ file.remove(fname);
+};
+
+// The same, but write and read in chunks.
+exports.testWriteReadChunks = function (test) {
+ let str = "";
+ let bufLen = BUFFER_BYTE_LEN;
+ let fileSize = bufLen * 10;
+ for (let i = 0; i < fileSize; i++)
+ str += i % 10;
+ let fname = dataFileFilename();
+ let stream = open(test, fname, true);
+ let i = 0;
+ while (i < str.length) {
+ // Use a chunk length that spans buffers.
+ let chunk = str.substr(i, bufLen + 1);
+ stream.write(chunk);
+ i += bufLen + 1;
+ }
+ stream.close();
+ stream = open(test, fname);
+ let readStr = "";
+ bufLen = BUFFER_BYTE_LEN;
+ let readLen = bufLen + 1;
+ do {
+ var frag = stream.read(readLen);
+ readStr += frag;
+ } while (frag);
+ stream.close();
+ test.assertEqual(readStr, str,
+ "stream.write and read in chunks should work as expected");
+ file.remove(fname);
+};
+
+exports.testReadLengths = function (test) {
+ let fname = dataFileFilename();
+ let str = "exports.testReadLengths data!";
+ let stream = open(test, fname, true);
+ stream.write(str);
+ stream.close();
+
+ stream = open(test, fname);
+ test.assertEqual(stream.read(str.length * 1000), str,
+ "stream.read with big byte length should return string " +
+ "written");
+ stream.close();
+
+ stream = open(test, fname);
+ test.assertEqual(stream.read(0), "",
+ "string.read with zero byte length should return empty " +
+ "string");
+ stream.close();
+
+ stream = open(test, fname);
+ test.assertEqual(stream.read(-1), "",
+ "string.read with negative byte length should return " +
+ "empty string");
+ stream.close();
+
+ file.remove(fname);
+};
+
+exports.testTruncate = function (test) {
+ let fname = dataFileFilename();
+ let str = "exports.testReadLengths data!";
+ let stream = open(test, fname, true);
+ stream.write(str);
+ stream.close();
+
+ stream = open(test, fname);
+ test.assertEqual(stream.read(), str,
+ "stream.read should return string written");
+ stream.close();
+
+ stream = open(test, fname, true);
+ stream.close();
+
+ stream = open(test, fname);
+ test.assertEqual(stream.read(), "",
+ "stream.read after truncate should be empty");
+ stream.close();
+
+ file.remove(fname);
+};
+
+exports.testUnload = function (test) {
+ let loader = test.makeSandboxedLoader();
+ let file = loader.require("file");
+
+ let filename = url.toFilename(__url__);
+ let stream = file.open(filename, "b");
+
+ loader.unload();
+ test.assert(stream.closed, "Stream should be closed after module unload");
+};
+
+// Returns the name of a file that should be used to test writing and reading.
+function dataFileFilename() {
+ let dir = file.dirname(url.toFilename(__url__));
+ return file.join(dir, "test-byte-streams-data");
+}
+
+// Opens and returns the given file and ensures it's of the correct class.
+function open(test, filename, forWriting) {
+ let stream = file.open(filename, forWriting ? "wb" : "b");
+ let klass = forWriting ? "ByteWriter" : "ByteReader";
+ test.assert(stream instanceof byteStreams[klass],
+ "Opened stream should be a " + klass);
+ return stream;
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-collection.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-collection.js
new file mode 100644
index 0000000..9db638e
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-collection.js
@@ -0,0 +1,160 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Drew Willcoxon <adw@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const collection = require("collection");
+
+exports.testAddRemove = function (test) {
+ let coll = new collection.Collection();
+ compare(test, coll, []);
+ addRemove(test, coll, [], false);
+};
+
+exports.testAddRemoveBackingArray = function (test) {
+ let items = ["foo"];
+ let coll = new collection.Collection(items);
+ compare(test, coll, items);
+ addRemove(test, coll, items, true);
+
+ items = ["foo", "bar"];
+ coll = new collection.Collection(items);
+ compare(test, coll, items);
+ addRemove(test, coll, items, true);
+};
+
+exports.testProperty = function (test) {
+ let obj = makeObjWithCollProp();
+ compare(test, obj.coll, []);
+ addRemove(test, obj.coll, [], false);
+
+ // Test single-value set.
+ let items = ["foo"];
+ obj.coll = items[0];
+ compare(test, obj.coll, items);
+ addRemove(test, obj.coll, items, false);
+
+ // Test array set.
+ items = ["foo", "bar"];
+ obj.coll = items;
+ compare(test, obj.coll, items);
+ addRemove(test, obj.coll, items, false);
+};
+
+exports.testPropertyBackingArray = function (test) {
+ let items = ["foo"];
+ let obj = makeObjWithCollProp(items);
+ compare(test, obj.coll, items);
+ addRemove(test, obj.coll, items, true);
+
+ items = ["foo", "bar"];
+ obj = makeObjWithCollProp(items);
+ compare(test, obj.coll, items);
+ addRemove(test, obj.coll, items, true);
+};
+
+// Adds some values to coll and then removes them. initialItems is an array
+// containing coll's initial items. isBacking is true if initialItems is coll's
+// backing array; the point is that updates to coll should affect initialItems
+// if that's the case.
+function addRemove(test, coll, initialItems, isBacking) {
+ let items = isBacking ? initialItems : initialItems.slice(0);
+ let numInitialItems = items.length;
+
+ // Test add(val).
+ let numInsertions = 5;
+ for (let i = 0; i < numInsertions; i++) {
+ compare(test, coll, items);
+ coll.add(i);
+ if (!isBacking)
+ items.push(i);
+ }
+ compare(test, coll, items);
+
+ // Add the items we just added to make sure duplicates aren't added.
+ for (let i = 0; i < numInsertions; i++)
+ coll.add(i);
+ compare(test, coll, items);
+
+ // Test remove(val). Do a kind of shuffled remove. Remove item 1, then
+ // item 0, 3, 2, 5, 4, ...
+ for (let i = 0; i < numInsertions; i++) {
+ let val = i % 2 ? i - 1 :
+ i === numInsertions - 1 ? i : i + 1;
+ coll.remove(val);
+ if (!isBacking)
+ items.splice(items.indexOf(val), 1);
+ compare(test, coll, items);
+ }
+ test.assertEqual(coll.length, numInitialItems,
+ "All inserted items should be removed");
+
+ // Remove the items we just removed. coll should be unchanged.
+ for (let i = 0; i < numInsertions; i++)
+ coll.remove(i);
+ compare(test, coll, items);
+
+ // Test add and remove([val1, val2]).
+ let newItems = [0, 1];
+ coll.add(newItems);
+ compare(test, coll, isBacking ? items : items.concat(newItems));
+ coll.remove(newItems);
+ compare(test, coll, items);
+ test.assertEqual(coll.length, numInitialItems,
+ "All inserted items should be removed");
+}
+
+// Asserts that the items in coll are the items of array.
+function compare(test, coll, array) {
+ test.assertEqual(coll.length, array.length,
+ "Collection length should be correct");
+ let numItems = 0;
+ for (let item in coll) {
+ test.assertEqual(item, array[numItems], "Items should be equal");
+ numItems++;
+ }
+ test.assertEqual(numItems, array.length,
+ "Number of items in iteration should be correct");
+}
+
+// Returns a new object with a collection property named "coll". backingArray,
+// if defined, will create the collection with that backing array.
+function makeObjWithCollProp(backingArray) {
+ let obj = {};
+ collection.addCollectionProperty(obj, "coll", backingArray);
+ return obj;
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-commonjs-test-adapter.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-commonjs-test-adapter.js
new file mode 100644
index 0000000..71fc4a0
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-commonjs-test-adapter.js
@@ -0,0 +1,7 @@
+"use strict";
+
+exports["test custom `Assert`'s"] = require("./commonjs-test-adapter/asserts");
+
+// Disabling this check since it is not yet supported by jetpack.
+// if (module == require.main)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-loader.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-loader.js
new file mode 100644
index 0000000..0e91ee5
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-loader.js
@@ -0,0 +1,223 @@
+"use strict";
+const { Loader } = require('content/loader');
+const self = require("self");
+
+exports['test:contentURL'] = function(test) {
+ let loader = Loader(),
+ value, emitted = 0, changes = 0;
+
+ test.assertRaises(
+ function() loader.contentURL = undefined,
+ 'The `contentURL` option must be a valid URL.',
+ 'Must throw an exception if `contentURL` is not URL.'
+ );
+ test.assertRaises(
+ function() loader.contentURL = null,
+ 'The `contentURL` option must be a valid URL.',
+ 'Must throw an exception if `contentURL` is not URL.'
+ );
+ test.assertRaises(
+ function() loader.contentURL = 4,
+ 'The `contentURL` option must be a valid URL.',
+ 'Must throw an exception if `contentURL` is not URL.'
+ );
+ test.assertRaises(
+ function() loader.contentURL = { toString: function() 'Oops' },
+ 'The `contentURL` option must be a valid URL.',
+ 'Must throw an exception if `contentURL` is not URL.'
+ );
+
+ function listener(e) {
+ emitted ++;
+ test.assert(
+ 'contentURL' in e,
+ 'emitted event must contain "content" property'
+ );
+ test.assert(
+ value,
+ '' + e.contentURL,
+ 'content property of an event must match value'
+ );
+ }
+ loader.on('propertyChange', listener);
+
+ test.assertEqual(
+ null,
+ loader.contentURL,
+ 'default value is `null`'
+ );
+ loader.contentURL = value = 'data:text/html,<html><body>Hi</body><html>';
+ test.assertEqual(
+ value,
+ '' + loader.contentURL,
+ 'data uri is ok'
+ );
+ test.assertEqual(
+ ++changes,
+ emitted,
+ 'had to emit `propertyChange`'
+ );
+ loader.contentURL = value;
+ test.assertEqual(
+ changes,
+ emitted,
+ 'must not emit `propertyChange` if same value is set'
+ );
+
+ loader.contentURL = value = 'http://google.com/';
+ test.assertEqual(
+ value,
+ '' + loader.contentURL,
+ 'value must be set'
+ );
+ test.assertEqual(
+ ++ changes,
+ emitted,
+ 'had to emit `propertyChange`'
+ );
+ loader.contentURL = value;
+ test.assertEqual(
+ changes,
+ emitted,
+ 'must not emit `propertyChange` if same value is set'
+ );
+
+ loader.removeListener('propertyChange', listener);
+ loader.contentURL = value = 'about:blank';
+ test.assertEqual(
+ value,
+ '' + loader.contentURL,
+ 'contentURL must be an actual value'
+ );
+ test.assertEqual(
+ changes,
+ emitted,
+ 'listener had to be romeved'
+ );
+};
+
+exports['test:contentScriptWhen'] = function(test) {
+ let loader = Loader();
+ test.assertEqual(
+ 'end',
+ loader.contentScriptWhen,
+ '`contentScriptWhen` defaults to "end"'
+ );
+ loader.contentScriptWhen = "end";
+ test.assertEqual(
+ "end",
+ loader.contentScriptWhen
+ );
+ try {
+ loader.contentScriptWhen = 'boom';
+ test.fail('must throw when wrong value is set');
+ } catch(e) {
+ test.assertEqual(
+ 'The `contentScriptWhen` option must be either "start", "ready" or "end".',
+ e.message
+ );
+ }
+ loader.contentScriptWhen = null;
+ test.assertEqual(
+ 'end',
+ loader.contentScriptWhen,
+ '`contentScriptWhen` defaults to "end"'
+ );
+ loader.contentScriptWhen = "ready";
+ test.assertEqual(
+ "ready",
+ loader.contentScriptWhen
+ );
+ loader.contentScriptWhen = "start";
+ test.assertEqual(
+ 'start',
+ loader.contentScriptWhen
+ );
+};
+
+exports['test:contentScript'] = function(test) {
+ let loader = Loader(), value;
+ test.assertEqual(
+ null,
+ loader.contentScript,
+ '`contentScript` defaults to `null`'
+ );
+ loader.contentScript = value = 'let test = {};';
+ test.assertEqual(
+ value,
+ loader.contentScript
+ );
+ try {
+ loader.contentScript = { 1: value }
+ test.fail('must throw when wrong value is set');
+ } catch(e) {
+ test.assertEqual(
+ 'The script option must be a string or an array of strings.',
+ e.message
+ );
+ }
+ try {
+ loader.contentScript = ['oue', 2]
+ test.fail('must throw when wrong value is set');
+ } catch(e) {
+ test.assertEqual(
+ 'The script option must be a string or an array of strings.',
+ e.message
+ );
+ }
+ loader.contentScript = undefined;
+ test.assertEqual(
+ null,
+ loader.contentScript
+ );
+ loader.contentScript = value = ["1;", "2;"];
+ test.assertEqual(
+ value,
+ loader.contentScript
+ );
+};
+
+exports['test:contentScriptFile'] = function(test) {
+ let loader = Loader(), value, uri = self.data.url("test-content-loader.js");
+ test.assertEqual(
+ null,
+ loader.contentScriptFile,
+ '`contentScriptFile` defaults to `null`'
+ );
+ loader.contentScriptFile = value = uri;
+ test.assertEqual(
+ value,
+ loader.contentScriptFile
+ );
+ try {
+ loader.contentScriptFile = { 1: uri }
+ test.fail('must throw when wrong value is set');
+ } catch(e) {
+ test.assertEqual(
+ 'The `contentScriptFile` option must be a local file URL or an array of'
+ + 'URLs.',
+ e.message
+ );
+ }
+ try {
+ loader.contentScriptFile = ['oue', uri]
+ test.fail('must throw when wrong value is set');
+ } catch(e) {
+ test.assertEqual(
+ 'The `contentScriptFile` option must be a local file URL or an array of'
+ + 'URLs.',
+ e.message
+ );
+ }
+ loader.contentScriptFile = undefined;
+ test.assertEqual(
+ null,
+ loader.contentScriptFile
+ );
+ loader.contentScriptFile = value = [uri];
+ test.assertEqual(
+ value,
+ loader.contentScriptFile
+ );
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-proxy.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-proxy.js
new file mode 100644
index 0000000..47e168a
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-proxy.js
@@ -0,0 +1,406 @@
+const xulApp = require("xul-app");
+const proxy = require("content/content-proxy");
+const hiddenFrames = require("hidden-frame");
+
+exports.testProxy = function (test) {
+ let html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' +
+ '<input id="input2" type="checkbox" />' +
+ '<script>var documentGlobal = true</script>' +
+ '<iframe id="iframe" name="test" src="data:text/html," />';
+ let url = 'data:text/html,' + encodeURI(html);
+ test.waitUntilDone();
+
+ let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({
+ onReady: function () {
+
+ function onDOMReady() {
+ hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady,
+ false);
+ let win = hiddenFrame.element.contentWindow.wrappedJSObject;
+
+ test.assert(win.documentGlobal, "`win` object is unwrapped");
+
+ let wrapped = proxy.create(win);
+ let document = wrapped.document;
+ let body = document.body;
+
+
+ // Ensure that postMessage is working correctly.
+ // 1/ Check across documents with an iframe
+ let ifWindow = win.document.getElementById("iframe").contentWindow;
+ // Listen without proxies, to check that it will work in regular case
+ // simulate listening from a web document.
+ ifWindow.addEventListener("message", function listener(event) {
+ ifWindow.removeEventListener("message", listener, false);
+ // As we are in system principal, event is an XrayWrapper
+ test.assertEqual(event.source.wrappedJSObject, ifWindow,
+ "event.source is the iframe window");
+ test.assertEqual(event.origin, "null", "origin is null");
+ test.assertEqual(event.data, "ok", "message data is correct");
+ }, false);
+ // Dispatch a message from the content script proxy
+ document.getElementById("iframe").contentWindow.postMessage("ok", "*");
+
+ test.assertEqual(wrapped.postMessage, wrapped.postMessage,
+ "verify that we doesn't generate multiple functions for the same method");
+
+
+ // Test objects being given as event listener
+ let input = document.getElementById("input2");
+ let myClickListener = {
+ called: false,
+ handleEvent: function(event) {
+ test.assertEqual(this, myClickListener, "`this` is the original object");
+ test.assert(!this.called, "called only once");
+ this.called = true;
+ test.assertNotEqual(event.valueOf(), event.valueOf(proxy.UNWRAP_ACCESS_KEY), "event is wrapped");
+ test.assertEqual(event.target, input, "event.target is the wrapped window");
+ }
+ };
+
+ wrapped.addEventListener("click", myClickListener, true);
+ input.click();
+ wrapped.removeEventListener("click", myClickListener, true);
+
+ // Verify object as DOM event listener
+ let myMessageListener = {
+ called: false,
+ handleEvent: function(event) {
+ wrapped.removeEventListener("message", myMessageListener, true);
+
+ test.assertEqual(this, myMessageListener, "`this` is the original object");
+ test.assert(!this.called, "called only once");
+ this.called = true;
+ test.assertNotEqual(event.valueOf(), event.valueOf(proxy.UNWRAP_ACCESS_KEY), "event is wrapped");
+ test.assertEqual(event.target, wrapped, "event.target is the wrapped window");
+ test.assertEqual(event.source, wrapped, "event.source is the wrapped window");
+ test.assertEqual(event.origin, "null", "origin is null");
+ test.assertEqual(event.data, "ok", "message data is correct");
+ }
+ };
+
+ wrapped.addEventListener("message", myMessageListener, true);
+ wrapped.postMessage("ok", '*');
+
+
+ // RightJS is hacking around String.prototype, and do similar thing:
+ // Pass `this` from a String prototype method.
+ // It is funny because typeof this == "object"!
+ // So that when we pass `this` to a native method,
+ // our proxy code can fail on another even more crazy thing.
+ // See following test to see what fails around proxies.
+ String.prototype.update = function () {
+ test.assertEqual(typeof this, "object");
+ test.assertEqual(this.toString(), "input");
+ return document.querySelectorAll(this);
+ };
+ test.assertEqual("input".update().length, 3, "String.prototype overload works");
+
+ // Proxy - toString error
+ let originalString = "string";
+ let p = Proxy.create({
+ get: function(receiver, name) {
+ if (name == "binded")
+ return originalString.toString.bind(originalString);
+ return originalString[name];
+ }
+ });
+ test.assertRaises(function () {
+ p.toString();
+ },
+ /String.prototype.toString called on incompatible Proxy/,
+ "toString can't be called with this being the proxy");
+ test.assertEqual(p.binded(), "string", "but it works if we bind this to the original string");
+
+
+ // Check mozMatchesSelector XrayWrappers bug:
+ // mozMatchesSelector returns bad results when we are not calling it from the node itself
+ // SEE BUG 658909: mozMatchesSelector returns incorrect results with XrayWrappers
+ test.assert(document.createElement( "div" ).mozMatchesSelector("div"),
+ "mozMatchesSelector works while being called from the node");
+ test.assert(document.documentElement.mozMatchesSelector.call(
+ document.createElement( "div" ),
+ "div"
+ ),
+ "mozMatchesSelector works while being called from a " +
+ "function reference to " +
+ "document.documentElement.mozMatchesSelector.call");
+
+ // If we add a "____proxy" attribute on XrayWrappers in order to store
+ // the related proxy to create an unique proxy for each wrapper;
+ // we end up setting this attribute to prototype objects :x
+ // And so, instances created with such prototype will be considered
+ // as equal to the prototype ...
+ // // Internal method that return the proxy for a given XrayWrapper
+ // function proxify(obj) {
+ // if (obj._proxy) return obj._proxy;
+ // return obj._proxy = Proxy.create(...);
+ // }
+ //
+ // // Get a proxy of a XrayWrapper prototype object
+ // let proto = proxify(xpcProto);
+ //
+ // // Use this proxy as a prototype
+ // function Constr() {}
+ // Constr.proto = proto;
+ //
+ // // Try to create an instance using this prototype
+ // let xpcInstance = new Constr();
+ // let wrapper = proxify(xpcInstance)
+ //
+ // xpcProto._proxy = proto and as xpcInstance.__proto__ = xpcProto,
+ // xpcInstance._proxy = proto ... and profixy(xpcInstance) = proto :(
+ //
+ let proto = wrapped.document.createEvent('HTMLEvents').__proto__;
+ wrapped.Event.prototype = proto;
+ let event = document.createEvent('HTMLEvents');
+ test.assertNotEqual(event, proto, "Event should not be equal to its prototype");
+ event.initEvent('dataavailable', true, true);
+ test.assertEqual(event.type, 'dataavailable', "Events are working fine");
+
+ // XrayWrappers has a bug when you set an attribute on it,
+ // in some cases, it creates an unnecessary wrapper that introduces
+ // a different object that refers to the same original object
+ // Check that our wrappers don't reproduce this bug
+ // SEE BUG 658560: Fix identity problem with CrossOriginWrappers
+ let o = {sandboxObject:true};
+ wrapped.nested = o;
+ o.foo = true;
+ test.assertEqual(o, wrapped.nested, "Nested attribute to sandbox object should not be proxified");
+ wrapped.nested = document;
+ test.assertEqual(wrapped.nested, document, "Nested attribute to proxy should not be double proxified");
+
+ // Check form[nodeName]
+ let form = document.createElement("form");
+ let input = document.createElement("input");
+ input.setAttribute("name", "test");
+ form.appendChild(input);
+ body.appendChild(form);
+ test.assertEqual(form.test, input, "form[nodeName] is valid");
+ body.removeChild(form);
+
+ // Check localStorage:
+ test.assert(wrapped.localStorage, "has access to localStorage");
+ wrapped.localStorage.name = 1;
+ test.assertEqual(wrapped.localStorage.name, 1, "localStorage appears to work");
+ test.assertEqual(win.localStorage.name, 1, "localStorage really works");
+ wrapped.localStorage.clear();
+ test.assertEqual(wrapped.localStorage.name, undefined, "localStorage really, really works");
+
+ // Check sessionStorage:
+ /*
+ // Does not work on data: uri
+ console.log(wrapped.sessionStorage);
+ //test.assert(wrapped.sessionStorage, "has access to localStorage");
+ wrapped.sessionStorage.setItem('name', 1);
+ test.assertEqual(wrapped.sessionStorage.getItem('name'), 1, "localStorage appears to work");
+ test.assertEqual(win.sessionStorage.getItem('name'), 1, "localStorage really work");
+ wrapped.sessionStorage.clear();
+ test.assert(!wrapped.sessionStorage.hasItem('name'), "localStorage really,really work");
+ */
+
+ // Setting a custom object to a proxy attribute is not wrapped when we get it afterward
+ let object = {custom: true, enumerable: false};
+ body.customAttribute = object;
+ test.assertEqual(body.customAttribute.valueOf(), body.customAttribute.valueOf(proxy.UNWRAP_ACCESS_KEY), "custom JS attributes are not wrapped");
+ test.assertEqual(object, body.customAttribute, "custom JS attributes are not wrapped");
+
+ /*
+ let originalToString = win.Object.prototype.toString;
+ win.Object.prototype.toString = function overloadedToString() {
+ return originalToString.apply(this.valueOf(proxy.UNWRAP_ACCESS_KEY));
+ };
+ */
+ // <object>, <embed> and other tags return typeof 'function'
+ let flash = document.createElement("object");
+ test.assertEqual(typeof flash, "function", "<object> is typeof 'function'");
+ test.assertMatches(flash.toString(), /\[object HTMLObjectElement.*\]/, "<object> is HTMLObjectElement");
+ test.assert("setAttribute" in flash, "<object> has a setAttribute method");
+ flash.setAttribute("classid", "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000");
+ // This is how jquery call toString:
+ test.assertMatches(win.Object.prototype.toString.call(""), /\[object String.*\]/, "strings are strings");
+ test.assertMatches(win.Object.prototype.toString.call({}), /\[object Object.*\]/, "objects are objects");
+ // We do not have any workaround this particular use of toString
+ // applied on <object> elements. So disable this test until we found one!
+ //test.assertEqual(win.Object.prototype.toString.call(flash), "[object HTMLObjectElement]", "<object> is HTMLObjectElement");
+ function f() {};
+ test.assertMatches(Object.prototype.toString.call(f), /\[object Function.*\]/, "functions are functions 1");
+ // Make sure to pass a function from the same compartments
+ // or toString will return [object Object] on FF8+
+ let f2 = win.eval("(function () {})");
+ test.assertMatches(win.Object.prototype.toString.call(f2), /\[object Function.*\]/, "functions are functions 2");
+
+ // Verify isolated JS values
+ test.assert(!wrapped.documentGlobal, "proxy doesn't expose document variable");
+
+ // Check document[tagName]
+ let div = document.createElement("div");
+ div.setAttribute("name", "test");
+ body.appendChild(div);
+ test.assert(!document.test, "document[divName] is undefined");
+ body.removeChild(div);
+
+ let form = document.createElement("form");
+ form.setAttribute("name", "test");
+ body.appendChild(form);
+ test.assertEqual(document.test, form, "document[formName] is valid");
+ body.removeChild(form);
+
+ let img = document.createElement("img");
+ img.setAttribute("name", "test");
+ body.appendChild(img);
+ test.assertEqual(document.test, img, "document[imgName] is valid");
+ body.removeChild(img);
+
+ // Check window[frameName] and window.frames[i]
+ let iframe = document.getElementById("iframe");
+ test.assertEqual(wrapped.frames.length, 1, "The iframe is reported in window.frames check1");
+ test.assertEqual(wrapped.frames[0], iframe.contentWindow, "The iframe is reported in window.frames check2");
+ test.assertEqual(wrapped.test, iframe.contentWindow, "window[frameName] is valid");
+
+ // Highlight XPCNativeWrapper bug with HTMLCollection
+ // tds[0] is only defined on first access :o
+ let div = document.createElement("div");
+ body.appendChild(div);
+ div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
+ let tds = div.getElementsByTagName("td");
+ test.assertEqual(tds[0], tds[0], "We can get array element multiple times");
+ body.removeChild(div);
+
+ // Verify that NodeList/HTMLCollection are working fine
+ let inputs = body.getElementsByTagName("input");
+ test.assertEqual(body.childNodes.length, 5, "body.childNodes length is correct");
+ test.assertEqual(inputs.length, 3, "inputs.length is correct");
+ test.assertEqual(body.childNodes[0], inputs[0], "body.childNodes[0] is correct");
+ test.assertEqual(body.childNodes[1], inputs[1], "body.childNodes[1] is correct");
+ test.assertEqual(body.childNodes[2], inputs[2], "body.childNodes[2] is correct");
+ let count = 0;
+ for(let i in body.childNodes) {
+ count++;
+ }
+ test.assertEqual(count, 5, "body.childNodes is iterable");
+
+ // Check internal use of valueOf()
+ test.assertMatches(wrapped.valueOf().toString(), /\[object Window.*\]/, "proxy.valueOf() returns the wrapped version");
+ test.assertMatches(wrapped.valueOf({}).toString(), /\[object Window.*\]/, "proxy.valueOf({}) returns the wrapped version");
+ test.assertMatches(wrapped.valueOf(proxy.UNWRAP_ACCESS_KEY).toString(), /\[object XrayWrapper \[object Window.*\].*\]/, "proxy.valueOf(UNWRAP_ACCESS_KEY) returns the unwrapped version");
+
+ // XMLHttpRequest doesn't support XMLHttpRequest.apply,
+ // that may break our proxy code
+ test.assert(wrapped.XMLHttpRequest(), "we are able to instantiate XMLHttpRequest object");
+
+ // Check XPathResult bug with constants being undefined on
+ // XPCNativeWrapper
+ let value =
+ win.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE;
+ let xpcXPathResult = XPCNativeWrapper(win).XPathResult;
+ test.assertEqual(xpcXPathResult.wrappedJSObject.
+ UNORDERED_NODE_SNAPSHOT_TYPE,
+ value,
+ "XPathResult's constants are valid on unwrapped node");
+
+ if (xulApp.versionInRange(xulApp.platformVersion, "10.0a1", "*")) {
+ test.assertEqual(xpcXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, 6,
+ "XPathResult's constants are defined on " +
+ "XPCNativeWrapper (platform bug #)");
+ }
+ else {
+ test.assertEqual(xpcXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
+ undefined,
+ "XPathResult's constants are undefined on " +
+ "XPCNativeWrapper (platform bug #665279)");
+ // Check that our work around is working:
+ test.assertEqual(wrapped.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
+ value, "XPathResult works correctly on Proxies");
+ }
+
+ // Verify that inherited prototype function like initEvent
+ // are handled correctly. (e2.type will return an error if it's not the case)
+ let event1 = document.createEvent( 'MouseEvents' );
+ event1.initEvent( "click", true, true );
+ let event2 = document.createEvent( 'MouseEvents' );
+ event2.initEvent( "click", true, true );
+ test.assert(event2.type, "click", "We are able to create an event");
+
+ // Check basic usage of functions
+ win.callFunction = function (f) f();
+ let closure2 = function () {return "ok";};
+ test.assertEqual(wrapped.wrappedJSObject.callFunction(closure2), "ok", "Function references work");
+
+ // Ensure that functions are cached when being wrapped to native code
+ win.isEqual = function (a, b) a == b;
+ let closure = function () {};
+ test.assert(wrapped.wrappedJSObject.isEqual(closure, closure), "Function references are cached before being wrapped to native");
+
+ // Verify listeners:
+ let input = document.getElementById("input2");
+ test.assert(input, "proxy.getElementById works");
+
+ function onclick() {};
+ input.onclick = onclick;
+ test.assertEqual(input.onclick, onclick, "on* attributes are equal to original function set");
+
+ let addEventListenerCalled = false;
+ let expandoCalled = false;
+ input.addEventListener("click", function onclick(event) {
+ input.removeEventListener("click", onclick, true);
+
+ test.assert(!addEventListenerCalled, "closure given to addEventListener is called once");
+ if (addEventListenerCalled)
+ return;
+ addEventListenerCalled = true;
+
+ test.assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals");
+ test.assert("__isWrappedProxy" in event.target, "event object is a proxy");
+
+ let input2 = document.getElementById("input2");
+
+ input.onclick = function (event) {
+ input.onclick = null;
+ test.assert(!expandoCalled, "closure set to expando is called once");
+ if (expandoCalled) return;
+ expandoCalled = true;
+
+ test.assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals");
+ test.assert("__isWrappedProxy" in event.target, "event object is a proxy");
+
+ require("timer").setTimeout(function () {
+ input.click();
+
+ // Next test:
+ checkRequestAnimation();
+ }, 0);
+
+ }
+
+ require("timer").setTimeout(function () {
+ input.click();
+ }, 0);
+
+ }, true);
+
+ input.click();
+
+ // Check ContentScriptFunction with function as "this" object
+ // For example, window.mozRequestAnimationFrame call its callback
+ // argument with `this` being the callback itself.
+ function checkRequestAnimation() {
+ wrapped.mozRequestAnimationFrame(function callback() {
+ test.assertEqual(callback, this, "callback is equal to `this`");
+
+ end();
+ });
+ }
+
+ function end() {
+ hiddenFrames.remove(hiddenFrame);
+ test.done();
+ }
+ }
+
+ hiddenFrame.element.addEventListener("DOMContentLoaded", onDOMReady, false);
+ hiddenFrame.element.setAttribute("src", url);
+
+ }
+ }));
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-symbiont.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-symbiont.js
new file mode 100644
index 0000000..7d7d3bb
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-symbiont.js
@@ -0,0 +1,153 @@
+"use strict";
+
+const { Cc, Ci } = require('chrome');
+const { Symbiont } = require('content/symbiont');
+const self = require("self");
+
+function makeWindow() {
+ let content =
+ '<?xml version="1.0"?>' +
+ '<window ' +
+ 'xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' +
+ '<iframe id="content" type="content"/>' +
+ '</window>';
+ var url = "data:application/vnd.mozilla.xul+xml," +
+ encodeURIComponent(content);
+ var features = ["chrome", "width=10", "height=10"];
+
+ return Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher).
+ openWindow(null, url, null, features.join(","), null);
+}
+
+exports['test:constructing symbiont && validating API'] = function(test) {
+ let window = makeWindow();
+ window.addEventListener("load", function onLoad() {
+ window.removeEventListener("load", onLoad, false);
+ let frame = window.document.getElementById("content");
+ // TODO: support arrays ??
+ let contentScripts = ["1;", "2;"];
+ let contentSymbiont = Symbiont({
+ frame: frame,
+ contentScriptFile: self.data.url("test-content-symbiont.js"),
+ contentScript: contentScripts,
+ contentScriptWhen: "start"
+ });
+
+ test.assertEqual(
+ self.data.url("test-content-symbiont.js"),
+ contentSymbiont.contentScriptFile,
+ "There is one contentScriptFile, as specified in options."
+ );
+ test.assertEqual(
+ contentScripts.length,
+ contentSymbiont.contentScript.length,
+ "There are two contentScripts, as specified in options."
+ );
+ test.assertEqual(
+ contentScripts[0],
+ contentSymbiont.contentScript[0],
+ "There are two contentScripts, as specified in options."
+ );
+ test.assertEqual(
+ contentScripts[1],
+ contentSymbiont.contentScript[1],
+ "There are two contentScripts, as specified in options."
+ )
+ test.assertEqual(
+ contentSymbiont.contentScriptWhen,
+ "start",
+ "contentScriptWhen is as specified in options."
+ );
+
+ test.done();
+ window.close();
+ frame.setAttribute("src", "data:text/html,<html><body></body></html>");
+ }, false);
+ test.waitUntilDone();
+};
+
+exports["test:communication with worker global scope"] = function(test) {
+ let window = makeWindow();
+ let contentSymbiont;
+
+ function onMessage1(message) {
+ test.assertEqual(message, 1, "Program gets message via onMessage.");
+ contentSymbiont.removeListener('message', onMessage1);
+ contentSymbiont.on('message', onMessage2);
+ contentSymbiont.postMessage(2);
+ };
+
+ function onMessage2(message) {
+ if (5 == message) {
+ test.done();
+ } else {
+ test.assertEqual(message, 3, "Program gets message via onMessage2.");
+ contentSymbiont.postMessage(4)
+ }
+ }
+
+ window.addEventListener("load", function onLoad() {
+ window.removeEventListener("load", onLoad, false);
+ let frame = window.document.getElementById("content");
+ contentSymbiont = Symbiont({
+ frame: frame,
+ contentScript: 'new ' + function() {
+ self.postMessage(1);
+ self.on("message", function onMessage(message) {
+ if (message === 2)
+ self.postMessage(3);
+ if (message === 4)
+ self.postMessage(5);
+ });
+ } + '()',
+ contentScriptWhen: 'ready',
+ onMessage: onMessage1
+ });
+
+ frame.setAttribute("src", "data:text/html,<html><body></body></html>");
+ }, false);
+ test.waitUntilDone();
+};
+
+exports['test:pageWorker'] = function(test) {
+ test.waitUntilDone();
+ let worker = Symbiont({
+ contentURL: 'about:buildconfig',
+ contentScript: 'new ' + function WorkerScope() {
+ self.on('message', function(data) {
+ if (data.valid)
+ self.postMessage('bye!');
+ })
+ self.postMessage(window.location.toString());
+ },
+ onMessage: function(msg) {
+ if (msg == 'bye!') {
+ test.done()
+ } else {
+ test.assertEqual(
+ worker.contentURL + '',
+ msg
+ );
+ worker.postMessage({ valid: true });
+ }
+ }
+ });
+};
+
+exports["test:document element present on 'start'"] = function(test) {
+ test.waitUntilDone();
+ let xulApp = require("xul-app");
+ let worker = Symbiont({
+ contentURL: "about:buildconfig",
+ contentScript: "self.postMessage(!!document.documentElement)",
+ contentScriptWhen: "start",
+ onMessage: function(message) {
+ if (xulApp.versionInRange(xulApp.platformVersion, "2.0b6", "*"))
+ test.assert(message, "document element present on 'start'");
+ else
+ test.pass("document element not necessarily present on 'start'");
+ test.done();
+ }
+ });
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-worker.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-worker.js
new file mode 100644
index 0000000..2d88540
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-content-worker.js
@@ -0,0 +1,347 @@
+"use stirct";
+
+const { Cc, Ci } = require('chrome');
+const timer = require('timer');
+
+function makeWindow(contentURL) {
+ let content =
+ '<?xml version="1.0"?>' +
+ '<window ' +
+ 'xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' +
+ '<iframe id="content" type="content" src="' +
+ encodeURIComponent(contentURL) + '"/>' +
+ '<script>var documentValue=true;</script>' +
+ '</window>';
+ var url = "data:application/vnd.mozilla.xul+xml," +
+ encodeURIComponent(content);
+ var features = ["chrome", "width=10", "height=10"];
+
+ return Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher).
+ openWindow(null, url, null, features.join(","), null);
+}
+
+const { Worker } = require('content/worker');
+exports['test:sample'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ // As window has just being created, its document is still loading,
+ // and we have about:blank document before the expected one
+ test.assertEqual(window.document.location.href, "about:blank",
+ "window starts by loading about:blank");
+
+ // We need to wait for the load/unload of temporary about:blank
+ // or our worker is going to be automatically destroyed
+ window.addEventListener("load", function onload() {
+ window.removeEventListener("load", onload, true);
+
+ test.assertNotEqual(window.document.location.href, "about:blank",
+ "window is now on the right document");
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ // window is accessible
+ let myLocation = window.location.toString();
+ self.on('message', function(data) {
+ if (data == 'hi!')
+ self.postMessage('bye!');
+ });
+ },
+ contentScriptWhen: 'ready',
+ onMessage: function(msg) {
+ test.assertEqual('bye!', msg);
+ test.assertEqual(worker.url, window.document.location.href,
+ "worker.url still works");
+ test.done();
+ }
+ });
+
+ test.assertEqual(worker.url, window.document.location.href,
+ "worker.url works");
+ worker.postMessage('hi!');
+
+ }, true);
+
+}
+
+exports['test:emit'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ // Validate self.on and self.emit
+ self.port.on('addon-to-content', function (data) {
+ self.port.emit('content-to-addon', data);
+ });
+
+ // Check for global pollution
+ //if (typeof on != "undefined")
+ // self.postMessage("`on` is in globals");
+ if (typeof once != "undefined")
+ self.postMessage("`once` is in globals");
+ if (typeof emit != "undefined")
+ self.postMessage("`emit` is in globals");
+
+ },
+ onMessage: function(msg) {
+ test.fail("Got an unexpected message : "+msg);
+ }
+ });
+
+ // Validate worker.port
+ worker.port.on('content-to-addon', function (data) {
+ test.assertEqual(data, "event data");
+ test.done();
+ });
+ worker.port.emit('addon-to-content', 'event data');
+
+}
+
+exports['test:emit hack message'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ // Validate self.port
+ self.port.on('message', function (data) {
+ self.port.emit('message', data);
+ });
+ // We should not receive message on self, but only on self.port
+ self.on('message', function (data) {
+ self.postMessage('message', data);
+ });
+ },
+ onError: function(e) {
+ test.fail("Got exception: "+e);
+ }
+ });
+
+ worker.port.on('message', function (data) {
+ test.assertEqual(data, "event data");
+ test.done();
+ });
+ worker.on('message', function (data) {
+ test.fail("Got an unexpected message : "+msg);
+ });
+ worker.port.emit('message', 'event data');
+
+}
+
+exports['test:n-arguments emit'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ // Validate self.on and self.emit
+ self.port.on('addon-to-content', function (a1, a2, a3) {
+ self.port.emit('content-to-addon', a1, a2, a3);
+ });
+ }
+ });
+
+ // Validate worker.port
+ worker.port.on('content-to-addon', function (arg1, arg2, arg3) {
+ test.assertEqual(arg1, "first argument");
+ test.assertEqual(arg2, "second");
+ test.assertEqual(arg3, "third");
+ test.done();
+ });
+ worker.port.emit('addon-to-content', 'first argument', 'second', 'third');
+}
+
+exports['test:post-json-values-only'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ self.on('message', function (message) {
+ self.postMessage([ message.fun === undefined,
+ typeof message.w,
+ "port" in message.w,
+ message.w.url ]);
+ });
+ }
+ });
+
+ // Validate worker.onMessage
+ worker.on('message', function (message) {
+ test.assertEqual(message[0], true, "function becomes undefined");
+ test.assertEqual(message[1], "object", "object stays object");
+ test.assertEqual(message[2], true, "object's attributes are enumerable");
+ test.assertEqual(message[3], "about:blank", "jsonable attributes are accessible");
+ test.done();
+ });
+ worker.postMessage({ fun: function () {}, w: worker });
+};
+
+exports['test:emit-json-values-only'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ // Validate self.on and self.emit
+ self.port.on('addon-to-content', function (fun, w, obj) {
+ self.port.emit('content-to-addon', [
+ fun === null,
+ typeof w,
+ "port" in w,
+ w.url,
+ "fun" in obj,
+ Object.keys(obj.dom).length
+ ]);
+ });
+ }
+ });
+
+ // Validate worker.port
+ worker.port.on('content-to-addon', function (result) {
+ test.assertEqual(result[0], true, "functions become null");
+ test.assertEqual(result[1], "object", "objects stay objects");
+ test.assertEqual(result[2], true, "object's attributes are enumerable");
+ test.assertEqual(result[3], "about:blank", "json attribute is accessible");
+ test.assertEqual(result[4], false, "function as object attribute is removed");
+ test.assertEqual(result[5], 0, "DOM nodes are converted into empty object");
+ test.done();
+ });
+ let obj = {
+ fun: function () {},
+ dom: window.document.documentElement
+ };
+ worker.port.emit('addon-to-content', function () {}, worker, obj);
+}
+
+exports['test:content is wrapped'] = function(test) {
+ let contentURL = 'data:text/html,<script>var documentValue=true;</script>';
+ let window = makeWindow(contentURL);
+ test.waitUntilDone();
+
+ window.addEventListener("load", function onload() {
+ window.removeEventListener("load", onload, true);
+
+ let worker = Worker({
+ window: window.document.getElementById("content").contentWindow,
+ contentScript: 'new ' + function WorkerScope() {
+ self.postMessage(!window.documentValue);
+ },
+ contentScriptWhen: 'ready',
+ onMessage: function(msg) {
+ test.assert(msg,
+ "content script has a wrapped access to content document");
+ test.done();
+ }
+ });
+
+ }, true);
+
+}
+
+exports['test:chrome is unwrapped'] = function(test) {
+ let window = makeWindow();
+ test.waitUntilDone();
+
+ window.addEventListener("load", function onload() {
+ window.removeEventListener("load", onload, true);
+
+ let worker = Worker({
+ window: window,
+ contentScript: 'new ' + function WorkerScope() {
+ self.postMessage(window.documentValue);
+ },
+ contentScriptWhen: 'ready',
+ onMessage: function(msg) {
+ test.assert(msg,
+ "content script has an unwrapped access to chrome document");
+ test.done();
+ }
+ });
+
+ }, true);
+
+}
+
+exports['test:setTimeout can\'t be cancelled by content'] = function(test) {
+ let contentURL = 'data:text/html,<script>var documentValue=true;</script>';
+ let window = makeWindow(contentURL);
+ test.waitUntilDone();
+
+ window.addEventListener("load", function onload() {
+ window.removeEventListener("load", onload, true);
+
+ let worker = Worker({
+ window: window.document.getElementById("content").contentWindow,
+ contentScript: 'new ' + function WorkerScope() {
+ let id = setTimeout(function () {
+ self.postMessage("timeout");
+ }, 100);
+ unsafeWindow.eval("clearTimeout("+id+");");
+ },
+ contentScriptWhen: 'ready',
+ onMessage: function(msg) {
+ test.assert(msg,
+ "content didn't managed to cancel our setTimeout");
+ test.done();
+ }
+ });
+
+ }, true);
+
+}
+
+exports['test:setTimeout are unregistered on content unload'] = function(test) {
+ let contentURL = 'data:text/html,foo';
+ let window = makeWindow(contentURL);
+ test.waitUntilDone();
+
+ window.addEventListener("load", function onload() {
+ window.removeEventListener("load", onload, true);
+
+ let iframe = window.document.getElementById("content");
+ let originalDocument = iframe.contentDocument;
+ let worker = Worker({
+ window: iframe.contentWindow,
+ contentScript: 'new ' + function WorkerScope() {
+ document.title = "ok";
+ let i = 0;
+ setInterval(function () {
+ document.title = i++;
+ }, 10);
+ },
+ contentScriptWhen: 'ready'
+ });
+
+ // Change location so that content script is destroyed,
+ // and all setTimeout/setInterval should be unregistered.
+ // Wait some cycles in order to execute some intervals.
+ timer.setTimeout(function () {
+ // Bug 689621: Wait for the new document load so that we are sure that
+ // previous document cancelled its intervals
+ iframe.addEventListener("load", function onload() {
+ iframe.removeEventListener("load", onload, true);
+ let titleAfterLoad = originalDocument.title;
+ // Wait additional cycles to verify that intervals are really cancelled
+ timer.setTimeout(function () {
+ test.assertEqual(iframe.contentDocument.title, "final",
+ "New document has not been modified");
+ test.assertEqual(originalDocument.title, titleAfterLoad,
+ "Nor previous one");
+ test.done();
+ }, 100);
+ }, true);
+ iframe.setAttribute("src", "data:text/html,<title>final</title>");
+ }, 100);
+
+ }, true);
+
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-cortex.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-cortex.js
new file mode 100644
index 0000000..11ed397
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-cortex.js
@@ -0,0 +1,118 @@
+// vim:set ts=2 sw=2 sts=2
+
+"use strict";
+
+var Cortex = require("cortex").Cortex;
+
+exports["test property changes propagate"] = function (assert) {
+ var source = {
+ _foo: "secret",
+ get foo() {
+ return this._foo;
+ },
+ set foo(value) {
+ this._foo = value;
+ },
+ get getOnly() {
+ return this._foo;
+ },
+ set setOnly(value) {
+ this._setOnly = value;
+ },
+ bar: "public",
+ method: function method(a, b) {
+ return this._foo + a + b
+ }
+ };
+ var fixture = Cortex(source);
+
+ assert.ok(!('_foo' in fixture),
+ "properties that start with `_` are omitted");
+ assert.equal(fixture.foo, "secret", "get accessor alias works");
+ fixture.foo = "new secret";
+ assert.equal(fixture.foo, "new secret", "set accessor alias works");
+ assert.equal(source.foo, "new secret", "accessor delegates to the source");
+ assert.equal(fixture.bar, "public", "data property alias works");
+ fixture.bar = "bar";
+ assert.equal(source.bar, "bar", "data property change propagates");
+ source.bar = "foo"
+ assert.equal(fixture.bar, "foo", "data property change probagets back");
+ assert.equal(fixture.method("a", "b"), "new secretab",
+ "public methods are callable");
+ assert.equal(fixture.method.call({ _foo: "test" }, " a,", "b"),
+ "new secret a,b",
+ "`this` pseudo-variable can not be passed through call.");
+ assert.equal(fixture.method.apply({ _foo: "test" }, [" a,", "b"]),
+ "new secret a,b",
+ "`this` pseudo-variable can not be passed through apply.");
+ assert.equal(fixture.getOnly, source._foo,
+ "getter returned property of wrapped object");
+ fixture.setOnly = 'bar'
+ assert.equal(source._setOnly, 'bar', "setter modified wrapped object")
+};
+
+
+exports["test immunity of inheritance"] = function(assert) {
+ function Type() {}
+ Type.prototype = {
+ constructor: Type,
+ _bar: 2,
+ bar: 3,
+ get_Foo: function getFoo() {
+ return this._foo;
+ }
+ }
+ var source = Object.create(Type.prototype, {
+ _foo: { value: 'secret' },
+ getBar: { value: function get_Bar() {
+ return this.bar
+ }},
+ get_Bar: { value: function getBar() {
+ return this._bar
+ }}
+ });
+
+ var fixture = Cortex(source);
+
+ assert.ok(Cortex({}, null, Type.prototype) instanceof Type,
+ "if custom prototype is providede cortex will inherit from it");
+ assert.ok(fixture instanceof Type,
+ "if no prototype is given cortex inherits from object's prototype");
+
+ source.bar += 1;
+ assert.notEqual(fixture.bar, source.bar,
+ "chages of properties don't propagate to non-aliases");
+ assert.equal(fixture.getBar(), source.bar,
+ "methods accessing public properties are bound to the source");
+
+ fixture._bar += 1;
+ assert.notEqual(fixture._bar, source._bar,
+ "changes of non aliased properties don't propagate");
+ assert.equal(fixture.get_Bar(), source._bar,
+ "methods accessing privates are bound to the source");
+ assert.notEqual(fixture.get_Foo(), source._foo,
+ "prototoype methods are not bound to the source");
+}
+
+exports["test customized public properties"] = function(assert) {
+ var source = {
+ _a: 'a',
+ b: 'b',
+ get: function get(name) {
+ return this[name];
+ }
+ };
+
+ var fixture = Cortex(source, ['_a', 'get']);
+ fixture._a += "#change";
+
+
+ assert.ok(!("b" in fixture), "non-public own property is not defined");
+ assert.equal(fixture.get("b"), source.b,
+ "public methods preserve access to the private properties");
+ assert.equal(fixture._a, source._a,
+ "custom public property changes propagate");
+}
+
+//if (require.main == module)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-cuddlefish.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-cuddlefish.js
new file mode 100644
index 0000000..05dcff6
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-cuddlefish.js
@@ -0,0 +1,40 @@
+exports.testLoader = function(test) {
+ var prints = [];
+ function print(message) {
+ prints.push(message);
+ }
+
+ var loader = test.makeSandboxedLoader({print: print,
+ globals: {foo: 1}});
+
+ test.pass("loader instantiates within a securablemodule");
+
+ test.assertEqual(loader.runScript("foo"), 1,
+ "custom globals must work.");
+
+ loader.runScript("console.log('testing', 1, [2, 3, 4])");
+
+ test.assertEqual(prints[0], "info: testing 1 2,3,4\n",
+ "global console must work.");
+
+ var unloadsCalled = '';
+
+ loader.require("unload").when(function() { unloadsCalled += 'a'; });
+ loader.require("unload.js").when(function() { unloadsCalled += 'b'; });
+
+ loader.unload();
+
+ test.assertEqual(unloadsCalled, 'ba',
+ "loader.unload() must call cb's in LIFO order.");
+
+ loader = test.makeSandboxedLoader();
+
+ loader.runScript("memory.track({}, 'blah');");
+
+ test.assertEqual([name for each (name in loader.memory.getBins())
+ if (name == "blah")].length,
+ 1,
+ "global memory must work.");
+
+ loader.unload();
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-dom.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-dom.js
new file mode 100644
index 0000000..57b1afe
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-dom.js
@@ -0,0 +1,84 @@
+"use strict";
+
+const events = require("dom/events");
+const { activeBrowserWindow: { document } } = require("window-utils");
+const window = document.window;
+
+exports["test on / emit"] = function (assert, done) {
+ let element = document.createElement("div");
+ events.on(element, "click", function listener(event) {
+ assert.equal(event.target, element, "event has correct target");
+ events.removeListener(element, "click", listener);
+ done();
+ });
+
+ events.emit(element, "click", {
+ category: "MouseEvents",
+ settings: [
+ true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
+ ]
+ });
+};
+
+exports["test remove"] = function (assert, done) {
+ let element = document.createElement("span");
+ let l1 = 0;
+ let l2 = 0;
+ let options = {
+ category: "MouseEvents",
+ settings: [
+ true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
+ ]
+ };
+
+ events.on(element, "click", function listener1(event) {
+ l1 ++;
+ assert.equal(event.target, element, "event has correct target");
+ events.removeListener(element, "click", listener1);
+ });
+
+ events.on(element, "click", function listener2(event) {
+ l2 ++;
+ if (l1 < l2) {
+ assert.equal(l1, 1, "firs listener was called and then romeved");
+ events.removeListener(element, "click", listener2);
+ done();
+ }
+ events.emit(element, "click", options);
+ });
+
+ events.emit(element, "click", options);
+};
+
+exports["test once"] = function (assert, done) {
+ let element = document.createElement("h1");
+ let l1 = 0;
+ let l2 = 0;
+ let options = {
+ category: "MouseEvents",
+ settings: [
+ true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
+ ]
+ };
+
+
+ events.once(element, "click", function listener(event) {
+ assert.equal(event.target, element, "event target is a correct element");
+ l1 ++;
+ });
+
+ events.on(element, "click", function listener(event) {
+ l2 ++;
+ if (l2 > 3) {
+ events.removeListener(element, "click", listener);
+ assert.equal(event.target, element, "event has correct target");
+ assert.equal(l1, 1, "once was called only once");
+ done();
+ }
+ events.emit(element, "click", options);
+ });
+
+ events.emit(element, "click", options);
+}
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s-porting.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s-porting.js
new file mode 100644
index 0000000..3dc4d32
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s-porting.js
@@ -0,0 +1,73 @@
+// This file just runs all test suites we've white-listed as being
+// compatible with E10s. Once we're done with the porting effort,
+// we'll just enable cfx's '--e10s' option by default and remove
+// this file.
+
+// This is just to serve as an indicator not to run these tests in
+// the addon process.
+require("chrome");
+
+const E10S_COMPATIBLE_TEST_SUITES = [
+ 'test-api-utils.js',
+ 'test-traits-core.js',
+ 'test-traits.js',
+ 'test-list.js',
+ 'test-self.js'
+];
+
+exports.runE10SCompatibleTestSuites = function(test) {
+ var xulApp = require("xul-app");
+ if (xulApp.is("Firefox") &&
+ xulApp.versionInRange(xulApp.version, "4.0b7", "4.0b8pre")) {
+ test.pass("Due to bug 609066, Firefox 4.0b7 will never pass this test, " +
+ "so we'll skip it.");
+ return;
+ }
+
+ // If the "jetpack/service" XPCOM component is not present, then the host
+ // application does not support e10s, so we can't run any e10s-compatible
+ // test suites under e10s mode.
+ if (!require("chrome").Cc["@mozilla.org/jetpack/service;1"]) {
+ test.pass("This application does not support e10s.");
+ return;
+ }
+
+ if (packaging.enableE10s) {
+ // Don't worry about running these E10S-compatible test
+ // suites, cfx will find them by default because its
+ // '--e10s' option is enabled.
+ test.pass("'cfx --e10s' detected, skipping this test.");
+ return;
+ }
+
+ var {TestFinder} = require("unit-test-finder");
+ var {TestRunner} = require("unit-test");
+ var url = require("url");
+
+ var thisDir = url.toFilename(url.URL('./', __url__));
+ var finder = new TestFinder({
+ dirs: [thisDir],
+ filter: function(name) {
+ return E10S_COMPATIBLE_TEST_SUITES.indexOf(name) != -1;
+ },
+ testInProcess: false,
+ testOutOfProcess: true
+ });
+ var runner = new TestRunner();
+ finder.findTests(function(tests) {
+ test.assert(tests.length >= 1, "must find at least one test");
+ runner.startMany({
+ tests: tests,
+ onDone: function(runner) {
+ test.assertEqual(runner.failed, 0,
+ "No tests in addon process should have failed");
+ test.assert(runner.passed > 0,
+ "Some tests in addon process must have been run");
+ test.failed += runner.failed;
+ test.passed += runner.passed;
+ test.done();
+ }
+ });
+ });
+ test.waitUntilDone();
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s.js
new file mode 100644
index 0000000..537fb2d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-e10s.js
@@ -0,0 +1,268 @@
+var xulApp = require("xul-app");
+var timer = require('timer');
+
+// If the "jetpack/service" XPCOM component is not present, then the host app
+// does not support e10s, so we can't run any e10s tests, so we check for E10S
+// support here and then return early in test functions without it.
+var hasE10S =
+ typeof require("chrome").Cc["@mozilla.org/jetpack/service;1"] != "undefined";
+
+function makeConsoleTest(options) {
+ return function(test) {
+ if (!hasE10S) {
+ test.pass("This application does not support e10s.");
+ return;
+ }
+
+ if (xulApp.is("Firefox") &&
+ xulApp.versionInRange(xulApp.version, "4.0b7", "4.0b8pre")) {
+ test.pass("Due to bug 609066, Firefox 4.0b7 will never pass this test, " +
+ "so we'll skip it.");
+ return;
+ }
+
+ var actions = [];
+
+ if (options.setup)
+ options.setup(test);
+
+ function addAction(action) {
+ if (options.expect.length == actions.length) {
+ test.fail("Didn't expect another action: " + JSON.stringify(action));
+ return;
+ }
+ actions.push(action);
+ var expected = options.expect[actions.length-1];
+ if (typeof(expected) == "function")
+ expected(test, action);
+ else
+ test.assertEqual(JSON.stringify(action), JSON.stringify(expected));
+ if (options.expect.length == actions.length &&
+ action[0] == "exception") {
+ process.destroy();
+ test.done();
+ }
+ }
+
+ function msg(name, args) {
+ var action = [name];
+ for (var i = 0; i < args.length; i++)
+ action.push(args[i]);
+ addAction(action);
+ }
+
+ var fakeConsole = {
+ exception: function(ex) {
+ addAction(["exception", ex.toString()]);
+ }
+ };
+
+ ["log", "warn", "debug", "error", "info"].forEach(function(name) {
+ fakeConsole[name] = function() { msg(name, arguments); };
+ });
+
+ var process = require('e10s').AddonProcess({
+ console: fakeConsole,
+ quit: function(status) {
+ addAction(["quit", status]);
+ process.destroy();
+ test.done();
+ }
+ });
+ process.send("startMain", options.main);
+ test.waitUntilDone();
+ };
+}
+
+exports.testStartMain = makeConsoleTest({
+ main: "e10s-samples/hello-world",
+ expect: [
+ ["log", "hello", "world"],
+ ["info", "sup", "dogg"],
+ ["warn", "how", "r", "u"],
+ ["debug", "gud"],
+ ["error", "NO U"],
+ ["exception", "Error: o snap"],
+ ["log", "<toString() error>"],
+ function testConsoleTrace(test, action) {
+ test.assertEqual(action[0], "log",
+ "remote console.trace() issues " +
+ "local console.log()");
+ test.assertMatches(action[1], /^Traceback /,
+ "remote console.trace logs traceback");
+ },
+ ["quit", "OK"]
+ ]
+});
+
+exports.testStartMainWithNonexistentModule = makeConsoleTest({
+ main: "nonexistent-module",
+ expect: [
+ ["log", "An exception occurred in the child Jetpack process."],
+ ["exception", "Error: Unknown module 'nonexistent-module'."]
+ ]
+});
+
+exports.testRemoteSyntaxError = makeConsoleTest({
+ main: "e10s-samples/syntax-error",
+ expect: [
+ ["log", "An exception occurred in the child Jetpack process."],
+ ["exception", "Error: uncaught exception: SyntaxError: missing ;" +
+ " before statement"]
+ ]
+});
+
+exports.testRemoteException = makeConsoleTest({
+ main: "e10s-samples/thrown-exception",
+ expect: [
+ ["log", "An exception occurred in the child Jetpack process."],
+ ["exception", "Error: uncaught exception: Error: alas"]
+ ]
+});
+
+exports.testE10sAdapter = makeConsoleTest({
+ main: "e10s-samples/superpower-client",
+ setup: function(test) {
+ require("e10s-samples/superpower").setDelegate(function(a, b) {
+ test.assertEqual(JSON.stringify([a, b]),
+ JSON.stringify(["hello", "there"]));
+ return "thanks dude";
+ });
+ },
+ expect: [
+ ["log", "superpower.use returned", "thanks dude"],
+ ["quit", "OK"]
+ ]
+});
+
+exports.testAccessDeniedToLoadModule = makeConsoleTest({
+ main: "e10s-samples/chrome-only-module-client",
+ expect: [
+ ["log", "An exception occurred in the child Jetpack process."],
+ ["exception",
+ "Error: Module 'e10s-samples/chrome-only-module' requires " +
+ "chrome privileges and has no e10s adapter."]
+ ]
+});
+
+exports.testAdapterOnlyModule = makeConsoleTest({
+ main: "e10s-samples/adapter-only-client",
+ expect: [
+ ["log", "An exception occurred in the child Jetpack process."],
+ ["exception", "Error: Unknown module 'e10s-samples/adapter-only'."]
+ ]
+});
+
+exports.testSyncCallReturnValueArrivesAfterAsyncMsgSends = makeConsoleTest({
+ main: "e10s-samples/bug-617499-main",
+ expect: [
+ ["log", "about to send sync message to firefox"],
+ ["log", "i am an async message from firefox"],
+ ["log", "returned from sync message to firefox"],
+ ["quit", "OK"]
+ ]
+});
+
+exports.testCommonJSCompliance = function(test) {
+ if (!hasE10S) {
+ test.pass("This application does not support e10s.");
+ return;
+ }
+
+ if (xulApp.is("Firefox") &&
+ xulApp.versionInRange(xulApp.version, "4.0b7", "4.0b8pre")) {
+ test.pass("Due to bug 609066, Firefox 4.0b7 will never pass this test, " +
+ "so we'll skip it.");
+ return;
+ }
+
+ let {Cc, Ci} = require("chrome");
+
+ var url = require("url");
+ var path = url.URL("interoperablejs-read-only/compliance/",
+ __url__).toString();
+ path = url.toFilename(path);
+
+ var rootDir = Cc['@mozilla.org/file/local;1']
+ .createInstance(Ci.nsILocalFile);
+ rootDir.initWithPath(path);
+
+ var testDirs = [];
+ var enumer = rootDir.directoryEntries;
+ while (enumer.hasMoreElements()) {
+ var testDir = enumer.getNext().QueryInterface(Ci.nsIFile);
+ if (testDir.isDirectory() &&
+ testDir.leafName.charAt(0) != '.')
+ testDirs.push(testDir);
+ }
+
+ var sm = require("securable-module");
+
+ function runComplianceTest(testDir) {
+ console.info("running compliance test '" + testDir.leafName + "'");
+ var loader = new sm.Loader({
+ rootPath: testDir
+ });
+ var interceptingConsole = {
+ log: function(msg, type) {
+ switch (type) {
+ case "fail":
+ test.fail(msg);
+ break;
+ case "pass":
+ test.pass(msg);
+ break;
+ case "info":
+ console.info(msg);
+ if (msg == "DONE") {
+ console.info("Running next test.");
+ process.destroy();
+ runNextComplianceTest();
+ }
+ }
+ },
+ __proto__: console
+ };
+ var process = require("e10s").AddonProcess({
+ loader: loader,
+ packaging: {
+ getModuleInfo: function(url) {
+ return {
+ 'e10s-adapter': null,
+ needsChrome: false
+ };
+ }
+ },
+ console: interceptingConsole
+ });
+
+ function injectSysPrint(globalScope) {
+ globalScope.sys = {
+ // The CommonJS compliance tests use this
+ // to report test pass/fail.
+ print: function(msg, type) {
+ // This ultimately gets intercepted by our
+ // interceptingConsole.
+ console.log(msg, type);
+ }
+ };
+ }
+
+ process.send("addInjectedSandboxScript", {
+ filename: "<string>",
+ contents: "(" + uneval(injectSysPrint) + ")(this);"
+ });
+
+ process.send("startMain", "program");
+ }
+
+ function runNextComplianceTest() {
+ if (testDirs.length)
+ runComplianceTest(testDirs.pop());
+ else
+ test.done();
+ }
+
+ runNextComplianceTest();
+ test.waitUntilDone();
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-errors.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-errors.js
new file mode 100644
index 0000000..6db9c87
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-errors.js
@@ -0,0 +1,66 @@
+var errors = require("errors");
+
+exports.testCatchAndLog = function(test) {
+ var caught = [];
+ function dummyLog(e) { caught.push(e); }
+
+ var wrapped = errors.catchAndLog(function(x) {
+ throw Error("blah" + x + this);
+ },
+ "boop",
+ dummyLog);
+ test.assertEqual(wrapped.call("hi", 1), "boop",
+ "exceptions should be trapped, def. resp. returned");
+ test.assertEqual(caught.length, 1,
+ "logging function should be called");
+ test.assertEqual(caught[0].message, "blah1hi",
+ "args and this should be passed to wrapped func");
+};
+
+exports.testCatchAndLogProps = function(test) {
+ var caught = [];
+ function dummyLog(e) { caught.push(e); }
+
+ var thing = {
+ foo: function(x) { throw Error("nowai" + x); },
+ bar: function() { throw Error("blah"); },
+ baz: function() { throw Error("fnarg"); }
+ };
+
+ errors.catchAndLogProps(thing, "foo", "ugh", dummyLog);
+
+ test.assertEqual(thing.foo(1), "ugh",
+ "props should be wrapped");
+ test.assertEqual(caught.length, 1,
+ "logging function should be called");
+ test.assertEqual(caught[0].message, "nowai1",
+ "args should be passed to wrapped func");
+ test.assertRaises(function() { thing.bar(); },
+ "blah",
+ "non-wrapped props should be wrapped");
+
+ errors.catchAndLogProps(thing, ["bar", "baz"], "err", dummyLog);
+ test.assert((thing.bar() == thing.baz()) &&
+ (thing.bar() == "err"),
+ "multiple props should be wrapped if array passed in");
+};
+
+exports.testCatchAndReturn = function(test) {
+ var wrapped = errors.catchAndReturn(function(x) {
+ if (x == 1)
+ return "one";
+ if (x == 2)
+ throw new Error("two");
+ return this + x;
+ });
+
+ test.assertEqual(wrapped(1).returnValue, "one",
+ "arg should be passed; return value should be returned");
+ test.assert(wrapped(2).exception, "exception should be returned");
+ test.assertEqual(wrapped(2).exception.message, "two", "message is correct");
+ test.assert(wrapped(2).exception.fileName.indexOf("test-errors.js") != -1,
+ "filename is present");
+ test.assert(wrapped(2).exception.stack, "stack is available");
+ test.assertEqual(wrapped.call("hi", 3).returnValue, "hi3",
+ "`this` should be set correctly");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-events.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-events.js
new file mode 100644
index 0000000..8bd846b
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-events.js
@@ -0,0 +1,182 @@
+'use strict';
+
+// Exposing private methods as public in order to test
+const EventEmitter = require('events').EventEmitter.compose({
+ listeners: function(type) this._listeners(type),
+ emit: function() this._emit.apply(this, arguments),
+ emitOnObject: function() this._emitOnObject.apply(this, arguments),
+ removeAllListeners: function(type) this._removeAllListeners(type)
+});
+
+exports['test:add listeners'] = function(test) {
+ let e = new EventEmitter();
+
+ let events_new_listener_emited = [];
+ let times_hello_emited = 0;
+
+ e.on("newListener", function (event, listener) {
+ events_new_listener_emited.push(event)
+ })
+
+ e.on("hello", function (a, b) {
+ times_hello_emited += 1
+ test.assertEqual("a", a)
+ test.assertEqual("b", b)
+ test.assertEqual(this, e, '`this` pseudo-variable is bound to instance');
+ })
+
+ e.emit("hello", "a", "b")
+};
+
+exports['test:remove listeners'] = function(test) {
+ let count = 0;
+
+ function listener1 () {
+ count++;
+ }
+ function listener2 () {
+ count++;
+ }
+ function listener3 () {
+ count++;
+ }
+
+ let e1 = new EventEmitter();
+ e1.on("hello", listener1);
+ test.assertEqual(1, e1.listeners('hello').length);
+ e1.removeListener("hello", listener1);
+ test.assertEqual(0, e1.listeners('hello').length);
+
+ let e2 = new EventEmitter();
+ e2.on("hello", listener1);
+ test.assertEqual(1, e2.listeners('hello').length);
+ e2.removeListener("hello", listener2);
+ test.assertEqual(1, e2.listeners('hello').length);
+ test.assertEqual(listener1, e2.listeners('hello')[0]);
+
+ let e3 = new EventEmitter();
+ e3.on("hello", listener1);
+ test.assertEqual(1, e3.listeners('hello').length);
+ e3.on("hello", listener2);
+ test.assertEqual(2, e3.listeners('hello').length);
+ e3.removeListener("hello", listener1);
+ test.assertEqual(1, e3.listeners('hello').length);
+ test.assertEqual(listener2, e3.listeners('hello')[0]);
+};
+
+exports['test: modify in emit'] = function(test) {
+ let callbacks_called = [ ];
+ let e = new EventEmitter();
+
+ function callback1() {
+ callbacks_called.push("callback1");
+ e.on("foo", callback2);
+ e.on("foo", callback3);
+ e.removeListener("foo", callback1);
+ }
+ function callback2() {
+ callbacks_called.push("callback2");
+ e.removeListener("foo", callback2);
+ }
+ function callback3() {
+ callbacks_called.push("callback3");
+ e.removeListener("foo", callback3);
+ }
+
+ e.on("foo", callback1);
+ test.assertEqual(1, e.listeners("foo").length);
+
+ e.emit("foo");
+ test.assertEqual(2, e.listeners("foo").length);
+ test.assertEqual(1, callbacks_called.length);
+ test.assertEqual('callback1', callbacks_called[0]);
+
+ e.emit("foo");
+ test.assertEqual(0, e.listeners("foo").length);
+ test.assertEqual(3, callbacks_called.length);
+ test.assertEqual('callback1', callbacks_called[0]);
+ test.assertEqual('callback2', callbacks_called[1]);
+ test.assertEqual('callback3', callbacks_called[2]);
+
+ e.emit("foo");
+ test.assertEqual(0, e.listeners("foo").length);
+ test.assertEqual(3, callbacks_called.length);
+ test.assertEqual('callback1', callbacks_called[0]);
+ test.assertEqual('callback2', callbacks_called[1]);
+ test.assertEqual('callback3', callbacks_called[2]);
+
+ e.on("foo", callback1);
+ e.on("foo", callback2);
+ test.assertEqual(2, e.listeners("foo").length);
+ e.removeAllListeners("foo");
+ test.assertEqual(0, e.listeners("foo").length);
+
+ // Verify that removing callbacks while in emit allows emits to propagate to
+ // all listeners
+ callbacks_called = [ ];
+
+ e.on("foo", callback2);
+ e.on("foo", callback3);
+ test.assertEqual(2, e.listeners("foo").length);
+ e.emit("foo");
+ test.assertEqual(2, callbacks_called.length);
+ test.assertEqual('callback2', callbacks_called[0]);
+ test.assertEqual('callback3', callbacks_called[1]);
+ test.assertEqual(0, e.listeners("foo").length);
+};
+
+exports['test:adding same listener'] = function(test) {
+ function foo() {}
+ let e = new EventEmitter();
+ e.on("foo", foo);
+ e.on("foo", foo);
+ test.assertEqual(
+ 1,
+ e.listeners("foo").length,
+ "listener reregistration is ignored"
+ );
+}
+
+exports['test:errors are reported if listener throws'] = function(test) {
+ let e = new EventEmitter(),
+ reported = false;
+ e.on('error', function(e) reported = true)
+ e.on('boom', function() { throw new Error('Boom!') });
+ e.emit('boom', 3);
+ test.assert(reported, 'error should be reported through event');
+};
+
+exports['test:emitOnObject'] = function(test) {
+ let e = new EventEmitter();
+
+ e.on("foo", function() {
+ test.assertEqual(this, e, "`this` should be emitter");
+ });
+ e.emitOnObject(e, "foo");
+
+ e.on("bar", function() {
+ test.assertEqual(this, obj, "`this` should be other object");
+ });
+ let obj = {};
+ e.emitOnObject(obj, "bar");
+};
+
+exports['test:once'] = function(test) {
+ let e = new EventEmitter();
+ let called = false;
+
+ e.once('foo', function(value) {
+ test.assert(!called, "listener called only once");
+ test.assertEqual(value, "bar", "correct argument was passed");
+ });
+
+ e.emit('foo', 'bar');
+ e.emit('foo', 'baz');
+};
+
+exports["test romeving once"] = function(test) {
+ let e = require("events").EventEmitterTrait.create();
+ e.once("foo", function() { test.pass("listener was called"); });
+ e.once("error", function() { test.fail("error event was emitted"); });
+ e._emit("foo", "bug-656684");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-file.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-file.js
new file mode 100644
index 0000000..89c27dd
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-file.js
@@ -0,0 +1,276 @@
+var file = require("file");
+var url = require("url");
+var byteStreams = require("byte-streams");
+var textStreams = require("text-streams");
+
+const ERRORS = {
+ FILE_NOT_FOUND: /^path does not exist: .+$/,
+ NOT_A_DIRECTORY: /^path is not a directory: .+$/,
+ NOT_A_FILE: /^path is not a file: .+$/,
+};
+
+var myurl = __url__;
+var mydir = myurl.slice(0, -("test-file.js".length));
+var otherdir = mydir + "interoperablejs-read-only/";
+
+exports.testDirName = function(test) {
+ var aDir = url.toFilename(otherdir);
+ test.assertEqual(file.dirname(aDir),
+ aDir.slice(0, aDir.lastIndexOf("interoperablejs-read-only")-1),
+ "file.dirname() of dir should return parent dir");
+
+ aDir = url.toFilename(myurl);
+ test.assertEqual(file.dirname(aDir),
+ aDir.slice(0, aDir.lastIndexOf("test-file")-1),
+ "file.dirname() of file should return its dir");
+
+ while (aDir)
+ aDir = file.dirname(aDir);
+ test.assertEqual(aDir, "",
+ "dirname should return empty string when dir has no parent");
+};
+
+exports.testBasename = function(test) {
+ // Get the top-most path -- the path with no basename. E.g., on Unix-like
+ // systems this will be /. We'll use it below to build up some test paths.
+ // We have to go to this trouble because file.join() needs a legal path as a
+ // base case; join("foo", "bar") doesn't work unfortunately.
+ var topPath = url.toFilename(myurl);
+ var parentPath = file.dirname(topPath);
+ while (parentPath) {
+ topPath = parentPath;
+ parentPath = file.dirname(topPath);
+ }
+
+ var path = topPath;
+ test.assertEqual(file.basename(path), "",
+ "basename should work on paths with no components");
+
+ path = file.join(path, "foo");
+ test.assertEqual(file.basename(path), "foo",
+ "basename should work on paths with a single component");
+
+ path = file.join(path, "bar");
+ test.assertEqual(file.basename(path), "bar",
+ "basename should work on paths with multiple components");
+};
+
+exports.testList = function(test) {
+ var list = file.list(url.toFilename(otherdir));
+ var found = [true for each (name in list)
+ if (name == "README.txt")];
+ if (found.length > 1)
+ test.fail("a dir can't contain two files of the same name!");
+ test.assertEqual(found[0], true, "file.list() should work");
+
+ test.assertRaises(
+ function() { file.list(url.toFilename(__url__)); },
+ ERRORS.NOT_A_DIRECTORY,
+ "file.list() on non-dir should raise error"
+ );
+
+ test.assertRaises(
+ function() { file.list(url.toFilename(mydir + "foo/")); },
+ ERRORS.FILE_NOT_FOUND,
+ "file.list() on nonexistent dir should raise error"
+ );
+};
+
+exports.testRead = function(test) {
+ var filename = url.toFilename(__url__);
+ var contents = file.read(filename);
+ test.assertMatches(contents, /file\.read\(\) should work/,
+ "file.read() should work");
+
+ test.assertRaises(
+ function() { file.read(filename + "blah"); },
+ ERRORS.FILE_NOT_FOUND,
+ "file.read() on nonexistent file should raise error"
+ );
+
+ test.assertRaises(
+ function() { file.read(url.toFilename(otherdir)); },
+ ERRORS.NOT_A_FILE,
+ "file.read() on dir should raise error"
+ );
+};
+
+exports.testJoin = function(test) {
+ var filename = url.toFilename(myurl);
+ var baseDir = file.dirname(filename);
+
+ test.assertEqual(file.join(baseDir, "test-file.js"),
+ filename,
+ "file.join() should work");
+};
+
+exports.testOpenNonexistentForRead = function (test) {
+ var filename = dataFileFilename(test);
+ test.assertRaises(function () file.open(filename),
+ ERRORS.FILE_NOT_FOUND,
+ "file.open() on nonexistent file should raise error");
+ test.assertRaises(function () file.open(filename, "r"),
+ ERRORS.FILE_NOT_FOUND,
+ "file.open('r') on nonexistent file should raise error");
+ test.assertRaises(function () file.open(filename, "zzz"),
+ ERRORS.FILE_NOT_FOUND,
+ "file.open('zzz') on nonexistent file should raise error");
+};
+
+exports.testOpenNonexistentForWrite = function (test) {
+ var filename = dataFileFilename(test);
+
+ var stream = file.open(filename, "w");
+ stream.close();
+
+ test.assert(file.exists(filename),
+ "file.exists() should return true after file.open('w')");
+ file.remove(filename);
+ test.assert(!file.exists(filename),
+ "file.exists() should return false after file.remove()");
+
+ stream = file.open(filename, "rw");
+ stream.close();
+
+ test.assert(file.exists(filename),
+ "file.exists() should return true after file.open('rw')");
+ file.remove(filename);
+ test.assert(!file.exists(filename),
+ "file.exists() should return false after file.remove()");
+};
+
+exports.testOpenDirectory = function (test) {
+ var dir = file.dirname(url.toFilename(__url__));
+ test.assertRaises(function () file.open(dir),
+ ERRORS.NOT_A_FILE,
+ "file.open() on directory should raise error");
+ test.assertRaises(function () file.open(dir, "w"),
+ ERRORS.NOT_A_FILE,
+ "file.open('w') on directory should raise error");
+};
+
+exports.testOpenTypes = function (test) {
+ var filename = dataFileFilename(test);
+
+ // Do the opens first to create the data file.
+ var stream = file.open(filename, "w");
+ test.assert(stream instanceof textStreams.TextWriter,
+ "open(w) should return a TextWriter");
+ stream.close();
+
+ stream = file.open(filename, "wb");
+ test.assert(stream instanceof byteStreams.ByteWriter,
+ "open(wb) should return a ByteWriter");
+ stream.close();
+
+ stream = file.open(filename);
+ test.assert(stream instanceof textStreams.TextReader,
+ "open() should return a TextReader");
+ stream.close();
+
+ stream = file.open(filename, "r");
+ test.assert(stream instanceof textStreams.TextReader,
+ "open(r) should return a TextReader");
+ stream.close();
+
+ stream = file.open(filename, "b");
+ test.assert(stream instanceof byteStreams.ByteReader,
+ "open(b) should return a ByteReader");
+ stream.close();
+
+ stream = file.open(filename, "rb");
+ test.assert(stream instanceof byteStreams.ByteReader,
+ "open(rb) should return a ByteReader");
+ stream.close();
+
+ file.remove(filename);
+};
+
+exports.testMkpathRmdir = function (test) {
+ var basePath = file.dirname(url.toFilename(__url__));
+ var dirs = [];
+ for (var i = 0; i < 3; i++)
+ dirs.push("test-file-dir");
+ var paths = [];
+ for (var i = 0; i < dirs.length; i++) {
+ var args = [basePath].concat(dirs.slice(0, i + 1));
+ paths.unshift(file.join.apply(null, args));
+ }
+ for (i = 0; i < paths.length; i++) {
+ test.assert(!file.exists(paths[i]),
+ "Sanity check: path should not exist: " + paths[i]);
+ }
+ file.mkpath(paths[0]);
+ test.assert(file.exists(paths[0]), "mkpath should create path: " + paths[0]);
+ for (i = 0; i < paths.length; i++) {
+ file.rmdir(paths[i]);
+ test.assert(!file.exists(paths[i]),
+ "rmdir should remove path: " + paths[i]);
+ }
+};
+
+exports.testMkpathTwice = function (test) {
+ var dir = file.dirname(url.toFilename(__url__));
+ var path = file.join(dir, "test-file-dir");
+ test.assert(!file.exists(path),
+ "Sanity check: path should not exist: " + path);
+ file.mkpath(path);
+ test.assert(file.exists(path), "mkpath should create path: " + path);
+ file.mkpath(path);
+ test.assert(file.exists(path),
+ "After second mkpath, path should still exist: " + path);
+ file.rmdir(path);
+ test.assert(!file.exists(path), "rmdir should remove path: " + path);
+};
+
+exports.testMkpathExistingNondirectory = function (test) {
+ var fname = dataFileFilename(test);
+ file.open(fname, "w").close();
+ test.assert(file.exists(fname), "File should exist");
+ test.assertRaises(function () file.mkpath(fname),
+ /^The path already exists and is not a directory: .+$/,
+ "mkpath on file should raise error");
+ file.remove(fname);
+};
+
+exports.testRmdirNondirectory = function (test) {
+ var fname = dataFileFilename(test);
+ file.open(fname, "w").close();
+ test.assert(file.exists(fname), "File should exist");
+ test.assertRaises(function () file.rmdir(fname),
+ ERRORS.NOT_A_DIRECTORY,
+ "rmdir on file should raise error");
+ file.remove(fname);
+ test.assert(!file.exists(fname), "File should not exist");
+ test.assertRaises(function () file.rmdir(fname),
+ ERRORS.FILE_NOT_FOUND,
+ "rmdir on non-existing file should raise error");
+};
+
+exports.testRmdirNonempty = function (test) {
+ var dir = file.dirname(url.toFilename(__url__));
+ var path = file.join(dir, "test-file-dir");
+ test.assert(!file.exists(path),
+ "Sanity check: path should not exist: " + path);
+ file.mkpath(path);
+ var filePath = file.join(path, "file");
+ file.open(filePath, "w").close();
+ test.assert(file.exists(filePath),
+ "Sanity check: path should exist: " + filePath);
+ test.assertRaises(function () file.rmdir(path),
+ /^The directory is not empty: .+$/,
+ "rmdir on non-empty directory should raise error");
+ file.remove(filePath);
+ file.rmdir(path);
+ test.assert(!file.exists(path), "Path should not exist");
+};
+
+// Returns the name of a file that should be used to test writing and reading.
+function dataFileFilename(test) {
+ var dir = file.dirname(url.toFilename(__url__));
+ var fname = file.join(dir, "test-file-data");
+ test.assert(!file.exists(fname),
+ "Sanity check: the file that this test assumes does not " +
+ "exist should really not exist!");
+ return fname;
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-function-utils.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-function-utils.js
new file mode 100644
index 0000000..292380a
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-function-utils.js
@@ -0,0 +1,23 @@
+const { invoke, Enqueued } = require('utils/function');
+
+exports['test forwardApply'] = function(test) {
+ function sum(b, c) this.a + b + c
+ test.assertEqual(invoke(sum, [2, 3], { a: 1 }), 6,
+ 'passed arguments and pseoude-variable are used');
+ test.assertEqual(invoke(sum.bind({ a: 2 }), [2, 3], { a: 1 }), 7,
+ 'bounded `this` pseoudo variable is used')
+}
+
+exports['test enqueued function'] = function(test) {
+ test.waitUntilDone();
+ let nextTurn = false;
+ function sum(b, c) {
+ test.assert(nextTurn, 'enqueued is called in next turn of event loop');
+ test.assertEqual(this.a + b + c, 6,
+ 'passed arguments an pseoude-variable are used');
+ test.done();
+ }
+ let fixture = { a: 1, method: Enqueued(sum) }
+ fixture.method(2, 3);
+ nextTurn = true;
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-globals.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-globals.js
new file mode 100644
index 0000000..6cceeb8
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-globals.js
@@ -0,0 +1,12 @@
+var global = this;
+
+exports.testGlobals = function(test) {
+ test.assertMatches(global.__url__, /test-globals\.js$/,
+ "__url__ global should contain filename");
+
+ ['console', 'memory'].forEach(
+ function(name) {
+ test.assertNotEqual(global[name], undefined,
+ name + " should be defined");
+ });
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-hidden-frame.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-hidden-frame.js
new file mode 100644
index 0000000..c92046b
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-hidden-frame.js
@@ -0,0 +1,47 @@
+let tests = {}, hiddenFrames, HiddenFrame;
+
+tests.testFrame = function(test) {
+ let url = "data:text/html,<!DOCTYPE%20html>";
+ test.waitUntilDone();
+ let hiddenFrame = hiddenFrames.add(HiddenFrame({
+ onReady: function () {
+ test.assertEqual(this.element.contentWindow.location, "about:blank",
+ "HiddenFrame loads about:blank by default.");
+
+ function onDOMReady() {
+ hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady,
+ false);
+ test.assertEqual(hiddenFrame.element.contentWindow.location, url,
+ "HiddenFrame loads the specified content.");
+ test.done();
+ }
+ this.element.addEventListener("DOMContentLoaded", onDOMReady, false);
+ this.element.setAttribute("src", url);
+ }
+ }));
+};
+
+let hiddenFrameSupported = true;
+
+try {
+ hiddenFrames = require("hidden-frame");
+ HiddenFrame = hiddenFrames.HiddenFrame;
+}
+catch(ex if ex.message == [
+ "The hidden-frame module currently supports only Firefox and Thunderbird. ",
+ "In the future, we would like it to support other applications, however. ",
+ "Please see https://bugzilla.mozilla.org/show_bug.cgi?id=546740 for more ",
+ "information."
+ ].join("")) {
+ hiddenFrameSupported = false;
+}
+
+if (hiddenFrameSupported) {
+ for (let test in tests)
+ exports[test] = tests[test];
+}
+else {
+ exports.testHiddenFrameNotSupported = function(test) {
+ test.pass("The hidden-frame module is not supported on this app.");
+ }
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-observer.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-observer.js
new file mode 100644
index 0000000..1f6ff71
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-observer.js
@@ -0,0 +1,31 @@
+"use strict";
+
+const { keyPress } = require("api-utils/dom/events/keys");
+
+exports["test unload keyboard observer"] = function(assert, done) {
+ // Hacky way to be able to create unloadable modules via makeSandboxedLoader.
+ let loader = assert._log.makeSandboxedLoader();
+ let element = loader.require("api-utils/window-utils").activeBrowserWindow.
+ document.documentElement;
+ let observer = loader.require("api-utils/keyboard/observer").observer;
+ let called = 0;
+
+ observer.on("keypress", function () { called++; });
+
+ // dispatching "keypress" event to trigger observer listeners.
+ keyPress(element, "accel-%");
+
+ // Unload the module.
+ loader.unload();
+
+ // dispatching "keypress" even once again.
+ keyPress(element, "accel-%");
+
+ // Enqueuing asserts to make sure that assertion is not performed early.
+ require("timer").setTimeout(function () {
+ assert.equal(called, 1, "observer was called before unload only.");
+ done();
+ }, 0);
+};
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-utils.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-utils.js
new file mode 100644
index 0000000..137e6b1
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-keyboard-utils.js
@@ -0,0 +1,58 @@
+"use strict";
+
+const utils = require("keyboard/utils");
+const runtime = require("runtime");
+
+const isMac = runtime.OS === "Darwin";
+
+exports["test toString"] = function(assert) {
+ assert.equal(utils.toString({
+ key: "B",
+ modifiers: [ "Shift", "Ctrl" ]
+ }), "Shift-Ctrl-B", "toString does not normalizes JSON");
+
+ assert.equal(utils.toString({
+ key: "C",
+ modifiers: [],
+ }), "C", "Works with objects with empty array of modifiers");
+
+ assert.equal(utils.toString(Object.create((function Type() {}).prototype, {
+ key: { value: "d" },
+ modifiers: { value: [ "alt" ] },
+ method: { value: function() {} }
+ })), "alt-d", "Works with non-json objects");
+
+ assert.equal(utils.toString({
+ modifiers: [ "shift", "alt" ]
+ }), "shift-alt-", "works with only modifiers");
+};
+
+exports["test toJSON"] = function(assert) {
+ assert.deepEqual(utils.toJSON("Shift-Ctrl-B"), {
+ key: "b",
+ modifiers: [ "control", "shift" ]
+ }, "toJSON normalizes input");
+
+ assert.deepEqual(utils.toJSON("Meta-Alt-option-C"), {
+ key: "c",
+ modifiers: [ "alt", "meta" ]
+ }, "removes dublicates");
+
+ assert.deepEqual(utils.toJSON("AccEl+sHiFt+Z", "+"), {
+ key: "z",
+ modifiers: isMac ? [ "meta", "shift" ] : [ "control", "shift" ]
+ }, "normalizes OS specific keys and adjustes seperator");
+};
+
+exports["test normalize"] = function assert(assert) {
+ assert.equal(utils.normalize("Shift Ctrl A control ctrl", " "),
+ "control shift a", "removes reapeted modifiers");
+ assert.equal(utils.normalize("shift-ctrl-left"), "control-shift-left",
+ "normilizes non printed characters");
+
+ assert.throws(function() {
+ utils.normalize("shift-alt-b-z");
+ }, "throws if contains more then on non-modifier key");
+};
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-light-traits.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-light-traits.js
new file mode 100644
index 0000000..4ad97b5
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-light-traits.js
@@ -0,0 +1,7 @@
+"use strict";
+
+exports["test traits from objects"] = require("./traits/object-tests");
+exports["test traits from descriptors"] = require("./traits/descriptor-tests");
+exports["test inheritance"] = require("./traits/inheritance-tests");
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-list.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-list.js
new file mode 100644
index 0000000..56143bd
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-list.js
@@ -0,0 +1,203 @@
+"use strict";
+
+function assertList(test, array, list) {
+ for (let i = 0, ii = array.length; i < ii; i < ii, i++) {
+ test.assertEqual(
+ array.length,
+ list.length,
+ 'list must contain same amount of elements as array'
+ );
+ test.assertEqual(
+ 'List(' + array + ')',
+ list + '',
+ 'toString must output array like result'
+ );
+ test.assert(
+ i in list,
+ 'must contain element with index: ' + i
+ );
+ test.assertEqual(
+ array[i],
+ list[i],
+ 'element with index: ' + i + ' should match'
+ );
+ }
+}
+
+const { List } = require('list');
+
+exports['test:test for'] = function(test) {
+ let fixture = List(3, 2, 1);
+
+ test.assertEqual(3, fixture.length, 'length is 3');
+ let i = 0;
+ for (let key in fixture) {
+ test.assertEqual(i++, key, 'key should match');
+ }
+};
+
+exports['test:test for each'] = function(test) {
+ let fixture = new List(3, 2, 1);
+
+ test.assertEqual(3, fixture.length, 'length is 3');
+ let i = 3;
+ for each (let value in fixture) {
+ test.assertEqual(i--, value, 'value should match');
+ }
+};
+
+exports['test: for each using Iterator'] = function(test) {
+ let fixture = new List(3, 2, 1);
+
+ test.assertEqual(3, fixture.length, 'length is 3');
+ let v = 3, k = 0;
+ for each (let [key, value] in Iterator(fixture)) {
+ test.assertEqual(k++, key, 'key should match');
+ test.assertEqual(v--, value, 'value should match');
+ }
+};
+
+exports['test:test toString'] = function(test) {
+ let fixture = List(3, 2, 1);
+
+ test.assertEqual(
+ 'List(3,2,1)',
+ fixture + '',
+ 'toString must output array like result'
+ )
+};
+
+exports['test:test constructor with apply'] = function(test) {
+ let array = ['a', 'b', 'c'];
+ let fixture = List.apply(null, array);
+
+ test.assertEqual(
+ 3,
+ fixture.length,
+ 'should have applied arguments'
+ );
+};
+
+exports['test:direct element access'] = function(test) {
+ let array = [1, 'foo', 2, 'bar', {}, 'bar', function a() {}, test, 1];
+ let fixture = List.apply(null, array);
+ array.splice(5, 1);
+ array.splice(7, 1);
+
+ test.assertEqual(
+ array.length,
+ fixture.length,
+ 'list should omit duplicate elements'
+ );
+
+ test.assertEqual(
+ 'List(' + array + ')',
+ fixture.toString(),
+ 'elements should not be rearranged'
+ );
+
+ for (let key in array) {
+ test.assert(key in fixture,'should contain key for index:' + key);
+ test.assertEqual(
+ array[key],
+ fixture[key],
+ 'values should match for: ' + key
+ );
+ }
+};
+
+exports['test:removing adding elements'] = function(test) {
+ let array = [1, 'foo', 2, 'bar', {}, 'bar', function a() {}, test, 1];
+ let fixture = List.compose({
+ add: function() this._add.apply(this, arguments),
+ remove: function() this._remove.apply(this, arguments),
+ clear: function() this._clear()
+ }).apply(null, array);
+ array.splice(5, 1);
+ array.splice(7, 1);
+
+ assertList(test, array, fixture);
+
+ array.splice(array.indexOf(2), 1);
+ fixture.remove(2);
+ assertList(test, array, fixture);
+
+ array.splice(array.indexOf('foo'), 1);
+ fixture.remove('foo');
+ array.splice(array.indexOf(1), 1);
+ fixture.remove(1);
+ array.push('foo');
+ fixture.add('foo');
+ assertList(test, array, fixture);
+
+ array.splice(0);
+ fixture.clear(0);
+ assertList(test, array, fixture);
+
+ array.push(1, 'foo', 2, 'bar', 3);
+ fixture.add(1);
+ fixture.add('foo');
+ fixture.add(2);
+ fixture.add('bar');
+ fixture.add(3);
+
+ assertList(test, array, fixture);
+};
+
+exports['test: remove does not leave invalid numerical properties'] = function(test) {
+ let fixture = List.compose({
+ remove: function() this._remove.apply(this, arguments),
+ }).apply(null, [1, 2, 3]);
+
+ fixture.remove(1);
+ test.assertEqual(fixture[fixture.length], undefined);
+}
+
+exports['test:add list item from Iterator'] = function(test) {
+ let array = [1, 2, 3, 4], sum = 0, added = false;
+
+ let fixture = List.compose({
+ add: function() this._add.apply(this, arguments),
+ }).apply(null, array);
+
+ for each (let item in fixture) {
+ sum += item;
+
+ if (!added) {
+ fixture.add(5);
+ added = true;
+ }
+ }
+
+ test.assertEqual(sum, 1 + 2 + 3 + 4);
+};
+
+exports['test:remove list item from Iterator'] = function(test) {
+ let array = [1, 2, 3, 4], sum = 0;
+
+ let fixture = List.compose({
+ remove: function() this._remove.apply(this, arguments),
+ }).apply(null, array);
+
+ for each (let item in fixture) {
+ sum += item;
+ fixture.remove(item);
+ }
+
+ test.assertEqual(sum, 1 + 2 + 3 + 4);
+};
+
+exports['test:clear list from Iterator'] = function(test) {
+ let array = [1, 2, 3, 4], sum = 0;
+
+ let fixture = List.compose({
+ clear: function() this._clear()
+ }).apply(null, array);
+
+ for each (let item in fixture) {
+ sum += item;
+ fixture.clear();
+ }
+
+ test.assertEqual(sum, 1 + 2 + 3 + 4);
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-match-pattern.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-match-pattern.js
new file mode 100644
index 0000000..0352ba9
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-match-pattern.js
@@ -0,0 +1,161 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Irakli Gozalishvili <gozala@mozilla.com> (Original Author)
+ * Drew Willcoxon <adw@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const { MatchPattern } = require("match-pattern");
+
+exports.testMatchPatternTestTrue = function(test) {
+ function ok(pattern, url) {
+ let mp = new MatchPattern(pattern);
+ test.assert(mp.test(url), pattern + " should match " + url);
+ }
+
+ ok("*", "http://example.com");
+ ok("*", "https://example.com");
+ ok("*", "ftp://example.com");
+
+ ok("*.example.com", "http://example.com");
+ ok("*.example.com", "http://hamburger.example.com");
+ ok("*.example.com", "http://hotdog.hamburger.example.com");
+
+ ok("http://example.com*", "http://example.com");
+ ok("http://example.com*", "http://example.com/");
+ ok("http://example.com/*", "http://example.com/");
+ ok("http://example.com/*", "http://example.com/potato-salad");
+ ok("http://example.com/pickles/*", "http://example.com/pickles/");
+ ok("http://example.com/pickles/*", "http://example.com/pickles/lemonade");
+
+ ok("http://example.com", "http://example.com");
+ ok("http://example.com/ice-cream", "http://example.com/ice-cream");
+
+ ok(/.*zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
+ ok(/https:.*zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
+};
+
+exports.testMatchPatternTestFalse = function(test) {
+ function ok(pattern, url) {
+ let mp = new MatchPattern(pattern);
+ test.assert(!mp.test(url), pattern + " should not match " + url);
+ }
+
+ ok("*", null);
+ ok("*", "");
+ ok("*", "bogus");
+ ok("*", "chrome://browser/content/browser.xul");
+ ok("*", "nttp://example.com");
+
+ ok("*.example.com", null);
+ ok("*.example.com", "");
+ ok("*.example.com", "bogus");
+ ok("*.example.com", "http://example.net");
+ ok("*.example.com", "http://foo.com");
+ ok("*.example.com", "http://example.com.foo");
+ ok("*.example2.com", "http://example.com");
+
+ ok("http://example.com/*", null);
+ ok("http://example.com/*", "");
+ ok("http://example.com/*", "bogus");
+ ok("http://example.com/*", "http://example.com");
+ ok("http://example.com/*", "http://foo.com/");
+
+ ok("http://example.com", null);
+ ok("http://example.com", "");
+ ok("http://example.com", "bogus");
+ ok("http://example.com", "http://example.com/");
+
+ ok(/zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
+ ok(/.*zilla/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
+ ok(/https:.*zilla/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
+};
+
+exports.testMatchPatternErrors = function(test) {
+ test.assertRaises(
+ function() new MatchPattern("*.google.com/*"),
+ /There can be at most one/,
+ "MatchPattern throws when supplied multiple '*'"
+ );
+
+ test.assertRaises(
+ function() new MatchPattern("google.com"),
+ /expected to be either an exact URL/,
+ "MatchPattern throws when the wildcard doesn't use '*' and doesn't " +
+ "look like a URL"
+ );
+
+ test.assertRaises(
+ function() new MatchPattern("http://google*.com"),
+ /expected to be the first or the last/,
+ "MatchPattern throws when a '*' is in the middle of the wildcard"
+ );
+
+ test.assertRaises(
+ function() new MatchPattern(/ /g),
+ /^A RegExp match pattern cannot be set to `global` \(i\.e\. \/\/g\)\.$/,
+ "MatchPattern throws on a RegExp set to `global` (i.e. //g)."
+ );
+
+ test.assertRaises(
+ function() new MatchPattern(/ /i),
+ /^A RegExp match pattern cannot be set to `ignoreCase` \(i\.e\. \/\/i\)\.$/,
+ "MatchPattern throws on a RegExp set to `ignoreCase` (i.e. //i)."
+ );
+
+ test.assertRaises(
+ function() new MatchPattern( / /m ),
+ /^A RegExp match pattern cannot be set to `multiline` \(i\.e\. \/\/m\)\.$/,
+ "MatchPattern throws on a RegExp set to `multiline` (i.e. //m)."
+ );
+};
+
+exports.testMatchPatternInternals = function(test) {
+ test.assertEqual(
+ new MatchPattern("http://google.com/test").exactURL,
+ "http://google.com/test"
+ );
+
+ test.assertEqual(
+ new MatchPattern("http://google.com/test/*").urlPrefix,
+ "http://google.com/test/"
+ );
+
+ test.assertEqual(
+ new MatchPattern("*.example.com").domain,
+ "example.com"
+ );
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-memory.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-memory.js
new file mode 100644
index 0000000..7e172bf
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-memory.js
@@ -0,0 +1,15 @@
+var memory = require("memory");
+
+exports.testMemory = function(test) {
+ test.pass("Skipping this test until Gecko memory debugging issues " +
+ "are resolved (see bug 592774).");
+ return;
+
+ var obj = {};
+ memory.track(obj, "testMemory.testObj");
+ var objs = memory.getObjects("testMemory.testObj");
+ test.assertEqual(objs[0].weakref.get(), obj);
+ obj = null;
+ memory.gc();
+ test.assertEqual(objs[0].weakref.get(), null);
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-modules.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-modules.js
new file mode 100644
index 0000000..53069de
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-modules.js
@@ -0,0 +1,131 @@
+
+// define() that exports a function as the module value,
+// specifying a module name.
+exports.testDefExport = function(test) {
+ var add = require('modules/add');
+ test.assertEqual(add(1, 1), 2, 'Named define() exporting a function');
+};
+
+// define() that exports function as a value, but is anonymous
+exports.testAnonDefExport = function (test) {
+ var subtract = require('modules/subtract');
+ test.assertEqual(subtract(4, 2), 2,
+ 'Anonymous define() exporting a function');
+}
+
+// using require([], function () {}) to load modules.
+exports.testSimpleRequire = function (test) {
+ require(['modules/blue', 'modules/orange'], function (blue, orange) {
+ test.assertEqual(blue.name, 'blue', 'Simple require for blue');
+ test.assertEqual(orange.name, 'orange', 'Simple require for orange');
+ test.assertEqual(orange.parentType, 'color',
+ 'Simple require dependency check for orange');
+ });
+}
+
+// using nested require([]) calls.
+exports.testSimpleRequireNested = function (test) {
+ require(['modules/blue', 'modules/orange', 'modules/green'],
+ function (blue, orange, green) {
+
+ require(['modules/orange', 'modules/red'], function (orange, red) {
+ test.assertEqual(red.name, 'red', 'Simple require for red');
+ test.assertEqual(red.parentType, 'color',
+ 'Simple require dependency check for red');
+ test.assertEqual(blue.name, 'blue', 'Simple require for blue');
+ test.assertEqual(orange.name, 'orange', 'Simple require for orange');
+ test.assertEqual(orange.parentType, 'color',
+ 'Simple require dependency check for orange');
+ test.assertEqual(green.name, 'green', 'Simple require for green');
+ test.assertEqual(green.parentType, 'color',
+ 'Simple require dependency check for green');
+ });
+
+ });
+}
+
+// requiring a traditional module, that uses async, that use traditional and
+// async, with a circular reference
+exports.testMixedCircular = function (test) {
+ var t = require('modules/traditional1');
+ test.assertEqual(t.name, 'traditional1', 'Testing name');
+ test.assertEqual(t.traditional2Name, 'traditional2',
+ 'Testing dependent name');
+ test.assertEqual(t.traditional1Name, 'traditional1', 'Testing circular name');
+ test.assertEqual(t.async2Name, 'async2', 'Testing async2 name');
+ test.assertEqual(t.async2Traditional2Name, 'traditional2',
+ 'Testing nested traditional2 name');
+}
+
+// Testing define()(function(require) {}) with some that use exports,
+// some that use return.
+exports.testAnonExportsReturn = function (test) {
+ var lion = require('modules/lion');
+ require(['modules/tiger', 'modules/cheetah'], function (tiger, cheetah) {
+ test.assertEqual('lion', lion, 'Check lion name');
+ test.assertEqual('tiger', tiger.name, 'Check tiger name');
+ test.assertEqual('cat', tiger.type, 'Check tiger type');
+ test.assertEqual('cheetah', cheetah(), 'Check cheetah name');
+ });
+}
+
+// circular dependency
+exports.testCircular = function (test) {
+ var pollux = require('modules/pollux'),
+ castor = require('modules/castor');
+
+ test.assertEqual(pollux.name, 'pollux', 'Pollux\'s name');
+ test.assertEqual(pollux.getCastorName(),
+ 'castor', 'Castor\'s name from Pollux.');
+ test.assertEqual(castor.name, 'castor', 'Castor\'s name');
+ test.assertEqual(castor.getPolluxName(), 'pollux',
+ 'Pollux\'s name from Castor.');
+}
+
+// test a bad module that asks for exports but also does a define() return
+exports.testBadExportAndReturn = function (test) {
+ var passed = false;
+ try {
+ var bad = require('modules/badExportAndReturn');
+ } catch(e) {
+ passed = /cannot use exports and also return/.test(e.toString());
+ }
+ test.assertEqual(passed, true, 'Make sure exports and return fail');
+}
+
+// test a bad circular dependency, where an exported value is needed, but
+// the return value happens too late, a module already asked for the exported
+// value.
+exports.testBadExportAndReturnCircular = function (test) {
+ var passed = false;
+ try {
+ var bad = require('modules/badFirst');
+ } catch(e) {
+ passed = /after another module has referenced its exported value/
+ .test(e.toString());
+ }
+ test.assertEqual(passed, true, 'Make sure return after an exported ' +
+ 'value is grabbed by another module fails.');
+}
+
+// only allow one define call per file.
+exports.testOneDefine = function (test) {
+ var passed = false;
+ try {
+ var dupe = require('modules/dupe');
+ } catch(e) {
+ passed = /Only one call to define/.test(e.toString());
+ }
+ test.assertEqual(passed, true, 'Only allow one define call per module');
+}
+
+// only allow one define call per file, testing a bad nested define call.
+exports.testOneDefineNested = function (test) {
+ var passed = false;
+ try {
+ var dupe = require('modules/dupeNested');
+ } catch(e) {
+ passed = /Only one call to define/.test(e.toString());
+ }
+ test.assertEqual(passed, true, 'Only allow one define call per module');
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-observer-service.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-observer-service.js
new file mode 100644
index 0000000..9d409fb
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-observer-service.js
@@ -0,0 +1,73 @@
+var observers = require("observer-service");
+var {Cc,Ci} = require("chrome");
+
+exports.testUnloadAndErrorLogging = function(test) {
+ var prints = [];
+ function print(message) {
+ prints.push(message);
+ }
+ var loader = test.makeSandboxedLoader({print: print});
+ var sbobsvc = loader.require("observer-service");
+
+ var timesCalled = 0;
+ var cb = function(subject, data) {
+ timesCalled++;
+ };
+ var badCb = function(subject, data) {
+ throw new Error("foo");
+ };
+ sbobsvc.add("blarg", cb);
+ observers.notify("blarg", "yo yo");
+ test.assertEqual(timesCalled, 1);
+ sbobsvc.add("narg", badCb);
+ observers.notify("narg", "yo yo");
+ var lines = prints[0].split("\n");
+ test.assertEqual(lines[0], "error: An exception occurred.");
+ test.assertEqual(lines[1], "Traceback (most recent call last):");
+ test.assertEqual(lines.slice(-2)[0], "Error: foo");
+
+ loader.unload();
+ observers.notify("blarg", "yo yo");
+ test.assertEqual(timesCalled, 1);
+};
+
+exports.testObserverService = function(test) {
+ var ios = Cc['@mozilla.org/network/io-service;1']
+ .getService(Ci.nsIIOService);
+ var service = Cc["@mozilla.org/observer-service;1"].
+ getService(Ci.nsIObserverService);
+ var uri = ios.newURI("http://www.foo.com", null, null);
+ var timesCalled = 0;
+ var lastSubject = null;
+ var lastData = null;
+
+ var cb = function(subject, data) {
+ timesCalled++;
+ lastSubject = subject;
+ lastData = data;
+ };
+
+ observers.add("blarg", cb);
+ service.notifyObservers(uri, "blarg", "some data");
+ test.assertEqual(timesCalled, 1,
+ "observer-service.add() should call callback");
+ test.assertEqual(lastSubject, uri,
+ "observer-service.add() should pass subject");
+ test.assertEqual(lastData, "some data",
+ "observer-service.add() should pass data");
+
+ function customSubject() {}
+ function customData() {}
+ observers.notify("blarg", customSubject, customData);
+ test.assertEqual(timesCalled, 2,
+ "observer-service.notify() should work");
+ test.assertEqual(lastSubject, customSubject,
+ "observer-service.notify() should pass+wrap subject");
+ test.assertEqual(lastData, customData,
+ "observer-service.notify() should pass data");
+
+ observers.remove("blarg", cb);
+ service.notifyObservers(null, "blarg", "some data");
+ test.assertEqual(timesCalled, 2,
+ "observer-service.remove() should work");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-passwords-utils.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-passwords-utils.js
new file mode 100644
index 0000000..651296f
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-passwords-utils.js
@@ -0,0 +1,138 @@
+"use strict";
+
+const { store, search, remove } = require("passwords/utils");
+
+exports["test store requires `password` field"] = function(assert) {
+ assert.throws(function() {
+ store({ username: "foo", realm: "bar" });
+ }, "`password` is required");
+};
+
+exports["test store requires `username` field"] = function(assert) {
+ assert.throws(function() {
+ store({ password: "foo", realm: "bar" });
+ }, "`username` is required");
+};
+
+exports["test store requires `realm` field"] = function(assert) {
+ assert.throws(function() {
+ store({ username: "foo", password: "bar" });
+ }, "`password` is required");
+};
+
+exports["test can't store same login twice"] = function(assert) {
+ let options = { username: "user", password: "pass", realm: "realm" };
+ store(options);
+ assert.throws(function() {
+ store(options);
+ }, "can't store same pass twice");
+ remove(options);
+};
+
+exports["test remove throws if no login found"] = function(assert) {
+ assert.throws(function() {
+ remove({ username: "foo", password: "bar", realm: "baz" });
+ }, "can't remove unstored credentials");
+};
+
+exports["test addon associated credentials"] = function(assert) {
+ let options = { username: "foo", password: "bar", realm: "baz" };
+ store(options);
+
+ assert.ok(search().length, "credential was stored");
+ assert.ok(search(options).length, "stored credential found");
+ assert.ok(search({ username: options.username }).length, "found by username");
+ assert.ok(search({ password: options.password }).length, "found by password");
+ assert.ok(search({ realm: options.realm }).length, "found by realm");
+
+ let credential = search(options)[0];
+ assert.equal(credential.url.indexOf("addon:"), 0,
+ "`addon:` uri is used for add-on associated credentials");
+ assert.equal(credential.username, options.username, "username matches");
+ assert.equal(credential.password, options.password, "password matches");
+ assert.equal(credential.realm, options.realm, "realm matches");
+ assert.equal(credential.formSubmitURL, null,
+ "`formSubmitURL` is `null` for add-on associated credentials");
+ assert.equal(credential.usernameField, "", "usernameField is empty");
+ assert.equal(credential.passwordField, "", "passwordField is empty");
+
+ remove(search(options)[0]);
+ assert.ok(!search(options).length, "remove worked");
+};
+
+exports["test web page associated credentials"] = function(assert) {
+ let options = {
+ url: "http://www.example.com",
+ formSubmitURL: "http://login.example.com",
+ username: "user",
+ password: "pass",
+ usernameField: "user-f",
+ passwordField: "pass-f"
+ };
+ store({
+ url: "http://www.example.com/login",
+ formSubmitURL: "http://login.example.com/foo/authenticate.cgi",
+ username: options.username,
+ password: options.password,
+ usernameField: options.usernameField,
+ passwordField: options.passwordField
+ });
+
+ assert.ok(search().length, "credential was stored");
+ assert.ok(search(options).length, "stored credential found");
+ assert.ok(search({ username: options.username }).length, "found by username");
+ assert.ok(search({ password: options.password }).length, "found by password");
+ assert.ok(search({ formSubmitURL: options.formSubmitURL }).length,
+ "found by formSubmitURL");
+ assert.ok(search({ usernameField: options.usernameField }).length,
+ "found by usernameField");
+ assert.ok(search({ passwordField: options.passwordField }).length,
+ "found by passwordField");
+
+ let credential = search(options)[0];
+ assert.equal(credential.url, options.url, "url matches");
+ assert.equal(credential.username, options.username, "username matches");
+ assert.equal(credential.password, options.password, "password matches");
+ assert.equal(credential.realm, null, "realm is ");
+ assert.equal(credential.formSubmitURL, options.formSubmitURL,
+ "`formSubmitURL` matches");
+ assert.equal(credential.usernameField, options.usernameField,
+ "usernameField matches");
+ assert.equal(credential.passwordField, options.passwordField,
+ "passwordField matches");
+
+ remove(search(options)[0]);
+ assert.ok(!search(options).length, "remove worked");
+};
+
+exports["test site authentication credentials"] = function(assert) {
+ let options = {
+ url: "http://test.authentication.com",
+ username: "u",
+ password: "p",
+ realm: "r"
+ };
+
+ store(options);
+ assert.ok(search().length, "credential was stored");
+ assert.ok(search(options).length, "stored credential found");
+ assert.ok(search({ username: options.username }).length, "found by username");
+ assert.ok(search({ password: options.password }).length, "found by password");
+ assert.ok(search({ realm: options.realm }).length, "found by realm");
+ assert.ok(search({ url: options.url }).length, "found by url");
+
+ let credential = search(options)[0];
+ assert.equal(credential.url, options.url, "url matches");
+ assert.equal(credential.username, options.username, "username matches");
+ assert.equal(credential.password, options.password, "password matches");
+ assert.equal(credential.realm, options.realm, "realm matches");
+ assert.equal(credential.formSubmitURL, null,
+ "`formSubmitURL` is `null` for site authentication credentials");
+ assert.equal(credential.usernameField, "", "usernameField is empty");
+ assert.equal(credential.passwordField, "", "passwordField is empty");
+
+ remove(search(options)[0]);
+ assert.ok(!search(options).length, "remove worked");
+};
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-plain-text-console.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-plain-text-console.js
new file mode 100644
index 0000000..a0c9dda
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-plain-text-console.js
@@ -0,0 +1,64 @@
+exports.testPlainTextConsole = function(test) {
+ var prints = [];
+ function print(message) {
+ prints.push(message);
+ }
+ function lastPrint() {
+ var last = prints.slice(-1)[0];
+ prints = [];
+ return last;
+ }
+
+ var Console = require("plain-text-console").PlainTextConsole;
+ var con = new Console(print);
+
+ test.pass("PlainTextConsole instantiates");
+
+ con.log('testing', 1, [2, 3, 4]);
+ test.assertEqual(lastPrint(), "info: testing 1 2,3,4\n",
+ "PlainTextConsole.log() must work.");
+
+ con.info('testing', 1, [2, 3, 4]);
+ test.assertEqual(lastPrint(), "info: testing 1 2,3,4\n",
+ "PlainTextConsole.info() must work.");
+
+ con.warn('testing', 1, [2, 3, 4]);
+ test.assertEqual(lastPrint(), "warning: testing 1 2,3,4\n",
+ "PlainTextConsole.warn() must work.");
+
+ con.error('testing', 1, [2, 3, 4]);
+ test.assertEqual(lastPrint(), "error: testing 1 2,3,4\n",
+ "PlainTextConsole.error() must work.");
+
+ con.debug('testing', 1, [2, 3, 4]);
+ test.assertEqual(lastPrint(), "debug: testing 1 2,3,4\n",
+ "PlainTextConsole.debug() must work.");
+
+ con.log('testing', undefined);
+ test.assertEqual(lastPrint(), "info: testing undefined\n",
+ "PlainTextConsole.log() must stringify undefined.");
+
+ con.log('testing', null);
+ test.assertEqual(lastPrint(), "info: testing null\n",
+ "PlainTextConsole.log() must stringify null.");
+
+ con.log("testing", { toString: function() "obj.toString()" });
+ test.assertEqual(lastPrint(), "info: testing obj.toString()\n",
+ "PlainTextConsole.log() must stringify custom toString.");
+
+ con.log("testing", { toString: function() { throw "fail!"; } });
+ test.assertEqual(lastPrint(), "info: testing <toString() error>\n",
+ "PlainTextConsole.log() must stringify custom bad toString.");
+
+ con.exception(new Error("blah"));
+ var tbLines = prints[0].split("\n");
+ test.assertEqual(tbLines[0], "error: An exception occurred.");
+ test.assertEqual(tbLines[1], "Traceback (most recent call last):");
+ test.assertEqual(tbLines.slice(-2)[0], "Error: blah");
+
+ prints = [];
+ con.trace();
+ tbLines = prints[0].split("\n");
+ test.assertEqual(tbLines[0], "info: Traceback (most recent call last):");
+ test.assertEqual(tbLines.slice(-2)[0].trim(), "con.trace();");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-preferences-service.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-preferences-service.js
new file mode 100644
index 0000000..dd0de38
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-preferences-service.js
@@ -0,0 +1,87 @@
+var prefs = require("preferences-service");
+var {Cc,Ci} = require("chrome");
+
+exports.testReset = function(test) {
+ prefs.reset("test_reset_pref");
+ test.assertEqual(prefs.has("test_reset_pref"), false);
+ test.assertEqual(prefs.isSet("test_reset_pref"), false);
+ prefs.set("test_reset_pref", 5);
+ test.assertEqual(prefs.has("test_reset_pref"), true);
+ test.assertEqual(prefs.isSet("test_reset_pref"), true);
+};
+
+exports.testGetAndSet = function(test) {
+ let svc = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefService).
+ getBranch(null);
+ svc.setCharPref("test_get_string_pref", "a normal string");
+ test.assertEqual(prefs.get("test_get_string_pref"), "a normal string",
+ "preferences-service should read from " +
+ "application-wide preferences service");
+
+ prefs.set("test_set_get_pref.integer", 1);
+ test.assertEqual(prefs.get("test_set_get_pref.integer"), 1,
+ "set/get integer preference should work");
+
+ prefs.set("test_set_get_number_pref", 42);
+ test.assertRaises(
+ function() { prefs.set("test_set_get_number_pref", 3.14159); },
+ "cannot store non-integer number: 3.14159",
+ "setting a float preference should raise an error"
+ );
+ test.assertEqual(prefs.get("test_set_get_number_pref"), 42,
+ "bad-type write attempt should not overwrite");
+
+ // 0x80000000 (no), 0x7fffffff (yes), -0x80000000 (yes), -0x80000001 (no)
+ test.assertRaises(
+ function() { prefs.set("test_set_get_number_pref", Math.pow(2, 31)); },
+ ("you cannot set the test_set_get_number_pref pref to the number " +
+ "2147483648, as number pref values must be in the signed 32-bit " +
+ "integer range -(2^31) to 2^31-1. To store numbers outside that " +
+ "range, store them as strings."),
+ "setting an int pref outside the range -(2^31) to 2^31-1 shouldn't work"
+ );
+ test.assertEqual(prefs.get("test_set_get_number_pref"), 42,
+ "out-of-range write attempt should not overwrite 1");
+ prefs.set("test_set_get_number_pref", Math.pow(2, 31)-1);
+ test.assertEqual(prefs.get("test_set_get_number_pref"), 0x7fffffff,
+ "in-range write attempt should work 1");
+ prefs.set("test_set_get_number_pref", -Math.pow(2, 31));
+ test.assertEqual(prefs.get("test_set_get_number_pref"), -0x80000000,
+ "in-range write attempt should work 2");
+ test.assertRaises(
+ function() { prefs.set("test_set_get_number_pref", -0x80000001); },
+ ("you cannot set the test_set_get_number_pref pref to the number " +
+ "-2147483649, as number pref values must be in the signed 32-bit " +
+ "integer range -(2^31) to 2^31-1. To store numbers outside that " +
+ "range, store them as strings."),
+ "setting an int pref outside the range -(2^31) to 2^31-1 shouldn't work"
+ );
+ test.assertEqual(prefs.get("test_set_get_number_pref"), -0x80000000,
+ "out-of-range write attempt should not overwrite 2");
+
+
+ prefs.set("test_set_get_pref.string", "foo");
+ test.assertEqual(prefs.get("test_set_get_pref.string"), "foo",
+ "set/get string preference should work");
+
+ prefs.set("test_set_get_pref.boolean", true);
+ test.assertEqual(prefs.get("test_set_get_pref.boolean"), true,
+ "set/get boolean preference should work");
+
+ prefs.set("test_set_get_unicode_pref", String.fromCharCode(960));
+ test.assertEqual(prefs.get("test_set_get_unicode_pref"),
+ String.fromCharCode(960),
+ "set/get unicode preference should work");
+
+ var unsupportedValues = [null, [], undefined];
+ unsupportedValues.forEach(
+ function(value) {
+ test.assertRaises(
+ function() { prefs.set("test_set_pref", value); },
+ ("can't set pref test_set_pref to value '" + value + "'; " +
+ "it isn't a string, integer, or boolean"),
+ "Setting a pref to " + uneval(value) + " should raise error"
+ );
+ });
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-registry.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-registry.js
new file mode 100644
index 0000000..8a251f7
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-registry.js
@@ -0,0 +1,76 @@
+'use strict';
+
+exports['test:add'] = function(test) {
+ function Class() {}
+ let fixture = require('utils/registry').Registry(Class);
+ let isAddEmitted = false;
+ fixture.on('add', function(item) {
+ test.assert(
+ item instanceof Class,
+ 'if object added is not an instance should construct instance from it'
+ );
+ test.assert(
+ fixture.has(item),
+ 'callback is called after instance is added'
+ );
+ test.assert(
+ !isAddEmitted,
+ 'callback should be called for the same item only once'
+ );
+ isAddEmitted = true;
+ });
+
+ let object = fixture.add({});
+ fixture.add(object);
+};
+
+exports['test:remove'] = function(test) {
+ function Class() {}
+ let fixture = require('utils/registry').Registry(Class);
+ fixture.on('remove', function(item) {
+ test.assert(
+ item instanceof Class,
+ 'if object removed can be only instance of Class'
+ );
+ test.assert(
+ fixture.has(item),
+ 'callback is called before instance is removed'
+ );
+ test.assert(
+ !isRemoveEmitted,
+ 'callback should be called for the same item only once'
+ );
+ isRemoveEmitted = true;
+ });
+
+ fixture.remove({});
+ let object = fixture.add({});
+ fixture.remove(object);
+ fixture.remove(object);
+};
+
+exports['test:items'] = function(test) {
+ function Class() {}
+ let fixture = require('utils/registry').Registry(Class),
+ actual,
+ times = 0;
+
+ function testItem(item) {
+ times ++;
+ test.assertEqual(
+ actual,
+ item,
+ 'item should match actual item being added/removed'
+ );
+ }
+
+ actual = fixture.add({});
+
+ fixture.on('add', testItem);
+ fixture.on('remove', testItem);
+
+ fixture.remove(actual);
+ fixture.remove(fixture.add(actual = new Class()));
+ test.assertEqual(3, times, 'should notify listeners on each call');
+}
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-require.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-require.js
new file mode 100644
index 0000000..35c613d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-require.js
@@ -0,0 +1,25 @@
+const traceback = require("traceback");
+
+exports.test_no_args = function(test) {
+ var passed = false;
+ try {
+ var oops = require(); // leave this on line 6!
+ } catch(e) {
+ let msg = e.toString();
+ test.assertEqual(msg.indexOf("Error: you must provide a module name when calling require() from "), 0);
+ test.assertNotEqual(msg.indexOf("test-require.js"), -1, msg);
+ // we'd also like to assert that the right filename and linenumber is in
+ // the stack trace, but this currently doesn't work (see bugs 679591 and
+ // 551604)
+ if (0) {
+ let tb = traceback.fromException(e);
+ let lastFrame = tb[tb.length-1];
+ test.assertNotEqual(lastFrame.filename.indexOf("test-require.js"), -1,
+ lastFrame.filename);
+ test.assertEqual(lastFrame.lineNo, 6);
+ test.assertEqual(lastFrame.funcName, "??");
+ }
+ passed = true;
+ }
+ test.assert(passed, 'require() with no args should raise helpful error');
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-securable-module.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-securable-module.js
new file mode 100644
index 0000000..c9c952a
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-securable-module.js
@@ -0,0 +1,382 @@
+const {Cc,Ci,Cu} = require("chrome");
+
+const COMPONENTS_DOT_CLASSES = "Com" + "ponents.classes";
+
+var beetFs = {
+ resolveModule: function(root, path) {
+ if (path == "beets")
+ return path;
+ },
+ getFile: function(path) {
+ return {contents: ('print("hi from ' + path + '");' +
+ ' exports.beets = 5;')};
+ }
+};
+
+function FakeCompositeFileSystem(fses) {
+ this.fses = fses;
+ this._pathMap = {};
+};
+
+FakeCompositeFileSystem.prototype = {
+ resolveModule: function resolveModule(base, path) {
+ for (var i = 0; i < this.fses.length; i++) {
+ var fs = this.fses[i];
+ var absPath = fs.resolveModule(base, path);
+ if (absPath) {
+ this._pathMap[absPath] = fs;
+ return absPath;
+ }
+ }
+ return null;
+ },
+ getFile: function getFile(path) {
+ return this._pathMap[path].getFile(path);
+ }
+};
+
+
+(function(global) {
+ var exports = new Object();
+
+ var ios = Cc['@mozilla.org/network/io-service;1']
+ .getService(Ci.nsIIOService);
+
+ exports.testSecurableModule = function(test) {
+ // The tests in this file weren't originally written for
+ // Cuddlefish. This function is essentially an adapter
+ // that runs the tests using the Cuddlefish testing
+ // framework.
+ function log(msg, type) {
+ switch (type) {
+ case "fail":
+ test.fail(msg);
+ break;
+ case "pass":
+ test.pass(msg);
+ break;
+ case "info":
+ console.info(msg);
+ }
+ }
+ var assert = {
+ pass: function(msg) {
+ test.pass(msg);
+ },
+ isEqual: function(a, b, msg) {
+ test.assertEqual(a, b, msg);
+ }
+ };
+
+ var url = require("url");
+ var path = url.URL("interoperablejs-read-only/compliance/",
+ __url__).toString();
+ path = url.toFilename(path);
+
+ var file = Cc['@mozilla.org/file/local;1']
+ .createInstance(Ci.nsILocalFile);
+ file.initWithPath(path);
+
+ run(require("securable-module"),
+ log,
+ assert,
+ file);
+ };
+
+ function run(SecurableModule, log, assert, rootDir) {
+ // Basic test of module loading with a fake fs.
+ var output = [];
+
+ function outPrint(msg) { output.push(msg); }
+
+ var loader = new SecurableModule.Loader({fs: beetFs,
+ globals: {print: outPrint},
+ uriPrefix: "resource://bogus-"});
+ var extraOutput = {};
+ loader.runScript({contents: 'print("beets is " + ' +
+ 'require("beets").beets);'}, extraOutput);
+ assert.isEqual(output[0], 'hi from beets', 'module should load');
+ assert.isEqual(output[1], 'beets is 5', 'module should export');
+ var printSrc = extraOutput.sandbox.getProperty('print');
+ if (printSrc == "function outPrint() {\n [native code]\n}")
+ assert.pass('extraOutput.sandbox should work');
+ else
+ assert.isEqual(printSrc,
+ outPrint,
+ 'extraOutput.sandbox should work');
+
+ var neatFs = {
+ resolveModule: function(root, path) {
+ if (path == "neat")
+ return path;
+ },
+ getFile: function(path) {
+ return {contents: ('require("beets");' +
+ 'print("hi from ' + path + '");' +
+ 'exports.neat = "yo";')};
+ }
+ };
+
+ loader = new SecurableModule.Loader(
+ {fs: new FakeCompositeFileSystem([beetFs, neatFs]),
+ globals: {print: outPrint},
+ uriPrefix: "resource://bogus-"
+ });
+ output = [];
+ loader.runScript({contents: 'print("neat is " + ' +
+ 'require("neat").neat);'});
+ assert.isEqual(output[0], 'hi from beets',
+ 'submodule from composite fs should load');
+ assert.isEqual(output[1], 'hi from neat',
+ 'module from composite fs should load');
+ assert.isEqual(output[2], 'neat is yo',
+ 'module from composite fs should export');
+
+ // Ensure parenting of anonymous script filenames works.
+ loader = new SecurableModule.Loader({fs: {},
+ uriPrefix: "resource://bogus-"});
+ try {
+ loader.runScript('throw new Error();');
+ log("errors must be propogated from content sandboxes", "fail");
+ } catch (e) {
+ assert.isEqual(e.fileName, '<string>',
+ ('anonymous scripts w/o chrome privs should be ' +
+ 'unparented'));
+ }
+
+ loader = new SecurableModule.Loader({fs: {},
+ defaultPrincipal: "system",
+ uriPrefix: "resource://bogus-"});
+ try {
+ loader.runScript('throw new Error();');
+ log("errors must be propogated from chrome sandboxes", "fail");
+ } catch (e) {
+ assert.isEqual(e.fileName.slice(-11), '-> <string>',
+ ('anonymous scripts w/ chrome privs should be ' +
+ 'parented'));
+ }
+
+ // Ensure loading nonexistent modules raises an error.
+ loader = new SecurableModule.Loader(
+ {fs: {
+ resolveModule: function() { return null; },
+ getFile: function(path) {
+ throw new Error('I should never get called.');
+ }
+ },
+ uriPrefix: "resource://bogus-"
+ });
+ try {
+ loader.runScript({contents: 'require("foo");'});
+ log("loading of nonexistent module did not raise exception",
+ "fail");
+ } catch (e) {
+ assert.isEqual(e.message, 'Module "foo" not found',
+ 'loading of nonexistent module should raise error');
+ }
+
+ loader = new SecurableModule.Loader({fs: {},
+ uriPrefix: "resource://bogus-"});
+ try {
+ loader.runScript({contents: COMPONENTS_DOT_CLASSES});
+ log("modules shouldn't have chrome privileges by default.",
+ "fail");
+ } catch (e) {
+ // The error message that gets thrown is localized, so we must compare
+ // it to the localized version. This should be as simple as retrieving
+ // that version from its string bundle, but the error message is also
+ // corrupted (its characters' high bytes thrown away due to bug 567597),
+ // so we have to do the same to the version to which we compare it.
+ let bundle =
+ require("app-strings").
+ StringBundle("chrome://global/locale/security/caps.properties");
+ let message = bundle.get("GetPropertyDeniedOriginsOnlySubject",
+ ["http://www.mozilla.org", "XPCComponents",
+ "classes"]).
+ split("").
+ map(function(v) v.charCodeAt(0)).
+ map(function(v) v % 256).
+ map(function(v) String.fromCharCode(v)).
+ join("");
+
+ assert.isEqual(e.message, message,
+ "modules shouldn't have chrome privileges by default.");
+ }
+
+ loader = new SecurableModule.Loader(
+ {fs: {},
+ defaultPrincipal: "system",
+ uriPrefix: "resource://bogus-"
+ });
+ loader.runScript({contents: COMPONENTS_DOT_CLASSES});
+ log("modules should be able to have chrome privileges.", "pass");
+
+ // Test the way LocalFileSystem infers root directories.
+ var fs = new SecurableModule.LocalFileSystem(rootDir);
+ assert.isEqual(fs._rootURIDir, ios.newFileURI(rootDir).spec,
+ "fs rootdir should be same as passed-in dir");
+
+ var someFile = rootDir.clone();
+ someFile.append("ORACLE");
+ fs = new SecurableModule.LocalFileSystem(someFile);
+ assert.isEqual(fs._rootURIDir, ios.newFileURI(rootDir).spec,
+ "fs rootdir sould be dirname of file");
+
+ someFile = rootDir.clone();
+ someFile.append("monkeys");
+ fs = new SecurableModule.LocalFileSystem(someFile);
+ assert.isEqual(fs._rootURIDir, ios.newFileURI(someFile).spec,
+ "fs rootdir should be same as passed-in subdir");
+
+ if (SecurableModule.baseURI) {
+ // Note that a '/' must be put after the directory name.
+ var newURI = ios.newURI('lib/', null, SecurableModule.baseURI);
+ fs = new SecurableModule.LocalFileSystem(newURI);
+ assert.isEqual(fs._rootURIDir, newURI.spec,
+ "fs rootdir should be subdir of document's dir");
+
+ loader = new SecurableModule.Loader();
+ assert.isEqual(loader._fs._rootURI.spec, SecurableModule.baseURI.spec,
+ "fs rootdir should be document's dir");
+ } else {
+ try {
+ loader = new SecurableModule.Loader();
+ log("Loader() w/ no params in a non-document context should " +
+ "raise an exception.", "fail");
+ } catch (e if e.message == "Need a root path for module filesystem") {
+ log("Loader() w/ no params in a non-document context should " +
+ "raise an exception.", "pass");
+ }
+ }
+
+ // Run all CommonJS SecurableModule compliance tests.
+ var testDirs = [];
+ var enumer = rootDir.directoryEntries;
+ while (enumer.hasMoreElements()) {
+ var testDir = enumer.getNext().QueryInterface(Ci.nsIFile);
+ if (testDir.isDirectory() &&
+ testDir.leafName.charAt(0) != '.')
+ testDirs.push(testDir);
+ }
+
+ for (var i = 0; i < testDirs.length; i++) {
+ var testDir = testDirs[i];
+ log("running compliance test '" + testDir.leafName + "'", "info");
+ loader = new SecurableModule.Loader(
+ {rootPath: testDir,
+ defaultPrincipal: "system",
+ globals: {sys: {print: log}},
+ uriPrefix: "resource://bogus-"
+ });
+ loader.require("program");
+ }
+
+ // Confirm callback-based require works from an instantiated loader.
+ // want to be back in api-utils/tests directory instead of
+ // what rootDir is now:
+ // api-utils/tests/interoperablejs-read-only/compliance/
+ var moduleDir = rootDir.parent.parent;
+ moduleDir.append("modules"),
+ loader = new SecurableModule.Loader(
+ {rootPath: moduleDir,
+ defaultPrincipal: "system",
+ globals: {sys: {print: log}},
+ uriPrefix: "resource://bogus-"
+ });
+
+ loader.require(["subtract"], function (subtract) {
+ assert.isEqual(2, subtract(3, 1),
+ "subtract module works with callback-style require");
+ });
+
+ };
+
+ if (global.window) {
+ // We're being loaded in a chrome window, or a web page with
+ // UniversalXPConnect privileges.
+ global.SecurableModuleTests = exports;
+ } else if (global.exports) {
+ // We're being loaded in a SecurableModule.
+ for (let name in exports) {
+ global.exports[name] = exports[name];
+ }
+ } else {
+ // We're being loaded in a JS module.
+ global.EXPORTED_SYMBOLS = [];
+ for (let name in exports) {
+ global.EXPORTED_SYMBOLS.push(name);
+ global[name] = exports[name];
+ }
+ }
+ })(this);
+
+exports.testFindSandboxForModule = function(test) {
+ var fs = {
+ resolveModule: function(base, path) {
+ test.assertEqual(base, null);
+ test.assertEqual(path, "foo");
+ return "/blarg/foo";
+ },
+ getFile: function(path) {
+ test.assertEqual(path, "/blarg/foo");
+ return {contents: "var baz = 1;"};
+ }
+ };
+
+ var sm = require("securable-module");
+ var loader = new sm.Loader({fs: fs});
+ var sandbox = loader.findSandboxForModule("foo");
+ test.assertEqual(sandbox.globalScope.baz, 1);
+};
+
+exports.testUtf8 = function (test) {
+ // This test ensures that the securable module loader assumes files are
+ // UTF-8-encoded and therefore decodes them properly when it reads them.
+ var str = "文字";
+
+ // Read this file into readStr, decoding from UTF-8.
+ var filename = require("url").toFilename(__url__);
+ var readStr = require("file").read(filename);
+
+ // If str is not in readStr, then str and therefore this file were not decoded
+ // from UTF-8 by the loader.
+ test.assert(readStr.indexOf(str) >= 0, "Loader should treat files as UTF-8");
+};
+
+exports.testGetModuleExports = function (test) {
+ var sm = require("securable-module");
+
+ function myGetModuleExports(basePath, module) {
+ if (module == "foo")
+ return {bar: 1};
+ return null;
+ }
+
+ var loader = new sm.Loader({getModuleExports: myGetModuleExports,
+ fs: beetFs,
+ globals: {print: function() {}}});
+
+ test.assertEqual(loader.require("foo").bar, 1,
+ "getModuleExports() works");
+ test.assertEqual(loader.require("beets").beets, 5,
+ "loader falls through to fs when getModuleExports() " +
+ "returns null");
+};
+
+exports.testModifyModuleSandbox = function (test) {
+ var sm = require("securable-module");
+ var out;
+
+ function modifyModuleSandbox(sandbox, options) {
+ sandbox.defineProperty("print", function() { out = options.contents; });
+ }
+
+ var loader = new sm.Loader({modifyModuleSandbox: modifyModuleSandbox,
+ globals: {print: function() {}},
+ fs: beetFs});
+
+ loader.require("beets");
+ test.assertEqual(out,
+ "print(\"hi from beets\"); exports.beets = 5;",
+ "testModifyModuleSandbox() mods override globals");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-self.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-self.js
new file mode 100644
index 0000000..6608862
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-self.js
@@ -0,0 +1,34 @@
+exports.testSelf = function(test) {
+ var self = require("self");
+ // We can't assert anything about the ID inside the unit test right now,
+ // because the ID we get depends upon how the test was invoked. The idea
+ // is that it is supposed to come from the main top-level package's
+ // package.json file, from the "id" key.
+ test.assertEqual(typeof(self.id), "string", "self.id is a string");
+ test.assert(self.id.length > 0);
+
+ var source = self.data.load("bootstrap-remote-process.js");
+ test.assert(source.match(/registerReceiver/), "self.data.load() works");
+
+ // Likewise, we can't assert anything about the full URL, because that
+ // depends on self.id . We can only assert that it ends in the right
+ // thing.
+ var url = self.data.url("bootstrap-remote-process.js");
+ test.assertEqual(typeof(url), "string", "self.data.url('x') returns string");
+ test.assertEqual(/\/bootstrap-remote-process\.js$/.test(url), true);
+
+ // Make sure 'undefined' is not in url when no string is provided.
+ url = self.data.url();
+ test.assertEqual(typeof(url), "string", "self.data.url() returns string");
+ test.assertEqual(/\/undefined$/.test(url), false);
+
+ // When tests are run on just the api-utils package, self.name is
+ // api-utils and the version is whatever packages/api-utils/package.json
+ // contains (usually the same as the overall SDK version, but let's not
+ // enforce that). When they're run as 'cfx testall', self.name is testpkgs,
+ // and the version is "fake" because python-lib/cuddlefish/__init__.py
+ // makes a fake package.json Bunch in test_all_packages().
+ test.assert((self.name == "api-utils") || (self.name == "testpkgs"),
+ "self.name is api-utils or testpkgs");
+ test.assertEqual(typeof(self.version), "string", "self.version exists");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-set-exports.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-set-exports.js
new file mode 100644
index 0000000..dd856c8
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-set-exports.js
@@ -0,0 +1,28 @@
+let four = require("modules/exportsEquals");
+exports.testExportsEquals = function(test) {
+ test.assertEqual(four, 4);
+}
+
+let five = require("modules/setExports");
+exports.testSetExports = function(test) {
+ test.assertEqual(five, 5);
+}
+
+exports.testDupeSetExports = function(test) {
+ var passed = false;
+ try {
+ var dupe = require('modules/dupeSetExports');
+ } catch(e) {
+ passed = /define\(\) was used, so module\.exports= and module\.setExports\(\) may not be used/.test(e.toString());
+ }
+ test.assertEqual(passed, true, 'define() or setExports(), not both');
+}
+
+exports.testModule = function(test) {
+ // module.id is not cast in stone yet. In the future, it may include the
+ // package name, or may possibly be a/ URL of some sort. For now, it's a
+ // URL that starts with resource: and ends with this module name, but the
+ // part in between varies depending upon how the test is run.
+ var found = /test-set-exports\.js$/.test(module.id);
+ test.assertEqual(found, true, module.id+" ends with test-set-exports.js");
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-browser.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-browser.js
new file mode 100644
index 0000000..d6bf6f5
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-browser.js
@@ -0,0 +1,525 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var timer = require("timer");
+var {Cc,Ci} = require("chrome");
+
+function onBrowserLoad(callback, event) {
+ if (event.target && event.target.defaultView == this) {
+ this.removeEventListener("load", onBrowserLoad, true);
+ let browsers = this.document.getElementsByTagName("tabbrowser");
+ try {
+ require("timer").setTimeout(function (window) {
+ callback(window, browsers[0]);
+ }, 10, this);
+ } catch (e) { console.exception(e); }
+ }
+}
+// Utility function to open a new browser window.
+function openBrowserWindow(callback, url) {
+ let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher);
+ let urlString = Cc["@mozilla.org/supports-string;1"].
+ createInstance(Ci.nsISupportsString);
+ urlString.data = url;
+ let window = ww.openWindow(null, "chrome://browser/content/browser.xul",
+ "_blank", "chrome,all,dialog=no", urlString);
+ if (callback)
+ window.addEventListener("load", onBrowserLoad.bind(window, callback), true);
+
+ return window;
+}
+
+// Helper for calling code at window close
+function closeBrowserWindow(window, callback) {
+ require("timer").setTimeout(function() {
+ window.addEventListener("unload", function onUnload() {
+ window.removeEventListener("unload", onUnload, false);
+ callback();
+ }, false);
+ window.close();
+ }, 0);
+}
+
+// Helper for opening two windows at once
+function openTwoWindows(callback) {
+ openBrowserWindow(function (window1) {
+ openBrowserWindow(function (window2) {
+ callback(window1, window2);
+ });
+ });
+}
+
+// Helper for closing two windows at once
+function closeTwoWindows(window1, window2, callback) {
+ closeBrowserWindow(window1, function() {
+ closeBrowserWindow(window2, callback);
+ });
+}
+
+exports.testAddTab = function(test) {
+ test.waitUntilDone();
+ openBrowserWindow(function(window, browser) {
+ const tabBrowser = require("tab-browser");
+
+ let cache = [];
+ let windowUtils = require("window-utils");
+ new windowUtils.WindowTracker({
+ onTrack: function(win) {
+ cache.push(win);
+ },
+ onUntrack: function(win) {
+ cache.splice(cache.indexOf(win), 1)
+ }
+ });
+ let startWindowCount = cache.length;
+
+ // Test 1: add a tab
+ let firstUrl = "data:text/html,one";
+ tabBrowser.addTab(firstUrl, {
+ onLoad: function(e) {
+ let win1 = cache[startWindowCount - 1];
+ test.assertEqual(win1.content.location, firstUrl, "URL of new tab in first window matches");
+
+ // Test 2: add a tab in a new window
+ let secondUrl = "data:text/html,two";
+ tabBrowser.addTab(secondUrl, {
+ inNewWindow: true,
+ onLoad: function(e) {
+ test.assertEqual(cache.length, startWindowCount + 1, "a new window was opened");
+ let win2 = cache[startWindowCount];
+ let gBrowser = win2.gBrowser;
+ gBrowser.addEventListener("DOMContentLoaded", function onLoad(e) {
+ gBrowser.removeEventListener("DOMContentLoaded", onLoad, false);
+ test.assertEqual(win2.content.location, secondUrl, "URL of new tab in the new window matches");
+
+ closeBrowserWindow(win2, function() {
+ closeBrowserWindow(win1, function() {
+ test.done();
+ });
+ });
+ }, false);
+ }
+ });
+ }
+ });
+ });
+};
+
+exports.testTrackerWithDelegate = function(test) {
+ test.waitUntilDone();
+ const tabBrowser = require("tab-browser");
+
+ var delegate = {
+ state: "initializing",
+ onTrack: function onTrack(browser) {
+ if (this.state == "initializing") {
+ this.state = "waiting for browser window to open";
+ }
+ else if (this.state == "waiting for browser window to open") {
+ this.state = "waiting for browser window to close";
+ require("timer").setTimeout(function() {
+ closeBrowserWindow(browser.ownerDocument.defaultView, function() {
+ test.assertEqual(delegate.state, "deinitializing");
+ tb.unload();
+ test.done();
+ });
+ }, 0);
+ }
+ else
+ test.fail("invalid state");
+ },
+ onUntrack: function onUntrack(browser) {
+ if (this.state == "waiting for browser window to close") {
+ test.pass("proper state in onUntrack");
+ this.state = "deinitializing";
+ }
+ else if (this.state != "deinitializing")
+ test.fail("invalid state");
+ }
+ };
+ var tb = new tabBrowser.Tracker(delegate);
+
+ delegate.state = "waiting for browser window to open";
+
+ openBrowserWindow();
+};
+
+exports.testWhenContentLoaded = function(test) {
+ test.waitUntilDone();
+ const tabBrowser = require("tab-browser");
+
+ var tracker = tabBrowser.whenContentLoaded(
+ function(window) {
+ var item = window.document.getElementById("foo");
+ test.assertEqual(item.textContent, "bar",
+ "whenContentLoaded() works.");
+ tracker.unload();
+ closeBrowserWindow(activeWindow, function() {
+ test.done();
+ });
+ });
+
+ openBrowserWindow(function(browserWindow, browser) {
+ var html = '<div id="foo">bar</div>';
+ browser.addTab("data:text/html," + html);
+ });
+};
+
+exports.testTrackerWithoutDelegate = function(test) {
+ test.waitUntilDone();
+ const tabBrowser = require("tab-browser");
+
+ openBrowserWindow(function(browserWindow, browser) {
+ var tb = new tabBrowser.Tracker();
+
+ if (tb.length == 0)
+ test.fail("expect at least one tab browser to exist.");
+
+ for (var i = 0; i < tb.length; i++)
+ test.assertEqual(tb.get(i).nodeName, "tabbrowser",
+ "get() method and length prop should work");
+ for (var b in tb)
+ test.assertEqual(b.nodeName, "tabbrowser",
+ "iterator should work");
+
+ var matches = [b for (b in tb)
+ if (b == browser)];
+ test.assertEqual(matches.length, 1,
+ "New browser should be in tracker.");
+ tb.unload();
+
+ closeBrowserWindow(browserWindow, function() {
+ test.done();
+ });
+ });
+};
+
+exports.testTabTracker = function(test) {
+ test.waitUntilDone();
+ const tabBrowser = require("tab-browser");
+
+ openBrowserWindow(function(browserWindow, browser) {
+ var delegate = {
+ tracked: 0,
+ onTrack: function(tab) {
+ this.tracked++;
+ },
+ onUntrack: function(tab) {
+ this.tracked--;
+ }
+ };
+
+ let tabTracker = tabBrowser.TabTracker(delegate);
+
+ let tracked = delegate.tracked;
+ let url1 = "data:text/html,1";
+ let url2 = "data:text/html,2";
+ let url3 = "data:text/html,3";
+ let tabCount = 0;
+
+ function tabLoadListener(e) {
+ let loadedURL = e.target.defaultView.location;
+ if (loadedURL == url1)
+ tabCount++;
+ else if (loadedURL == url2)
+ tabCount++;
+ else if (loadedURL == url3)
+ tabCount++;
+
+ if (tabCount == 3) {
+ test.assertEqual(delegate.tracked, tracked + 3, "delegate tracked tabs matched count");
+ tabTracker.unload();
+ closeBrowserWindow(browserWindow, function() {
+ require("timer").setTimeout(function() test.done(), 0);
+ });
+ }
+ }
+
+ tabBrowser.addTab(url1, {
+ onLoad: tabLoadListener
+ });
+ tabBrowser.addTab(url2, {
+ onLoad: tabLoadListener
+ });
+ tabBrowser.addTab(url3, {
+ onLoad: tabLoadListener
+ });
+ });
+};
+
+exports.testActiveTab = function(test) {
+ test.waitUntilDone();
+ openBrowserWindow(function(browserWindow, browser) {
+ const tabBrowser = require("tab-browser");
+ const TabModule = require("tab-browser").TabModule;
+ let tm = new TabModule(browserWindow);
+ test.assertEqual(tm.length, 1);
+ let url1 = "data:text/html,foo";
+ let url2 = "data:text/html,bar";
+
+ function tabURL(tab) tab.ownerDocument.defaultView.content.location.toString()
+
+ tabBrowser.addTab(url1, {
+ onLoad: function(e) {
+ // make sure we're running in the right window.
+ test.assertEqual(tabBrowser.activeTab.ownerDocument.defaultView, browserWindow, "active window matches");
+ browserWindow.focus();
+
+ test.assertEqual(tabURL(tabBrowser.activeTab), url1, "url1 matches");
+ let tabIndex = browser.getBrowserIndexForDocument(e.target);
+ let tabAtIndex = browser.tabContainer.getItemAtIndex(tabIndex);
+ test.assertEqual(tabAtIndex, tabBrowser.activeTab, "activeTab element matches");
+
+ tabBrowser.addTab(url2, {
+ inBackground: true,
+ onLoad: function() {
+ test.assertEqual(tabURL(tabBrowser.activeTab), url1, "url1 still matches");
+ let tabAtIndex = browser.tabContainer.getItemAtIndex(tabIndex);
+ test.assertEqual(tabAtIndex, tabBrowser.activeTab, "activeTab element matches");
+ closeBrowserWindow(browserWindow, function() {
+ test.done()
+ });
+ }
+ });
+ }
+ });
+ });
+};
+
+// TabModule tests
+exports.testEventsAndLengthStayInModule = function(test) {
+ test.waitUntilDone();
+ let TabModule = require("tab-browser").TabModule;
+
+ openTwoWindows(function(window1, window2) {
+ let tm1 = new TabModule(window1);
+ let tm2 = new TabModule(window2);
+
+ let counter1 = 0, counter2 = 0;
+ let counterTabs = 0;
+
+ function onOpenListener() {
+ ++counterTabs;
+ if (counterTabs < 5)
+ return;
+ test.assertEqual(counter1, 2, "Correct number of events fired from window 1");
+ test.assertEqual(counter2, 3, "Correct number of events fired from window 2");
+ test.assertEqual(counterTabs, 5, "Correct number of events fired from all windows");
+ test.assertEqual(tm1.length, 3, "Correct number of tabs in window 1");
+ test.assertEqual(tm2.length, 4, "Correct number of tabs in window 2");
+ closeTwoWindows(window1, window2, function() test.done());
+ }
+
+ tm1.onOpen = function() ++counter1 && onOpenListener();
+ tm2.onOpen = function() ++counter2 && onOpenListener();
+
+ let url = "data:text/html,default";
+ tm1.open(url);
+ tm1.open(url);
+
+ tm2.open(url);
+ tm2.open(url);
+ tm2.open(url);
+ });
+}
+
+exports.testTabModuleActiveTab_getterAndSetter = function(test) {
+ test.waitUntilDone();
+ let TabModule = require("tab-browser").TabModule;
+
+ openTwoWindows(function(window1, window2) {
+ let tm1 = new TabModule(window1);
+ let tm2 = new TabModule(window2);
+
+ let tab1 = null;
+ tm1.open({
+ url: "data:text/html,<title>window1,tab1</title>",
+ onOpen: function(tab) tab1 = tab,
+ });
+ tm1.open("data:text/html,<title>window1,tab2</title>");
+
+ tm1.onActivate = function onActivate() {
+ tm1.onActivate.remove(onActivate);
+ require("timer").setTimeout(function() {
+ test.assertEqual(tm1.activeTab.title, "window1,tab1", "activeTab setter works");
+ closeTwoWindows(window1, window2, function() test.done());
+ }, 1000);
+ }
+
+ tm2.open("data:text/html,<title>window2,tab1</title>");
+ tm2.open({
+ url: "data:text/html,<title>window2,tab2</title>",
+ onOpen: function(tab4) {
+ test.assertEqual(tm1.activeTab.title, "window1,tab2", "Correct active tab on window 1");
+ test.assertEqual(tm2.activeTab.title, "window2,tab2", "Correct active tab on window 2");
+
+ tm1.activeTab = tab1;
+ tm1.activeTab = tab4; // Setting activeTab from another window should have no effect
+ }
+ });
+ });
+}
+
+// test tabs iterator
+exports.testTabModuleTabsIterator = function(test) {
+ test.waitUntilDone();
+ let TabModule = require("tab-browser").TabModule;
+
+ openBrowserWindow(function(window) {
+ let tm1 = new TabModule(window);
+ let url = "data:text/html,default";
+ tm1.open(url);
+ tm1.open(url);
+ tm1.open({
+ url: url,
+ onOpen: function(tab) {
+ let count = 0;
+ for each (let t in tm1) count++;
+ test.assertEqual(count, 4, "iterated tab count matches");
+ test.assertEqual(count, tm1.length, "length tab count matches");
+ closeBrowserWindow(window, function() test.done());
+ }
+ });
+ });
+};
+
+// inNewWindow parameter is ignored on single-window modules
+exports.testTabModuleCantOpenInNewWindow = function(test) {
+ test.waitUntilDone();
+ let TabModule = require("tab-browser").TabModule;
+
+ openBrowserWindow(function(window) {
+ let tm = new TabModule(window);
+ let url = "data:text/html,default";
+ tm.open({
+ url: url,
+ inNewWindow: true,
+ onOpen: function() {
+ test.assertEqual(tm.length, 2, "Tab was open on same window");
+ closeBrowserWindow(window, function() test.done());
+ }
+ });
+ });
+};
+
+// Test that having two modules attached to the same
+// window won't duplicate events fired on each module
+exports.testModuleListenersDontInteract = function(test) {
+ test.waitUntilDone();
+ let TabModule = require("tab-browser").TabModule;
+
+ openBrowserWindow(function(window) {
+ let tm1 = new TabModule(window);
+ let tm2 = new TabModule(window);
+
+ let url = "data:text/html,foo";
+ let eventCount = 0, eventModule1 = 0, eventModule2 = 0;
+
+
+ let listener1 = function() {
+ // this should be called twice: when tab is open and when
+ // the url location is changed
+ eventCount++;
+ eventModule1++;
+ }
+ tm1.onReady = listener1;
+
+ tm2.open({
+ url: "about:blank",
+ onOpen: function(tab) {
+ // add listener via property assignment
+ let listener2 = function() {
+ eventCount++;
+ eventModule2++;
+ };
+ tab.onReady = listener2;
+
+ // add listener via collection add
+ let listener3 = function() {
+ eventCount++;
+ eventModule2++;
+ };
+ tab.onReady.add(listener3);
+
+ tab.location = url;
+
+ test.waitUntilEqual(function () eventCount, 4,
+ "Correct global number of events")
+ .then(function () {
+ test.assertEqual(eventModule1, 2,
+ "Correct number of events on module 1");
+ test.assertEqual(eventModule2, 2,
+ "Correct number of events on module 2");
+
+ tm1.onReady.remove(listener1);
+ tab.onReady.remove(listener2);
+ tab.onReady.remove(listener3);
+ closeBrowserWindow(window, function() test.done());
+ });
+ }
+ });
+ });
+};
+
+/******************* helpers *********************/
+
+// Helper for getting the active window
+this.__defineGetter__("activeWindow", function activeWindow() {
+ return Cc["@mozilla.org/appshell/window-mediator;1"].
+ getService(Ci.nsIWindowMediator).
+ getMostRecentWindow("navigator:browser");
+});
+
+// If the module doesn't support the app we're being run in, require() will
+// throw. In that case, remove all tests above from exports, and add one dummy
+// test that passes.
+try {
+ require("tab-browser");
+}
+catch (err) {
+ // This bug should be mentioned in the error message.
+ let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=560716";
+ if (err.message.indexOf(bug) < 0)
+ throw err;
+ for (let [prop, val] in Iterator(exports)) {
+ if (/^test/.test(prop) && typeof(val) === "function")
+ delete exports[prop];
+ }
+ exports.testAppNotSupported = function (test) {
+ test.pass("the tab-browser module does not support this application.");
+ };
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-observer.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-observer.js
new file mode 100644
index 0000000..d8e6a0a
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab-observer.js
@@ -0,0 +1,35 @@
+"use strict";
+
+const { openTab, closeTab } = require("api-utils/tabs/utils");
+
+exports["test unload tab observer"] = function(assert, done) {
+ // Hacky way to be able to create unloadable modules via makeSandboxedLoader.
+ let loader = assert._log.makeSandboxedLoader();
+
+
+ let window = loader.require("api-utils/window-utils").activeBrowserWindow;
+ let observer = loader.require("api-utils/tabs/observer").observer;
+ let opened = 0;
+ let closed = 0;
+
+ observer.on("open", function onOpen(window) { opened++; });
+ observer.on("close", function onClose(window) { closed++; });
+
+ // Open and close tab to trigger observers.
+ closeTab(openTab(window, "data:text/html,tab-1"));
+
+ // Unload the module so that all listeners set by observer are removed.
+ loader.unload();
+
+ // Open and close tab once again.
+ closeTab(openTab(window, "data:text/html,tab-2"));
+
+ // Enqueuing asserts to make sure that assertion is not performed early.
+ require("timer").setTimeout(function () {
+ assert.equal(1, opened, "observer open was called before unload only");
+ assert.equal(1, closed, "observer close was called before unload only");
+ done();
+ }, 0);
+};
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab.js
new file mode 100644
index 0000000..4015faa
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-tab.js
@@ -0,0 +1,106 @@
+const tabAPI = require("tabs/tab");
+const tabs = require("tabs"); // From addon-kit
+const windowUtils = require("window-utils");
+
+// The primary test tab
+var primaryTab;
+
+// We have an auxiliary tab to test background tabs.
+var auxTab;
+
+// The window for the outer iframe in the primary test page
+var iframeWin;
+
+exports.testGetTabForWindow = function(test) {
+ test.waitUntilDone();
+
+ test.assertEqual(tabAPI.getTabForWindow(windowUtils.activeWindow), null,
+ "getTabForWindow return null on topwindow");
+ test.assertEqual(tabAPI.getTabForWindow(windowUtils.activeBrowserWindow), null,
+ "getTabForWindow return null on topwindow");
+
+ let subSubDocument = encodeURIComponent(
+ 'Sub iframe<br/>'+
+ '<iframe id="sub-sub-iframe" src="data:text/html,SubSubIframe" />');
+ let subDocument = encodeURIComponent(
+ 'Iframe<br/>'+
+ '<iframe id="sub-iframe" src="data:text/html,'+subSubDocument+'" />');
+ let url = 'data:text/html,' + encodeURIComponent(
+ 'Content<br/><iframe id="iframe" src="data:text/html,'+subDocument+'" />');
+
+ // Open up a new tab in the background.
+ //
+ // This lets us test whether GetTabForWindow works even when the tab in
+ // question is not active.
+ tabs.open({
+ inBackground: true,
+ url: "about:mozilla",
+ onReady: function(tab) { auxTab = tab; step2(url, test);},
+ onActivate: function(tab) { step3(test); }
+ });
+}
+
+function step2(url, test) {
+
+ tabs.open({
+ url: url,
+ onReady: function(tab) {
+ primaryTab = tab;
+ let window = windowUtils.activeBrowserWindow.content;
+
+ let matchedTab = tabAPI.getTabForWindow(window);
+ test.assertEqual(matchedTab, tab,
+ "We are able to find the tab with his content window object");
+
+ let timer = require("timer");
+ function waitForFrames() {
+ let iframe = window.document.getElementById("iframe");
+ if (!iframe) {
+ timer.setTimeout(waitForFrames, 100);
+ return;
+ }
+ iframeWin = iframe.contentWindow;
+ let subIframe = iframeWin.document.getElementById("sub-iframe");
+ if (!subIframe) {
+ timer.setTimeout(waitForFrames, 100);
+ return;
+ }
+ let subIframeWin = subIframe.contentWindow;
+ let subSubIframe = subIframeWin.document.getElementById("sub-sub-iframe");
+ if (!subSubIframe) {
+ timer.setTimeout(waitForFrames, 100);
+ return;
+ }
+ let subSubIframeWin = subSubIframe.contentWindow;
+
+ matchedTab = tabAPI.getTabForWindow(iframeWin);
+ test.assertEqual(matchedTab, tab,
+ "We are able to find the tab with an iframe window object");
+
+ matchedTab = tabAPI.getTabForWindow(subIframeWin);
+ test.assertEqual(matchedTab, tab,
+ "We are able to find the tab with a sub-iframe window object");
+
+ matchedTab = tabAPI.getTabForWindow(subSubIframeWin);
+ test.assertEqual(matchedTab, tab,
+ "We are able to find the tab with a sub-sub-iframe window object");
+
+ // Put our primary tab in the background and test again.
+ // The onActivate listener will take us to step3.
+ auxTab.activate();
+ }
+ waitForFrames();
+ }
+ });
+}
+
+function step3(test) {
+
+ let matchedTab = tabAPI.getTabForWindow(iframeWin);
+ test.assertEqual(matchedTab, primaryTab,
+ "We get the correct tab even when it's in the background");
+
+ primaryTab.close(function () {
+ auxTab.close(function () { test.done();});
+ });
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-text-streams.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-text-streams.js
new file mode 100644
index 0000000..6b8988c
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-text-streams.js
@@ -0,0 +1,189 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim:set ts=2 sw=2 sts=2 et filetype=javascript
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Drew Willcoxon <adw@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const file = require("file");
+const url = require("url");
+
+const STREAM_CLOSED_ERROR = "The stream is closed and cannot be used.";
+
+// This should match the constant of the same name in text-streams.js.
+const BUFFER_BYTE_LEN = 0x8000;
+
+exports.testWriteRead = function (test) {
+ let fname = dataFileFilename();
+
+ // Write a small string less than the stream's buffer size...
+ let str = "exports.testWriteRead data!";
+ let stream = file.open(fname, "w");
+ test.assert(!stream.closed, "stream.closed after open should be false");
+ stream.write(str);
+ stream.close();
+ test.assert(stream.closed, "stream.closed after close should be true");
+ test.assertRaises(function () stream.close(),
+ STREAM_CLOSED_ERROR,
+ "stream.close after already closed should raise error");
+ test.assertRaises(function () stream.write("This shouldn't be written!"),
+ STREAM_CLOSED_ERROR,
+ "stream.write after close should raise error");
+
+ // ... and read it.
+ stream = file.open(fname);
+ test.assert(!stream.closed, "stream.closed after open should be false");
+ test.assertEqual(stream.read(), str,
+ "stream.read should return string written");
+ test.assertEqual(stream.read(), "",
+ "stream.read at EOS should return empty string");
+ stream.close();
+ test.assert(stream.closed, "stream.closed after close should be true");
+ test.assertRaises(function () stream.close(),
+ STREAM_CLOSED_ERROR,
+ "stream.close after already closed should raise error");
+ test.assertRaises(function () stream.read(),
+ STREAM_CLOSED_ERROR,
+ "stream.read after close should raise error");
+
+ // Write a big string many times the size of the stream's buffer and read it.
+ // Since it comes after the previous test, this also ensures that the file is
+ // truncated when it's opened for writing.
+ str = "";
+ let bufLen = BUFFER_BYTE_LEN;
+ let fileSize = bufLen * 10;
+ for (let i = 0; i < fileSize; i++)
+ str += i % 10;
+ stream = file.open(fname, "w");
+ stream.write(str);
+ stream.close();
+ stream = file.open(fname);
+ test.assertEqual(stream.read(), str,
+ "stream.read should return string written");
+ stream.close();
+
+ // The same, but write and read in chunks.
+ stream = file.open(fname, "w");
+ let i = 0;
+ while (i < str.length) {
+ // Use a chunk length that spans buffers.
+ let chunk = str.substr(i, bufLen + 1);
+ stream.write(chunk);
+ i += bufLen + 1;
+ }
+ stream.close();
+ stream = file.open(fname);
+ let readStr = "";
+ bufLen = BUFFER_BYTE_LEN;
+ let readLen = bufLen + 1;
+ do {
+ var frag = stream.read(readLen);
+ readStr += frag;
+ } while (frag);
+ stream.close();
+ test.assertEqual(readStr, str,
+ "stream.write and read in chunks should work as expected");
+
+ // Read the same file, passing in strange numbers of bytes to read.
+ stream = file.open(fname);
+ test.assertEqual(stream.read(fileSize * 100), str,
+ "stream.read with big byte length should return string " +
+ "written");
+ stream.close();
+
+ stream = file.open(fname);
+ test.assertEqual(stream.read(0), "",
+ "string.read with zero byte length should return empty " +
+ "string");
+ stream.close();
+
+ stream = file.open(fname);
+ test.assertEqual(stream.read(-1), "",
+ "string.read with negative byte length should return " +
+ "empty string");
+ stream.close();
+
+ file.remove(fname);
+};
+
+exports.testWriteAsync = function (test) {
+ test.waitUntilDone();
+
+ let fname = dataFileFilename();
+ let str = "exports.testWriteAsync data!";
+ let stream = file.open(fname, "w");
+ test.assert(!stream.closed, "stream.closed after open should be false");
+
+ // Write.
+ stream.writeAsync(str, function (err) {
+ test.assertEqual(this, stream, "|this| should be the stream object");
+ test.assertEqual(err, undefined,
+ "stream.writeAsync should not cause error");
+ test.assert(stream.closed, "stream.closed after write should be true");
+ test.assertRaises(function () stream.close(),
+ STREAM_CLOSED_ERROR,
+ "stream.close after already closed should raise error");
+ test.assertRaises(function () stream.writeAsync("This shouldn't work!"),
+ STREAM_CLOSED_ERROR,
+ "stream.writeAsync after close should raise error");
+
+ // Read.
+ stream = file.open(fname, "r");
+ test.assert(!stream.closed, "stream.closed after open should be false");
+ let readStr = stream.read();
+ test.assertEqual(readStr, str,
+ "string.read should yield string written");
+ stream.close();
+ file.remove(fname);
+ test.done();
+ });
+};
+
+exports.testUnload = function (test) {
+ let loader = test.makeSandboxedLoader();
+ let file = loader.require("file");
+
+ let filename = url.toFilename(__url__);
+ let stream = file.open(filename);
+
+ loader.unload();
+ test.assert(stream.closed, "stream should be closed after module unload");
+};
+
+// Returns the name of a file that should be used to test writing and reading.
+function dataFileFilename() {
+ let dir = file.dirname(url.toFilename(__url__));
+ return file.join(dir, "test-text-streams-data");
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-timer.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-timer.js
new file mode 100644
index 0000000..164616f
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-timer.js
@@ -0,0 +1,126 @@
+var timer = require("timer");
+
+exports.testSetTimeout = function(test) {
+ timer.setTimeout(function() {
+ test.pass("testSetTimeout passed");
+ test.done();
+ }, 1);
+ test.waitUntilDone();
+};
+
+exports.testParamedSetTimeout = function(test) {
+ let params = [1, 'foo', { bar: 'test' }, null, undefined];
+ timer.setTimeout.apply(null, [function() {
+ test.assertEqual(arguments.length, params.length);
+ for (let i = 0, ii = params.length; i < ii; i++)
+ test.assertEqual(params[i], arguments[i]);
+ test.done();
+ }, 1].concat(params));
+ test.waitUntilDone();
+};
+
+exports.testClearTimeout = function(test) {
+ var myFunc = function myFunc() {
+ test.fail("myFunc() should not be called in testClearTimeout");
+ };
+ var id = timer.setTimeout(myFunc, 1);
+ timer.setTimeout(function() {
+ test.pass("testClearTimeout passed");
+ test.done();
+ }, 2);
+ timer.clearTimeout(id);
+ test.waitUntilDone();
+};
+
+exports.testParamedClearTimeout = function(test) {
+ let params = [1, 'foo', { bar: 'test' }, null, undefined];
+ var myFunc = function myFunc() {
+ test.fail("myFunc() should not be called in testClearTimeout");
+ };
+ var id = timer.setTimeout(myFunc, 1);
+ timer.setTimeout.apply(null, [function() {
+ test.assertEqual(arguments.length, params.length);
+ for (let i = 0, ii = params.length; i < ii; i++)
+ test.assertEqual(params[i], arguments[i]);
+ test.done();
+ }, 1].concat(params));
+ timer.clearTimeout(id);
+ test.waitUntilDone();
+};
+
+exports.testSetInterval = function (test) {
+ var count = 0;
+ var id = timer.setInterval(function () {
+ count++;
+ if (count >= 5) {
+ timer.clearInterval(id);
+ test.pass("testSetInterval passed");
+ test.done();
+ }
+ }, 1);
+ test.waitUntilDone();
+};
+
+exports.testParamedSetInerval = function(test) {
+ let params = [1, 'foo', { bar: 'test' }, null, undefined];
+ let count = 0;
+ let id = timer.setInterval.apply(null, [function() {
+ count ++;
+ if (count < 5) {
+ test.assertEqual(arguments.length, params.length);
+ for (let i = 0, ii = params.length; i < ii; i++)
+ test.assertEqual(params[i], arguments[i]);
+ } else {
+ timer.clearInterval(id);
+ test.done();
+ }
+ }, 1].concat(params));
+ test.waitUntilDone();
+};
+
+exports.testClearInterval = function (test) {
+ timer.clearInterval(timer.setInterval(function () {
+ test.fail("setInterval callback should not be called");
+ }, 1));
+ var id = timer.setInterval(function () {
+ timer.clearInterval(id);
+ test.pass("testClearInterval passed");
+ test.done();
+ }, 2);
+ test.waitUntilDone();
+};
+
+exports.testParamedClearInterval = function(test) {
+ timer.clearInterval(timer.setInterval(function () {
+ test.fail("setInterval callback should not be called");
+ }, 1, timer, {}, null));
+
+ let id = timer.setInterval(function() {
+ timer.clearInterval(id);
+ test.assertEqual(3, arguments.length);
+ test.done();
+ }, 2, undefined, 'test', {});
+ test.waitUntilDone();
+};
+
+
+exports.testUnload = function(test) {
+ var loader = test.makeSandboxedLoader();
+ var sbtimer = loader.require("timer");
+
+ var myFunc = function myFunc() {
+ test.fail("myFunc() should not be called in testUnload");
+ };
+
+ sbtimer.setTimeout(myFunc, 1);
+ sbtimer.setTimeout(myFunc, 1, 'foo', 4, {}, undefined);
+ sbtimer.setInterval(myFunc, 1);
+ sbtimer.setInterval(myFunc, 1, {}, null, 'bar', undefined, 87);
+ loader.unload();
+ timer.setTimeout(function() {
+ test.pass("timer testUnload passed");
+ test.done();
+ }, 2);
+ test.waitUntilDone();
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-traceback.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-traceback.js
new file mode 100644
index 0000000..6cf50f0
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-traceback.js
@@ -0,0 +1,114 @@
+var traceback = require("traceback");
+var {Cc,Ci,Cr,Cu} = require("chrome");
+
+function throwNsIException() {
+ var ios = Cc['@mozilla.org/network/io-service;1']
+ .getService(Ci.nsIIOService);
+ ios.newURI("i'm a malformed URI", null, null);
+}
+
+function throwError() {
+ throw new Error("foob");
+}
+
+exports.testFormatDoesNotFetchRemoteFiles = function(test) {
+ var observers = require("observer-service");
+ ["http", "https"].forEach(
+ function(scheme) {
+ var httpRequests = 0;
+ function onHttp() {
+ httpRequests++;
+ }
+
+ observers.add("http-on-modify-request", onHttp);
+
+ try {
+ var tb = [{filename: scheme + "://www.mozilla.org/",
+ lineNo: 1,
+ funcName: "blah"}];
+ traceback.format(tb);
+ } catch (e) {
+ test.exception(e);
+ }
+
+ observers.remove("http-on-modify-request", onHttp);
+
+ test.assertEqual(httpRequests, 0,
+ "traceback.format() does not make " +
+ scheme + " request");
+ });
+};
+
+exports.testFromExceptionWithString = function(test) {
+ try {
+ throw "foob";
+ test.fail("an exception should've been thrown");
+ } catch (e if e == "foob") {
+ var tb = traceback.fromException(e);
+ test.assertEqual(tb.length, 0);
+ }
+};
+
+exports.testFormatWithString = function(test) {
+ // This can happen if e.g. a thrown exception was
+ // a string instead of an Error instance.
+ test.assertEqual(traceback.format("blah"),
+ "Traceback (most recent call last):");
+};
+
+exports.testFromExceptionWithError = function(test) {
+ try {
+ throwError();
+ test.fail("an exception should've been thrown");
+ } catch (e if e instanceof Error) {
+ var tb = traceback.fromException(e);
+ var xulApp = require("xul-app");
+ test.assertEqual(tb.slice(-1)[0].funcName, "throwError");
+ }
+};
+
+exports.testFromExceptionWithNsIException = function(test) {
+ try {
+ throwNsIException();
+ test.fail("an exception should've been thrown");
+ } catch (e if e.result == Cr.NS_ERROR_MALFORMED_URI) {
+ var tb = traceback.fromException(e);
+ test.assertEqual(tb.slice(-1)[0].funcName,
+ "throwNsIException");
+ }
+};
+
+exports.testFormat = function(test) {
+ function getTraceback() {
+ return traceback.format();
+ }
+
+ var formatted = getTraceback();
+ test.assertEqual(typeof(formatted), "string");
+ var lines = formatted.split("\n");
+ test.assertEqual(lines.slice(-2)[0].indexOf("getTraceback") > 0,
+ true,
+ "formatted traceback should include function name");
+ test.assertEqual(lines.slice(-1)[0].trim(),
+ "return traceback.format();",
+ "formatted traceback should include source code");
+};
+
+exports.testExceptionsWithEmptyStacksAreLogged = function(test) {
+ // Ensures that our fix to bug 550368 works.
+ var sandbox = Cu.Sandbox("http://www.foo.com");
+ var excRaised = false;
+ try {
+ Cu.evalInSandbox("returns 1 + 2;", sandbox, "1.8",
+ "blah.js", 25);
+ } catch (e) {
+ excRaised = true;
+ var stack = traceback.fromException(e);
+ test.assertEqual(stack.length, 1, "stack should have one frame");
+ test.assert(stack[0].filename, "blah.js", "frame should have filename");
+ test.assert(stack[0].lineNo, 25, "frame should have line no");
+ test.assertEqual(stack[0].funcName, null, "frame should have null function name");
+ }
+ if (!excRaised)
+ test.fail("Exception should have been raised.");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-traits-core.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-traits-core.js
new file mode 100644
index 0000000..ecc2c51
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-traits-core.js
@@ -0,0 +1,834 @@
+"use strict";
+
+const ERR_CONFLICT = 'Remaining conflicting property: ',
+ ERR_REQUIRED = 'Missing required property: ';
+
+function assertSametrait(test, trait1, trait2) {
+ let names1 = Object.getOwnPropertyNames(trait1),
+ names2 = Object.getOwnPropertyNames(trait2);
+
+ test.assertEqual(
+ names1.length,
+ names2.length,
+ 'equal traits must have same amount of properties'
+ );
+
+ for (let i = 0; i < names1.length; i++) {
+ let name = names1[i];
+ test.assertNotEqual(
+ -1,
+ names2.indexOf(name),
+ 'equal traits must contain same named properties: ' + name
+ );
+ assertSameDescriptor(test, name, trait1[name], trait2[name]);
+ }
+}
+
+function assertSameDescriptor(test, name, desc1, desc2) {
+ if (desc1.conflict || desc2.conflict) {
+ test.assertEqual(
+ desc1.conflict,
+ desc2.conflict,
+ 'if one of same descriptors has `conflict` another must have it: '
+ + name
+ );
+ } else if (desc1.required || desc2.required) {
+ test.assertEqual(
+ desc1.required,
+ desc2.required,
+ 'if one of same descriptors is has `required` another must have it: '
+ + name
+ );
+ } else {
+ test.assertEqual(
+ desc1.get,
+ desc2.get,
+ 'get must be the same on both descriptors: ' + name
+ );
+ test.assertEqual(
+ desc1.set,
+ desc2.set,
+ 'set must be the same on both descriptors: ' + name
+ );
+ test.assertEqual(
+ desc1.value,
+ desc2.value,
+ 'value must be the same on both descriptors: ' + name
+ );
+ test.assertEqual(
+ desc1.enumerable,
+ desc2.enumerable,
+ 'enumerable must be the same on both descriptors: ' + name
+ );
+ test.assertEqual(
+ desc1.required,
+ desc2.required,
+ 'value must be the same on both descriptors: ' + name
+ );
+ }
+}
+
+function Data(value, enumerable, confligurable, writable) {
+ return {
+ value: value,
+ enumerable: false !== enumerable,
+ confligurable: false !== confligurable,
+ writable: false !== writable
+ };
+}
+
+function Method(method, enumerable, confligurable, writable) {
+ return {
+ value: method,
+ enumerable: false !== enumerable,
+ confligurable: false !== confligurable,
+ writable: false !== writable
+ };
+}
+
+function Accessor(get, set, enumerable, confligurable) {
+ return {
+ get: get,
+ set: set,
+ enumerable: false !== enumerable,
+ confligurable: false !== confligurable,
+ };
+}
+
+function Required(name) {
+ function required() { throw new Error(ERR_REQUIRED + name) }
+ return {
+ get: required,
+ set: required,
+ required: true
+ };
+}
+
+function Conflict(name) {
+ function conflict() { throw new Error(ERR_CONFLICT + name) }
+ return {
+ get: conflict,
+ set: conflict,
+ conflict: true
+ };
+}
+
+function testMethod() {};
+
+const { trait, compose, resolve, required, override, create } =
+ require('traits/core');
+
+
+exports['test:empty trait'] = function(test) {
+ assertSametrait(
+ test,
+ trait({}),
+ {}
+ );
+};
+
+exports['test:simple trait'] = function(test) {
+ assertSametrait(
+ test,
+ trait({
+ a: 0,
+ b: testMethod
+ }),
+ {
+ a: Data(0, true, true, true),
+ b: Method(testMethod, true, true, true)
+ }
+ );
+};
+
+exports['test:simple trait with required prop'] = function(test) {
+ assertSametrait(
+ test,
+ trait({
+ a: required,
+ b: 1
+ }),
+ {
+ a: Required('a'),
+ b: Data(1)
+ }
+ );
+};
+
+exports['test:ordering of trait properties is irrelevant'] = function(test) {
+ assertSametrait(test,
+ trait({ a: 0, b: 1, c: required }),
+ trait({ b: 1, c: required, a: 0 })
+ );
+};
+
+exports['test:trait with accessor property'] = function(test) {
+ let record = { get a() {}, set a(v) {} };
+ let get = Object.getOwnPropertyDescriptor(record,'a').get;
+ let set = Object.getOwnPropertyDescriptor(record,'a').set;
+ assertSametrait(test,
+ trait(record),
+ { a: Accessor(get, set ) }
+ );
+};
+
+exports['test:simple composition'] = function(test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: 0, b: 1 }),
+ trait({ c: 2, d: testMethod })
+ ),
+ {
+ a: Data(0),
+ b: Data(1),
+ c: Data(2),
+ d: Method(testMethod)
+ }
+ );
+};
+
+exports['test:composition with conflict'] = function(test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: 0, b: 1 }),
+ trait({ a: 2, c: testMethod })
+ ),
+ {
+ a: Conflict('a'),
+ b: Data(1),
+ c: Method(testMethod)
+ }
+ );
+};
+
+exports['test:composition of identical props does not cause conflict'] =
+function(test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: 0, b: 1 }),
+ trait({ a: 0, c: testMethod })
+ ),
+ {
+ a: Data(0),
+ b: Data(1),
+ c: Method(testMethod) }
+ )
+};
+
+exports['test:composition with identical required props'] =
+function(test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: required, b: 1 }),
+ trait({ a: required, c: testMethod })
+ ),
+ {
+ a: Required(),
+ b: Data(1),
+ c: Method(testMethod)
+ }
+ );
+};
+
+exports['test:composition satisfying a required prop'] = function (test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: required, b: 1 }),
+ trait({ a: testMethod })
+ ),
+ {
+ a: Method(testMethod),
+ b: Data(1)
+ }
+ );
+};
+
+exports['test:compose is neutral wrt conflicts'] = function (test) {
+ assertSametrait(test,
+ compose(
+ compose(
+ trait({ a: 1 }),
+ trait({ a: 2 })
+ ),
+ trait({ b: 0 })
+ ),
+ {
+ a: Conflict('a'),
+ b: Data(0)
+ }
+ );
+};
+
+exports['test:conflicting prop overrides required prop'] = function (test) {
+ assertSametrait(test,
+ compose(
+ compose(
+ trait({ a: 1 }),
+ trait({ a: 2 })
+ ),
+ trait({ a: required })
+ ),
+ {
+ a: Conflict('a')
+ }
+ );
+};
+
+exports['test:compose is commutative'] = function (test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: 0, b: 1 }),
+ trait({ c: 2, d: testMethod })
+ ),
+ compose(
+ trait({ c: 2, d: testMethod }),
+ trait({ a: 0, b: 1 })
+ )
+ );
+};
+
+exports['test:compose is commutative, also for required/conflicting props'] =
+function (test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: 0, b: 1, c: 3, e: required }),
+ trait({ c: 2, d: testMethod })
+ ),
+ compose(
+ trait({ c: 2, d: testMethod }),
+ trait({ a: 0, b: 1, c: 3, e: required })
+ )
+ );
+};
+exports['test:compose is associative'] = function (test) {
+ assertSametrait(test,
+ compose(
+ trait({ a: 0, b: 1, c: 3, d: required }),
+ compose(
+ trait({ c: 3, d: required }),
+ trait({ c: 2, d: testMethod, e: 'foo' })
+ )
+ ),
+ compose(
+ compose(
+ trait({ a: 0, b: 1, c: 3, d: required }),
+ trait({ c: 3, d: required })
+ ),
+ trait({ c: 2, d: testMethod, e: 'foo' })
+ )
+ );
+};
+
+exports['test:diamond import of same prop does not generate conflict'] =
+function (test) {
+ assertSametrait(test,
+ compose(
+ compose(
+ trait({ b: 2 }),
+ trait({ a: 1 })
+ ),
+ compose(
+ trait({ c: 3 }),
+ trait({ a: 1 })
+ ),
+ trait({ d: 4 })
+ ),
+ {
+ a: Data(1),
+ b: Data(2),
+ c: Data(3),
+ d: Data(4)
+ }
+ );
+};
+
+exports['test:resolve with empty resolutions has no effect'] =
+function (test) {
+ assertSametrait(test, resolve({}, trait({
+ a: 1,
+ b: required,
+ c: testMethod
+ })), {
+ a: Data(1),
+ b: Required(),
+ c: Method(testMethod)
+ });
+};
+
+exports['test:resolve: renaming'] = function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'A', c: 'C' },
+ trait({ a: 1, b: required, c: testMethod })
+ ),
+ {
+ A: Data(1),
+ b: Required(),
+ C: Method(testMethod),
+ a: Required(),
+ c: Required()
+ }
+ );
+};
+
+exports['test:resolve: renaming to conflicting name causes conflict, order 1']
+= function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'b'},
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ b: Conflict('b'),
+ a: Required()
+ }
+ );
+};
+
+exports['test:resolve: renaming to conflicting name causes conflict, order 2']
+= function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'b' },
+ trait({ b: 2, a: 1 })
+ ),
+ {
+ b: Conflict('b'),
+ a: Required()
+ }
+ );
+};
+
+exports['test:resolve: simple exclusion'] = function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: undefined },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Required(),
+ b: Data(2)
+ }
+ );
+};
+
+exports['test:resolve: exclusion to "empty" trait'] = function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: undefined, b: undefined },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Required(),
+ b: Required()
+ }
+ );
+};
+
+exports['test:resolve: exclusion and renaming of disjoint props'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: undefined, b: 'c' },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Required(),
+ c: Data(2),
+ b: Required()
+ }
+ );
+};
+
+exports['test:resolve: exclusion and renaming of overlapping props'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: undefined, b: 'a' },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Data(2),
+ b: Required()
+ }
+ );
+};
+
+exports['test:resolve: renaming to a common alias causes conflict'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'c', b: 'c' },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ c: Conflict('c'),
+ a: Required(),
+ b: Required()
+ }
+ );
+};
+
+exports['test:resolve: renaming overrides required target'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { b: 'a' },
+ trait({ a: required, b: 2 })
+ ),
+ {
+ a: Data(2),
+ b: Required()
+ }
+ );
+};
+
+exports['test:resolve: renaming required properties has no effect'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { b: 'a' },
+ trait({ a: 2, b: required })
+ ),
+ {
+ a: Data(2),
+ b: Required()
+ }
+ );
+};
+
+exports['test:resolve: renaming of non-existent props has no effect'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'c', d: 'c' },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ c: Data(1),
+ b: Data(2),
+ a: Required()
+ }
+ );
+};
+
+exports['test:resolve: exclusion of non-existent props has no effect'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { b: undefined },
+ trait({ a: 1 })
+ ),
+ {
+ a: Data(1)
+ }
+ );
+};
+
+exports['test:resolve is neutral w.r.t. required properties'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'c', b: undefined },
+ trait({ a: required, b: required, c: 'foo', d: 1 })
+ ),
+ {
+ a: Required(),
+ b: Required(),
+ c: Data('foo'),
+ d: Data(1)
+ }
+ );
+};
+
+exports['test:resolve supports swapping of property names, ordering 1'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'b', b: 'a' },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Data(2),
+ b: Data(1)
+ }
+ );
+};
+
+exports['test:resolve supports swapping of property names, ordering 2'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { b: 'a', a: 'b' },
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Data(2),
+ b: Data(1)
+ }
+ );
+};
+
+exports['test:resolve supports swapping of property names, ordering 3'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { b: 'a', a: 'b' },
+ trait({ b: 2, a: 1 })
+ ),
+ {
+ a: Data(2),
+ b: Data(1)
+ }
+ );
+};
+
+exports['test:resolve supports swapping of property names, ordering 4'] =
+function (test) {
+ assertSametrait(test,
+ resolve(
+ { a: 'b', b: 'a' },
+ trait({ b: 2, a: 1 })
+ ),
+ {
+ a: Data(2),
+ b: Data(1)
+ }
+ );
+};
+
+exports['test:override of mutually exclusive traits'] = function (test) {
+ assertSametrait(test,
+ override(
+ trait({ a: 1, b: 2 }),
+ trait({ c: 3, d: testMethod })
+ ),
+ {
+ a: Data(1),
+ b: Data(2),
+ c: Data(3),
+ d: Method(testMethod)
+ }
+ );
+};
+
+exports['test:override of mutually exclusive traits is compose'] =
+function (test) {
+ assertSametrait(test,
+ override(
+ trait({ a: 1, b: 2 }),
+ trait({ c: 3, d: testMethod })
+ ),
+ compose(
+ trait({ d: testMethod, c: 3 }),
+ trait({ b: 2, a: 1 })
+ )
+ );
+};
+
+exports['test:override of overlapping traits'] = function (test) {
+ assertSametrait(test,
+ override(
+ trait({ a: 1, b: 2 }),
+ trait({ a: 3, c: testMethod })
+ ),
+ {
+ a: Data(1),
+ b: Data(2),
+ c: Method(testMethod)
+ }
+ );
+};
+
+exports['test:three-way override of overlapping traits'] = function (test) {
+ assertSametrait(test,
+ override(
+ trait({ a: 1, b: 2 }),
+ trait({ b: 4, c: 3 }),
+ trait({ a: 3, c: testMethod, d: 5 })
+ ),
+ {
+ a: Data(1),
+ b: Data(2),
+ c: Data(3),
+ d: Data(5)
+ }
+ );
+};
+
+exports['test:override replaces required properties'] = function (test) {
+ assertSametrait(test,
+ override(
+ trait({ a: required, b: 2 }),
+ trait({ a: 1, c: testMethod })
+ ),
+ {
+ a: Data(1),
+ b: Data(2),
+ c: Method(testMethod)
+ }
+ );
+};
+
+exports['test:override is not commutative'] = function (test) {
+ assertSametrait(test,
+ override(
+ trait({ a: 1, b: 2 }),
+ trait({ a: 3, c: 4 })
+ ),
+ {
+ a: Data(1),
+ b: Data(2),
+ c: Data(4)
+ }
+ );
+
+ assertSametrait(test,
+ override(
+ trait({ a: 3, c: 4 }),
+ trait({ a: 1, b: 2 })
+ ),
+ {
+ a: Data(3),
+ b: Data(2),
+ c: Data(4)
+ }
+ );
+};
+
+exports['test:override is associative'] = function (test) {
+ assertSametrait(test,
+ override(
+ override(
+ trait({ a: 1, b: 2 }),
+ trait({ a: 3, c: 4, d: 5 })
+ ),
+ trait({ a: 6, c: 7, e: 8 })
+ ),
+ override(
+ trait({ a: 1, b: 2 }),
+ override(
+ trait({ a: 3, c: 4, d: 5 }),
+ trait({ a: 6, c: 7, e: 8 })
+ )
+ )
+ );
+};
+
+exports['test:create simple'] = function(test) {
+ let o1 = create(
+ Object.prototype,
+ trait({ a: 1, b: function() { return this.a; } })
+ );
+
+ test.assertEqual(
+ Object.prototype,
+ Object.getPrototypeOf(o1),
+ 'o1 prototype'
+ );
+ test.assertEqual(1, o1.a, 'o1.a');
+ test.assertEqual(1, o1.b(), 'o1.b()');
+ test.assertEqual(
+ 2,
+ Object.getOwnPropertyNames(o1).length,
+ 'Object.keys(o1).length === 2'
+ );
+};
+
+exports['test:create with Array.prototype'] = function(test) {
+ let o2 = create(Array.prototype, trait({}));
+ test.assertEqual(
+ Array.prototype,
+ Object.getPrototypeOf(o2),
+ "o2 prototype"
+ );
+};
+
+exports['test:exception for incomplete required properties'] =
+function(test) {
+ try {
+ create(Object.prototype, trait({ foo: required }));
+ test.fail('expected create to complain about missing required props');
+ } catch(e) {
+ test.assertEqual(
+ 'Error: Missing required property: foo',
+ e.toString(),
+ 'required prop error'
+ );
+ }
+};
+
+exports['test:exception for unresolved conflicts'] = function(test) {
+ try {
+ create({}, compose(trait({ a: 0 }), trait({ a: 1 })));
+ test.fail('expected create to complain about unresolved conflicts');
+ } catch(e) {
+ test.assertEqual(
+ 'Error: Remaining conflicting property: a',
+ e.toString(),
+ 'conflicting prop error'
+ );
+ }
+};
+
+exports['test:verify that required properties are present but undefined'] =
+function(test) {
+ try {
+ let o4 = Object.create(Object.prototype, trait({ foo: required }));
+ test.assertEqual(true, 'foo' in o4, 'required property present');
+ try {
+ let foo = o4.foo;
+ test.fail('access to required property must throw');
+ } catch(e) {
+ test.assertEqual(
+ 'Error: Missing required property: foo',
+ e.toString(),
+ 'required prop error'
+ )
+ }
+ } catch(e) {
+ test.fail('did not expect create to complain about required props');
+ }
+};
+
+exports['test:verify that conflicting properties are present'] =
+function(test) {
+ try {
+ let o5 = Object.create(
+ Object.prototype,
+ compose(trait({ a: 0 }), trait({ a: 1 }))
+ );
+ test.assertEqual(true, 'a' in o5, 'conflicting property present');
+ try {
+ let a = o5.a; // accessors or data prop
+ test.fail('expected conflicting prop to cause exception');
+ } catch (e) {
+ test.assertEqual(
+ 'Error: Remaining conflicting property: a',
+ e.toString(),
+ 'conflicting prop access error'
+ );
+ }
+ } catch(e) {
+ test.fail('did not expect create to complain about conflicting props');
+ }
+};
+
+exports['test diamond with conflicts'] = function(test) {
+ function makeT1(x) trait({ m: function() { return x; } })
+ function makeT2(x) compose(trait({ t2: 'foo' }), makeT1(x))
+ function makeT3(x) compose(trait({ t3: 'bar' }), makeT1(x))
+
+ let T4 = compose(makeT2(5), makeT3(5));
+ try {
+ let o = create(Object.prototype, T4);
+ test.fail('expected diamond prop to cause exception');
+ } catch(e) {
+ test.assertEqual(
+ 'Error: Remaining conflicting property: m',
+ e.toString(),
+ 'diamond prop conflict'
+ );
+ }
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-traits.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-traits.js
new file mode 100644
index 0000000..6940616
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-traits.js
@@ -0,0 +1,394 @@
+"use strict";
+
+const { Trait } = require('traits');
+
+exports['test:simple compose'] = function(test) {
+ let List = Trait.compose({
+ _list: null,
+ constructor: function List() {
+ this._list = [];
+ },
+ list: function list() this._list.slice(0),
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list;
+ let index = list.indexOf(item);
+ if (0 <= index) list.slice(index, 1);
+ }
+ });
+
+ test.assertNotEqual(undefined, List, 'should not be undefined');
+ test.assertEqual('function', typeof List, 'type should be function');
+ test.assertEqual(
+ Trait.compose,
+ List.compose,
+ 'should inherit static compose'
+ );
+ test.assertEqual(
+ Trait.override,
+ List.override,
+ 'should inherit static override'
+ );
+ test.assertEqual(
+ Trait.required,
+ List.required,
+ 'should inherit static required'
+ );
+ test.assertEqual(
+ Trait.resolve,
+ List.resolve,
+ 'should inherit static resolve'
+ );
+
+ test.assert(
+ !('_list' in List.prototype),
+ 'should not expose private API'
+ );
+}
+exports['test: compose trait instance and create instance'] = function(test) {
+ let List = Trait.compose({
+ constructor: function List(options) {
+ this._list = [];
+ this._public.publicMember = options.publicMember;
+ },
+ _privateMember: true,
+ get privateMember() this._privateMember,
+ get list() this._list.slice(0),
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list
+ let index = list.indexOf(item)
+ if (0 <= index) list.slice(index, 1)
+ }
+ });
+ let list = List({ publicMember: true });
+
+ test.assertEqual('object', typeof list, 'should return an object')
+ test.assertEqual(
+ true,
+ list instanceof List,
+ 'should be instance of a List'
+ );
+
+ test.assertEqual(
+ undefined,
+ list._privateMember,
+ 'instance should not expose private API'
+ );
+
+ test.assertEqual(
+ true,
+ list.privateMember,
+ 'privates are accessible by public API'
+ );
+
+ list._privateMember = false;
+
+ test.assertEqual(
+ true,
+ list.privateMember,
+ 'property changes on instance must not affect privates'
+ );
+
+ test.assert(
+ !('_list' in list),
+ 'instance should not expose private members'
+ );
+
+ test.assertEqual(
+ true,
+ list.publicMember,
+ 'public members are exposed'
+ )
+ test.assertEqual(
+ 'function',
+ typeof list.add,
+ 'should be function'
+ )
+ test.assertEqual(
+ 'function',
+ typeof list.remove,
+ 'should be function'
+ );
+
+ list.add(1);
+ test.assertEqual(
+ 1,
+ list.list[0],
+ 'exposed public API should be able of modifying privates'
+ )
+};
+
+
+exports['test:instances must not be hackable'] = function(test) {
+ let SECRET = 'There is no secret!',
+ secret = null;
+
+ let Class = Trait.compose({
+ _secret: null,
+ protect: function(data) this._secret = data
+ });
+
+ let i1 = Class();
+ i1.protect(SECRET);
+
+ test.assertEqual(
+ undefined,
+ (function() this._secret).call(i1),
+ 'call / apply can\'t access private state'
+ );
+
+ let proto = Object.getPrototypeOf(i1);
+ try {
+ proto.reveal = function() this._secret;
+ secret = i1.reveal();
+ } catch(e) {}
+ test.assertNotEqual(
+ SECRET,
+ secret,
+ 'public __proto__ changes should not affect privates'
+ );
+ secret = null;
+
+ let Class2 = Trait.compose({
+ _secret: null,
+ protect: function(data) this._secret = data
+ });
+ let i2 = Class2();
+ i2.protect(SECRET);
+ try {
+ Object.prototype.reveal = function() this._secret;
+ secret = i2.reveal();
+ } catch(e) {}
+ test.assertNotEqual(
+ SECRET,
+ secret,
+ 'Object.prototype changes must not affect instances'
+ );
+}
+
+exports['test:instanceof'] = function(test) {
+ const List = Trait.compose({
+ // private API:
+ _list: null,
+ // public API
+ constructor: function List() {
+ this._list = []
+ },
+ get length() this._list.length,
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list;
+ let index = list.indexOf(item);
+ if (0 <= index) list.slice(index, 1);
+ }
+ });
+
+ test.assert(List() instanceof List, 'Must be instance of List');
+ test.assert(new List() instanceof List, 'Must be instance of List');
+};
+
+exports['test:privates are unaccessible'] = function(test) {
+ const List = Trait.compose({
+ // private API:
+ _list: null,
+ // public API
+ constructor: function List() {
+ this._list = [];
+ },
+ get length() this._list.length,
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list;
+ let index = list.indexOf(item);
+ if (0 <= index) list.slice(index, 1);
+ }
+ });
+
+ let list = List();
+ test.assert(!('_list' in list), 'no privates on instance');
+ test.assert(
+ !('_list' in List.prototype),
+ 'no privates on prototype'
+ );
+};
+
+exports['test:public API can access private API'] = function(test) {
+ const List = Trait.compose({
+ // private API:
+ _list: null,
+ // public API
+ constructor: function List() {
+ this._list = [];
+ },
+ get length() this._list.length,
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list;
+ let index = list.indexOf(item);
+ if (0 <= index) list.slice(index, 1);
+ }
+ });
+ let list = List();
+
+ list.add('test');
+
+ test.assertEqual(
+ 1,
+ list.length,
+ 'should be able to add element and access it from public getter'
+ );
+};
+
+exports['test:required'] = function(test) {
+ const Enumerable = Trait.compose({
+ list: Trait.required,
+ forEach: function forEach(consumer) {
+ return this.list.forEach(consumer);
+ }
+ });
+
+ try {
+ let i = Enumerable();
+ test.fail('should throw when creating instance with required properties');
+ } catch(e) {
+ test.assertEqual(
+ 'Error: Missing required property: list',
+ e.toString(),
+ 'required prop error'
+ );
+ }
+};
+
+exports['test:compose with required'] = function(test) {
+ const List = Trait.compose({
+ // private API:
+ _list: null,
+ // public API
+ constructor: function List() {
+ this._list = [];
+ },
+ get length() this._list.length,
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list;
+ let index = list.indexOf(item);
+ if (0 <= index) list.slice(index, 1);
+ }
+ });
+
+ const Enumerable = Trait.compose({
+ list: Trait.required,
+ forEach: function forEach(consumer) {
+ return this.list.forEach(consumer);
+ }
+ });
+
+ const EnumerableList = Enumerable.compose({
+ get list() this._list.slice(0)
+ }, List);
+
+ let array = [1,2, 'ab']
+ let l = EnumerableList(array);
+ array.forEach(function(element) l.add(element));
+ let number = 0;
+ l.forEach(function(element, index) {
+ number ++;
+ test.assertEqual(array[index], element, 'should mach array element')
+ });
+ test.assertEqual(
+ array.length,
+ number,
+ 'should perform as many asserts as elements in array'
+ );
+};
+
+exports['test:resolve'] = function(test) {
+ const List = Trait.compose({
+ // private API:
+ _list: null,
+ // public API
+ constructor: function List() {
+ this._list = [];
+ },
+ get length() this._list.length,
+ add: function add(item) this._list.push(item),
+ remove: function remove(item) {
+ let list = this._list;
+ let index = list.indexOf(item);
+ if (0 <= index) list.slice(index, 1);
+ }
+ });
+
+ const Range = List.resolve({
+ constructor: null,
+ add: '_add',
+ }).compose({
+ min: null,
+ max: null,
+ get list() this._list.slice(0),
+ constructor: function Range(min, max) {
+ this.min = min;
+ this.max = max;
+ this._list = [];
+ },
+ add: function(item) {
+ if (item <= this.max && item >= this.min)
+ this._add(item)
+ }
+ });
+
+ let r = Range(0, 10);
+
+ test.assertEqual(
+ 0,
+ r.min,
+ 'constructor must have set min'
+ );
+ test.assertEqual(
+ 10,
+ r.max,
+ 'constructor must have set max'
+ );
+
+ test.assertEqual(
+ 0,
+ r.length,
+ 'should not contain any elements'
+ );
+
+ r.add(5);
+
+ test.assertEqual(
+ 1,
+ r.length,
+ 'should add `5` to list'
+ );
+
+ r.add(12);
+
+ test.assertEqual(
+ 1,
+ r.length,
+ 'should not add `12` to list'
+ );
+};
+
+exports['test:custom iterator'] = function(test) {
+ let Sub = Trait.compose({
+ foo: "foo",
+ bar: "bar",
+ baz: "baz",
+ __iterator__: function() {
+ yield 1;
+ yield 2;
+ yield 3;
+ }
+ });
+
+ let (i = 0, sub = Sub()) {
+ for (let item in sub)
+ test.assertEqual(++i, item, "iterated item has the right value");
+ };
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-type.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-type.js
new file mode 100644
index 0000000..072075c
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-type.js
@@ -0,0 +1,88 @@
+"use strict"
+
+var utils = require("type");
+
+exports["test function"] = function (assert) {
+ assert.ok(utils.isFunction(function(){}), "value is function");
+ assert.ok(utils.isFunction(Object), "Object is function");
+ assert.ok(utils.isFunction(new Function("")), "Genertaed value is function");
+ assert.ok(!utils.isFunction({}), "object is not a function");
+ assert.ok(!utils.isFunction(4), "number is not a function");
+};
+
+exports["test atoms"] = function (assert) {
+ assert.ok(utils.isPrimitive(2), "number is primitive");
+ assert.ok(utils.isPrimitive(NaN), "`NaN` is primitve");
+ assert.ok(utils.isPrimitive(undefined), "`undefined` is primitive");
+ assert.ok(utils.isPrimitive(null), "`null` is primitive");
+ assert.ok(utils.isPrimitive(Infinity), "`Infinity` is primitive");
+ assert.ok(utils.isPrimitive("foo"), "strings are primitive");
+ assert.ok(utils.isPrimitive(true) && utils.isPrimitive(false),
+ "booleans are primitive");
+};
+
+exports["test object"] = function (assert) {
+ assert.ok(utils.isObject({}), "`{}` is object");
+ assert.ok(!utils.isObject(null), "`null` is not an object");
+ assert.ok(!utils.isObject(Object), "functions is not an object");
+};
+
+exports["test flat objects"] = function (assert) {
+ assert.ok(utils.isFlat({}), "`{}` is a flat object");
+ assert.ok(!utils.isFlat([]), "`[]` is not a flat object");
+ assert.ok(!utils.isFlat(new function() {}), "derived objects are not flat");
+ assert.ok(utils.isFlat(Object.prototype), "Object.prototype is flat");
+};
+
+exports["test json atoms"] = function (assert) {
+ assert.ok(utils.isJSON(null), "`null` is JSON");
+ assert.ok(utils.isJSON(undefined), "`undefined` is JSON");
+ assert.ok(utils.isJSON(NaN), "`NaN` is JSON");
+ assert.ok(utils.isJSON(Infinity), "`Infinity` is JSON");
+ assert.ok(utils.isJSON(true) && utils.isJSON(false), "booleans are JSON");
+ assert.ok(utils.isJSON(4), utils.isJSON(0), "numbers are JSON");
+ assert.ok(utils.isJSON("foo bar"), "strings are JSON");
+};
+
+exports["test instanceOf"] = function (assert) {
+ assert.ok(utils.instanceOf(assert, Object),
+ "assert is object from other sandbox");
+ assert.ok(utils.instanceOf(new Date(), Date), "instance of date");
+ assert.ok(!utils.instanceOf(null, Object), "null is not an instance");
+};
+
+exports["test json"] = function (assert) {
+ assert.ok(!utils.isJSON(function(){}), "functions are not json");
+ assert.ok(utils.isJSON({}), "`{}` is JSON");
+ assert.ok(utils.isJSON({
+ a: "foo",
+ b: 3,
+ c: undefined,
+ d: null,
+ e: {
+ f: {
+ g: "bar",
+ p: [{}, "oueou", 56]
+ },
+ q: { nan: NaN, infinity: Infinity },
+ "non standard name": "still works"
+ }
+ }), "JSON can contain nested objects");
+
+ var foo = {};
+ var bar = { foo: foo };
+ foo.bar = bar;
+ assert.ok(!utils.isJSON(foo), "recursive objects are not json");
+
+
+ assert.ok(!utils.isJSON({ get foo() { return 5 } }),
+ "json can not have getter");
+
+ assert.ok(!utils.isJSON({ foo: "bar", baz: function () {} }),
+ "json can not contain functions");
+
+ assert.ok(!utils.isJSON(Object.create({})),
+ "json must be direct descendant of `Object.prototype`");
+};
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-unit-test.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-unit-test.js
new file mode 100644
index 0000000..8dcb2ca
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-unit-test.js
@@ -0,0 +1,218 @@
+const timer = require("timer");
+
+var setupCalled = false, teardownCalled = false;
+
+exports.setup = function() {
+ setupCalled = true;
+};
+
+exports.teardown = function() {
+ teardownCalled = true;
+ setupCalled = false;
+};
+
+// Important note - unit tests are run in alphabetical order. The following
+// unit tests for setup/teardown are order dependent, sometimes the result of
+// one test is checked in the next test (testing for teardown does this). When
+// tests are cohesively a single unit, they are named <test_name> - partN where
+// N is their order in the sequence. Secondly, because these tests should be
+// run before all others, they start with an A.
+exports.testASetupTeardownSyncTestPart1 = function(test) {
+ test.assertEqual(true, setupCalled, 'setup function was called before this');
+ test.assertEqual(false, teardownCalled, 'teardown function was not called before this');
+};
+
+exports.testASetupTeardownSyncTestPart2 = function(test) {
+ test.assertEqual(true, setupCalled, 'setup was re-called before this');
+ test.assertEqual(true, teardownCalled, 'teardown was called after first function');
+};
+
+exports.testATeardownAsyncTestPart1 = function(test) {
+ teardownCalled = false;
+
+ timer.setTimeout(function() {
+ test.assertEqual(false, teardownCalled, "teardown not called until done");
+ test.done();
+ }, 200);
+ test.waitUntilDone();
+};
+
+exports.testATeardownAsyncTestPart2 = function(test) {
+ test.assertEqual(true, teardownCalled, "teardown called after done");
+};
+
+exports.testModuleOverrides = function(test) {
+ var options = {
+ moduleOverrides: {
+ 'unit-test': {
+ foo: 5
+ }
+ }
+ };
+ var loader = test.makeSandboxedLoader(options);
+ test.assertEqual(loader.require('unit-test').foo, 5,
+ "options.moduleOverrides works");
+ loader.unload();
+};
+
+exports.testWaitUntilInstant = function(test) {
+ test.waitUntilDone();
+
+ test.waitUntil(function () true, "waitUntil with instant true pass")
+ .then(function () test.done());
+}
+
+exports.testWaitUntil = function(test) {
+ test.waitUntilDone();
+ let succeed = false;
+
+ test.waitUntil(function () succeed, "waitUntil pass")
+ .then(function () test.done());
+
+ timer.setTimeout(function () {
+ succeed = true;
+ }, 200);
+}
+
+exports.testWaitUntilEqual = function(test) {
+ test.waitUntilDone();
+ let succeed = false;
+
+ test.waitUntilEqual("foo", function () succeed ? "foo" : "bar",
+ "waitUntilEqual pass")
+ .then(function () test.done());
+
+ timer.setTimeout(function () {
+ succeed = true;
+ }, 200);
+}
+
+exports.testWaitUntilNotEqual = function(test) {
+ test.waitUntilDone();
+ let succeed = false;
+
+ test.waitUntilNotEqual("foo", function () succeed ? "bar" : "foo",
+ "waitUntilNotEqual pass")
+ .then(function () test.done());
+
+ timer.setTimeout(function () {
+ succeed = true;
+ }, 200);
+}
+
+exports.testWaitUntilMatches = function(test) {
+ test.waitUntilDone();
+ let succeed = false;
+
+ test.waitUntilMatches(function () succeed ? "foo" : "bar",
+ /foo/, "waitUntilEqual pass")
+ .then(function () test.done());
+
+ timer.setTimeout(function () {
+ succeed = true;
+ }, 200);
+}
+
+exports.testWaitUntilErrorInCallback = function(test) {
+ test.waitUntilDone();
+
+ test.expectFail(function() {
+ test.waitUntil(function () {throw "oops"}, "waitUntil pass")
+ .then(function () test.done());
+ });
+}
+
+exports.testExpectFail = function(test) {
+ test.expectFail(function() {
+ test.fail('expectFail masking .fail');
+ });
+
+ test.expectFail(function() {
+ test.assert(false, 'expectFail masking .assert');
+ });
+
+ test.assert(true, 'assert should pass with no expectFail');
+/*
+ test.expectFail(function() {
+ test.expectFail(function() {
+ test.fail('this should blow up');
+ });
+ });
+*/
+};
+
+exports.testAssertFunction = function(test) {
+ test.assertFunction(function() {}, 'assertFunction with function');
+ test.expectFail(function() {
+ test.assertFunction(null, 'assertFunction with non-function');
+ });
+};
+
+exports.testAssertUndefined = function(test) {
+ test.assertUndefined(undefined, 'assertUndefined with undefined');
+ test.expectFail(function() {
+ test.assertUndefined(null, 'assertUndefined with null');
+ });
+ test.expectFail(function() {
+ test.assertUndefined(false, 'assertUndefined with false');
+ });
+ test.expectFail(function() {
+ test.assertUndefined(0, 'assertUndefined with 0');
+ });
+};
+
+exports.testAssertNotUndefined = function(test) {
+ test.expectFail(function() {
+ test.assertNotUndefined(undefined, 'assertNotUndefined with undefined');
+ });
+ test.assertNotUndefined(null, 'assertNotUndefined with null');
+ test.assertNotUndefined(false, 'assertNotUndefined with false');
+ test.assertNotUndefined(0, 'assertNotUndefined with 0');
+};
+
+exports.testAssertNull = function(test) {
+ test.assertNull(null, 'assertNull with null');
+ test.expectFail(function() {
+ test.assertNull(undefined, 'assertNull with undefined');
+ });
+ test.expectFail(function() {
+ test.assertNull(false, 'assertNull with false');
+ });
+ test.expectFail(function() {
+ test.assertNull(0, 'assertNull with 0');
+ });
+};
+
+exports.testAssertNotNull = function(test) {
+ test.assertNotNull(undefined, 'assertNotNull with undefined');
+ test.assertNotNull(false, 'assertNotNull with false');
+ test.assertNotNull(0, 'assertNotNull with 0');
+
+ test.expectFail(function() {
+ test.assertNotNull(null, 'testAssertNotNull with null');
+ });
+};
+
+exports.testAssertObject = function(test) {
+ test.assertObject({}, 'assertObject with {}' );
+ test.assertObject(new Object(), 'assertObject with new Object');
+ test.expectFail(function() {
+ test.assertObject('fail', 'assertObject with string');
+ });
+};
+
+exports.testAssertString = function(test) {
+ test.assertString('', 'assertString with ""');
+ test.assertString(new String(), 'assertString with new String');
+};
+
+exports.testAssertArray = function(test) {
+ test.assertArray([], 'assertArray with []');
+ test.assertArray(new Array(), 'assertArray with new Array');
+};
+
+exports.testNumber = function(test) {
+ test.assertNumber(1, 'assertNumber with 1');
+ test.assertNumber(new Number('2'), 'assertNumber with new Number("2")' );
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-unload.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-unload.js
new file mode 100644
index 0000000..2f90b43
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-unload.js
@@ -0,0 +1,195 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Atul Varma <atul@mozilla.com> (Original Author)
+ * Drew Willcoxon <adw@mozilla.com>
+ * Erik Vold <erikvvold@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var unload = require("unload");
+
+exports.testUnloading = function(test) {
+ var loader = test.makeSandboxedLoader();
+ var ul = loader.require("unload");
+ var unloadCalled = 0;
+ var errorsReported = 0;
+ function unload() {
+ unloadCalled++;
+ throw new Error("error");
+ }
+ ul.when(unload);
+
+ // This should be ignored, as we already registered it
+ ul.when(unload);
+
+ function unload2() { unloadCalled++; }
+ ul.when(unload2);
+ loader.unload(undefined, function onError() { errorsReported++; });
+ test.assertEqual(unloadCalled, 2,
+ "Unloader functions are called on unload.");
+ test.assertEqual(errorsReported, 1,
+ "One unload handler threw exception");
+};
+
+exports.testEnsure = function(test) {
+ test.assertRaises(function() { unload.ensure({}); },
+ "object has no 'unload' property",
+ "passing obj with no unload prop should fail");
+ test.assertRaises(function() { unload.ensure({}, "destroy"); },
+ "object has no 'destroy' property",
+ "passing obj with no custom unload prop should fail");
+
+ var called = 0;
+ var obj = {unload: function() { called++; }};
+
+ unload.ensure(obj);
+ obj.unload();
+ test.assertEqual(called, 1,
+ "unload() should be called");
+ obj.unload();
+ test.assertEqual(called, 1,
+ "unload() should be called only once");
+};
+
+/**
+ * Check that destructors are called only once with Traits.
+ * - check that public API is calling the destructor and unregister it,
+ * - check that composed traits with multiple ensure calls, leads to only
+ * one destructor call.
+ */
+exports.testEnsureWithTraits = function(test) {
+
+ let { Trait } = require("traits");
+ let loader = test.makeSandboxedLoader();
+ let ul = loader.require("unload");
+
+ let called = 0;
+ let composedCalled = 0;
+ let composedTrait = Trait.compose({
+ constructor: function () {
+ // We have to give "public interface" of this trait, as we want to
+ // call public `unload` method and ensure that we call it only once,
+ // either when we call this public function manually or on add-on unload
+ ul.ensure(this._public);
+ },
+ unload: function unload() {
+ composedCalled++;
+ }
+ });
+ let obj = Trait.compose(
+ composedTrait.resolve({
+ constructor: "_constructor",
+ unload : "_unload"
+ }), {
+ constructor: function constructor() {
+ // Same thing applies here, we need to pass public interface
+ ul.ensure(this._public);
+ this._constructor();
+ },
+ unload: function unload() {
+ called++;
+ this._unload();
+ }
+ })();
+
+ obj.unload();
+ test.assertEqual(called, 1,
+ "unload() should be called");
+
+ test.assertEqual(composedCalled, 1,
+ "composed object unload() should be called");
+
+ obj.unload();
+ test.assertEqual(called, 1,
+ "unload() should be called only once");
+ test.assertEqual(composedCalled, 1,
+ "composed object unload() should be called only once");
+
+ loader.unload();
+ test.assertEqual(called, 1,
+ "unload() should be called only once, after addon unload");
+ test.assertEqual(composedCalled, 1,
+ "composed object unload() should be called only once, " +
+ "after addon unload");
+};
+
+exports.testEnsureWithTraitsPrivate = function(test) {
+
+ let { Trait } = require("traits");
+ let loader = test.makeSandboxedLoader();
+ let ul = loader.require("unload");
+
+ let called = 0;
+ let privateObj = null;
+ let obj = Trait.compose({
+ constructor: function constructor() {
+ // This time wa don't have to give public interface,
+ // as we want to call a private method:
+ ul.ensure(this, "_unload");
+ privateObj = this;
+ },
+ _unload: function unload() {
+ called++;
+ this._unload();
+ }
+ })();
+
+ loader.unload();
+ test.assertEqual(called, 1,
+ "unload() should be called");
+
+ privateObj._unload();
+ test.assertEqual(called, 1,
+ "_unload() should be called only once, after addon unload");
+};
+
+exports.testReason = function (test) {
+ var reason = "Reason doesn't actually have to be anything in particular.";
+ var loader = test.makeSandboxedLoader();
+ var ul = loader.require("unload");
+ ul.when(function (rsn) {
+ test.assertEqual(rsn, reason,
+ "when() reason should be reason given to loader");
+ });
+ var obj = {
+ unload: function (rsn) {
+ test.assertEqual(rsn, reason,
+ "ensure() reason should be reason given to loader");
+ }
+ };
+ ul.ensure(obj);
+ loader.unload(reason);
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-url.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-url.js
new file mode 100644
index 0000000..05a14cc
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-url.js
@@ -0,0 +1,157 @@
+var url = require("url");
+
+exports.testResolve = function(test) {
+ test.assertEqual(url.URL("bar", "http://www.foo.com/").toString(),
+ "http://www.foo.com/bar");
+
+ test.assertEqual(url.URL("bar", "http://www.foo.com"),
+ "http://www.foo.com/bar");
+
+ test.assertEqual(url.URL("http://bar.com/", "http://foo.com/"),
+ "http://bar.com/",
+ "relative should override base");
+
+ test.assertRaises(function() { url.URL("blah"); },
+ "malformed URI: blah",
+ "url.resolve() should throw malformed URI on base");
+
+ test.assertRaises(function() { url.URL("chrome://global"); },
+ "invalid URI: chrome://global",
+ "url.resolve() should throw invalid URI on base");
+
+ test.assertRaises(function() { url.URL("chrome://foo/bar"); },
+ "invalid URI: chrome://foo/bar",
+ "url.resolve() should throw on bad chrome URI");
+
+ test.assertEqual(url.URL("", "http://www.foo.com"),
+ "http://www.foo.com/",
+ "url.resolve() should add slash to end of domain");
+};
+
+exports.testParseHttp = function(test) {
+ var info = url.URL("http://foo.com/bar");
+ test.assertEqual(info.scheme, "http");
+ test.assertEqual(info.host, "foo.com");
+ test.assertEqual(info.port, null);
+ test.assertEqual(info.userPass, null);
+ test.assertEqual(info.path, "/bar");
+};
+
+exports.testParseHttpWithPort = function(test) {
+ var info = url.URL("http://foo.com:5/bar");
+ test.assertEqual(info.port, 5);
+};
+
+exports.testParseChrome = function(test) {
+ var info = url.URL("chrome://global/content/blah");
+ test.assertEqual(info.scheme, "chrome");
+ test.assertEqual(info.host, "global");
+ test.assertEqual(info.port, null);
+ test.assertEqual(info.userPass, null);
+ test.assertEqual(info.path, "/content/blah");
+};
+
+exports.testParseAbout = function(test) {
+ var info = url.URL("about:boop");
+ test.assertEqual(info.scheme, "about");
+ test.assertEqual(info.host, null);
+ test.assertEqual(info.port, null);
+ test.assertEqual(info.userPass, null);
+ test.assertEqual(info.path, "boop");
+};
+
+exports.testParseFTP = function(test) {
+ var info = url.URL("ftp://1.2.3.4/foo");
+ test.assertEqual(info.scheme, "ftp");
+ test.assertEqual(info.host, "1.2.3.4");
+ test.assertEqual(info.port, null);
+ test.assertEqual(info.userPass, null);
+ test.assertEqual(info.path, "/foo");
+};
+
+exports.testParseFTPWithUserPass = function(test) {
+ var info = url.URL("ftp://user:pass@1.2.3.4/foo");
+ test.assertEqual(info.userPass, "user:pass");
+};
+
+exports.testToFilename = function(test) {
+ test.assertRaises(
+ function() { url.toFilename("resource://nonexistent"); },
+ "resource does not exist: resource://nonexistent/",
+ "url.toFilename() on nonexistent resources should throw"
+ );
+
+ test.assertMatches(url.toFilename(__url__),
+ /.*test-url\.js$/,
+ "url.toFilename() on resource: URIs should work");
+
+ test.assertRaises(
+ function() { url.toFilename("http://foo.com/"); },
+ "cannot map to filename: http://foo.com/",
+ "url.toFilename() on http: URIs should raise error"
+ );
+
+ try {
+ test.assertMatches(
+ url.toFilename("chrome://global/content/console.xul"),
+ /.*console\.xul$/,
+ "url.toFilename() w/ console.xul works when it maps to filesystem"
+ );
+ } catch (e) {
+ if (/chrome url isn\'t on filesystem/.test(e.message))
+ test.pass("accessing console.xul in jar raises exception");
+ else
+ test.fail("accessing console.xul raises " + e);
+ }
+
+ // TODO: Are there any chrome URLs that we're certain exist on the
+ // filesystem?
+ // test.assertMatches(url.toFilename("chrome://myapp/content/main.js"),
+ // /.*main\.js$/);
+};
+
+exports.testFromFilename = function(test) {
+ var fileUrl = url.fromFilename(url.toFilename(__url__));
+ test.assertEqual(url.URL(fileUrl).scheme, 'file',
+ 'url.toFilename() should return a file: url');
+ test.assertEqual(url.fromFilename(url.toFilename(fileUrl)),
+ fileUrl);
+};
+
+exports.testURL = function(test) {
+ let URL = url.URL;
+ test.assert(URL("h:foo") instanceof URL, "instance is of correct type");
+ test.assertRaises(function() URL(),
+ "malformed URI: undefined",
+ "url.URL should throw on undefined");
+ test.assertRaises(function() URL(""),
+ "malformed URI: ",
+ "url.URL should throw on empty string");
+ test.assertRaises(function() URL("foo"),
+ "malformed URI: foo",
+ "url.URL should throw on invalid URI");
+ test.assert(URL("h:foo").scheme, "has scheme");
+ test.assertEqual(URL("h:foo").toString(),
+ "h:foo",
+ "toString should roundtrip");
+ // test relative + base
+ test.assertEqual(URL("mypath", "http://foo").toString(),
+ "http://foo/mypath",
+ "relative URL resolved to base");
+ // test relative + no base
+ test.assertRaises(function() URL("path").toString(),
+ "malformed URI: path",
+ "no base for relative URI should throw");
+
+ let a = URL("h:foo");
+ let b = URL(a);
+ test.assertEqual(b.toString(),
+ "h:foo",
+ "a URL can be initialized from another URL");
+ test.assertNotStrictEqual(a, b,
+ "a URL initialized from another URL is not the same object");
+ test.assert(a == "h:foo",
+ "toString is implicit when a URL is compared to a string via ==");
+ test.assertStrictEqual(a + "", "h:foo",
+ "toString is implicit when a URL is concatenated to a string");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-loader.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-loader.js
new file mode 100644
index 0000000..fc6f144
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-loader.js
@@ -0,0 +1,152 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Jetpack.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Irakli Gozalishvili <gozala@mozilla.com> (Original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+"use strict";
+
+const { WindowLoader } = require('windows/loader'),
+ { Trait } = require('traits');
+
+const Loader = Trait.compose(
+ WindowLoader,
+ {
+ constructor: function Loader(options) {
+ this._onLoad = options.onLoad;
+ this._onUnload = options.onUnload;
+ if ('window' in options)
+ this._window = options.window;
+ this._load();
+ this.window = this._window;
+ },
+ window: null,
+ _onLoad: null,
+ _onUnload: null,
+ _tabOptions: []
+ }
+);
+
+exports['test compositions with missing required properties'] = function(test) {
+ test.assertRaises(
+ function() WindowLoader.compose({})(),
+ 'Missing required property: _onLoad',
+ 'should throw missing required property exception'
+ );
+ test.assertRaises(
+ function() WindowLoader.compose({ _onLoad: null, _tabOptions: null })(),
+ 'Missing required property: _onUnload',
+ 'should throw missing required property `_onUnload`'
+ );
+ test.assertRaises(
+ function() WindowLoader.compose({ _onUnload: null, _tabOptions: null })(),
+ 'Missing required property: _onLoad',
+ 'should throw missing required property `_onLoad`'
+ );
+ test.assertRaises(
+ function() WindowLoader.compose({ _onUnload: null, _onLoad: null })(),
+ 'Missing required property: _tabOptions',
+ 'should throw missing required property `_tabOptions`'
+ );
+};
+
+exports['test `load` events'] = function(test) {
+ test.waitUntilDone();
+ let onLoadCalled = false;
+ Loader({
+ onLoad: function(window) {
+ onLoadCalled = true;
+ test.assertEqual(
+ window, this._window, 'windows should match'
+ );
+ test.assertEqual(
+ window.document.readyState, 'complete', 'window must be fully loaded'
+ );
+ window.close();
+ },
+ onUnload: function(window) {
+ test.assertEqual(
+ window, this._window, 'windows should match'
+ );
+ test.assertEqual(
+ window.document.readyState, 'complete', 'window must be fully loaded'
+ );
+ test.assert(onLoadCalled, 'load callback is supposed to be called');
+ test.done();
+ }
+ });
+};
+
+exports['test removeing listeners'] = function(test) {
+ test.waitUntilDone();
+ Loader({
+ onLoad: function(window) {
+ test.assertEqual(
+ window, this._window, 'windows should match'
+ );
+ window.close();
+ },
+ onUnload: function(window) {
+ test.done();
+ }
+ });
+};
+
+exports['test create loader from opened window'] = function(test) {
+ test.waitUntilDone();
+ let onUnloadCalled = false;
+ Loader({
+ onLoad: function(window) {
+ test.assertEqual(
+ window, this._window, 'windows should match'
+ );
+ test.assertEqual(
+ window.document.readyState, 'complete', 'window must be fully loaded'
+ );
+ Loader({
+ window: window,
+ onLoad: function(win) {
+ test.assertEqual(win, window, 'windows should match');
+ window.close();
+ },
+ onUnload: function(window) {
+ test.assert(onUnloadCalled, 'first handler should be called already');
+ test.done();
+ }
+ });
+ },
+ onUnload: function(window) {
+ onUnloadCalled = true;
+ }
+ });
+};
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-observer.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-observer.js
new file mode 100644
index 0000000..8e32f5d
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-observer.js
@@ -0,0 +1,42 @@
+"use strict";
+
+exports["test unload window observer"] = function(assert, done) {
+ // Hacky way to be able to create unloadable modules via makeSandboxedLoader.
+ let loader = assert._log.makeSandboxedLoader();
+
+ let utils = loader.require("api-utils/window-utils");
+ let { isBrowser, activeBrowserWindow: activeWindow } = utils;
+ let observer = loader.require("api-utils/windows/observer").observer;
+ let opened = 0;
+ let closed = 0;
+
+ observer.on("open", function onOpen(window) {
+ // Ignoring non-browser windows
+ if (isBrowser(window))
+ opened++;
+ });
+ observer.on("close", function onClose(window) {
+ // Ignore non-browser windows & already opened `activeWindow` (unload will
+ // emit close on it even though it is not actually closed).
+ if (isBrowser(window) && window !== activeWindow)
+ closed++;
+ });
+
+ // Open window and close it to trigger observers.
+ activeWindow.open().close();
+
+ // Unload the module so that all listeners set by observer are removed.
+ loader.unload();
+
+ // Open and close window once again.
+ activeWindow.open().close();
+
+ // Enqueuing asserts to make sure that assertion is not performed early.
+ require("timer").setTimeout(function () {
+ assert.equal(1, opened, "observer open was called before unload only");
+ assert.equal(1, closed, "observer close was called before unload only");
+ done();
+ }, 0);
+};
+
+require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-utils.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-utils.js
new file mode 100644
index 0000000..c5a5c78
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-window-utils.js
@@ -0,0 +1,276 @@
+var windowUtils = require("window-utils");
+var timer = require("timer");
+var {Cc,Ci} = require("chrome");
+
+function makeEmptyWindow() {
+ var xulNs = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ var blankXul = ('<?xml version="1.0"?>' +
+ '<?xml-stylesheet href="chrome://global/skin/" ' +
+ ' type="text/css"?>' +
+ '<window xmlns="' + xulNs + '" windowtype="test:window">' +
+ '</window>');
+ var url = "data:application/vnd.mozilla.xul+xml," + escape(blankXul);
+ var features = ["chrome", "width=10", "height=10"];
+
+ var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Ci.nsIWindowWatcher);
+ return ww.openWindow(null, url, null, features.join(","), null);
+}
+
+exports.testCloseOnUnload = function(test) {
+ var timesClosed = 0;
+ var fakeWindow = {
+ _listeners: [],
+ addEventListener: function(name, func, bool) {
+ this._listeners.push(func);
+ },
+ removeEventListener: function(name, func, bool) {
+ var index = this._listeners.indexOf(func);
+ if (index == -1)
+ throw new Error("event listener not found");
+ this._listeners.splice(index, 1);
+ },
+ close: function() {
+ timesClosed++;
+ this._listeners.forEach(
+ function(func) {
+ func({target: fakeWindow.document});
+ });
+ },
+ document: {
+ get defaultView() { return fakeWindow; }
+ }
+ };
+
+ var loader = test.makeSandboxedLoader();
+ loader.require("window-utils").closeOnUnload(fakeWindow);
+ test.assertEqual(fakeWindow._listeners.length, 1,
+ "unload listener added on closeOnUnload()");
+ test.assertEqual(timesClosed, 0,
+ "window not closed when registered.");
+ loader.require("unload").send();
+ test.assertEqual(timesClosed, 1,
+ "window closed on module unload.");
+ test.assertEqual(fakeWindow._listeners.length, 0,
+ "unload event listener removed on module unload");
+
+ timesClosed = 0;
+ loader.require("window-utils").closeOnUnload(fakeWindow);
+ test.assertEqual(timesClosed, 0,
+ "window not closed when registered.");
+ fakeWindow.close();
+ test.assertEqual(timesClosed, 1,
+ "window closed when close() called.");
+ test.assertEqual(fakeWindow._listeners.length, 0,
+ "unload event listener removed on window close");
+ loader.require("unload").send();
+ test.assertEqual(timesClosed, 1,
+ "window not closed again on module unload.");
+ loader.unload();
+};
+
+exports.testWindowWatcher = function(test) {
+ var myWindow;
+ var finished = false;
+
+ var delegate = {
+ onTrack: function(window) {
+ if (window == myWindow) {
+ test.pass("onTrack() called with our test window");
+ timer.setTimeout(function() { myWindow.close(); }, 1);
+ }
+ },
+ onUntrack: function(window) {
+ if (window == myWindow) {
+ test.pass("onUntrack() called with our test window");
+ timer.setTimeout(function() {
+ if (!finished) {
+ finished = true;
+ myWindow = null;
+ wt.unload();
+ test.done();
+ } else
+ test.fail("finishTest() called multiple times.");
+ }, 1);
+ }
+ }
+ };
+
+ var wt = new windowUtils.WindowTracker(delegate);
+ myWindow = makeEmptyWindow();
+ test.waitUntilDone(5000);
+};
+
+// test that _unregWindow calls _unregLoadingWindow
+exports.testWindowWatcherUnregs4LoadingWindows = function(test) {
+ var myWindow;
+ var finished = false;
+ let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getMostRecentWindow("navigator:browser");
+ var counter = 0;
+
+ var delegate = {
+ onTrack: function(window) {
+ var type = window.document.documentElement.getAttribute("windowtype");
+ if (type == "test:window")
+ test.fail("onTrack shouldn't have been executed.");
+ }
+ };
+ var wt = new windowUtils.WindowTracker(delegate);
+
+ // make a new window
+ myWindow = makeEmptyWindow();
+
+ // make sure that the window hasn't loaded yet
+ test.assertNotEqual(
+ myWindow.document.readyState,
+ "complete",
+ "window hasn't loaded yet.");
+
+ // unload WindowTracker
+ wt.unload();
+
+ // make sure that the window still hasn't loaded, which means that the onTrack
+ // would have been removed successfully assuming that it doesn't execute.
+ test.assertNotEqual(
+ myWindow.document.readyState,
+ "complete",
+ "window still hasn't loaded yet.");
+
+ // wait for the window to load and then close it. onTrack wouldn't be called
+ // until the window loads, so we must let it load before closing it to be
+ // certain that onTrack was removed.
+ myWindow.addEventListener("load", function() {
+ // allow all of the load handles to execute before closing
+ myWindow.setTimeout(function() {
+ myWindow.addEventListener("unload", function() {
+ // once the window unloads test is done
+ test.done();
+ }, false);
+ myWindow.close();
+ }, 0);
+ }, false);
+
+ test.waitUntilDone(5000);
+}
+
+exports.testWindowWatcherWithoutUntracker = function(test) {
+ var myWindow;
+ var finished = false;
+
+ var delegate = {
+ onTrack: function(window) {
+ if (window == myWindow) {
+ test.pass("onTrack() called with our test window");
+ timer.setTimeout(function() {
+ myWindow.close();
+
+ if (!finished) {
+ finished = true;
+ myWindow = null;
+ wt.unload();
+ test.done();
+ } else {
+ test.fail("onTrack() called multiple times.");
+ }
+ }, 1);
+ }
+ }
+ };
+
+ var wt = new windowUtils.WindowTracker(delegate);
+ myWindow = makeEmptyWindow();
+ test.waitUntilDone(5000);
+};
+
+exports.testActiveWindow = function(test) {
+ test.waitUntilDone(5000);
+
+ let testRunnerWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getMostRecentWindow(null);
+ let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getMostRecentWindow("navigator:browser");
+
+ test.assertEqual(windowUtils.activeWindow, testRunnerWindow,
+ "Test runner is the active window.");
+
+ test.assertEqual(windowUtils.activeBrowserWindow, browserWindow,
+ "Browser window is the active browser window.");
+
+
+ let testSteps = [
+ function() {
+ windowUtils.activeWindow = browserWindow;
+ continueAfterFocus(browserWindow);
+ },
+ function() {
+ test.assertEqual(windowUtils.activeWindow, browserWindow,
+ "Correct active window [1]");
+ windowUtils.activeWindow = testRunnerWindow;
+ continueAfterFocus(testRunnerWindow);
+ },
+ function() {
+ test.assertEqual(windowUtils.activeWindow, testRunnerWindow,
+ "Correct active window [2]");
+ test.assertEqual(windowUtils.activeBrowserWindow, browserWindow,
+ "Correct active browser window [3]");
+ windowUtils.activeWindow = browserWindow;
+ continueAfterFocus(browserWindow);
+ },
+ function() {
+ test.assertEqual(windowUtils.activeWindow, browserWindow,
+ "Correct active window [4]");
+ windowUtils.activeWindow = testRunnerWindow;
+ continueAfterFocus(testRunnerWindow);
+ },
+ function() {
+ test.assertEqual(windowUtils.activeWindow, testRunnerWindow,
+ "Correct active window [5]");
+ test.assertEqual(windowUtils.activeBrowserWindow, browserWindow,
+ "Correct active browser window [6]");
+ testRunnerWindow = null;
+ browserWindow = null;
+ test.done()
+ }
+ ];
+
+ let nextTest = function() {
+ let func = testSteps.shift();
+ if (func) {
+ func();
+ }
+ }
+
+ function continueAfterFocus(targetWindow) {
+
+ // Based on SimpleTest.waitForFocus
+ var fm = Cc["@mozilla.org/focus-manager;1"].
+ getService(Ci.nsIFocusManager);
+
+ var childTargetWindow = {};
+ fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow);
+ childTargetWindow = childTargetWindow.value;
+
+ var focusedChildWindow = {};
+ if (fm.activeWindow) {
+ fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow);
+ focusedChildWindow = focusedChildWindow.value;
+ }
+
+ var focused = (focusedChildWindow == childTargetWindow);
+ if (focused) {
+ nextTest();
+ } else {
+ childTargetWindow.addEventListener("focus", function focusListener() {
+ childTargetWindow.removeEventListener("focus", focusListener, true);
+ nextTest();
+ }, true);
+ }
+
+ }
+
+ nextTest();
+}
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-xhr.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-xhr.js
new file mode 100644
index 0000000..1b2a706
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-xhr.js
@@ -0,0 +1,67 @@
+var xhr = require("xhr");
+var timer = require("timer");
+
+exports.testAbortedXhr = function(test) {
+ var req = new xhr.XMLHttpRequest();
+ test.assertEqual(xhr.getRequestCount(), 1);
+ req.abort();
+ test.assertEqual(xhr.getRequestCount(), 0);
+};
+
+exports.testLocalXhr = function(test) {
+ var req = new xhr.XMLHttpRequest();
+ req.overrideMimeType("text/plain");
+ req.open("GET", __url__);
+ req.onreadystatechange = function() {
+ if (req.readyState == 4 && req.status == 0) {
+ test.assertMatches(req.responseText,
+ /onreadystatechange/,
+ "XMLHttpRequest should get local files");
+ timer.setTimeout(
+ function() { test.assertEqual(xhr.getRequestCount(), 0);
+ test.done(); },
+ 0
+ );
+ }
+ };
+ req.send(null);
+ test.assertEqual(xhr.getRequestCount(), 1);
+ test.waitUntilDone(4000);
+};
+
+exports.testUnload = function(test) {
+ var loader = test.makeSandboxedLoader();
+ var sbxhr = loader.require("xhr");
+ var req = new sbxhr.XMLHttpRequest();
+ req.overrideMimeType("text/plain");
+ req.open("GET", __url__);
+ req.send(null);
+ test.assertEqual(sbxhr.getRequestCount(), 1);
+ loader.unload();
+ test.assertEqual(sbxhr.getRequestCount(), 0);
+};
+
+exports.testDelegatedReturns = function(test) {
+ var req = new xhr.XMLHttpRequest();
+ req.overrideMimeType("text/plain");
+ req.open("GET", __url__);
+ req.onreadystatechange = function() {
+ if (req.readyState == 4 && req.status == 0) {
+ // This response isn't going to have any headers, so the return value
+ // should be null. Previously it wasn't returning anything, and thus was
+ // undefined.
+
+ // Depending on whether Bug 608939 has been applied
+ // to the platform, getAllResponseHeaders() may return
+ // null or the empty string; accept either.
+ var headers = req.getAllResponseHeaders();
+ test.assert(headers === null || headers === "",
+ "XHR's delegated methods should return");
+ test.done();
+ }
+ };
+ req.send(null);
+ test.assertEqual(xhr.getRequestCount(), 1);
+ test.waitUntilDone(4000);
+}
+
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-xpcom.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-xpcom.js
new file mode 100644
index 0000000..b154eb6
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-xpcom.js
@@ -0,0 +1,106 @@
+var traceback = require("traceback");
+var xpcom = require("xpcom");
+var {Cc,Ci,Cm,Cr} = require("chrome");
+
+exports.testRegister = function(test, text) {
+ if (!text)
+ text = "hai2u";
+
+ function Component() {}
+
+ Component.prototype = {
+ newChannel : function(aURI) {
+ var ios = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+
+ var channel = ios.newChannel(
+ "data:text/plain," + text,
+ null,
+ null
+ );
+
+ channel.originalURI = aURI;
+ return channel;
+ },
+ getURIFlags: function(aURI) {
+ return Ci.nsIAboutModule.ALLOW_SCRIPT;
+ },
+ QueryInterface: xpcom.utils.generateQI([Ci.nsIAboutModule])
+ };
+
+ var contractID = "@mozilla.org/network/protocol/about;1?what=boop";
+
+ var factory = xpcom.register({name: "test about:boop page",
+ contractID: contractID,
+ create: Component});
+
+ var manager = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ test.assertEqual(manager.isCIDRegistered(factory.uuid), true);
+
+ // We don't want to use Cc[contractID] here because it's immutable,
+ // so it can't accept updated versions of a contractID during the
+ // same application session.
+ var aboutFactory = xpcom.getClass(contractID, Ci.nsIFactory);
+
+ test.assertNotEqual(aboutFactory.wrappedJSObject,
+ undefined,
+ "Factory wrappedJSObject should exist.");
+
+ var about = aboutFactory.createInstance(null, Ci.nsIAboutModule);
+ var ios = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+ test.assertEqual(
+ about.getURIFlags(ios.newURI("http://foo.com", null, null)),
+ Ci.nsIAboutModule.ALLOW_SCRIPT
+ );
+
+ var aboutURI = ios.newURI("about:boop", null, null);
+ var channel = ios.newChannelFromURI(aboutURI);
+ var iStream = channel.open();
+ var siStream = Cc['@mozilla.org/scriptableinputstream;1']
+ .createInstance(Ci.nsIScriptableInputStream);
+ siStream.init(iStream);
+ var data = new String();
+ data += siStream.read(-1);
+ siStream.close();
+ iStream.close();
+ test.assertEqual(data, text);
+
+ factory.unregister();
+ test.assertEqual(manager.isCIDRegistered(factory.uuid), false);
+};
+
+exports.testReRegister = function(test) {
+ exports.testRegister(test, "hai2u again");
+};
+
+exports.testMakeUuid = function(test) {
+ var first = xpcom.makeUuid().toString();
+ var second = xpcom.makeUuid().toString();
+ test.assertMatches(first, /{[0-9a-f\-]+}/);
+ test.assertMatches(second, /{[0-9a-f\-]+}/);
+ test.assertNotEqual(first, second);
+};
+
+exports.testUnload = function(test) {
+ var loader = test.makeSandboxedLoader();
+ var sbxpcom = loader.require("xpcom");
+
+ function Component() {}
+
+ Component.prototype = {
+ QueryInterface: sbxpcom.utils.generateQI([Ci.nsISupports])
+ };
+
+ var contractID = "@mozilla.org/blargle;1";
+ var factory = sbxpcom.register({name: "test component",
+ contractID: contractID,
+ create: Component});
+
+ var manager = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ test.assertEqual(manager.isCIDRegistered(factory.uuid), true);
+
+ loader.unload();
+
+ test.assertEqual(manager.isCIDRegistered(factory.uuid), false);
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/test-xul-app.js b/tools/addon-sdk-1.3/packages/api-utils/tests/test-xul-app.js
new file mode 100644
index 0000000..cda4a2e
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/test-xul-app.js
@@ -0,0 +1,41 @@
+var xulApp = require("xul-app");
+
+exports.testXulApp = function(test) {
+ test.assertEqual(typeof(xulApp.ID), "string",
+ "ID is a string");
+ test.assertEqual(typeof(xulApp.name), "string",
+ "name is a string");
+ test.assertEqual(typeof(xulApp.version), "string",
+ "version is a string");
+ test.assertEqual(typeof(xulApp.platformVersion), "string",
+ "platformVersion is a string");
+
+ test.assertRaises(function() { xulApp.is("blargy"); },
+ "Unkown Mozilla Application: blargy",
+ "is() throws error on bad app name");
+ test.assertRaises(function() { xulApp.isOneOf(["blargy"]); },
+ "Unkown Mozilla Application: blargy",
+ "isOneOf() throws error on bad app name");
+
+ function testSupport(name) {
+ var item = xulApp.is(name);
+ test.assert(item === true || item === false,
+ "is('" + name + "') is true or false.");
+ }
+
+ var apps = ["Firefox", "Mozilla", "Sunbird", "SeaMonkey",
+ "Fennec", "Thunderbird"];
+
+ apps.forEach(function(name) { testSupport(name); });
+
+ test.assert(xulApp.isOneOf(apps) == true ||
+ xulApp.isOneOf(apps) == false,
+ "isOneOf() returns true or false.");
+
+ test.assertEqual(xulApp.versionInRange(xulApp.platformVersion, "1.9", "*"),
+ true, "platformVersion in range [1.9, *)");
+ test.assertEqual(xulApp.versionInRange("3.6.4", "3.6.4", "3.6.*"),
+ true, "3.6.4 in [3.6.4, 3.6.*)");
+ test.assertEqual(xulApp.versionInRange("1.9.3", "1.9.2", "1.9.3"),
+ false, "1.9.3 not in [1.9.2, 1.9.3)");
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/traits/assert.js b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/assert.js
new file mode 100644
index 0000000..dd662a4
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/assert.js
@@ -0,0 +1,94 @@
+"use strict";
+
+var BaseAssert = require("test/assert").Assert;
+
+/**
+ * Whether or not given property descriptors are equivalent. They are
+ * equivalent either if both are marked as "conflict" or "required" property
+ * or if all the properties of descriptors are equal.
+ * @param {Object} actual
+ * @param {Object} expected
+ */
+function equivalentDescriptors(actual, expected) {
+ return (actual.conflict && expected.conflict) ||
+ (actual.required && expected.required) ||
+ equalDescriptors(actual, expected);
+}
+
+function equalDescriptors(actual, expected) {
+ return actual.get === expected.get &&
+ actual.set === expected.set &&
+ actual.value === expected.value &&
+ !!actual.enumerable === !!expected.enumerable &&
+ !!actual.configurable === !!expected.configurable &&
+ !!actual.writable === !!expected.writable;
+}
+
+/**
+ * Whether or not given `target` array contains all the element
+ * from a given `source` array.
+ */
+function containsSet(source, target) {
+ return source.some(function(element) {
+ return 0 > target.indexOf(element);
+ });
+}
+
+/**
+ * Whether or not given two arrays contain all elements from another.
+ */
+function equivalentSets(source, target) {
+ return containsSet(source, target) && containsSet(target, source);
+}
+
+/**
+ * Finds name of the property from `source` property descriptor map, that
+ * is not equivalent of the name named property in the `target` property
+ * descriptor map. If not found `null` is returned instead.
+ */
+function findNonEquivalentPropertyName(source, target) {
+ var value = null;
+ Object.getOwnPropertyNames(source).some(function(key) {
+ var areEquivalent = false;
+ if (!equivalentDescriptors(source[key], target[key])) {
+ value = key;
+ areEquivalent = true;
+ }
+ return areEquivalent;
+ });
+ return value;
+}
+
+var AssertDescriptor = {
+ equalTraits: {
+ value: function equivalentTraits(actual, expected, message) {
+ var difference;
+ var actualKeys = Object.getOwnPropertyNames(actual);
+ var expectedKeys = Object.getOwnPropertyNames(expected);
+
+ if (equivalentSets(actualKeys, expectedKeys)) {
+ this.fail({
+ operator: "equalTraits",
+ message: "Traits define different properties",
+ actual: actualKeys.sort().join(","),
+ expected: expectedKeys.sort().join(","),
+ });
+ }
+ else if ((difference = findNonEquivalentPropertyName(actual, expected))) {
+ this.fail({
+ operator: "equalTraits",
+ message: "Traits define non-equivalent property `" + difference + "`",
+ actual: actual[difference],
+ expected: expected[difference]
+ });
+ }
+ else {
+ this.pass(message || "Traits are equivalent.");
+ }
+ }
+ }
+};
+
+exports.Assert = function Assert() {
+ return Object.create(BaseAssert.apply(null, arguments), AssertDescriptor);
+};
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/traits/descriptor-tests.js b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/descriptor-tests.js
new file mode 100644
index 0000000..7c27ac4
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/descriptor-tests.js
@@ -0,0 +1,331 @@
+"use strict";
+
+var Trait = require("light-traits").Trait;
+var utils = require("./utils");
+var Data = utils.Data;
+var Method = utils.Method;
+var Accessor = utils.Accessor;
+var Required = utils.Required;
+var Conflict = utils.Conflict;
+
+function method() {}
+
+exports.Assert = require("./assert").Assert
+exports["test simple composition"] = function(assert) {
+ var actual = Trait.compose(
+ Trait({ a: 0, b: 1 }),
+ { c: { value: 2 }, d: { value: method, enumerable: true } }
+ );
+
+ var expected = {
+ a: Data(0),
+ b: Data(1),
+ c: Data(2, false, false, false),
+ d: Method(method, true, false, false)
+ };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition with conflict"] = function(assert) {
+ var actual = Trait.compose(
+ Trait({ a: 0, b: 1 }),
+ {
+ a: {
+ value: 2,
+ writable: true,
+ configurable: true,
+ enumerable: true
+ },
+ c: {
+ value: method,
+ configurable: true
+ }
+ }
+ );
+
+ var expected = {
+ a: Conflict("a"),
+ b: Data(1),
+ c: Method(method, false, true, false)
+ };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test identical props does not cause conflict"] = function(assert) {
+ var actual = Trait.compose(
+ {
+ a: {
+ value: 0,
+ writable: true,
+ configurable: true,
+ enumerable: true
+ },
+ b: {
+ value: 1
+ }
+ },
+ Trait({
+ a: 0,
+ c: method
+ })
+ );
+
+ var expected = {
+ a: Data(0),
+ b: Data(1, false, false, false),
+ c: Method(method)
+ }
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition with identical required props"] = function(assert) {
+ var actual = Trait.compose(
+ Trait({ a: Trait.required, b: 1 }),
+ { a: { required: true }, c: { value: method } }
+ );
+
+ var expected = {
+ a: Required(),
+ b: Data(1),
+ c: Method(method, false, false, false)
+ };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition satisfying a required prop"] = function(assert) {
+ var actual = Trait.compose(
+ Trait({ a: Trait.required, b: 1 }),
+ { a: { value: method, enumerable: true } }
+ );
+
+ var expected = {
+ a: Method(method, true, false, false),
+ b: Data(1)
+ };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is neutral wrt conflicts"] = function(assert) {
+ var actual = Trait.compose(
+ Trait({ a: { value: 1 } }, Trait({ a: 2 })),
+ { b: { value: 0, writable: true, configurable: true, enumerable: false } }
+ );
+
+ var expected = { a: Conflict("a"), b: Data(0, false) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test conflicting prop overrides Trait.required"] = function(assert) {
+ var actual = Trait.compose(
+ Trait.compose(
+ Trait({ a: 1 }),
+ { a: { value: 2 } }
+ ),
+ { a: { value: Trait.required } }
+ );
+
+ var expected = { a: Conflict("a") };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is commutative"] = function(assert) {
+ var actual = Trait.compose(
+ Trait({ a: 0, b: 1 }),
+ { c: { value: 2 }, d: { value: method } }
+ );
+
+ var expected = Trait.compose(
+ { c: { value: 2 }, d: { value: method } },
+ Trait({ a: 0, b: 1 })
+ );
+
+ assert.equalTraits(actual, expected);
+}
+
+exports["test compose is commutative, also for required/conflicting props"] = function(assert) {
+ var actual = Trait.compose(
+ {
+ a: { value: 0 },
+ b: { value: 1 },
+ c: { value: 3 },
+ e: { value: Trait.required }
+ },
+ {
+ c: { value: 2 },
+ d: { get: method }
+ }
+ );
+
+ var expected = Trait.compose(
+ Trait({ c: 3 }),
+ {
+ c: { value: 2 },
+ d: { get: method },
+ a: { value: 0 },
+ b: { value: 1 },
+ e: { value: Trait.required },
+ }
+ );
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is associative"] = function(assert) {
+ var actual = Trait.compose(
+ {
+ a: { value: 0 },
+ b: { value: 1 },
+ c: { value: 3 },
+ d: { value: Trait.required }
+ },
+ Trait.compose(
+ { c: { value: 3 }, d: { value: Trait.required } },
+ { c: { value: 2 }, d: { value: method }, e: { value: "foo" } }
+ )
+ );
+
+ var expected = Trait.compose(
+ Trait.compose(
+ {
+ a: { value: 0 },
+ b: { value: 1 },
+ c: { value: 3 },
+ d: { value: Trait.required }
+ },
+ {
+ c: { value: 3 },
+ d: { value: Trait.required }
+ }
+ ),
+ {
+ c: { value: 2 },
+ d: { value: method },
+ e: { value: "foo" }
+ }
+ );
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test diamond import of same prop do not conflict"] = function(assert) {
+ var actual = Trait.compose(
+ Trait.compose(
+ { b: { value: 2 } },
+ { a: { value: 1, enumerable: true, configurable: true, writable: true } }
+ ),
+ Trait.compose(
+ { c: { value: 3 } },
+ Trait({ a: 1 })
+ ),
+ Trait({ d: 4 })
+ );
+
+ var expected = {
+ a: Data(1),
+ b: Data(2, false, false, false),
+ c: Data(3, false, false, false),
+ d: Data(4)
+ };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test create simple"] = function(assert) {
+ var o1 = Trait.compose(
+ Trait({ a: 1 }),
+ {
+ b: {
+ value: function() {
+ return this.a;
+ }
+ }
+ }
+ ).create(Object.prototype);
+
+ assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype");
+ assert.equal(1, o1.a, "o1.a");
+ assert.equal(1, o1.b(), "o1.b()");
+ assert.equal(Object.keys(o1).length, 1, "Object.keys(o1).length === 2");
+};
+
+exports["test create with Array.prototype"] = function(assert) {
+ var o2 = Trait.compose({}, {}).create(Array.prototype);
+ assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype");
+};
+
+exports["test exception for incomplete required properties"] = function(assert) {
+ assert.throws(function() {
+ Trait({ foo: Trait.required }).create(Object.prototype)
+ }, /Missing required property: `foo`/, "required prop error");
+}
+
+exports["test exception for unresolved conflicts"] = function(assert) {
+ assert.throws(function() {
+ Trait(Trait({ a: 0 }), Trait({ a: 1 })).create({})
+ }, /Remaining conflicting property: `a`/, "conflicting prop error");
+}
+
+exports["test conflicting properties are present"] = function(assert) {
+ var o5 = Object.create(Object.prototype, Trait.compose(
+ { a: { value: 0 } },
+ { a: { value: 1 } }
+ ));
+
+ assert.ok("a" in o5, "conflicting property present");
+ assert.throws(function() {
+ o5.a
+ }, /Remaining conflicting property: `a`/, "conflicting prop access error");
+};
+
+exports["test diamond with conflicts"] = function(assert) {
+ function makeT1(x) {
+ return {
+ m: {
+ value: function() {
+ return x
+ }
+ }
+ };
+ };
+
+ function makeT2(x) {
+ return Trait.compose(
+ Trait({ t2: "foo" }),
+ makeT1(x)
+ );
+ };
+
+ function makeT3(x) {
+ return Trait.compose(
+ {
+ t3: { value: "bar" }
+ },
+ makeT1(x)
+ );
+ };
+
+ var T4 = Trait.compose(makeT2(5), makeT3(5));
+
+ assert.throws(function() {
+ T4.create(Object.prototype);
+ }, /Remaining conflicting property: `m`/, "diamond prop conflict");
+};
+
+exports["test providing requirements through proto"] = function(assert) {
+ var t = Trait.compose(
+ {},
+ { required: { required: true } }
+ ).create({ required: "test" });
+
+ assert.equal(t.required, "test", "property from proto is inherited");
+};
+
+if (module == require.main)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/traits/inheritance-tests.js b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/inheritance-tests.js
new file mode 100644
index 0000000..73a23b7
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/inheritance-tests.js
@@ -0,0 +1,100 @@
+"use strict";
+
+var Trait = require("light-traits").Trait;
+
+exports["test custom constructor and inherited toString"] = function(assert) {
+ function Type() {
+ return Object.create(Type.prototype);
+ }
+ Type.prototype = Trait({
+ method: function method() {
+ return 2;
+ }
+ }).create(Object.freeze(Type.prototype));
+
+ var fixture = Type();
+
+ assert.equal(fixture.constructor, Type, "must override constructor");
+ assert.equal(fixture.toString(), "[object Type]", "must inherit toString");
+};
+
+exports["test custom toString and inherited constructor"] = function(assert) {
+ function Type() {
+ return Object.create(Type.prototype);
+ }
+ Type.prototype = Trait({
+ toString: function toString() {
+ return "<toString>";
+ }
+ }).create();
+
+ var fixture = Type();
+
+ assert.equal(fixture.constructor, Trait, "must inherit constructor Trait");
+ assert.equal(fixture.toString(), "<toString>", "Must override toString");
+};
+
+exports["test custom toString and constructor"] = function(assert) {
+ function Type() {
+ return TypeTrait.create(Type.prototype);
+ }
+ Object.freeze(Type.prototype);
+ var TypeTrait = Trait({
+ toString: function toString() {
+ return "<toString>";
+ }
+ });
+
+ var fixture = Type();
+
+ assert.equal(fixture.constructor, Type, "constructor is provided to create");
+ assert.equal(fixture.toString(), "<toString>", "toString was overridden");
+};
+
+exports["test resolve constructor"] = function (assert) {
+ function Type() {}
+ var T1 = Trait({ constructor: Type }).resolve({ constructor: '_foo' });
+ var f1 = T1.create();
+
+ assert.equal(f1._foo, Type, "constructor was resolved");
+ assert.equal(f1.constructor, Trait, "constructor of prototype is inherited");
+ assert.equal(f1.toString(), "[object Trait]", "toString is inherited");
+};
+
+exports["test compose read-only"] = function (assert) {
+ function Type() {}
+ Type.prototype = Trait.compose(Trait({}), {
+ constructor: { value: Type },
+ a: { value: "b", enumerable: true }
+ }).resolve({ a: "b" }).create({ a: "a" });
+
+ var f1 = new Type();
+
+ assert.equal(Object.getPrototypeOf(f1), Type.prototype, "inherits correctly");
+ assert.equal(f1.constructor, Type, "constructor was overridden");
+ assert.equal(f1.toString(), "[object Type]", "toString was inherited");
+ assert.equal(f1.a, "a", "property a was resolved");
+ assert.equal(f1.b, "b", "property a was renamed to b");
+ assert.ok(!Object.getOwnPropertyDescriptor(Type.prototype, "a"),
+ "a is not on the prototype of the instance");
+
+ var proto = Object.getPrototypeOf(Type.prototype);
+ var dc = Object.getOwnPropertyDescriptor(Type.prototype, "constructor");
+ var db = Object.getOwnPropertyDescriptor(Type.prototype, "b");
+ var da = Object.getOwnPropertyDescriptor(proto, "a");
+
+ assert.ok(!dc.writable, "constructor is not writable");
+ assert.ok(!dc.enumerable, "constructor is not enumerable");
+ assert.ok(dc.configurable, "constructor inherits configurability");
+
+ assert.ok(!db.writable, "a -> b is not writable");
+ assert.ok(db.enumerable, "a -> b is enumerable");
+ assert.ok(!db.configurable, "a -> b is not configurable");
+
+ assert.ok(da.writable, "a is writable");
+ assert.ok(da.enumerable, "a is enumerable");
+ assert.ok(da.configurable, "a is configurable");
+};
+
+if (require.main == module)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/traits/object-tests.js b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/object-tests.js
new file mode 100644
index 0000000..afea3ce
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/object-tests.js
@@ -0,0 +1,317 @@
+"use strict";
+
+var Trait = require("light-traits").Trait;
+var utils = require("./utils");
+var Data = utils.Data;
+var Method = utils.Method;
+var Accessor = utils.Accessor;
+var Required = utils.Required;
+var Conflict = utils.Conflict;
+
+function method() {}
+
+exports.Assert = require("./assert").Assert;
+
+exports["test empty trait"] = function (assert) {
+ assert.equalTraits(Trait({}), {});
+};
+
+exports["test simple trait"] = function (assert) {
+ var expected = {
+ a: Data(0, true, true, true),
+ b: Method(method, true, true, true)
+ };
+
+ assert.equalTraits(Trait({ a: 0, b: method }), expected);
+};
+
+exports["test simple trait with Trait.required property"] = function (assert) {
+ var actual = Trait({ a: Trait.required, b: 1 });
+ var expected = { a: Required("a"), b: Data(1) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test ordering of trait properties is irrelevant"] = function (assert) {
+ var actual = Trait({ a: 0, b: 1, c: Trait.required });
+ var expected = Trait({ b: 1, c: Trait.required, a: 0 });
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test trait with accessor property"] = function (assert) {
+ var record = { get a() {}, set a(v) {} };
+ var get = Object.getOwnPropertyDescriptor(record, "a").get;
+ var set = Object.getOwnPropertyDescriptor(record, "a").set;
+
+ assert.equalTraits(Trait(record), { a: Accessor(get, set) });
+};
+
+exports["test simple composition"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method }));
+ var expected = { a: Data(0), b: Data(1), c: Data(2), d: Method(method) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition with conflict"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 2, c: method }));
+ var expected = { a: Conflict("a"), b: Data(1), c: Method(method) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition of identical props does not cause conflict"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 0, c: method }));
+
+ assert.equalTraits(actual, { a: Data(0), b: Data(1), c: Method(method) });
+};
+
+exports["test composition with identical Trait.required props"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }),
+ Trait({ a: Trait.required, c: method }));
+
+ assert.equalTraits(actual, { a: Required(), b: Data(1), c: Method(method) });
+};
+
+exports["test composition satisfying a Trait.required prop"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }),
+ Trait({ a: method }));
+
+ assert.equalTraits(actual, { a: Method(method), b: Data(1) });
+};
+
+exports["test compose is neutral wrt conflicts"] = function (assert) {
+ var actual = Trait.compose(Trait.compose(Trait({ a: 1 }), Trait({ a: 2 })),
+ Trait({ b: 0 }));
+
+ assert.equalTraits(actual, { a: Conflict("a"), b: Data(0) });
+};
+
+exports["test conflicting prop overrides Trait.required prop"] = function (assert) {
+ var actual = Trait.compose(Trait.compose(Trait({ a: 1 }),
+ Trait({ a: 2 })),
+ Trait({ a: Trait.required }));
+
+ assert.equalTraits(actual, { a: Conflict("a") });
+};
+
+exports["test compose is commutative"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method }));
+ var expected = Trait.compose(Trait({ c: 2, d: method }),
+ Trait({ a: 0, b: 1 }));
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is commutative, also for Trait.required/conflicting props"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, e: Trait.required }),
+ Trait({ c: 2, d: method }));
+
+ var expected = Trait.compose(Trait({ c: 2, d: method }),
+ Trait({ a: 0, b: 1, c: 3, e: Trait.required }));
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is associative"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }),
+ Trait.compose(Trait({ c: 3, d: Trait.required }),
+ Trait({ c: 2, d: method,
+ e: "foo" })));
+
+ var expected = Trait.compose(
+ Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }),
+ Trait({ c: 3, d: Trait.required })),
+ Trait({ c: 2, d: method, e: "foo" }));
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test diamond import of same prop does not generate conflict"] = function (assert) {
+ var actual = Trait.compose(Trait.compose(Trait({ b: 2 }), Trait({ a: 1 })),
+ Trait.compose(Trait({ c: 3 }), Trait({ a: 1 })),
+ Trait({ d: 4 }));
+ var expected = { a: Data(1), b: Data(2), c: Data(3), d: Data(4) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test resolve with empty resolutions has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: Trait.required, c: method }).resolve({}),
+ { a: Data(1), b: Required(), c: Method(method) });
+};
+
+exports["test resolve: renaming"] = function (assert) {
+ var actual = Trait({ a: 1, b: Trait.required, c: method });
+
+ assert.equalTraits(actual.resolve({ a: "A", c: "C" }),
+ { A: Data(1), b: Required(), C: Method(method),
+ a: Required(), c: Required() });
+};
+
+exports["test resolve: renaming to conflicting name causes conflict, order 1"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b" }),
+ { b: Conflict("b"), a: Required() });
+};
+
+exports["test resolve: renaming to conflicting name causes conflict, order 2"] = function (assert) {
+ assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b" }),
+ { b: Conflict("b"), a: Required() });
+};
+
+exports["test resolve: simple exclusion"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined }),
+ { a: Required(), b: Data(2) });
+};
+
+exports["test resolve: exclusion to empty trait"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: null, b: undefined }),
+ { a: Required(), b: Required() });
+};
+
+exports["test resolve: exclusion and renaming of disjoint props"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "c" }),
+ { a: Required(), c: Data(2), b: Required() });
+};
+
+exports["test resolve: exclusion and renaming of overlapping props"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "a" }),
+ { a: Data(2), b: Required() });
+};
+
+exports["test resolve: renaming to a common alias causes conflict"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", b: "c" }),
+ { c: Conflict("c"), a: Required(), b: Required() });
+};
+
+exports["test resolve: renaming overrides Trait.required target"] = function (assert) {
+ assert.equalTraits(Trait({ a: Trait.required, b: 2 }).resolve({ b: "a" }),
+ { a: Data(2), b: Required() });
+};
+
+exports["test resolve: renaming Trait.required properties has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 2, b: Trait.required }).resolve({ b: "a" }),
+ { a: Data(2), b: Required() });
+};
+
+exports["test resolve: renaming of non-existent props has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", d: "c" }),
+ { c: Data(1), b: Data(2), a: Required() });
+};
+
+exports["test resolve: exclusion of non-existent props has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1 }).resolve({ b: undefined }), { a: Data(1) });
+};
+
+exports["test resolve is neutral w.r.t. Trait.required properties"] = function (assert) {
+ var actual = Trait({ a: Trait.required, b: Trait.required, c: "foo", d: 1 });
+ var expected = { a: Required(), b: Required(), c: Data("foo"), d: Data(1) };
+ assert.equalTraits(actual.resolve({ a: "c", b: undefined }), expected);
+};
+
+exports["test resolve supports swapping of property names, ordering 1"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b", b: "a" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test resolve supports swapping of property names, ordering 2"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ b: "a", a: "b" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test resolve supports swapping of property names, ordering 3"] = function (assert) {
+ assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ b: "a", a: "b" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test resolve supports swapping of property names, ordering 4"] = function (assert) {
+ assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b", b: "a" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test create simple"] = function (assert) {
+ var o1 = Trait({
+ a: 1,
+ b: function () {
+ return this.a;
+ }
+ }).create(Object.prototype);
+
+ assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype");
+ assert.equal(1, o1.a, "o1.a");
+ assert.equal(1, o1.b(), "o1.b()");
+ assert.equal(Object.keys(o1).length, 2, "Object.keys(o1).length === 2");
+};
+
+exports["test create with Array.prototype"] = function (assert) {
+ var o2 = Trait({}).create(Array.prototype);
+ assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype");
+};
+
+exports["test exception for incomplete required properties"] = function (assert) {
+ assert.throws(function () {
+ Trait({ foo: Trait.required }).create(Object.prototype);
+ }, /Missing required property: `foo`/, "required prop error");
+};
+
+exports["test exception for unresolved conflicts"] = function (assert) {
+ assert.throws(function () {
+ Trait.compose(Trait({ a: 0 }), Trait({ a: 1 })).create({});
+ }, /Remaining conflicting property: `a`/, "conflicting prop error");
+};
+
+exports["test verify that required properties are present but undefined"] = function (assert) {
+ var o4 = Object.create(Object.prototype, Trait({ foo: Trait.required }));
+
+ assert.ok("foo" in o4, "required property present");
+ assert.throws(function () {
+ o4.foo;
+ }, /Missing required property: `foo`/, "required prop error");
+};
+
+exports["test verify that conflicting properties are present"] = function (assert) {
+ var o5 = Object.create(Object.prototype, Trait.compose(Trait({ a: 0 }),
+ Trait({ a: 1 })));
+
+ assert.ok("a" in o5, "conflicting property present");
+ assert.throws(function () {
+ o5.a;
+ }, /Remaining conflicting property: `a`/, "conflicting prop access error");
+};
+
+exports["test diamond with conflicts"] = function (assert) {
+ function makeT1(x) {
+ return Trait({
+ m: function () {
+ return x
+ }
+ })
+ };
+
+ function makeT2(x) {
+ return Trait.compose(Trait({
+ t2: "foo"
+ }), makeT1(x));
+ };
+
+ function makeT3(x) {
+ return Trait.compose(Trait({
+ t3: "bar"
+ }), makeT1(x));
+ };
+
+ var T4 = Trait.compose(makeT2(5), makeT3(5));
+
+ assert.throws(function () {
+ T4.create(Object.prototype);
+ }, /Remaining conflicting property: `m`/, "diamond prop conflict");
+};
+
+exports["test providing requirements through proto"] = function (assert) {
+ var t = Trait({ required: Trait.required }).create({ required: "test" });
+ assert.equal(t.required, "test", "property from proto is inherited");
+};
+
+if (module == require.main)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.3/packages/api-utils/tests/traits/utils.js b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/utils.js
new file mode 100644
index 0000000..5647fb9
--- /dev/null
+++ b/tools/addon-sdk-1.3/packages/api-utils/tests/traits/utils.js
@@ -0,0 +1,52 @@
+"use strict";
+
+var ERR_CONFLICT = "Remaining conflicting property: ";
+var ERR_REQUIRED = "Missing required property: ";
+
+exports.Data = function Data(value, enumerable, configurable, writable) {
+ return ({
+ value: value,
+ enumerable: enumerable !== false,
+ configurable: configurable !== false,
+ writable: writable !== false
+ });
+};
+
+exports.Method = function Method(method, enumerable, configurable, writable) {
+ return ({
+ value: method,
+ enumerable: enumerable !== false,
+ configurable: configurable !== false,
+ writable: writable !== false
+ });
+};
+
+exports.Accessor = function Accessor(get, set, enumerable, configurable) {
+ return ({
+ get: get,
+ set: set,
+ enumerable: enumerable !== false,
+ configurable: configurable !== false
+ });
+};
+
+exports.Required = function Required(name) {
+ function required() { throw new Error(ERR_REQUIRED + name) }
+
+ return ({
+ get: required,
+ set: required,
+ required: true
+ });
+};
+
+exports.Conflict = function Conflict(name) {
+ function conflict() { throw new Error(ERR_CONFLICT + name) }
+
+ return ({
+ get: conflict,
+ set: conflict,
+ conflict: true
+ });
+};
+