Bug 382752: Unit test harness for extension manager. r=robstrong.

This commit is contained in:
dtownsend@oxymoronical.com 2007-08-11 21:12:06 -07:00
parent 43455f9fc6
commit 223ab3f4a3
5 changed files with 437 additions and 0 deletions

View File

@ -43,4 +43,8 @@ include $(DEPTH)/config/autoconf.mk
DIRS = public src
ifdef ENABLE_TESTS
DIRS += test
endif
include $(topsrcdir)/config/rules.mk

View File

@ -2356,6 +2356,7 @@ var Blocklist = {
request.channel.notificationCallbacks = new BadCertHandler();
request.overrideMimeType("text/xml");
request.setRequestHeader("Cache-Control", "no-cache");
request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
var self = this;
request.onerror = function(event) { self.onXMLError(event); };
@ -6222,6 +6223,7 @@ RDFItemUpdater.prototype = {
request.channel.notificationCallbacks = new BadCertHandler();
request.overrideMimeType("text/xml");
request.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
var self = this;
request.onerror = function(event) { self.onXMLError(event, aItem); };

View File

@ -0,0 +1,68 @@
# ***** 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 Extension Manager.
#
# The Initial Developer of the Original Code is
# Dave Townsend <dtownsend@oxymoronical.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 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
ADDONSRC = $(srcdir)/unit/addons
TESTROOT = $(shell cd $(DEPTH) && pwd)/_tests/xpcshell-simple/$(MODULE)
TESTPROFILE = $(TESTROOT)/profile
TESTXPI = $(TESTROOT)/unit/addons
include $(DEPTH)/config/autoconf.mk
MODULE = test_extensionmanager
XPCSHELL_TESTS = \
unit \
$(NULL)
include $(topsrcdir)/config/rules.mk
libs::
rm -rf $(TESTXPI)
mkdir -p $(TESTXPI)
if [ -d $(ADDONSRC) ]; then \
for dir in $(ADDONSRC)/*; do \
if [ "$$dir" != "$(ADDONSRC)/CVS" ]; then \
base=`basename $$dir` ; \
cd $$dir ; \
zip $(TESTXPI)/$$base.xpi * ; \
fi \
done \
fi

View File

@ -0,0 +1,312 @@
/* ***** 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
* Dave Townsend <dtownsend@oxymoronical.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 *****
*/
/*
* These are intended to be a set of base functions enabling unit testing
* for the Extension Manager component.
*/
const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
const PREFIX_NS_CHROME = "http://www.mozilla.org/rdf/chrome#";
const PREFIX_ITEM_URI = "urn:mozilla:item:";
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
const NS_APP_PROFILE_DIR_STARTUP = "ProfDS";
const NS_OS_TEMP_DIR = "TmpD";
const NS_INSTALL_LOCATION_APPPROFILE = "app-profile";
const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
var gEM = null;
var gRDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
/**
* Utility functions
*/
function EM_NS(property) {
return PREFIX_NS_EM + property;
}
function CHROME_NS(property) {
return PREFIX_NS_CHROME + property;
}
function EM_R(property) {
return gRDF.GetResource(EM_NS(property));
}
function EM_L(literal) {
return gRDF.GetLiteral(literal);
}
function EM_I(integer) {
return gRDF.GetIntLiteral(integer);
}
function EM_D(integer) {
return gRDF.GetDateLiteral(integer);
}
/**
* Extract the string value from a RDF Literal or Resource
* @param literalOrResource
* RDF String Literal or Resource
* @returns String value of the literal or resource, or undefined if the object
* supplied is not a RDF string literal or resource.
*/
function stringData(literalOrResource) {
if (literalOrResource instanceof Components.interfaces.nsIRDFLiteral)
return literalOrResource.Value;
if (literalOrResource instanceof Components.interfaces.nsIRDFResource)
return literalOrResource.Value;
return undefined;
}
/**
* Extract the integer value of a RDF Literal
* @param literal
* nsIRDFInt literal
* @return integer value of the literal
*/
function intData(literal) {
if (literal instanceof Components.interfaces.nsIRDFInt)
return literal.Value;
return undefined;
}
/**
* Gets a RDF Resource for item with the given ID
* @param id
* The GUID of the item to construct a RDF resource to the
* active item for
* @returns The RDF Resource to the Active item.
*/
function getResourceForID(id) {
return gRDF.GetResource(PREFIX_ITEM_URI + id);
}
/**
* Extract a string property for an add-on
* @param id
* ID of the add-on to retrieve a property for
* @param property
* The localname of the property
* @returns String value of the property or undefined if the property
* does not exist
*/
function getManifestProperty(id, property) {
return stringData(gEM.datasource.GetTarget(getResourceForID(id), EM_R(property), true));
}
/**
* Returns a testcase xpi
* @param name
* The name of the testcase (without extension)
* @returns an nsILocalFile pointing to the testcase xpi
*/
function do_get_addon(name)
{
var lf = gTestRoot.clone();
lf.append("unit");
lf.append("addons");
lf.append(name + ".xpi");
if (!lf.exists())
do_throw("Addon "+name+" does not exist.");
return lf;
}
/**
* Creates an nsIXULAppInfo
* @param id
* The ID of the test application
* @param name
* A name for the test application
* @param version
* The version of the application
* @param platformVersion
* The gecko version of the application
*/
function createAppInfo(id, name, version, platformVersion)
{
var XULAppInfo = {
vendor: "Mozilla",
name: name,
ID: id,
version: version,
appBuildID: "2007010101",
platformVersion: platformVersion,
platformBuildID: "2007010101",
inSafeMode: false,
logConsoleErrors: true,
OS: "XPCShell",
XPCOMABI: "noarch-spidermonkey",
QueryInterface: function QueryInterface(iid) {
if (iid.equals(Components.interfaces.nsIXULAppInfo)
|| iid.equals(Components.interfaces.nsIXULRuntime)
|| iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
var XULAppInfoFactory = {
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return XULAppInfo.QueryInterface(iid);
}
};
var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo",
XULAPPINFO_CONTRACTID, XULAppInfoFactory);
}
/**
* This simulates an application startup. Since we will be starting from an
* empty profile we follow that path.
*/
function startupEM()
{
// Make sure the update service is initialised.
var updateSvc = Components.classes["@mozilla.org/updates/update-service;1"]
.getService(Components.interfaces.nsISupports);
gEM = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
gEM.QueryInterface(Components.interfaces.nsIObserver);
gEM.observe(null, "app-startup", null);
gEM.observe(null, "profile-after-change", "startup");
var needsRestart = false;
try {
needsRestart = gEM.checkForMismatches();
}
catch (e) {
needsRestart = gEM.start(null);
}
if (needsRestart)
gEM.start(null);
}
/**
* Simple function to simulate the termination of an app to the EM.
* This harness does not support creating a new EM after calling this.
*/
function shutdownEM()
{
// xpcshell calls xpcom-shutdown so we don't actually do anything here.
gDirSvc.unregisterProvider(dirProvider);
gEM = null;
}
/**
* Many operations require restarts to take effect. This function should
* perform all that is necessary for this to happen.
*/
function restartEM()
{
// We must unregister any datasources that may have been read from addons.
var extensions = gProfD.clone();
extensions.append("extensions");
if (extensions.exists()) {
var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var addons = extensions.directoryEntries;
while (addons.hasMoreElements()) {
var addon = addons.getNext().QueryInterface(Components.interfaces.nsIFile);
if (addon.isDirectory() && addon.leafName != "staged-xpis") {
addon.append("install.rdf");
if (addon.exists()) {
var ds = gRDF.GetDataSource(ioServ.newFileURI(addon).spec);
gRDF.UnregisterDataSource(ds);
}
}
}
}
var needsRestart = gEM.start(null);
if (needsRestart)
gEM.start(null);
}
var gDirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var gTestRoot = gDirSvc.get("CurProcD", Components.interfaces.nsILocalFile);
gTestRoot = gTestRoot.parent.parent;
gTestRoot.append("_tests");
gTestRoot.append("xpcshell-simple");
gTestRoot.append("test_extensionmanager");
// Need to create and register a profile folder.
var gProfD = gTestRoot.clone();
gProfD.append("profile");
if (gProfD.exists())
gProfD.remove(true);
gProfD.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
var dirProvider = {
getFile: function(prop, persistent) {
persistent.value = true;
if (prop == NS_APP_USER_PROFILE_50_DIR ||
prop == NS_APP_PROFILE_DIR_STARTUP)
return gProfD.clone();
return null;
},
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) ||
iid.equals(Components.interfaces.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
gDirSvc.QueryInterface(Components.interfaces.nsIDirectoryService)
.registerProvider(dirProvider);
var gPrefs = Components.classes["@mozilla.org/preferences;1"]
.getService(Components.interfaces.nsIPrefBranch);
// Enable more extensive EM logging
gPrefs.setBoolPref("extensions.logging.enabled", true);

View File

@ -0,0 +1,51 @@
/* ***** 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
* Dave Townsend <dtownsend@oxymoronical.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 *****
*/
// Close down any remaining EM
if (gEM)
shutdownEM();
// Clean up the temporary profile dir.
try {
if (gProfD.exists())
gProfD.remove(true);
}
catch (e) {
// There are many valid reasons for being unable to remove the temporary
// profile dir so not much point in failing on it.
}