Home | History | Annotate | Download | only in task_scheduler
      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