blob: ba973788abd25e93513c4250d7ebb0f271ba0005 [file] [log] [blame]
ilnik531100d2017-02-21 03:33:24 -08001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/cpu_time.h"
Henrik Kjellander00725112017-06-30 15:14:45 +020012#include <algorithm>
kjellandere96c45b2017-06-30 10:45:21 -070013#include <memory>
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "rtc_base/platform_thread.h"
15#include "rtc_base/timeutils.h"
16#include "system_wrappers/include/cpu_info.h"
17#include "system_wrappers/include/sleep.h"
18#include "test/gtest.h"
ilnik531100d2017-02-21 03:33:24 -080019
deadbeef7311b242017-05-01 10:43:39 -070020// Only run these tests on non-instrumented builds, because timing on
21// instrumented builds is unreliable, causing the test to be flaky.
22#if defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \
23 defined(ADDRESS_SANITIZER)
24#define MAYBE_TEST(test_name) DISABLED_##test_name
25#else
26#define MAYBE_TEST(test_name) test_name
27#endif
28
ilnik531100d2017-02-21 03:33:24 -080029namespace {
30const int kAllowedErrorMillisecs = 30;
31const int kProcessingTimeMillisecs = 300;
ilnik78f2d212017-02-28 02:24:10 -080032const int kWorkingThreads = 2;
ilnik531100d2017-02-21 03:33:24 -080033
ilnik78f2d212017-02-28 02:24:10 -080034// Consumes approximately kProcessingTimeMillisecs of CPU time in single thread.
ilnik531100d2017-02-21 03:33:24 -080035bool WorkingFunction(void* counter_pointer) {
36 int64_t* counter = reinterpret_cast<int64_t*>(counter_pointer);
37 *counter = 0;
ilnik78f2d212017-02-28 02:24:10 -080038 int64_t stop_cpu_time =
39 rtc::GetThreadCpuTimeNanos() +
40 kProcessingTimeMillisecs * rtc::kNumNanosecsPerMillisec;
41 while (rtc::GetThreadCpuTimeNanos() < stop_cpu_time) {
ilnik531100d2017-02-21 03:33:24 -080042 (*counter)++;
43 }
44 return false;
45}
46} // namespace
47
48namespace rtc {
49
deadbeef7311b242017-05-01 10:43:39 -070050// A minimal test which can be run on instrumented builds, so that they're at
51// least exercising the code to check for memory leaks/etc.
52TEST(CpuTimeTest, BasicTest) {
53 int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
54 int64_t thread_start_time_nanos = GetThreadCpuTimeNanos();
55 int64_t process_duration_nanos =
56 GetProcessCpuTimeNanos() - process_start_time_nanos;
57 int64_t thread_duration_nanos =
58 GetThreadCpuTimeNanos() - thread_start_time_nanos;
59 EXPECT_GE(process_duration_nanos, 0);
60 EXPECT_GE(thread_duration_nanos, 0);
61}
62
63TEST(CpuTimeTest, MAYBE_TEST(TwoThreads)) {
ilnik78f2d212017-02-28 02:24:10 -080064 int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
65 int64_t thread_start_time_nanos = GetThreadCpuTimeNanos();
ilnik531100d2017-02-21 03:33:24 -080066 int64_t counter1;
67 int64_t counter2;
68 PlatformThread thread1(WorkingFunction, reinterpret_cast<void*>(&counter1),
69 "Thread1");
70 PlatformThread thread2(WorkingFunction, reinterpret_cast<void*>(&counter2),
71 "Thread2");
72 thread1.Start();
73 thread2.Start();
74 thread1.Stop();
75 thread2.Stop();
76
77 EXPECT_GE(counter1, 0);
78 EXPECT_GE(counter2, 0);
ilnik78f2d212017-02-28 02:24:10 -080079 int64_t process_duration_nanos =
80 GetProcessCpuTimeNanos() - process_start_time_nanos;
81 int64_t thread_duration_nanos =
82 GetThreadCpuTimeNanos() - thread_start_time_nanos;
83 // This thread did almost nothing.
84 // Therefore GetThreadCpuTime is not a wall clock.
85 EXPECT_LE(thread_duration_nanos,
86 kAllowedErrorMillisecs * kNumNanosecsPerMillisec);
ilnik3e530d22017-03-09 00:41:31 -080087 // Total process time is at least twice working threads' CPU time.
ilnik78f2d212017-02-28 02:24:10 -080088 // Therefore process and thread times are correctly related.
ilnik3e530d22017-03-09 00:41:31 -080089 EXPECT_GE(
ilnik78f2d212017-02-28 02:24:10 -080090 process_duration_nanos,
ilnik3e530d22017-03-09 00:41:31 -080091 kWorkingThreads * (kProcessingTimeMillisecs - kAllowedErrorMillisecs)
92 * kNumNanosecsPerMillisec);
ilnik531100d2017-02-21 03:33:24 -080093}
94
deadbeef7311b242017-05-01 10:43:39 -070095TEST(CpuTimeTest, MAYBE_TEST(Sleeping)) {
ilnik78f2d212017-02-28 02:24:10 -080096 int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
97 webrtc::SleepMs(kProcessingTimeMillisecs);
98 int64_t process_duration_nanos =
99 GetProcessCpuTimeNanos() - process_start_time_nanos;
100 // Sleeping should not introduce any additional CPU time.
101 // Therefore GetProcessCpuTime is not a wall clock.
102 EXPECT_LE(process_duration_nanos,
103 kWorkingThreads * kAllowedErrorMillisecs * kNumNanosecsPerMillisec);
ilnik531100d2017-02-21 03:33:24 -0800104}
105
106} // namespace rtc