michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: */ michael@0: michael@0: /* General URL Construction Tests */ michael@0: michael@0: Components.utils.import("resource://gre/modules/ctypes.jsm") michael@0: michael@0: const URL_PREFIX = URL_HOST + "/"; michael@0: michael@0: var gAppInfo; michael@0: michael@0: function run_test() { michael@0: // This test needs access to omni.ja to read the update.locale file so don't michael@0: // use a custom directory for the application directory. michael@0: gUseTestAppDir = false; michael@0: setupTestCommon(); michael@0: michael@0: // The mock XMLHttpRequest is MUCH faster michael@0: overrideXHR(callHandleEvent); michael@0: standardInit(); michael@0: gAppInfo = AUS_Cc["@mozilla.org/xre/app-info;1"]. michael@0: getService(AUS_Ci.nsIXULAppInfo). michael@0: QueryInterface(AUS_Ci.nsIXULRuntime); michael@0: do_execute_soon(run_test_pt1); michael@0: } michael@0: michael@0: // Callback function used by the custom XMLHttpRequest implementation to michael@0: // call the nsIDOMEventListener's handleEvent method for onload. michael@0: function callHandleEvent() { michael@0: var e = { target: gXHR }; michael@0: gXHR.onload(e); michael@0: } michael@0: michael@0: // Helper function for parsing the result from the contructed url michael@0: function getResult(url) { michael@0: return url.substr(URL_PREFIX.length).split("/")[0]; michael@0: } michael@0: michael@0: // url constructed with %PRODUCT% michael@0: function run_test_pt1() { michael@0: gCheckFunc = check_test_pt1; michael@0: var url = URL_PREFIX + "%PRODUCT%/"; michael@0: logTestInfo("testing url constructed with %PRODUCT% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt1() { michael@0: do_check_eq(getResult(gRequestURL), gAppInfo.name); michael@0: run_test_pt2(); michael@0: } michael@0: michael@0: // url constructed with %VERSION% michael@0: function run_test_pt2() { michael@0: gCheckFunc = check_test_pt2; michael@0: var url = URL_PREFIX + "%VERSION%/"; michael@0: logTestInfo("testing url constructed with %VERSION% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt2() { michael@0: do_check_eq(getResult(gRequestURL), gAppInfo.version); michael@0: run_test_pt3(); michael@0: } michael@0: michael@0: // url constructed with %BUILD_ID% michael@0: function run_test_pt3() { michael@0: gCheckFunc = check_test_pt3; michael@0: var url = URL_PREFIX + "%BUILD_ID%/"; michael@0: logTestInfo("testing url constructed with %BUILD_ID% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt3() { michael@0: do_check_eq(getResult(gRequestURL), gAppInfo.appBuildID); michael@0: run_test_pt4(); michael@0: } michael@0: michael@0: // url constructed with %BUILD_TARGET% michael@0: // XXX TODO - it might be nice if we tested the actual ABI michael@0: function run_test_pt4() { michael@0: gCheckFunc = check_test_pt4; michael@0: var url = URL_PREFIX + "%BUILD_TARGET%/"; michael@0: logTestInfo("testing url constructed with %BUILD_TARGET% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt4() { michael@0: var abi; michael@0: try { michael@0: abi = gAppInfo.XPCOMABI; michael@0: } catch (e) { michael@0: do_throw("nsIXULAppInfo:XPCOMABI not defined\n"); michael@0: } michael@0: michael@0: if (IS_MACOSX) { michael@0: // Mac universal build should report a different ABI than either macppc michael@0: // or mactel. This is necessary since nsUpdateService.js will set the ABI to michael@0: // Universal-gcc3 for Mac universal builds. michael@0: var macutils = AUS_Cc["@mozilla.org/xpcom/mac-utils;1"]. michael@0: getService(AUS_Ci.nsIMacUtils); michael@0: michael@0: if (macutils.isUniversalBinary) michael@0: abi += "-u-" + macutils.architecturesInBinary; michael@0: if (IS_SHARK) { michael@0: // Disambiguate optimised and shark nightlies michael@0: abi += "-shark" michael@0: } michael@0: michael@0: } michael@0: michael@0: do_check_eq(getResult(gRequestURL), gAppInfo.OS + "_" + abi); michael@0: run_test_pt5(); michael@0: } michael@0: michael@0: // url constructed with %LOCALE% michael@0: // Bug 488936 added the update.locale file that stores the update locale michael@0: function run_test_pt5() { michael@0: gCheckFunc = check_test_pt5; michael@0: var url = URL_PREFIX + "%LOCALE%/"; michael@0: logTestInfo("testing url constructed with %LOCALE% - " + url); michael@0: setUpdateURLOverride(url); michael@0: try { michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } catch (e) { michael@0: logTestInfo("The following error is most likely due to a missing " + michael@0: "update.locale file"); michael@0: do_throw(e); michael@0: } michael@0: } michael@0: michael@0: function check_test_pt5() { michael@0: do_check_eq(getResult(gRequestURL), INSTALL_LOCALE); michael@0: run_test_pt6(); michael@0: } michael@0: michael@0: // url constructed with %CHANNEL% michael@0: function run_test_pt6() { michael@0: gCheckFunc = check_test_pt6; michael@0: var url = URL_PREFIX + "%CHANNEL%/"; michael@0: logTestInfo("testing url constructed with %CHANNEL% - " + url); michael@0: setUpdateURLOverride(url); michael@0: setUpdateChannel("test_channel"); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt6() { michael@0: do_check_eq(getResult(gRequestURL), "test_channel"); michael@0: run_test_pt7(); michael@0: } michael@0: michael@0: // url constructed with %CHANNEL% with distribution partners michael@0: function run_test_pt7() { michael@0: gCheckFunc = check_test_pt7; michael@0: var url = URL_PREFIX + "%CHANNEL%/"; michael@0: logTestInfo("testing url constructed with %CHANNEL% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gDefaultPrefBranch.setCharPref(PREF_APP_PARTNER_BRANCH + "test_partner1", "test_partner1"); michael@0: gDefaultPrefBranch.setCharPref(PREF_APP_PARTNER_BRANCH + "test_partner2", "test_partner2"); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt7() { michael@0: do_check_eq(getResult(gRequestURL), "test_channel-cck-test_partner1-test_partner2"); michael@0: run_test_pt8(); michael@0: } michael@0: michael@0: // url constructed with %PLATFORM_VERSION% michael@0: function run_test_pt8() { michael@0: gCheckFunc = check_test_pt8; michael@0: var url = URL_PREFIX + "%PLATFORM_VERSION%/"; michael@0: logTestInfo("testing url constructed with %PLATFORM_VERSION% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt8() { michael@0: do_check_eq(getResult(gRequestURL), gAppInfo.platformVersion); michael@0: run_test_pt9(); michael@0: } michael@0: michael@0: // url constructed with %OS_VERSION% michael@0: function run_test_pt9() { michael@0: gCheckFunc = check_test_pt9; michael@0: var url = URL_PREFIX + "%OS_VERSION%/"; michael@0: logTestInfo("testing url constructed with %OS_VERSION% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function getServicePack() { michael@0: // NOTE: This function is a helper function and not a test. Thus, michael@0: // it uses throw() instead of do_throw(). Any tests that use this function michael@0: // should catch exceptions thrown in this function and deal with them michael@0: // appropriately (usually by calling do_throw). michael@0: const BYTE = ctypes.uint8_t; michael@0: const WORD = ctypes.uint16_t; michael@0: const DWORD = ctypes.uint32_t; michael@0: const WCHAR = ctypes.jschar; michael@0: const BOOL = ctypes.int; michael@0: michael@0: // This structure is described at: michael@0: // http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx michael@0: const SZCSDVERSIONLENGTH = 128; michael@0: const OSVERSIONINFOEXW = new ctypes.StructType('OSVERSIONINFOEXW', michael@0: [ michael@0: {dwOSVersionInfoSize: DWORD}, michael@0: {dwMajorVersion: DWORD}, michael@0: {dwMinorVersion: DWORD}, michael@0: {dwBuildNumber: DWORD}, michael@0: {dwPlatformId: DWORD}, michael@0: {szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH)}, michael@0: {wServicePackMajor: WORD}, michael@0: {wServicePackMinor: WORD}, michael@0: {wSuiteMask: WORD}, michael@0: {wProductType: BYTE}, michael@0: {wReserved: BYTE} michael@0: ]); michael@0: michael@0: let kernel32 = ctypes.open("kernel32"); michael@0: try { michael@0: let GetVersionEx = kernel32.declare("GetVersionExW", michael@0: ctypes.default_abi, michael@0: BOOL, michael@0: OSVERSIONINFOEXW.ptr); michael@0: let winVer = OSVERSIONINFOEXW(); michael@0: winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size; michael@0: michael@0: if(0 === GetVersionEx(winVer.address())) { michael@0: // Using "throw" instead of "do_throw" (see NOTE above) michael@0: throw("Failure in GetVersionEx (returned 0)"); michael@0: } michael@0: michael@0: return winVer.wServicePackMajor + "." + winVer.wServicePackMinor; michael@0: } finally { michael@0: kernel32.close(); michael@0: } michael@0: } michael@0: michael@0: function getProcArchitecture() { michael@0: // NOTE: This function is a helper function and not a test. Thus, michael@0: // it uses throw() instead of do_throw(). Any tests that use this function michael@0: // should catch exceptions thrown in this function and deal with them michael@0: // appropriately (usually by calling do_throw). michael@0: const WORD = ctypes.uint16_t; michael@0: const DWORD = ctypes.uint32_t; michael@0: michael@0: // This structure is described at: michael@0: // http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx michael@0: const SYSTEM_INFO = new ctypes.StructType('SYSTEM_INFO', michael@0: [ michael@0: {wProcessorArchitecture: WORD}, michael@0: {wReserved: WORD}, michael@0: {dwPageSize: DWORD}, michael@0: {lpMinimumApplicationAddress: ctypes.voidptr_t}, michael@0: {lpMaximumApplicationAddress: ctypes.voidptr_t}, michael@0: {dwActiveProcessorMask: DWORD.ptr}, michael@0: {dwNumberOfProcessors: DWORD}, michael@0: {dwProcessorType: DWORD}, michael@0: {dwAllocationGranularity: DWORD}, michael@0: {wProcessorLevel: WORD}, michael@0: {wProcessorRevision: WORD} michael@0: ]); michael@0: michael@0: let kernel32 = ctypes.open("kernel32"); michael@0: try { michael@0: let GetNativeSystemInfo = kernel32.declare("GetNativeSystemInfo", michael@0: ctypes.default_abi, michael@0: ctypes.void_t, michael@0: SYSTEM_INFO.ptr); michael@0: let sysInfo = SYSTEM_INFO(); michael@0: // Default to unknown michael@0: sysInfo.wProcessorArchitecture = 0xffff; michael@0: michael@0: GetNativeSystemInfo(sysInfo.address()); michael@0: switch(sysInfo.wProcessorArchitecture) { michael@0: case 9: michael@0: return "x64"; michael@0: case 6: michael@0: return "IA64"; michael@0: case 0: michael@0: return "x86"; michael@0: default: michael@0: // Using "throw" instead of "do_throw" (see NOTE above) michael@0: throw("Unknown architecture returned from GetNativeSystemInfo: " + sysInfo.wProcessorArchitecture); michael@0: } michael@0: } finally { michael@0: kernel32.close(); michael@0: } michael@0: } michael@0: michael@0: function check_test_pt9() { michael@0: var osVersion; michael@0: var sysInfo = AUS_Cc["@mozilla.org/system-info;1"]. michael@0: getService(AUS_Ci.nsIPropertyBag2); michael@0: osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version"); michael@0: michael@0: if(IS_WIN) { michael@0: try { michael@0: let servicePack = getServicePack(); michael@0: osVersion += "." + servicePack; michael@0: } catch (e) { michael@0: do_throw("Failure obtaining service pack: " + e); michael@0: } michael@0: michael@0: if("5.0" === sysInfo.getProperty("version")) { // Win2K michael@0: osVersion += " (unknown)"; michael@0: } else { michael@0: try { michael@0: osVersion += " (" + getProcArchitecture() + ")"; michael@0: } catch (e) { michael@0: do_throw("Failed to obtain processor architecture: " + e); michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (osVersion) { michael@0: try { michael@0: osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")"; michael@0: } catch (e) { michael@0: // Not all platforms have a secondary widget library, so an error is michael@0: // nothing to worry about. michael@0: } michael@0: osVersion = encodeURIComponent(osVersion); michael@0: } michael@0: michael@0: do_check_eq(getResult(gRequestURL), osVersion); michael@0: run_test_pt10(); michael@0: } michael@0: michael@0: // url constructed with %DISTRIBUTION% michael@0: function run_test_pt10() { michael@0: gCheckFunc = check_test_pt10; michael@0: var url = URL_PREFIX + "%DISTRIBUTION%/"; michael@0: logTestInfo("testing url constructed with %DISTRIBUTION% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_ID, "test_distro"); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt10() { michael@0: do_check_eq(getResult(gRequestURL), "test_distro"); michael@0: run_test_pt11(); michael@0: } michael@0: michael@0: // url constructed with %DISTRIBUTION_VERSION% michael@0: function run_test_pt11() { michael@0: gCheckFunc = check_test_pt11; michael@0: var url = URL_PREFIX + "%DISTRIBUTION_VERSION%/"; michael@0: logTestInfo("testing url constructed with %DISTRIBUTION_VERSION% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_VERSION, "test_distro_version"); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt11() { michael@0: do_check_eq(getResult(gRequestURL), "test_distro_version"); michael@0: run_test_pt12(); michael@0: } michael@0: michael@0: // url with force param that doesn't already have a param - bug 454357 michael@0: function run_test_pt12() { michael@0: gCheckFunc = check_test_pt12; michael@0: var url = URL_PREFIX; michael@0: logTestInfo("testing url with force param that doesn't already have a " + michael@0: "param - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt12() { michael@0: do_check_eq(getResult(gRequestURL), "?force=1"); michael@0: run_test_pt13(); michael@0: } michael@0: michael@0: // url with force param that already has a param - bug 454357 michael@0: function run_test_pt13() { michael@0: gCheckFunc = check_test_pt13; michael@0: var url = URL_PREFIX + "?extra=param"; michael@0: logTestInfo("testing url with force param that already has a param - " + url); michael@0: logTestInfo("testing url constructed that has a parameter - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt13() { michael@0: do_check_eq(getResult(gRequestURL), "?extra=param&force=1"); michael@0: run_test_pt14(); michael@0: } michael@0: michael@0: function run_test_pt14() { michael@0: Services.prefs.setCharPref("app.update.custom", "custom"); michael@0: gCheckFunc = check_test_pt14; michael@0: var url = URL_PREFIX + "?custom=%CUSTOM%"; michael@0: logTestInfo("testing url constructed with %CUSTOM% - " + url); michael@0: setUpdateURLOverride(url); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_pt14() { michael@0: do_check_eq(getResult(gRequestURL), "?custom=custom&force=1"); michael@0: doTestFinish(); michael@0: }