1 /*
2  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/cpu_time.h"
12 
13 #include "rtc_base/platform_thread.h"
14 #include "rtc_base/time_utils.h"
15 #include "system_wrappers/include/sleep.h"
16 #include "test/gtest.h"
17 
18 // Only run these tests on non-instrumented builds, because timing on
19 // instrumented builds is unreliable, causing the test to be flaky.
20 #if defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \
21     defined(ADDRESS_SANITIZER)
22 #define MAYBE_TEST(test_name) DISABLED_##test_name
23 #else
24 #define MAYBE_TEST(test_name) test_name
25 #endif
26 
27 namespace {
28 const int kAllowedErrorMillisecs = 30;
29 const int kProcessingTimeMillisecs = 500;
30 const int kWorkingThreads = 2;
31 
32 // Consumes approximately kProcessingTimeMillisecs of CPU time in single thread.
WorkingFunction(void * counter_pointer)33 void WorkingFunction(void* counter_pointer) {
34   int64_t* counter = reinterpret_cast<int64_t*>(counter_pointer);
35   *counter = 0;
36   int64_t stop_cpu_time =
37       rtc::GetThreadCpuTimeNanos() +
38       kProcessingTimeMillisecs * rtc::kNumNanosecsPerMillisec;
39   while (rtc::GetThreadCpuTimeNanos() < stop_cpu_time) {
40     (*counter)++;
41   }
42 }
43 }  // namespace
44 
45 namespace rtc {
46 
47 // A minimal test which can be run on instrumented builds, so that they're at
48 // least exercising the code to check for memory leaks/etc.
TEST(CpuTimeTest,BasicTest)49 TEST(CpuTimeTest, BasicTest) {
50   int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
51   int64_t thread_start_time_nanos = GetThreadCpuTimeNanos();
52   int64_t process_duration_nanos =
53       GetProcessCpuTimeNanos() - process_start_time_nanos;
54   int64_t thread_duration_nanos =
55       GetThreadCpuTimeNanos() - thread_start_time_nanos;
56   EXPECT_GE(process_duration_nanos, 0);
57   EXPECT_GE(thread_duration_nanos, 0);
58 }
59 
TEST(CpuTimeTest,MAYBE_TEST (TwoThreads))60 TEST(CpuTimeTest, MAYBE_TEST(TwoThreads)) {
61   int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
62   int64_t thread_start_time_nanos = GetThreadCpuTimeNanos();
63   int64_t counter1;
64   int64_t counter2;
65   PlatformThread thread1(WorkingFunction, reinterpret_cast<void*>(&counter1),
66                          "Thread1");
67   PlatformThread thread2(WorkingFunction, reinterpret_cast<void*>(&counter2),
68                          "Thread2");
69   thread1.Start();
70   thread2.Start();
71   thread1.Stop();
72   thread2.Stop();
73 
74   EXPECT_GE(counter1, 0);
75   EXPECT_GE(counter2, 0);
76   int64_t process_duration_nanos =
77       GetProcessCpuTimeNanos() - process_start_time_nanos;
78   int64_t thread_duration_nanos =
79       GetThreadCpuTimeNanos() - thread_start_time_nanos;
80   // This thread did almost nothing. Definetly less work than kProcessingTime.
81   // Therefore GetThreadCpuTime is not a wall clock.
82   EXPECT_LE(thread_duration_nanos,
83             (kProcessingTimeMillisecs - kAllowedErrorMillisecs) *
84                 kNumNanosecsPerMillisec);
85   // Total process time is at least twice working threads' CPU time.
86   // Therefore process and thread times are correctly related.
87   EXPECT_GE(process_duration_nanos,
88             kWorkingThreads *
89                 (kProcessingTimeMillisecs - kAllowedErrorMillisecs) *
90                 kNumNanosecsPerMillisec);
91 }
92 
TEST(CpuTimeTest,MAYBE_TEST (Sleeping))93 TEST(CpuTimeTest, MAYBE_TEST(Sleeping)) {
94   int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
95   webrtc::SleepMs(kProcessingTimeMillisecs);
96   int64_t process_duration_nanos =
97       GetProcessCpuTimeNanos() - process_start_time_nanos;
98   // Sleeping should not introduce any additional CPU time.
99   // Therefore GetProcessCpuTime is not a wall clock.
100   EXPECT_LE(process_duration_nanos,
101             (kProcessingTimeMillisecs - kAllowedErrorMillisecs) *
102                 kNumNanosecsPerMillisec);
103 }
104 
105 }  // namespace rtc
106