1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/task_scheduler/service_thread.h" 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/debug/stack_trace.h" 11 #include "base/task_scheduler/task_scheduler.h" 12 #include "base/task_scheduler/task_scheduler_impl.h" 13 #include "base/test/metrics/histogram_tester.h" 14 #include "base/threading/platform_thread.h" 15 #include "base/time/time.h" 16 #include "build/build_config.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace base { 20 namespace internal { 21 22 namespace { 23 24 // Verifies that |query| is found on the current stack. Ignores failures if this 25 // configuration doesn't have symbols. 26 void VerifyHasStringOnStack(const std::string& query) { 27 const std::string stack = debug::StackTrace().ToString(); 28 SCOPED_TRACE(stack); 29 const bool found_on_stack = stack.find(query) != std::string::npos; 30 const bool stack_has_symbols = 31 stack.find("SchedulerWorker") != std::string::npos; 32 EXPECT_TRUE(found_on_stack || !stack_has_symbols) << query; 33 } 34 35 } // namespace 36 37 #if defined(OS_POSIX) 38 // Many POSIX bots flakily crash on |debug::StackTrace().ToString()|, 39 // https://crbug.com/840429. 40 #define MAYBE_StackHasIdentifyingFrame DISABLED_StackHasIdentifyingFrame 41 #else 42 #define MAYBE_StackHasIdentifyingFrame StackHasIdentifyingFrame 43 #endif 44 45 TEST(TaskSchedulerServiceThreadTest, MAYBE_StackHasIdentifyingFrame) { 46 ServiceThread service_thread(nullptr); 47 service_thread.Start(); 48 49 service_thread.task_runner()->PostTask( 50 FROM_HERE, BindOnce(&VerifyHasStringOnStack, "ServiceThread")); 51 52 service_thread.FlushForTesting(); 53 } 54 55 #if defined(OS_ANDROID) 56 // The heartbeat latency report has been temporarily disabled on Android per 57 // https://crbug.com/848255. 58 #define MAYBE_HeartbeatLatencyReport DISABLED_HeartbeatLatencyReport 59 #else 60 #define MAYBE_HeartbeatLatencyReport HeartbeatLatencyReport 61 #endif 62 63 // Integration test verifying that a service thread running in a fully 64 // integrated TaskScheduler environment results in reporting 65 // HeartbeatLatencyMicroseconds metrics. 66 TEST(TaskSchedulerServiceThreadIntegrationTest, MAYBE_HeartbeatLatencyReport) { 67 ServiceThread::SetHeartbeatIntervalForTesting(TimeDelta::FromMilliseconds(1)); 68 69 TaskScheduler::SetInstance( 70 std::make_unique<internal::TaskSchedulerImpl>("Test")); 71 TaskScheduler::GetInstance()->StartWithDefaultParams(); 72 73 static constexpr const char* kExpectedMetrics[] = { 74 "TaskScheduler.HeartbeatLatencyMicroseconds.Test." 75 "UserBlockingTaskPriority", 76 "TaskScheduler.HeartbeatLatencyMicroseconds.Test." 77 "UserBlockingTaskPriority_MayBlock", 78 "TaskScheduler.HeartbeatLatencyMicroseconds.Test." 79 "UserVisibleTaskPriority", 80 "TaskScheduler.HeartbeatLatencyMicroseconds.Test." 81 "UserVisibleTaskPriority_MayBlock", 82 "TaskScheduler.HeartbeatLatencyMicroseconds.Test." 83 "BackgroundTaskPriority", 84 "TaskScheduler.HeartbeatLatencyMicroseconds.Test." 85 "BackgroundTaskPriority_MayBlock"}; 86 87 // Each report hits a single histogram above (randomly selected). But 1000 88 // reports should touch all histograms at least once the vast majority of the 89 // time. 90 constexpr TimeDelta kReasonableTimeout = TimeDelta::FromSeconds(1); 91 constexpr TimeDelta kBusyWaitTime = TimeDelta::FromMilliseconds(100); 92 93 const TimeTicks start_time = TimeTicks::Now(); 94 95 HistogramTester tester; 96 for (const char* expected_metric : kExpectedMetrics) { 97 while (tester.GetAllSamples(expected_metric).empty()) { 98 if (TimeTicks::Now() - start_time > kReasonableTimeout) 99 LOG(WARNING) << "Waiting a while for " << expected_metric; 100 PlatformThread::Sleep(kBusyWaitTime); 101 } 102 } 103 104 TaskScheduler::GetInstance()->JoinForTesting(); 105 TaskScheduler::SetInstance(nullptr); 106 107 ServiceThread::SetHeartbeatIntervalForTesting(TimeDelta()); 108 } 109 110 } // namespace internal 111 } // namespace base 112