Bug 1330184 - Add some GeckoProfiler tests that call functions on a background thread. r=njn
authorMarkus Stange <mstange@themasta.com>
Tue, 30 May 2017 17:48:19 -0400
changeset 409561 c9669890cf99c9db2374cf81055c19cb42e382c4
parent 409560 ac273d41a04478e7d380010cd1d1cab98d29a45c
child 409562 bb9f906e70e30d56c386717ee9a45b7d3c774573
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1330184
milestone55.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 1330184 - Add some GeckoProfiler tests that call functions on a background thread. r=njn MozReview-Commit-ID: 9fMPyQ909PW
tools/profiler/tests/gtest/GeckoProfiler.cpp
--- a/tools/profiler/tests/gtest/GeckoProfiler.cpp
+++ b/tools/profiler/tests/gtest/GeckoProfiler.cpp
@@ -12,16 +12,18 @@
 #include "gtest/gtest.h"
 
 #include "GeckoProfiler.h"
 #include "ProfilerMarkerPayload.h"
 #include "jsapi.h"
 #include "js/Initialization.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "ProfileJSONWriter.h"
+#include "nsIThread.h"
+#include "nsThreadUtils.h"
 
 #include <string.h>
 
 // Note: profiler_init() has already been called in XRE_main(), so we can't
 // test it here. Likewise for profiler_shutdown(), and GeckoProfilerInitRAII
 // (which is just an RAII wrapper for profiler_init() and profiler_shutdown()).
 
 using namespace mozilla;
@@ -163,16 +165,79 @@ TEST(GeckoProfiler, FeaturesAndParams)
     // These calls are no-ops.
     profiler_stop();
     profiler_stop();
 
     InactiveFeaturesAndParamsCheck();
   }
 }
 
+TEST(GeckoProfiler, DifferentThreads)
+{
+  InactiveFeaturesAndParamsCheck();
+
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_NewNamedThread("GeckoProfGTest", getter_AddRefs(thread));
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  // Control the profiler on a background thread and verify flags on the
+  // main thread.
+  {
+    uint32_t features = ProfilerFeature::JS | ProfilerFeature::Threads;
+    const char* filters[] = { "GeckoMain", "Compositor" };
+
+    thread->Dispatch(NS_NewRunnableFunction([&]() {
+      profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
+                    features, filters, MOZ_ARRAY_LENGTH(filters));
+    }), NS_DISPATCH_SYNC);
+
+    ASSERT_TRUE(profiler_is_active());
+    ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::GPU));
+    ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Privacy));
+    ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Restyle));
+
+    ActiveParamsCheck(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
+                      features, filters, MOZ_ARRAY_LENGTH(filters));
+
+    thread->Dispatch(NS_NewRunnableFunction([&]() {
+      profiler_stop();
+    }), NS_DISPATCH_SYNC);
+
+    InactiveFeaturesAndParamsCheck();
+  }
+
+  // Control the profiler on the main thread and verify flags on a
+  // background thread.
+  {
+    uint32_t features = ProfilerFeature::JS | ProfilerFeature::Threads;
+    const char* filters[] = { "GeckoMain", "Compositor" };
+
+    profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
+                  features, filters, MOZ_ARRAY_LENGTH(filters));
+
+    thread->Dispatch(NS_NewRunnableFunction([&]() {
+      ASSERT_TRUE(profiler_is_active());
+      ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::GPU));
+      ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Privacy));
+      ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Restyle));
+
+      ActiveParamsCheck(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
+                        features, filters, MOZ_ARRAY_LENGTH(filters));
+    }), NS_DISPATCH_SYNC);
+
+    profiler_stop();
+
+    thread->Dispatch(NS_NewRunnableFunction([&]() {
+      InactiveFeaturesAndParamsCheck();
+    }), NS_DISPATCH_SYNC);
+  }
+
+  thread->Shutdown();
+}
+
 TEST(GeckoProfiler, GetBacktrace)
 {
   ASSERT_TRUE(!profiler_get_backtrace());
 
   {
     uint32_t features = ProfilerFeature::StackWalk;
     const char* filters[] = { "GeckoMain" };
 
@@ -347,16 +412,55 @@ TEST(GeckoProfiler, StreamJSONForThisPro
   UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
   ASSERT_TRUE(profile && profile[0] == '{');
 
   profiler_stop();
 
   ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
 }
 
+TEST(GeckoProfiler, StreamJSONForThisProcessThreaded)
+{
+  // Same as the previous test, but calling some things on background threads.
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_NewNamedThread("GeckoProfGTest", getter_AddRefs(thread));
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  uint32_t features = ProfilerFeature::StackWalk;
+  const char* filters[] = { "GeckoMain" };
+
+  SpliceableChunkedJSONWriter w;
+  ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+
+  // Start the profiler on the main thread.
+  profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
+                features, filters, MOZ_ARRAY_LENGTH(filters));
+
+  // Call profiler_stream_json_for_this_process on a background thread.
+  thread->Dispatch(NS_NewRunnableFunction([&]() {
+    w.Start(SpliceableJSONWriter::SingleLineStyle);
+    ASSERT_TRUE(profiler_stream_json_for_this_process(w));
+    w.End();
+  }), NS_DISPATCH_SYNC);
+
+  UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
+  ASSERT_TRUE(profile && profile[0] == '{');
+
+  // Stop the profiler and call profiler_stream_json_for_this_process on a
+  // background thread.
+  thread->Dispatch(NS_NewRunnableFunction([&]() {
+    profiler_stop();
+    ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+  }), NS_DISPATCH_SYNC);
+  thread->Shutdown();
+
+  // Call profiler_stream_json_for_this_process on the main thread.
+  ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+}
+
 TEST(GeckoProfiler, PseudoStack)
 {
   uint32_t features = ProfilerFeature::StackWalk;
   const char* filters[] = { "GeckoMain" };
 
   PROFILER_LABEL("A", "B", js::ProfileEntry::Category::OTHER);
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);