Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'mac' && os_version == '10.15' && processor == 'x86_64' OR os == 'mac' && os_version == '11.20' && arch == 'aarch64' OR os == 'mac' && os_version == '14.70' && processor == 'x86_64'
- Manifest: toolkit/components/telemetry/tests/unit/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
const { ctypes } = ChromeUtils.importESModule(
"resource://gre/modules/ctypes.sys.mjs"
);
const MAX_NAME_LENGTH = 64;
// The following libraries (except libxul) are all built from the
// toolkit/components/telemetry/tests/modules-test.cpp file, which contains
// instructions on how to build them.
const libModules = ctypes.libraryName("modules-test");
const libUnicode = ctypes.libraryName("modĪ¼les-test");
const libLongName =
"lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_Fusce_sit_amet_tellus_non_magna_euismod_vestibulum_Vivamus_turpis_duis.dll";
function chooseDLL(x86, x64, aarch64) {
let xpcomabi = Services.appinfo.XPCOMABI;
let cpu = xpcomabi.split("-")[0];
switch (cpu) {
case "aarch64":
return aarch64;
case "x86_64":
return x64;
case "x86":
return x86;
// This case only happens on Android, which gets skipped below. The previous
// code was returning the x86 version when testing for arm.
case "arm":
return x86;
default:
Assert.ok(false, "unexpected CPU type: " + cpu);
return x86;
}
}
const libUnicodePDB = chooseDLL(
"testUnicodePDB32.dll",
"testUnicodePDB64.dll",
"testUnicodePDBAArch64.dll"
);
const libNoPDB = chooseDLL(
"testNoPDB32.dll",
"testNoPDB64.dll",
"testNoPDBAArch64.dll"
);
const libxul = PathUtils.filename(PathUtils.xulLibraryPath);
const libModulesFile = do_get_file(libModules).path;
const libUnicodeFile = PathUtils.join(
PathUtils.parent(libModulesFile),
libUnicode
);
const libLongNameFile = PathUtils.join(
PathUtils.parent(libModulesFile),
libLongName
);
const libUnicodePDBFile = do_get_file(libUnicodePDB).path;
const libNoPDBFile = do_get_file(libNoPDB).path;
let libModulesHandle,
libUnicodeHandle,
libLongNameHandle,
libUnicodePDBHandle,
libNoPDBHandle;
let expectedLibs;
if (AppConstants.platform === "win") {
const version = AppConstants.MOZ_APP_VERSION.substring(
0,
AppConstants.MOZ_APP_VERSION.indexOf(".") + 2
);
expectedLibs = [
{
name: libxul,
debugName: libxul.replace(".dll", ".pdb"),
version,
},
{
name: libModules,
debugName: libModules.replace(".dll", ".pdb"),
version,
},
{
name: libUnicode,
debugName: libModules.replace(".dll", ".pdb"),
version,
},
{
name: libLongName.substring(0, MAX_NAME_LENGTH - 1) + "ā¦",
debugName: libModules.replace(".dll", ".pdb"),
version,
},
{
name: libUnicodePDB,
debugName: "libmodĪ¼les.pdb",
version: null,
},
{
name: libNoPDB,
debugName: null,
version: null,
},
{
// We choose this DLL because it's guaranteed to exist in our process and
// be signed on all Windows versions that we support.
name: "ntdll.dll",
// debugName changes depending on OS version and is irrelevant to this test
// version changes depending on OS version and is irrelevant to this test
certSubject: "Microsoft Windows",
},
];
} else {
expectedLibs = [
{
name: libxul,
debugName: libxul,
version: null,
},
{
name: libModules,
debugName: libModules,
version: null,
},
{
name: libUnicode,
debugName: libUnicode,
version: null,
},
{
name: libLongName.substring(0, MAX_NAME_LENGTH - 1) + "ā¦",
debugName: libLongName.substring(0, MAX_NAME_LENGTH - 1) + "ā¦",
version: null,
},
];
}
add_task(async function setup() {
do_get_profile();
await IOUtils.copy(libModulesFile, libUnicodeFile);
await IOUtils.copy(libModulesFile, libLongNameFile);
libModulesHandle = ctypes.open(libModulesFile);
libUnicodeHandle = ctypes.open(libUnicodeFile);
libLongNameHandle = ctypes.open(libLongNameFile);
if (AppConstants.platform === "win") {
libUnicodePDBHandle = ctypes.open(libUnicodePDBFile);
libNoPDBHandle = ctypes.open(libNoPDBFile);
}
// Pretend the untrustedmodules ping has already been sent now to get it out
// of the way and avoid confusing the test with our PingServer receiving two
// pings during our test.
Services.prefs.setIntPref(
"app.update.lastUpdateTime.telemetry_untrustedmodules_ping",
Math.round(Date.now() / 1000)
);
// Force the timer to fire (using a small interval).
Cc["@mozilla.org/updates/timer-manager;1"]
.getService(Ci.nsIObserver)
.observe(null, "utm-test-init", "");
Services.prefs.setIntPref("toolkit.telemetry.modulesPing.interval", 0);
// Start the local ping server and setup Telemetry to use it during the tests.
PingServer.start();
Services.prefs.setStringPref(
TelemetryUtils.Preferences.Server,
);
});
registerCleanupFunction(function () {
if (libModulesHandle) {
libModulesHandle.close();
}
if (libUnicodeHandle) {
libUnicodeHandle.close();
}
if (libLongNameHandle) {
libLongNameHandle.close();
}
if (libUnicodePDBHandle) {
libUnicodePDBHandle.close();
}
if (libNoPDBHandle) {
libNoPDBHandle.close();
}
return IOUtils.remove(libUnicodeFile)
.then(() => IOUtils.remove(libLongNameFile))
.then(() => PingServer.stop());
});
add_task(
{
skip_if: () => !AppConstants.MOZ_GECKO_PROFILER,
},
async function test_send_ping() {
await TelemetryController.testSetup();
let found = await PingServer.promiseNextPing();
Assert.ok(!!found, "Telemetry ping submitted.");
Assert.strictEqual(found.type, "modules", "Ping type is 'modules'");
Assert.ok(found.environment, "'modules' ping has an environment.");
Assert.ok(!!found.clientId, "'modules' ping has a client ID.");
Assert.ok(
!!found.payload.modules,
"Telemetry ping payload contains the 'modules' array."
);
let nameComparator;
if (AppConstants.platform === "win") {
// Do case-insensitive checking of file/module names on Windows
nameComparator = function (a, b) {
if (typeof a === "string" && typeof b === "string") {
return a.toLowerCase() === b.toLowerCase();
}
return a === b;
};
} else {
nameComparator = function (a, b) {
return a === b;
};
}
for (let lib of expectedLibs) {
let test_lib = found.payload.modules.find(module =>
nameComparator(module.name, lib.name)
);
Assert.ok(!!test_lib, "There is a '" + lib.name + "' module.");
if ("version" in lib) {
if (lib.version !== null) {
Assert.ok(
test_lib.version.startsWith(lib.version),
"The version of the " +
lib.name +
" module (" +
test_lib.version +
") is correct (it starts with '" +
lib.version +
"')."
);
} else {
Assert.strictEqual(
test_lib.version,
null,
"The version of the " + lib.name + " module is null."
);
}
}
if ("debugName" in lib) {
Assert.ok(
nameComparator(test_lib.debugName, lib.debugName),
"The " + lib.name + " module has the correct debug name."
);
}
if (lib.debugName === null) {
Assert.strictEqual(
test_lib.debugID,
null,
"The " + lib.name + " module doesn't have a debug ID."
);
} else {
Assert.greater(
test_lib.debugID.length,
0,
"The " + lib.name + " module has a debug ID."
);
}
if ("certSubject" in lib) {
Assert.strictEqual(
test_lib.certSubject,
lib.certSubject,
"The " + lib.name + " module has the expected cert subject."
);
}
}
let test_lib = found.payload.modules.find(
module => module.name === libLongName
);
Assert.ok(!test_lib, "There isn't a '" + libLongName + "' module.");
}
);