blob: 21a0894a8e6ae1c8579f3285ff046c3d2dc689bc [file] [log] [blame]
Sebastian Janssonb55015e2019-04-09 11:44:041/*
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 */
10
Artem Titovb586d822021-02-04 14:06:5011#include "api/sequence_checker.h"
Sebastian Janssonb55015e2019-04-09 11:44:0412
13#include <memory>
14#include <utility>
15
Sebastian Janssonb55015e2019-04-09 11:44:0416#include "api/function_view.h"
17#include "rtc_base/event.h"
18#include "rtc_base/platform_thread.h"
19#include "rtc_base/task_queue_for_test.h"
Sebastian Janssonb55015e2019-04-09 11:44:0420#include "test/gtest.h"
21
22namespace webrtc {
23namespace {
24
25// This class is dead code, but its purpose is to make sure that
26// SequenceChecker is compatible with the RTC_GUARDED_BY and RTC_RUN_ON
27// attributes that are checked at compile-time.
28class CompileTimeTestForGuardedBy {
29 public:
30 int CalledOnSequence() RTC_RUN_ON(sequence_checker_) { return guarded_; }
31
32 void CallMeFromSequence() {
Tomas Gunnarsson4d177eb2020-06-08 21:08:4633 RTC_DCHECK_RUN_ON(&sequence_checker_);
Sebastian Janssonb55015e2019-04-09 11:44:0434 guarded_ = 41;
35 }
36
37 private:
38 int guarded_ RTC_GUARDED_BY(sequence_checker_);
39 ::webrtc::SequenceChecker sequence_checker_;
40};
41
42void RunOnDifferentThread(rtc::FunctionView<void()> run) {
Markus Handellad5037b2021-05-07 13:02:3643 rtc::Event thread_has_run_event;
44 rtc::PlatformThread::SpawnJoinable(
45 [&] {
46 run();
47 thread_has_run_event.Set();
48 },
49 "thread");
50 EXPECT_TRUE(thread_has_run_event.Wait(1000));
Sebastian Janssonb55015e2019-04-09 11:44:0451}
52
53} // namespace
54
55TEST(SequenceCheckerTest, CallsAllowedOnSameThread) {
56 SequenceChecker sequence_checker;
57 EXPECT_TRUE(sequence_checker.IsCurrent());
58}
59
60TEST(SequenceCheckerTest, DestructorAllowedOnDifferentThread) {
Mirko Bonadei317a1f02019-09-17 15:06:1861 auto sequence_checker = std::make_unique<SequenceChecker>();
Sebastian Janssonb55015e2019-04-09 11:44:0462 RunOnDifferentThread([&] {
63 // Verify that the destructor doesn't assert when called on a different
64 // thread.
65 sequence_checker.reset();
66 });
67}
68
69TEST(SequenceCheckerTest, Detach) {
70 SequenceChecker sequence_checker;
71 sequence_checker.Detach();
72 RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
73}
74
75TEST(SequenceCheckerTest, DetachFromThreadAndUseOnTaskQueue) {
76 SequenceChecker sequence_checker;
77 sequence_checker.Detach();
78 TaskQueueForTest queue;
Danil Chapovaloveb90e6f2019-10-15 08:04:5779 queue.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); },
80 RTC_FROM_HERE);
Sebastian Janssonb55015e2019-04-09 11:44:0481}
82
83TEST(SequenceCheckerTest, DetachFromTaskQueueAndUseOnThread) {
84 TaskQueueForTest queue;
Danil Chapovaloveb90e6f2019-10-15 08:04:5785 queue.SendTask(
86 [] {
87 SequenceChecker sequence_checker;
88 sequence_checker.Detach();
89 RunOnDifferentThread(
90 [&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
91 },
92 RTC_FROM_HERE);
Sebastian Janssonb55015e2019-04-09 11:44:0493}
94
95TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) {
96 SequenceChecker sequence_checker;
97 RunOnDifferentThread(
98 [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
99}
100
101TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) {
102 SequenceChecker sequence_checker;
103 TaskQueueForTest queue;
104 queue.SendTask(
Danil Chapovaloveb90e6f2019-10-15 08:04:57105 [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); },
106 RTC_FROM_HERE);
Sebastian Janssonb55015e2019-04-09 11:44:04107}
108
109TEST(SequenceCheckerTest, DetachFromTaskQueueInDebug) {
110 SequenceChecker sequence_checker;
111 sequence_checker.Detach();
112
113 TaskQueueForTest queue1;
Danil Chapovaloveb90e6f2019-10-15 08:04:57114 queue1.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); },
115 RTC_FROM_HERE);
Sebastian Janssonb55015e2019-04-09 11:44:04116
117 // IsCurrent should return false in debug builds after moving to
118 // another task queue.
119 TaskQueueForTest queue2;
120 queue2.SendTask(
Danil Chapovaloveb90e6f2019-10-15 08:04:57121 [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); },
122 RTC_FROM_HERE);
Sebastian Janssonb55015e2019-04-09 11:44:04123}
124
125class TestAnnotations {
126 public:
127 TestAnnotations() : test_var_(false) {}
128
129 void ModifyTestVar() {
130 RTC_DCHECK_RUN_ON(&checker_);
131 test_var_ = true;
132 }
133
134 private:
135 bool test_var_ RTC_GUARDED_BY(&checker_);
136 SequenceChecker checker_;
137};
138
139TEST(SequenceCheckerTest, TestAnnotations) {
140 TestAnnotations annotations;
141 annotations.ModifyTestVar();
142}
143
144#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
145
146void TestAnnotationsOnWrongQueue() {
147 TestAnnotations annotations;
148 TaskQueueForTest queue;
Danil Chapovaloveb90e6f2019-10-15 08:04:57149 queue.SendTask([&] { annotations.ModifyTestVar(); }, RTC_FROM_HERE);
Sebastian Janssonb55015e2019-04-09 11:44:04150}
151
152#if RTC_DCHECK_IS_ON
Tommiec3ba732020-05-17 12:33:40153// Note: Ending the test suite name with 'DeathTest' is important as it causes
154// gtest to order this test before any other non-death-tests, to avoid potential
155// global process state pollution such as shared worker threads being started
156// (e.g. a side effect of calling InitCocoaMultiThreading() on Mac causes one or
157// two additional threads to be created).
158TEST(SequenceCheckerDeathTest, TestAnnotationsOnWrongQueueDebug) {
Sebastian Janssonb55015e2019-04-09 11:44:04159 ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, "");
160}
161#else
162TEST(SequenceCheckerTest, TestAnnotationsOnWrongQueueRelease) {
163 TestAnnotationsOnWrongQueue();
164}
165#endif
166#endif // GTEST_HAS_DEATH_TEST
167} // namespace webrtc