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.
VerifyHasStringOnStack(const std::string & query)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
TEST(TaskSchedulerServiceThreadTest,MAYBE_StackHasIdentifyingFrame)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.
TEST(TaskSchedulerServiceThreadIntegrationTest,MAYBE_HeartbeatLatencyReport)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