--- a/content/xtf/Makefile.in
+++ b/content/xtf/Makefile.in
@@ -39,9 +39,13 @@ DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
+ifdef ENABLE_TESTS
+DIRS += test
+endif
+
include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/xtf/test/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** 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 mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla.org.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Boris Zbarsky <bzbarsky@mit.edu> (Original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of 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 *****
+
+#
+# Makefile for installing and running xpcshell-based tests. You can use
+# this file as template when creating tests for a new module. Don't
+# forget to change the lines marked below. See
+# http://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests
+# for detailed instructions.
+#
+
+# Note: DEPTH should be set to the relative path to mozilla/
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+# Note: set the test module's name to test_<yourmodule>
+MODULE = test_xtf
+
+XPCSHELL_TESTS = unit
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/xtf/test/unit/test_xtf.js
@@ -0,0 +1,82 @@
+/* ***** 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 XTF unit test components.
+ *
+ * The Initial Developer of the Original Code is
+ * Alexander J. Vincent <ajvincent@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+function run_test() {
+ const C_i = Components.interfaces;
+ const nsIXTFElementFactory = C_i.nsIXTFElementFactory;
+ const nsIXTFPrivate = C_i.nsIXTFPrivate;
+ const nsIDOMParser = C_i.nsIDOMParser;
+ const nsIDOMEventTarget = C_i.nsIDOMEventTarget;
+ do_load_module("/content/xtf/test/unit/xtfComponent.js");
+ const xtfClass = "@mozilla.org/xtf/element-factory;1?namespace=";
+
+ do_check_true(xtfClass + "xtf-tests;foo" in Components.classes);
+ var fooFactory = Components.classes[xtfClass + "xtf-tests;foo"]
+ .getService(nsIXTFElementFactory);
+ do_check_true(Boolean(fooFactory));
+
+ var xmlSource = "<bar xmlns='xtf-tests;foo'/>";
+ const parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
+ .createInstance(nsIDOMParser);
+ var xmlDoc = parser.parseFromString(xmlSource, "application/xml");
+ do_check_true(xmlDoc.documentElement instanceof nsIXTFPrivate);
+ do_check_true(xmlDoc.documentElement instanceof nsIDOMEventTarget);
+
+ do_check_true(xmlDoc.documentElement.inner.wrappedJSObject.testpassed);
+
+ // Bug 378247
+ xmlDoc.documentElement.addEventListener("DOMNodeInserted",
+ function foo() {
+ dump('This is a DOMNodeInserted test.\n');
+ },
+ true);
+ xmlDoc.documentElement.appendChild(xmlDoc.createTextNode("bar"));
+ do_check_true(xmlDoc.documentElement.inner.wrappedJSObject.testpassed);
+
+ xmlSource = "<handle_default xmlns='xtf-tests;foo'/>";
+ xmlDoc = parser.parseFromString(xmlSource, "application/xml");
+ do_check_true(xmlDoc.documentElement instanceof nsIXTFPrivate);
+ do_check_true(xmlDoc.documentElement instanceof nsIDOMEventTarget);
+
+ // Bug 378247
+ xmlDoc.documentElement.addEventListener("DOMNodeInserted",
+ function foo() {
+ dump('This is a DOMNodeInserted test.\n');
+ },
+ true);
+ xmlDoc.documentElement.appendChild(xmlDoc.createTextNode("bar"));
+ do_check_true(xmlDoc.documentElement.inner.wrappedJSObject.testpassed);
+}
new file mode 100644
--- /dev/null
+++ b/content/xtf/test/unit/xtfComponent.js
@@ -0,0 +1,252 @@
+/* ***** 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 XTF unit test components.
+ *
+ * The Initial Developer of the Original Code is
+ * Alexander J. Vincent <ajvincent@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+// Utility function.
+function NOT_IMPLEMENTED() {
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+const C_i = Components.interfaces;
+
+const nsIXTFElementFactory = C_i.nsIXTFElementFactory;
+const nsIXTFElement = C_i.nsIXTFElement;
+const nsIXTFPrivate = C_i.nsIXTFPrivate;
+const nsIXTFAttributeHandler = C_i.nsIXTFAttributeHandler;
+const mozIJSSubScriptLoader = C_i.mozIJSSubScriptLoader;
+const nsIProgrammingLanguage = C_i.nsIProgrammingLanguage;
+const nsIClassInfo = C_i.nsIClassInfo;
+const nsIComponentRegistrar = C_i.nsIComponentRegistrar;
+const nsIFactory = C_i.nsIFactory;
+const nsIModule = C_i.nsIModule;
+const nsISupports = C_i.nsISupports;
+
+const xtfClass = "@mozilla.org/xtf/element-factory;1?namespace=";
+
+/**
+ * Wrap a JavaScript object for passing to components code.
+ */
+function ObjectWrapper(object) {
+ this.wrappedJSObject = object;
+}
+
+/* <foo:element xmlns:foo="xtf-tests;foo"> */
+const FooInner = {
+ bar: {
+ testpassed: true
+ },
+
+ handle_default: {
+ testpassed: false
+ }
+}
+
+function FooElement(aLocalName) {
+ this._wrapper = null;
+
+ // nsIXTFPrivate
+ this.inner = new ObjectWrapper(FooInner[aLocalName]);
+}
+FooElement.prototype =
+{
+ // nsIXTFElement
+ onCreated: function onCreated(aWrapper) {
+ this._wrapper = aWrapper;
+ aWrapper.notificationMask = 0;
+ },
+
+ // nsIXTFElement
+ onDestroyed: function onDestroyed() {
+ },
+
+ // nsIXTFElement
+ isAttributeHandler: false,
+
+ // nsIXTFElement
+ getScriptingInterfaces: function getScriptingInterfaces(aCount) {
+ var interfaces = [];
+ aCount.value = interfaces.length;
+ return interfaces;
+ },
+
+ // nsIXTFElement
+ willChangeDocument: NOT_IMPLEMENTED,
+ documentChanged: NOT_IMPLEMENTED,
+ willChangeParent: NOT_IMPLEMENTED,
+ parentChanged: NOT_IMPLEMENTED,
+ willInsertChild: NOT_IMPLEMENTED,
+ childInserted: NOT_IMPLEMENTED,
+ willAppendChild: NOT_IMPLEMENTED,
+ childAppended: NOT_IMPLEMENTED,
+ willRemoveChild: NOT_IMPLEMENTED,
+ childRemoved: NOT_IMPLEMENTED,
+ willSetAttribute: NOT_IMPLEMENTED,
+ attributeSet: NOT_IMPLEMENTED,
+ willRemoveAttribute: NOT_IMPLEMENTED,
+ attributeRemoved: NOT_IMPLEMENTED,
+
+ beginAddingChildren: NOT_IMPLEMENTED,
+ doneAddingChildren: NOT_IMPLEMENTED,
+
+ handleDefault: NOT_IMPLEMENTED,
+ cloneState: NOT_IMPLEMENTED,
+
+ get accesskeyNode() {
+ return null;
+ },
+ performAccesskey: NOT_IMPLEMENTED,
+
+ // nsISupports
+ QueryInterface: function QueryInterface(aIID) {
+ if (aIID.equals(nsIXTFPrivate) ||
+ aIID.equals(nsIXTFElement) ||
+ aIID.equals(nsISupports))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+};
+
+function FooElementFactory() {}
+FooElementFactory.prototype =
+{
+ // nsIXTFElementFactory
+ createElement: function createElement(aLocalName) {
+ var rv = null;
+ switch (aLocalName) {
+ case "bar":
+ rv = new FooElement(aLocalName);
+ rv.handleDefault = function handleDefault(aEvent) {
+ this.inner.wrappedJSObject.testpassed = false;
+ }
+ break;
+
+ case "handle_default":
+ var rv = new FooElement(aLocalName);
+ rv.onCreated = function onCreated(aWrapper) {
+ this._wrapper = aWrapper;
+ aWrapper.notificationMask = nsIXTFElement.NOTIFY_HANDLE_DEFAULT;
+ }
+ rv.handleDefault = function handleDefault(aEvent) {
+ this.inner.wrappedJSObject.testpassed = true;
+ }
+ break;
+ }
+
+ return rv ? rv.QueryInterface(nsIXTFElement) : null;
+ },
+
+ // nsISupports
+ QueryInterface: function QueryInterface(aIID) {
+ if (aIID.equals(nsIXTFElementFactory) ||
+ aIID.equals(nsISupports))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+};
+
+const FooComponentFactory = {
+ // nsIFactory
+ createInstance: function createInstance(outer, iid) {
+ if (outer != null)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+
+ return (new FooElementFactory()).QueryInterface(iid);
+ },
+
+ // nsISupports
+ QueryInterface: function QueryInterface(aIID) {
+ if (aIID.equals(nsIFactory) ||
+ (aIID.equals(nsISupports)))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+};
+
+const fooClassID = Components.ID("{f367b65d-6b7f-4a7f-9a4b-8bde0ff4ef10}");
+const fooClassDesc = "XTF unit test: Foo element factory";
+const fooContractID = xtfClass + "xtf-tests;foo";
+
+/* </foo:element> */
+
+const Module = {
+ // nsIModule
+ registerSelf: function registerSelf(compMgr, fileSpec, location, type) {
+ compReg = compMgr.QueryInterface(nsIComponentRegistrar);
+
+ compReg.registerFactoryLocation(fooClassID,
+ fooClassDesc,
+ fooContractID,
+ fileSpec,
+ location,
+ type);
+ },
+
+ // nsIModule
+ getClassObject: function getClassObject(compMgr, aCID, aIID) {
+ if (!aIID.equals(nsIFactory)) {
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+ }
+ if (aCID.equals(fooClassID)) {
+ return FooComponentFactory;
+ }
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ // nsIModule
+ canUnload: function canUnload() {
+ return true;
+ },
+
+ // nsISupports
+ QueryInterface: function QueryInterface(aIID) {
+ if (aIID.equals(nsIModule) ||
+ (aIID.equals(nsISupports)))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+};
+
+function NSGetModule(compMgr, fileSpec) {
+ return Module;
+}
--- a/tools/test-harness/xpcshell-simple/head.js
+++ b/tools/test-harness/xpcshell-simple/head.js
@@ -54,17 +54,17 @@ function _TimerCallback(expr) {
_expr: "",
QueryInterface: function(iid) {
if (iid.Equals(Components.interfaces.nsITimerCallback) ||
iid.Equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
notify: function(timer) {
- eval(this._expr);
+ eval(this._expr);
}
};
function _do_main() {
if (_quit)
return;
dump("*** running event loop\n");
@@ -167,8 +167,15 @@ function do_get_file(path) {
if (comps[i].length > 0)
lf.append(comps[i]);
}
do_check_true(lf.exists());
return lf;
}
+
+function do_load_module(path) {
+ var lf = do_get_file(path);
+ const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
+ do_check_true(Components.manager instanceof nsIComponentRegistrar);
+ Components.manager.autoRegister(lf);
+}