Index: chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc |
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc |
index 173ebe02612d4185a20e5d9a3f6f364494234f22..c07ca4277bed84c120c3aada99b68e17b8c149d5 100644 |
--- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc |
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc |
@@ -4,15 +4,41 @@ |
#include "chrome/browser/metrics/process_memory_metrics_emitter.h" |
+#include "base/memory/ref_counted.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/test/histogram_tester.h" |
+#include "base/test/trace_event_analyzer.h" |
+#include "base/trace_event/memory_dump_manager.h" |
+#include "base/trace_event/trace_config_memory_test_util.h" |
#include "chrome/test/base/in_process_browser_test.h" |
+#include "chrome/test/base/tracing.h" |
+#include "chrome/test/base/ui_test_utils.h" |
#include "content/public/test/test_utils.h" |
+#include "url/gurl.h" |
namespace { |
+using base::trace_event::MemoryDumpType; |
+ |
+void RequestGlobalDumpCallback(base::Closure quit_closure, |
+ uint64_t, |
+ bool success) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); |
+ ASSERT_TRUE(success); |
+} |
+ |
+void OnStartTracingDoneCallback( |
+ base::trace_event::MemoryDumpLevelOfDetail explicit_dump_type, |
+ base::Closure quit_closure) { |
+ base::trace_event::MemoryDumpManager::GetInstance()->RequestGlobalDump( |
+ MemoryDumpType::EXPLICITLY_TRIGGERED, explicit_dump_type, |
+ Bind(&RequestGlobalDumpCallback, quit_closure)); |
+} |
+ |
class ProcessMemoryMetricsEmitterFake : public ProcessMemoryMetricsEmitter { |
public: |
- ProcessMemoryMetricsEmitterFake() {} |
+ explicit ProcessMemoryMetricsEmitterFake(base::RunLoop* run_loop) |
+ : run_loop_(run_loop) {} |
private: |
~ProcessMemoryMetricsEmitterFake() override {} |
@@ -22,12 +48,71 @@ class ProcessMemoryMetricsEmitterFake : public ProcessMemoryMetricsEmitter { |
bool success, |
memory_instrumentation::mojom::GlobalMemoryDumpPtr ptr) override { |
EXPECT_TRUE(success); |
- base::MessageLoop::current()->QuitWhenIdle(); |
+ ProcessMemoryMetricsEmitter::ReceivedMemoryDump(dump_guid, success, |
+ std::move(ptr)); |
+ if (run_loop_) |
+ run_loop_->Quit(); |
} |
+ base::RunLoop* run_loop_; |
+ |
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterFake); |
}; |
+void CheckMemoryMetric(const std::string& name, |
+ const base::HistogramTester& histogram_tester, |
+ int count, |
+ bool check_minimum) { |
+ std::unique_ptr<base::HistogramSamples> samples( |
+ histogram_tester.GetHistogramSamplesSinceCreation(name)); |
+ ASSERT_TRUE(samples); |
+ |
+ bool count_matches = samples->TotalCount() == count; |
+ // The exact number of renderers present at the time the metrics are emitted |
+ // is not deterministic. Sometimes there are 2 renderers instead of 1. |
+ if (name.find("Renderer") != std::string::npos) { |
+ count_matches = |
+ samples->TotalCount() >= count && samples->TotalCount() <= 2 * count; |
+ } |
+ |
+ EXPECT_TRUE(count_matches); |
+ if (check_minimum) |
+ EXPECT_GT(samples->sum(), 0u) << name; |
+ |
+ // As a sanity check, no memory stat should exceed 1 GB. |
+ int64_t maximum_expected_size = 1ll << 30; |
+ EXPECT_LT(samples->sum(), maximum_expected_size) << name; |
+} |
+ |
+void CheckAllMemoryMetrics(const base::HistogramTester& histogram_tester, |
+ int count) { |
+#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_LINUX) || \ |
+ defined(OS_ANDROID) |
+ bool private_footprint_implemented = true; |
+#else |
+ bool private_footprint_implemented = false; |
+#endif |
+ |
+ CheckMemoryMetric("Memory.Experimental.Browser2.Malloc", histogram_tester, |
+ count, true); |
+ CheckMemoryMetric("Memory.Experimental.Browser2.Resident", histogram_tester, |
+ count, true); |
+ CheckMemoryMetric("Memory.Experimental.Browser2.PrivateMemoryFootprint", |
+ histogram_tester, count, private_footprint_implemented); |
+ CheckMemoryMetric("Memory.Experimental.Renderer2.Malloc", histogram_tester, |
+ count, true); |
+ CheckMemoryMetric("Memory.Experimental.Renderer2.Resident", histogram_tester, |
+ count, true); |
+ CheckMemoryMetric("Memory.Experimental.Renderer2.BlinkGC", histogram_tester, |
+ count, false); |
+ CheckMemoryMetric("Memory.Experimental.Renderer2.PartitionAlloc", |
+ histogram_tester, count, false); |
+ CheckMemoryMetric("Memory.Experimental.Renderer2.V8", histogram_tester, count, |
+ true); |
+ CheckMemoryMetric("Memory.Experimental.Renderer2.PrivateMemoryFootprint", |
+ histogram_tester, count, private_footprint_implemented); |
+} |
+ |
} // namespace |
class ProcessMemoryMetricsEmitterTest : public InProcessBrowserTest { |
@@ -39,14 +124,111 @@ class ProcessMemoryMetricsEmitterTest : public InProcessBrowserTest { |
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterTest); |
}; |
-IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, FetchAndEmitMetrics) { |
+#if defined(ADDRESS_SANITIZER) |
+#define MAYBE_FetchAndEmitMetrics DISABLED_FetchAndEmitMetrics |
+#else |
+#define MAYBE_FetchAndEmitMetrics FetchAndEmitMetrics |
+#endif |
+IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, |
+ MAYBE_FetchAndEmitMetrics) { |
+ GURL url1("about:blank"); |
+ ui_test_utils::NavigateToURLWithDisposition( |
+ browser(), url1, WindowOpenDisposition::NEW_FOREGROUND_TAB, |
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
+ |
+ base::HistogramTester histogram_tester; |
+ base::RunLoop run_loop; |
+ |
// Intentionally let emitter leave scope to check that it correctly keeps |
// itself alive. |
{ |
scoped_refptr<ProcessMemoryMetricsEmitterFake> emitter( |
- new ProcessMemoryMetricsEmitterFake); |
+ new ProcessMemoryMetricsEmitterFake(&run_loop)); |
emitter->FetchAndEmitProcessMemoryMetrics(); |
} |
- content::RunMessageLoop(); |
+ run_loop.Run(); |
+ |
+ CheckAllMemoryMetrics(histogram_tester, 1); |
+} |
+ |
+#if defined(ADDRESS_SANITIZER) |
+#define MAYBE_FetchDuringTrace DISABLED_FetchDuringTrace |
+#else |
+#define MAYBE_FetchDuringTrace FetchDuringTrace |
+#endif |
+IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, |
+ MAYBE_FetchDuringTrace) { |
+ GURL url1("about:blank"); |
+ ui_test_utils::NavigateToURLWithDisposition( |
+ browser(), url1, WindowOpenDisposition::NEW_FOREGROUND_TAB, |
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
+ |
+ base::HistogramTester histogram_tester; |
+ |
+ { |
+ base::RunLoop run_loop; |
+ |
+ base::trace_event::TraceConfig trace_config( |
+ base::trace_event::TraceConfigMemoryTestUtil:: |
+ GetTraceConfig_EmptyTriggers()); |
+ ASSERT_TRUE(tracing::BeginTracingWithTraceConfig( |
+ trace_config, Bind(&OnStartTracingDoneCallback, |
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED, |
+ run_loop.QuitClosure()))); |
+ run_loop.Run(); |
+ } |
+ |
+ { |
+ base::RunLoop run_loop; |
+ scoped_refptr<ProcessMemoryMetricsEmitterFake> emitter( |
+ new ProcessMemoryMetricsEmitterFake(&run_loop)); |
+ emitter->FetchAndEmitProcessMemoryMetrics(); |
+ |
+ run_loop.Run(); |
+ } |
+ |
+ std::string json_events; |
+ ASSERT_TRUE(tracing::EndTracing(&json_events)); |
+ |
+ trace_analyzer::TraceEventVector events; |
+ std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer( |
+ trace_analyzer::TraceAnalyzer::Create(json_events)); |
+ analyzer->FindEvents( |
+ trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_MEMORY_DUMP), |
+ &events); |
+ |
+ ASSERT_GT(events.size(), 1u); |
+ ASSERT_TRUE(trace_analyzer::CountMatches( |
+ events, trace_analyzer::Query::EventNameIs(MemoryDumpTypeToString( |
+ MemoryDumpType::EXPLICITLY_TRIGGERED)))); |
+ |
+ CheckAllMemoryMetrics(histogram_tester, 1); |
+} |
+ |
+#if defined(ADDRESS_SANITIZER) |
+#define MAYBE_FetchThreeTimes DISABLED_FetchThreeTimes |
+#else |
+#define MAYBE_FetchThreeTimes FetchThreeTimes |
+#endif |
+IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, MAYBE_FetchThreeTimes) { |
+ GURL url1("about:blank"); |
+ ui_test_utils::NavigateToURLWithDisposition( |
+ browser(), url1, WindowOpenDisposition::NEW_FOREGROUND_TAB, |
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
+ |
+ base::HistogramTester histogram_tester; |
+ base::RunLoop run_loop; |
+ |
+ int count = 3; |
+ for (int i = 0; i < count; ++i) { |
+ // Only the last emitter should stop the run loop. |
+ auto emitter = base::MakeShared<ProcessMemoryMetricsEmitterFake>( |
+ (i == count - 1) ? &run_loop : nullptr); |
+ emitter->FetchAndEmitProcessMemoryMetrics(); |
+ } |
+ |
+ run_loop.Run(); |
+ |
+ CheckAllMemoryMetrics(histogram_tester, count); |
} |