Bug 1510979 - add a telemetry xpcshell-test for socket process r=janerik
authorJunior Hsu <juhsu@mozilla.com>
Tue, 15 Jan 2019 23:15:38 +0000
changeset 514034 fe00e2fad26f127775297d4b1886a1561e170232
parent 514033 847d1877fedaf7f30271b6a217138b80d0e7cbf2
child 514035 54b883fea35a02c8e7d332a5a6c0904318e598e1
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanerik
bugs1510979, 1496257
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1510979 - add a telemetry xpcshell-test for socket process r=janerik We need a test-only IPC message to socket process to trigger the Telemetry::Scalar set since no js engine in the socket process. And hook the IPC call to AddPendingEvent |CallOrWaitSocketProcess| introduced by bug 1496257. Differential Revision: https://phabricator.services.mozilla.com/D14822
netwerk/base/nsINetUtil.idl
netwerk/base/nsIOService.cpp
netwerk/ipc/PSocketProcess.ipdl
netwerk/ipc/SocketProcessChild.cpp
netwerk/ipc/SocketProcessChild.h
toolkit/components/telemetry/tests/unit/test_SocketScalars.js
toolkit/components/telemetry/tests/unit/xpcshell.ini
--- a/netwerk/base/nsINetUtil.idl
+++ b/netwerk/base/nsINetUtil.idl
@@ -219,15 +219,20 @@ interface nsINetUtil : nsISupports
    *
    * @param aPolicy
    *        the policy integer code (defined in nsIHttpChannel.idl)
    * @return aPolicyString
    *         referrer policy string from code
    */
   ACString getReferrerPolicyString(in unsigned long aPolicy);
 
+  /**
+   * This is test-only. Send an IPC message to let socket process send a
+   * telemetry.
+   */
+  void socketProcessTelemetryPing();
 
   /**
    * This is a void method that is C++ implemented and always
    * returns NS_ERROR_NOT_IMPLEMENTED. To be used for testing.
    */
   void notImplemented();
 };
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -502,16 +502,25 @@ RefPtr<MemoryReportingProcess> nsIOServi
   if (!Preferences::GetBool("network.process.enabled") || !SocketProcessReady()) {
     return nullptr;
 
   }
 
   return new SocketProcessMemoryReporter();
 }
 
+NS_IMETHODIMP
+nsIOService::SocketProcessTelemetryPing() {
+  CallOrWaitForSocketProcess([]() {
+    Unused << gIOService->mSocketProcess->GetActor()
+                  ->SendSocketProcessTelemetryPing();
+  });
+  return NS_OK;
+}
+
 NS_IMPL_ISUPPORTS(nsIOService, nsIIOService, nsINetUtil, nsISpeculativeConnect,
                   nsIObserver, nsIIOServiceInternal, nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 
 nsresult nsIOService::RecheckCaptivePortal() {
   MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread");
   if (!mCaptivePortalService) {
--- a/netwerk/ipc/PSocketProcess.ipdl
+++ b/netwerk/ipc/PSocketProcess.ipdl
@@ -38,12 +38,14 @@ child:
   async PreferenceUpdate(Pref pref);
   async RequestMemoryReport(uint32_t generation,
                             bool anonymize,
                             bool minimizeMemoryUsage,
                             MaybeFileDesc DMDFile);
   async SetOffline(bool offline);
   async InitSocketProcessBridgeParent(ProcessId processId, Endpoint<PSocketProcessBridgeParent> endpoint);
   async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
+  // test-only
+  async SocketProcessTelemetryPing();
 };
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.cpp
+++ b/netwerk/ipc/SocketProcessChild.cpp
@@ -146,16 +146,23 @@ mozilla::ipc::IPCResult SocketProcessChi
     Endpoint<PProfilerChild>&& aEndpoint) {
 #ifdef MOZ_GECKO_PROFILER
   mProfilerController =
       mozilla::ChildProfilerController::Create(std::move(aEndpoint));
 #endif
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult SocketProcessChild::RecvSocketProcessTelemetryPing() {
+  const uint32_t kExpectedUintValue = 42;
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_SOCKET_ONLY_UINT,
+      kExpectedUintValue);
+  return IPC_OK();
+}
+
 void SocketProcessChild::DestroySocketProcessBridgeParent(ProcessId aId) {
   MOZ_ASSERT(NS_IsMainThread());
 
   mSocketProcessBridgeParentMap.Remove(aId);
 }
 
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.h
+++ b/netwerk/ipc/SocketProcessChild.h
@@ -37,16 +37,17 @@ class SocketProcessChild final : public 
       const uint32_t& generation, const bool& anonymize,
       const bool& minimizeMemoryUsage, const MaybeFileDesc& DMDFile) override;
   mozilla::ipc::IPCResult RecvSetOffline(const bool& aOffline) override;
   mozilla::ipc::IPCResult RecvInitSocketProcessBridgeParent(
       const ProcessId& aContentProcessId,
       Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvInitProfiler(
       Endpoint<mozilla::PProfilerChild>&& aEndpoint) override;
+  mozilla::ipc::IPCResult RecvSocketProcessTelemetryPing() override;
 
   void CleanUp();
   void DestroySocketProcessBridgeParent(ProcessId aId);
 
  private:
   // Mapping of content process id and the SocketProcessBridgeParent.
   // This table keeps SocketProcessBridgeParent alive in socket process.
   nsRefPtrHashtable<nsUint32HashKey, SocketProcessBridgeParent>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/telemetry/tests/unit/test_SocketScalars.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/TelemetryController.jsm");
+ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm");
+
+const SOCKET_ONLY_UINT_SCALAR = "telemetry.test.socket_only_uint";
+
+/**
+ * This function waits until socket scalars are reported into the
+ * scalar snapshot.
+ */
+async function waitForSocketScalars() {
+  await ContentTaskUtils.waitForCondition(() => {
+    const scalars = Telemetry.getSnapshotForScalars("main", false);
+    return Object.keys(scalars).includes("socket");
+  });
+}
+
+add_task(async function() {
+  if (!Services.prefs.getBoolPref("network.process.enabled")) {
+    Assert.ok(true, "Test finished: no point to test telemetry from socket process with lanuching the process");
+    return;
+  }
+
+  do_test_pending();
+
+  do_get_profile(true);
+  await TelemetryController.testSetup();
+
+  Services.netUtils.socketProcessTelemetryPing();
+
+  // Once scalars are set by the socket process, they don't immediately get
+  // sent to the parent process. Wait for the Telemetry IPC Timer to trigger
+  // and batch send the data back to the parent process.
+  await waitForSocketScalars();
+
+  Assert.equal(Telemetry.getSnapshotForScalars("main", false)
+                   .socket[SOCKET_ONLY_UINT_SCALAR],
+               42,
+               `${SOCKET_ONLY_UINT_SCALAR} must have the correct value (socket process).`);
+  do_test_finished();
+});
+
--- a/toolkit/components/telemetry/tests/unit/xpcshell.ini
+++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini
@@ -62,16 +62,18 @@ skip-if = (verify && debug && os == 'lin
 skip-if = os == "android"
 [test_TelemetrySession_activeTicks.js]
 [test_TelemetrySend.js]
 [test_ChildHistograms.js]
 skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
 tags = addons
 [test_ChildScalars.js]
 skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
+[test_SocketScalars.js]
+skip-if = os == "android"
 [test_TelemetryReportingPolicy.js]
 skip-if = os == "android" # Disabled due to crashes (see bug 1367762)
 tags = addons
 [test_TelemetryScalars.js]
 [test_TelemetryScalars_buildFaster.js]
 [test_TelemetryScalars_multistore.js]
 [test_TelemetryTimestamps.js]
 skip-if = toolkit == 'android'