toolkit/mozapps/update/tests/shared.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /* Shared code for xpcshell and mochitests-chrome */
     7 // const Cc, Ci, and Cr are defined in netwerk/test/httpserver/httpd.js so we
     8 // need to define unique ones.
     9 const AUS_Cc = Components.classes;
    10 const AUS_Ci = Components.interfaces;
    11 const AUS_Cr = Components.results;
    12 const AUS_Cu = Components.utils;
    13 const AUS_Cm = Components.manager;
    15 const PREF_APP_UPDATE_AUTO                = "app.update.auto";
    16 const PREF_APP_UPDATE_BACKGROUNDERRORS    = "app.update.backgroundErrors";
    17 const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors";
    18 const PREF_APP_UPDATE_CERTS_BRANCH        = "app.update.certs.";
    19 const PREF_APP_UPDATE_CERT_CHECKATTRS     = "app.update.cert.checkAttributes";
    20 const PREF_APP_UPDATE_CERT_ERRORS         = "app.update.cert.errors";
    21 const PREF_APP_UPDATE_CERT_MAXERRORS      = "app.update.cert.maxErrors";
    22 const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn";
    23 const PREF_APP_UPDATE_CHANNEL             = "app.update.channel";
    24 const PREF_APP_UPDATE_ENABLED             = "app.update.enabled";
    25 const PREF_APP_UPDATE_METRO_ENABLED       = "app.update.metro.enabled";
    26 const PREF_APP_UPDATE_IDLETIME            = "app.update.idletime";
    27 const PREF_APP_UPDATE_LOG                 = "app.update.log";
    28 const PREF_APP_UPDATE_NEVER_BRANCH        = "app.update.never.";
    29 const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported";
    30 const PREF_APP_UPDATE_PROMPTWAITTIME      = "app.update.promptWaitTime";
    31 const PREF_APP_UPDATE_SERVICE_ENABLED     = "app.update.service.enabled";
    32 const PREF_APP_UPDATE_SHOW_INSTALLED_UI   = "app.update.showInstalledUI";
    33 const PREF_APP_UPDATE_SILENT              = "app.update.silent";
    34 const PREF_APP_UPDATE_STAGING_ENABLED     = "app.update.staging.enabled";
    35 const PREF_APP_UPDATE_URL                 = "app.update.url";
    36 const PREF_APP_UPDATE_URL_DETAILS         = "app.update.url.details";
    37 const PREF_APP_UPDATE_URL_OVERRIDE        = "app.update.url.override";
    38 const PREF_APP_UPDATE_SOCKET_ERRORS       = "app.update.socket.maxErrors";
    39 const PREF_APP_UPDATE_RETRY_TIMEOUT       = "app.update.socket.retryTimeout";
    41 const PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME = PREF_APP_UPDATE_CERTS_BRANCH +
    42                                                "1.invalidName";
    44 const PREF_APP_PARTNER_BRANCH             = "app.partner.";
    45 const PREF_DISTRIBUTION_ID                = "distribution.id";
    46 const PREF_DISTRIBUTION_VERSION           = "distribution.version";
    48 const PREF_EXTENSIONS_UPDATE_URL          = "extensions.update.url";
    49 const PREF_EXTENSIONS_STRICT_COMPAT       = "extensions.strictCompatibility";
    51 const NS_APP_PROFILE_DIR_STARTUP   = "ProfDS";
    52 const NS_APP_USER_PROFILE_50_DIR   = "ProfD";
    53 const NS_GRE_DIR                   = "GreD";
    54 const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
    55 const XRE_EXECUTABLE_FILE          = "XREExeF";
    56 const XRE_UPDATE_ROOT_DIR          = "UpdRootD";
    58 const CRC_ERROR   = 4;
    59 const WRITE_ERROR = 7;
    61 const DIR_PATCH        = "0";
    62 const DIR_TOBEDELETED  = "tobedeleted";
    63 const DIR_UPDATES      = "updates";
    64 #ifdef XP_MACOSX
    65 const DIR_BIN_REL_PATH = "Contents/MacOS/";
    66 const DIR_UPDATED      = "Updated.app";
    67 #else
    68 const DIR_BIN_REL_PATH = "";
    69 const DIR_UPDATED      = "updated";
    70 #endif
    72 const FILE_BACKUP_LOG                = "backup-update.log";
    73 const FILE_LAST_LOG                  = "last-update.log";
    74 const FILE_UPDATER_INI               = "updater.ini";
    75 const FILE_UPDATES_DB                = "updates.xml";
    76 const FILE_UPDATE_ACTIVE             = "active-update.xml";
    77 const FILE_UPDATE_ARCHIVE            = "update.mar";
    78 const FILE_UPDATE_LOG                = "update.log";
    79 const FILE_UPDATE_SETTINGS_INI       = "update-settings.ini";
    80 const FILE_UPDATE_SETTINGS_INI_BAK   = "update-settings.ini.bak";
    81 const FILE_UPDATE_STATUS             = "update.status";
    82 const FILE_UPDATE_VERSION            = "update.version";
    84 const UPDATE_SETTINGS_CONTENTS = "[Settings]\n" +
    85                                  "ACCEPTED_MAR_CHANNEL_IDS=xpcshell-test\n"
    87 const PR_RDWR        = 0x04;
    88 const PR_CREATE_FILE = 0x08;
    89 const PR_APPEND      = 0x10;
    90 const PR_TRUNCATE    = 0x20;
    91 const PR_SYNC        = 0x40;
    92 const PR_EXCL        = 0x80;
    94 const DEFAULT_UPDATE_VERSION = "999999.0";
    96 var gChannel;
    98 #include sharedUpdateXML.js
   100 AUS_Cu.import("resource://gre/modules/FileUtils.jsm");
   101 AUS_Cu.import("resource://gre/modules/Services.jsm");
   102 AUS_Cu.import("resource://gre/modules/XPCOMUtils.jsm");
   104 const PERMS_FILE      = FileUtils.PERMS_FILE;
   105 const PERMS_DIRECTORY = FileUtils.PERMS_DIRECTORY;
   107 const MODE_RDONLY   = FileUtils.MODE_RDONLY;
   108 const MODE_WRONLY   = FileUtils.MODE_WRONLY;
   109 const MODE_RDWR     = FileUtils.MODE_RDWR;
   110 const MODE_CREATE   = FileUtils.MODE_CREATE;
   111 const MODE_APPEND   = FileUtils.MODE_APPEND;
   112 const MODE_TRUNCATE = FileUtils.MODE_TRUNCATE;
   114 const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.properties";
   115 const gUpdateBundle = Services.strings.createBundle(URI_UPDATES_PROPERTIES);
   117 XPCOMUtils.defineLazyGetter(this, "gAUS", function test_gAUS() {
   118   return AUS_Cc["@mozilla.org/updates/update-service;1"].
   119          getService(AUS_Ci.nsIApplicationUpdateService).
   120          QueryInterface(AUS_Ci.nsITimerCallback).
   121          QueryInterface(AUS_Ci.nsIObserver).
   122          QueryInterface(AUS_Ci.nsIUpdateCheckListener);
   123 });
   125 XPCOMUtils.defineLazyServiceGetter(this, "gUpdateManager",
   126                                    "@mozilla.org/updates/update-manager;1",
   127                                    "nsIUpdateManager");
   129 XPCOMUtils.defineLazyGetter(this, "gUpdateChecker", function test_gUC() {
   130   return AUS_Cc["@mozilla.org/updates/update-checker;1"].
   131          createInstance(AUS_Ci.nsIUpdateChecker);
   132 });
   134 XPCOMUtils.defineLazyGetter(this, "gUP", function test_gUP() {
   135   return AUS_Cc["@mozilla.org/updates/update-prompt;1"].
   136          createInstance(AUS_Ci.nsIUpdatePrompt);
   137 });
   139 XPCOMUtils.defineLazyGetter(this, "gDefaultPrefBranch", function test_gDPB() {
   140   return Services.prefs.getDefaultBranch(null);
   141 });
   143 XPCOMUtils.defineLazyGetter(this, "gPrefRoot", function test_gPR() {
   144   return Services.prefs.getBranch(null);
   145 });
   147 XPCOMUtils.defineLazyGetter(this, "gZipW", function test_gZipW() {
   148   return AUS_Cc["@mozilla.org/zipwriter;1"].
   149          createInstance(AUS_Ci.nsIZipWriter);
   150 });
   152 /* Initializes the update service stub */
   153 function initUpdateServiceStub() {
   154   AUS_Cc["@mozilla.org/updates/update-service-stub;1"].
   155   createInstance(AUS_Ci.nsISupports);
   156 }
   158 /* Reloads the update metadata from disk */
   159 function reloadUpdateManagerData() {
   160   gUpdateManager.QueryInterface(AUS_Ci.nsIObserver).
   161   observe(null, "um-reload-update-data", "");
   162 }
   164 /**
   165  * Sets the app.update.channel preference.
   166  *
   167  * @param  aChannel
   168  *         The update channel.
   169  */
   170 function setUpdateChannel(aChannel) {
   171   gChannel = aChannel;
   172   debugDump("setting default pref " + PREF_APP_UPDATE_CHANNEL + " to " + gChannel);
   173   gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_CHANNEL, gChannel);
   174   gPrefRoot.addObserver(PREF_APP_UPDATE_CHANNEL, observer, false);
   175 }
   177 var observer = {
   178   observe: function(aSubject, aTopic, aData) {
   179     if (aTopic == "nsPref:changed" && aData == PREF_APP_UPDATE_CHANNEL) {
   180       var channel = gDefaultPrefBranch.getCharPref(PREF_APP_UPDATE_CHANNEL);
   181       if (channel != gChannel) {
   182         debugDump("Changing channel from " + channel + " to " + gChannel);
   183         gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_CHANNEL, gChannel);
   184       }
   185     }
   186   },
   187   QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIObserver])
   188 };
   190 /**
   191  * Sets the app.update.url.override preference.
   192  *
   193  * @param  aURL
   194  *         The update url. If not specified 'URL_HOST + "/update.xml"' will be
   195  *         used.
   196  */
   197 function setUpdateURLOverride(aURL) {
   198   let url = aURL ? aURL : URL_HOST + "/update.xml";
   199   debugDump("setting " + PREF_APP_UPDATE_URL_OVERRIDE + " to " + url);
   200   Services.prefs.setCharPref(PREF_APP_UPDATE_URL_OVERRIDE, url);
   201 }
   203 /**
   204  * Returns either the active or regular update database XML file.
   205  *
   206  * @param  isActiveUpdate
   207  *         If true this will return the active-update.xml otherwise it will
   208  *         return the updates.xml file.
   209  */
   210 function getUpdatesXMLFile(aIsActiveUpdate) {
   211   var file = getUpdatesRootDir();
   212   file.append(aIsActiveUpdate ? FILE_UPDATE_ACTIVE : FILE_UPDATES_DB);
   213   return file;
   214 }
   216 /**
   217  * Writes the updates specified to either the active-update.xml or the
   218  * updates.xml.
   219  *
   220  * @param  aContent
   221  *         The updates represented as a string to write to the XML file.
   222  * @param  isActiveUpdate
   223  *         If true this will write to the active-update.xml otherwise it will
   224  *         write to the updates.xml file.
   225  */
   226 function writeUpdatesToXMLFile(aContent, aIsActiveUpdate) {
   227   writeFile(getUpdatesXMLFile(aIsActiveUpdate), aContent);
   228 }
   230 /**
   231  * Writes the current update operation/state to a file in the patch
   232  * directory, indicating to the patching system that operations need
   233  * to be performed.
   234  *
   235  * @param  aStatus
   236  *         The status value to write.
   237  */
   238 function writeStatusFile(aStatus) {
   239   let file = getUpdatesPatchDir();
   240   file.append(FILE_UPDATE_STATUS);
   241   writeFile(file, aStatus + "\n");
   242 }
   244 /**
   245  * Writes the current update version to a file in the patch directory,
   246  * indicating to the patching system the version of the update.
   247  *
   248  * @param  aVersion
   249  *         The version value to write.
   250  */
   251 function writeVersionFile(aVersion) {
   252   let file = getUpdatesPatchDir();
   253   file.append(FILE_UPDATE_VERSION);
   254   writeFile(file, aVersion + "\n");
   255 }
   257 /**
   258  * Gets the root directory for the updates directory.
   259  *
   260  * @return nsIFile for the updates root directory.
   261  */
   262 function getUpdatesRootDir() {
   263   return Services.dirsvc.get(XRE_UPDATE_ROOT_DIR, AUS_Ci.nsIFile);
   264 }
   266 /**
   267  * Gets the updates directory.
   268  *
   269  * @return nsIFile for the updates directory.
   270  */
   271 function getUpdatesDir() {
   272   var dir = getUpdatesRootDir();
   273   dir.append(DIR_UPDATES);
   274   return dir;
   275 }
   277 /**
   278  * Gets the directory for update patches.
   279  *
   280  * @return nsIFile for the updates directory.
   281  */
   282 function getUpdatesPatchDir() {
   283   let dir = getUpdatesDir();
   284   dir.append(DIR_PATCH);
   285   return dir;
   286 }
   288 /**
   289  * Writes text to a file. This will replace existing text if the file exists
   290  * and create the file if it doesn't exist.
   291  *
   292  * @param  aFile
   293  *         The file to write to. Will be created if it doesn't exist.
   294  * @param  aText
   295  *         The text to write to the file. If there is existing text it will be
   296  *         replaced.
   297  */
   298 function writeFile(aFile, aText) {
   299   var fos = AUS_Cc["@mozilla.org/network/file-output-stream;1"].
   300             createInstance(AUS_Ci.nsIFileOutputStream);
   301   if (!aFile.exists())
   302     aFile.create(AUS_Ci.nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
   303   fos.init(aFile, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, PERMS_FILE, 0);
   304   fos.write(aText, aText.length);
   305   fos.close();
   306 }
   308 /**
   309  * Reads the current update operation/state in the status file in the patch
   310  * directory including the error code if it is present.
   311  *
   312  * @return The status value.
   313  */
   314 function readStatusFile() {
   315   let file = getUpdatesPatchDir();
   316   file.append(FILE_UPDATE_STATUS);
   318   if (!file.exists()) {
   319     logTestInfo("update status file does not exists! Path: " + file.path);
   320     return STATE_NONE;
   321   }
   323   return readFile(file).split("\n")[0];
   324 }
   326 /**
   327  * Reads the current update operation/state in the status file in the patch
   328  * directory without the error code if it is present.
   329  *
   330  * @return The state value.
   331  */
   332 function readStatusState() {
   333   return readStatusFile().split(": ")[0];
   334 }
   336 /**
   337  * Reads the current update operation/state in the status file in the patch
   338  * directory with the error code.
   339  *
   340  * @return The state value.
   341  */
   342 function readStatusFailedCode() {
   343   return readStatusFile().split(": ")[1];
   344 }
   346 /**
   347  * Reads text from a file and returns the string.
   348  *
   349  * @param  aFile
   350  *         The file to read from.
   351  * @return The string of text read from the file.
   352  */
   353 function readFile(aFile) {
   354   var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"].
   355             createInstance(AUS_Ci.nsIFileInputStream);
   356   if (!aFile.exists())
   357     return null;
   358   fis.init(aFile, MODE_RDONLY, PERMS_FILE, 0);
   359   var sis = AUS_Cc["@mozilla.org/scriptableinputstream;1"].
   360             createInstance(AUS_Ci.nsIScriptableInputStream);
   361   sis.init(fis);
   362   var text = sis.read(sis.available());
   363   sis.close();
   364   return text;
   365 }
   367 /**
   368  * Reads the binary contents of a file and returns it as a string.
   369  *
   370  * @param  aFile
   371  *         The file to read from.
   372  * @return The contents of the file as a string.
   373  */
   374 function readFileBytes(aFile) {
   375   var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"].
   376             createInstance(AUS_Ci.nsIFileInputStream);
   377   fis.init(aFile, -1, -1, false);
   378   var bis = AUS_Cc["@mozilla.org/binaryinputstream;1"].
   379             createInstance(AUS_Ci.nsIBinaryInputStream);
   380   bis.setInputStream(fis);
   381   var data = [];
   382   var count = fis.available();
   383   while (count > 0) {
   384     var bytes = bis.readByteArray(Math.min(65535, count));
   385     data.push(String.fromCharCode.apply(null, bytes));
   386     count -= bytes.length;
   387     if (bytes.length == 0)
   388       throw "Nothing read from input stream!";
   389   }
   390   data.join('');
   391   fis.close();
   392   return data.toString();
   393 }
   395 /* Returns human readable status text from the updates.properties bundle */
   396 function getStatusText(aErrCode) {
   397   return getString("check_error-" + aErrCode);
   398 }
   400 /* Returns a string from the updates.properties bundle */
   401 function getString(aName) {
   402   try {
   403     return gUpdateBundle.GetStringFromName(aName);
   404   } catch (e) {
   405   }
   406   return null;
   407 }
   409 /**
   410  * Gets the file extension for an nsIFile.
   411  *
   412  * @param  aFile
   413  *         The file to get the file extension for.
   414  * @return The file extension.
   415  */
   416 function getFileExtension(aFile) {
   417   return Services.io.newFileURI(aFile).QueryInterface(AUS_Ci.nsIURL).
   418          fileExtension;
   419 }
   421 /**
   422  * Removes the updates.xml file, active-update.xml file, and all files and
   423  * sub-directories in the updates directory except for the "0" sub-directory.
   424  * This prevents some tests from failing due to files being left behind when the
   425  * tests are interrupted.
   426  */
   427 function removeUpdateDirsAndFiles() {
   428   var file = getUpdatesXMLFile(true);
   429   try {
   430     if (file.exists())
   431       file.remove(false);
   432   } catch (e) {
   433     dump("Unable to remove file\nPath: " + file.path +
   434          "\nException: " + e + "\n");
   435   }
   437   file = getUpdatesXMLFile(false);
   438   try {
   439     if (file.exists())
   440       file.remove(false);
   441   } catch (e) {
   442     dump("Unable to remove file\nPath: " + file.path +
   443          "\nException: " + e + "\n");
   444   }
   446   // This fails sporadically on Mac OS X so wrap it in a try catch
   447   var updatesDir = getUpdatesDir();
   448   try {
   449     cleanUpdatesDir(updatesDir);
   450   } catch (e) {
   451     dump("Unable to remove files / directories from directory\nPath: " +
   452          updatesDir.path + "\nException: " + e + "\n");
   453   }
   454 }
   456 /**
   457  * Removes all files and sub-directories in the updates directory except for
   458  * the "0" sub-directory.
   459  *
   460  * @param  aDir
   461  *         nsIFile for the directory to be deleted.
   462  */
   463 function cleanUpdatesDir(aDir) {
   464   if (!aDir.exists())
   465     return;
   467   var dirEntries = aDir.directoryEntries;
   468   while (dirEntries.hasMoreElements()) {
   469     var entry = dirEntries.getNext().QueryInterface(AUS_Ci.nsIFile);
   471     if (entry.isDirectory()) {
   472       if (entry.leafName == DIR_PATCH && entry.parent.leafName == DIR_UPDATES) {
   473         cleanUpdatesDir(entry);
   474         entry.permissions = PERMS_DIRECTORY;
   475       } else {
   476         try {
   477           entry.remove(true);
   478           return;
   479         } catch (e) {
   480         }
   481         cleanUpdatesDir(entry);
   482         entry.permissions = PERMS_DIRECTORY;
   483         try {
   484           entry.remove(true);
   485         } catch (e) {
   486           dump("cleanUpdatesDir: unable to remove directory\nPath: " +
   487                entry.path + "\nException: " + e + "\n");
   488           throw(e);
   489         }
   490       }
   491     } else {
   492       entry.permissions = PERMS_FILE;
   493       try {
   494         entry.remove(false);
   495       } catch (e) {
   496         dump("cleanUpdatesDir: unable to remove file\nPath: " + entry.path +
   497              "\nException: " + e + "\n");
   498         throw(e);
   499       }
   500     }
   501   }
   502 }
   504 /**
   505  * Deletes a directory and its children. First it tries nsIFile::Remove(true).
   506  * If that fails it will fall back to recursing, setting the appropriate
   507  * permissions, and deleting the current entry.
   508  *
   509  * @param  aDir
   510  *         nsIFile for the directory to be deleted.
   511  */
   512 function removeDirRecursive(aDir) {
   513   if (!aDir.exists()) {
   514     return;
   515   }
   517   try {
   518     logTestInfo("attempting to remove directory. Path: " + aDir.path);
   519     aDir.remove(true);
   520     return;
   521   } catch (e) {
   522     logTestInfo("non-fatal error removing directory. Exception: " + e);
   523   }
   525   var dirEntries = aDir.directoryEntries;
   526   while (dirEntries.hasMoreElements()) {
   527     var entry = dirEntries.getNext().QueryInterface(AUS_Ci.nsIFile);
   529     if (entry.isDirectory()) {
   530       removeDirRecursive(entry);
   531     } else {
   532       entry.permissions = PERMS_FILE;
   533       try {
   534         logTestInfo("attempting to remove file. Path: " + entry.path);
   535         entry.remove(false);
   536       } catch (e) {
   537         logTestInfo("error removing file. Exception: " + e);
   538         throw(e);
   539       }
   540     }
   541   }
   543   aDir.permissions = PERMS_DIRECTORY;
   544   try {
   545     logTestInfo("attempting to remove directory. Path: " + aDir.path);
   546     aDir.remove(true);
   547   } catch (e) {
   548     logTestInfo("error removing directory. Exception: " + e);
   549     throw(e);
   550   }
   551 }
   553 /**
   554  * Returns the directory for the currently running process. This is used to
   555  * clean up after the tests and to locate the active-update.xml and updates.xml
   556  * files.
   557  *
   558  * @return nsIFile for the current process directory.
   559  */
   560 function getCurrentProcessDir() {
   561   return Services.dirsvc.get(NS_XPCOM_CURRENT_PROCESS_DIR, AUS_Ci.nsIFile);
   562 }
   564 /**
   565  * Gets the application base directory.
   566  *
   567  * @return  nsIFile object for the application base directory.
   568  */
   569 function getAppBaseDir() {
   570   return Services.dirsvc.get(XRE_EXECUTABLE_FILE, AUS_Ci.nsIFile).parent;
   571 }
   573 /**
   574  * Returns the Gecko Runtime Engine directory. This is used to locate the the
   575  * updater binary (Windows and Linux) or updater package (Mac OS X). For
   576  * XULRunner applications this is different than the currently running process
   577  * directory.
   578  *
   579  * @return nsIFile for the Gecko Runtime Engine directory.
   580  */
   581 function getGREDir() {
   582   return Services.dirsvc.get(NS_GRE_DIR, AUS_Ci.nsIFile);
   583 }
   585 /**
   586  * Get the "updated" directory inside the directory where we apply the
   587  * staged updates.
   588  * @return The active updates directory inside the updated directory, as a
   589  *         nsIFile object.
   590  */
   591 function getUpdatedDir() {
   592   let dir = getAppBaseDir();
   593 #ifdef XP_MACOSX
   594   dir = dir.parent.parent; // the bundle directory
   595 #endif
   596   dir.append(DIR_UPDATED);
   597   logTestInfo("updated directory path: " + dir.path);
   598   return dir;
   599 }
   601 /**
   602  * Logs TEST-INFO messages.
   603  *
   604  * @param  aText
   605  *         The text to log.
   606  * @param  aCaller (optional)
   607  *         An optional Components.stack.caller. If not specified
   608  *         Components.stack.caller will be used.
   609  */
   610 function logTestInfo(aText, aCaller) {
   611   let caller = (aCaller ? aCaller : Components.stack.caller);
   612   let now = new Date;
   613   let hh = now.getHours();
   614   let mm = now.getMinutes();
   615   let ss = now.getSeconds();
   616   let ms = now.getMilliseconds();
   617   let time = (hh < 10 ? "0" + hh : hh) + ":" +
   618              (mm < 10 ? "0" + mm : mm) + ":" +
   619              (ss < 10 ? "0" + ss : ss) + ":" +
   620              (ms < 10 ? "00" + ms : ms < 100 ? "0" + ms : ms);
   621   dump(time + " | TEST-INFO | " + caller.filename + " | [" + caller.name +
   622        " : " + caller.lineNumber + "] " + aText + "\n");
   623 }
   625 /**
   626  * Logs TEST-INFO messages when DEBUG_AUS_TEST evaluates to true.
   627  *
   628  * @param  aText
   629  *         The text to log.
   630  * @param  aCaller (optional)
   631  *         An optional Components.stack.caller. If not specified
   632  *         Components.stack.caller will be used.
   633  */
   634 function debugDump(aText, aCaller) {
   635   if (DEBUG_AUS_TEST) {
   636     let caller = aCaller ? aCaller : Components.stack.caller;
   637     logTestInfo(aText, caller);
   638   }
   639 }

mercurial