blob: 74cba8a4d5fb30789e3ba152bcbb4bcfccac3147 [file] [log] [blame]
perkj9c16fe82016-07-12 15:04:07 -07001/*
2 * Copyright (c) 2016 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 */
kwibergac9f8762016-09-30 22:29:43 -070010
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/sequenced_task_checker.h"
Tommi10b40ce2018-02-19 13:34:00 +010012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <memory>
14#include <utility>
15
Danil Chapovalov2214b912019-03-25 15:13:59 +010016#include "absl/memory/memory.h"
17#include "api/function_view.h"
Yves Gerey2e00abc2018-10-05 15:39:24 +020018#include "rtc_base/event.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/platform_thread.h"
Danil Chapovalov2214b912019-03-25 15:13:59 +010020#include "rtc_base/task_queue_for_test.h"
Tommi10b40ce2018-02-19 13:34:00 +010021#include "rtc_base/thread_checker.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
perkj9c16fe82016-07-12 15:04:07 -070023
24namespace rtc {
perkj9c16fe82016-07-12 15:04:07 -070025namespace {
Tommi10b40ce2018-02-19 13:34:00 +010026
Danil Chapovalov2214b912019-03-25 15:13:59 +010027using ::webrtc::TaskQueueForTest;
28
Tommi10b40ce2018-02-19 13:34:00 +010029// This class is dead code, but its purpose is to make sure that
30// SequencedTaskChecker is compatible with the RTC_GUARDED_BY and RTC_RUN_ON
31// attributes that are checked at compile-time.
32class CompileTimeTestForGuardedBy {
33 public:
Yves Gerey665174f2018-06-19 15:03:05 +020034 int CalledOnSequence() RTC_RUN_ON(sequence_checker_) { return guarded_; }
Tommi10b40ce2018-02-19 13:34:00 +010035
36 void CallMeFromSequence() {
Yves Gerey665174f2018-06-19 15:03:05 +020037 RTC_DCHECK_RUN_ON(&sequence_checker_) << "Should be called on sequence";
Danil Chapovalov2214b912019-03-25 15:13:59 +010038 guarded_ = 41;
Tommi10b40ce2018-02-19 13:34:00 +010039 }
40
41 private:
42 int guarded_ RTC_GUARDED_BY(sequence_checker_);
Danil Chapovalov2214b912019-03-25 15:13:59 +010043 SequencedTaskChecker sequence_checker_;
Tommi10b40ce2018-02-19 13:34:00 +010044};
45
Danil Chapovalov2214b912019-03-25 15:13:59 +010046void RunOnDifferentThread(FunctionView<void()> run) {
47 struct Object {
48 static void Run(void* obj) {
49 auto* me = static_cast<Object*>(obj);
50 me->run();
51 me->thread_has_run_event.Set();
52 }
perkj9c16fe82016-07-12 15:04:07 -070053
Danil Chapovalov2214b912019-03-25 15:13:59 +010054 FunctionView<void()> run;
55 Event thread_has_run_event;
56 } object{run};
perkj9c16fe82016-07-12 15:04:07 -070057
Danil Chapovalov2214b912019-03-25 15:13:59 +010058 PlatformThread thread(&Object::Run, &object, "thread");
59 thread.Start();
60 EXPECT_TRUE(object.thread_has_run_event.Wait(1000));
61 thread.Stop();
perkj9c16fe82016-07-12 15:04:07 -070062}
63
perkj9c16fe82016-07-12 15:04:07 -070064} // namespace
65
66TEST(SequencedTaskCheckerTest, CallsAllowedOnSameThread) {
Danil Chapovalov2214b912019-03-25 15:13:59 +010067 SequencedTaskChecker sequenced_task_checker;
68 EXPECT_TRUE(sequenced_task_checker.CalledSequentially());
perkj9c16fe82016-07-12 15:04:07 -070069}
70
71TEST(SequencedTaskCheckerTest, DestructorAllowedOnDifferentThread) {
Danil Chapovalov2214b912019-03-25 15:13:59 +010072 auto sequenced_task_checker = absl::make_unique<SequencedTaskChecker>();
73 RunOnDifferentThread([&] {
74 // Verify that the destructor doesn't assert when called on a different
75 // thread.
76 sequenced_task_checker.reset();
77 });
perkj9c16fe82016-07-12 15:04:07 -070078}
79
80TEST(SequencedTaskCheckerTest, DetachFromThread) {
Danil Chapovalov2214b912019-03-25 15:13:59 +010081 SequencedTaskChecker sequenced_task_checker;
82 sequenced_task_checker.Detach();
83 RunOnDifferentThread(
84 [&] { EXPECT_TRUE(sequenced_task_checker.CalledSequentially()); });
perkj9c16fe82016-07-12 15:04:07 -070085}
86
87TEST(SequencedTaskCheckerTest, DetachFromThreadAndUseOnTaskQueue) {
Danil Chapovalov2214b912019-03-25 15:13:59 +010088 SequencedTaskChecker sequenced_task_checker;
89 sequenced_task_checker.Detach();
90 TaskQueueForTest queue;
91 queue.SendTask(
92 [&] { EXPECT_TRUE(sequenced_task_checker.CalledSequentially()); });
perkj9c16fe82016-07-12 15:04:07 -070093}
94
95TEST(SequencedTaskCheckerTest, DetachFromTaskQueueAndUseOnThread) {
Danil Chapovalov2214b912019-03-25 15:13:59 +010096 TaskQueueForTest queue;
97 queue.SendTask([] {
98 SequencedTaskChecker sequenced_task_checker;
99 sequenced_task_checker.Detach();
100 RunOnDifferentThread(
101 [&] { EXPECT_TRUE(sequenced_task_checker.CalledSequentially()); });
perkj9c16fe82016-07-12 15:04:07 -0700102 });
perkj9c16fe82016-07-12 15:04:07 -0700103}
104
perkj9c16fe82016-07-12 15:04:07 -0700105TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) {
Danil Chapovalov2214b912019-03-25 15:13:59 +0100106 SequencedTaskChecker sequenced_task_checker;
107 RunOnDifferentThread([&] {
108 EXPECT_EQ(sequenced_task_checker.CalledSequentially(), !RTC_DCHECK_IS_ON);
109 });
perkj9c16fe82016-07-12 15:04:07 -0700110}
perkj9c16fe82016-07-12 15:04:07 -0700111
perkj9c16fe82016-07-12 15:04:07 -0700112TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) {
Danil Chapovalov2214b912019-03-25 15:13:59 +0100113 SequencedTaskChecker sequenced_task_checker;
114 TaskQueueForTest queue;
115 queue.SendTask([&] {
116 EXPECT_EQ(sequenced_task_checker.CalledSequentially(), !RTC_DCHECK_IS_ON);
117 });
perkj9c16fe82016-07-12 15:04:07 -0700118}
perkj9c16fe82016-07-12 15:04:07 -0700119
perkj9c16fe82016-07-12 15:04:07 -0700120TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInDebug) {
Danil Chapovalov2214b912019-03-25 15:13:59 +0100121 SequencedTaskChecker sequenced_task_checker;
122 sequenced_task_checker.Detach();
123
124 TaskQueueForTest queue1;
125 queue1.SendTask(
126 [&] { EXPECT_TRUE(sequenced_task_checker.CalledSequentially()); });
127
128 // CalledSequentially should return false in debug builds after moving to
129 // another task queue.
130 TaskQueueForTest queue2;
131 queue2.SendTask([&] {
132 EXPECT_EQ(sequenced_task_checker.CalledSequentially(), !RTC_DCHECK_IS_ON);
133 });
perkj9c16fe82016-07-12 15:04:07 -0700134}
perkj9c16fe82016-07-12 15:04:07 -0700135
136class TestAnnotations {
137 public:
138 TestAnnotations() : test_var_(false) {}
139
140 void ModifyTestVar() {
141 RTC_DCHECK_CALLED_SEQUENTIALLY(&checker_);
142 test_var_ = true;
143 }
144
145 private:
danilchap3c6abd22017-09-06 05:46:29 -0700146 bool test_var_ RTC_GUARDED_BY(&checker_);
perkj9c16fe82016-07-12 15:04:07 -0700147 SequencedTaskChecker checker_;
148};
149
150TEST(SequencedTaskCheckerTest, TestAnnotations) {
151 TestAnnotations annotations;
152 annotations.ModifyTestVar();
153}
154
155#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
156
157void TestAnnotationsOnWrongQueue() {
158 TestAnnotations annotations;
Danil Chapovalov2214b912019-03-25 15:13:59 +0100159 TaskQueueForTest queue;
160 queue.SendTask([&] { annotations.ModifyTestVar(); });
perkj9c16fe82016-07-12 15:04:07 -0700161}
162
163#if RTC_DCHECK_IS_ON
164TEST(SequencedTaskCheckerTest, TestAnnotationsOnWrongQueueDebug) {
165 ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, "");
166}
167#else
168TEST(SequencedTaskCheckerTest, TestAnnotationsOnWrongQueueRelease) {
169 TestAnnotationsOnWrongQueue();
170}
171#endif
172#endif // GTEST_HAS_DEATH_TEST
173} // namespace rtc