blob: 5a991486739f98edfdaa7a6388c164b81b7e9e83 [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"
Markus Handell2cfc1af2022-08-19 08:16:4817#include "api/units/time_delta.h"
Sebastian Janssonb55015e2019-04-09 11:44:0418#include "rtc_base/event.h"
19#include "rtc_base/platform_thread.h"
20#include "rtc_base/task_queue_for_test.h"
Sebastian Janssonb55015e2019-04-09 11:44:0421#include "test/gtest.h"
22
23namespace webrtc {
24namespace {
25
26// This class is dead code, but its purpose is to make sure that
27// SequenceChecker is compatible with the RTC_GUARDED_BY and RTC_RUN_ON
28// attributes that are checked at compile-time.
29class CompileTimeTestForGuardedBy {
30 public:
31 int CalledOnSequence() RTC_RUN_ON(sequence_checker_) { return guarded_; }
32
33 void CallMeFromSequence() {
Tomas Gunnarsson4d177eb2020-06-08 21:08:4634 RTC_DCHECK_RUN_ON(&sequence_checker_);
Sebastian Janssonb55015e2019-04-09 11:44:0435 guarded_ = 41;
36 }
37
38 private:
39 int guarded_ RTC_GUARDED_BY(sequence_checker_);
40 ::webrtc::SequenceChecker sequence_checker_;
41};
42
43void RunOnDifferentThread(rtc::FunctionView<void()> run) {
Markus Handellad5037b2021-05-07 13:02:3644 rtc::Event thread_has_run_event;
45 rtc::PlatformThread::SpawnJoinable(
46 [&] {
47 run();
48 thread_has_run_event.Set();
49 },
50 "thread");
Markus Handell2cfc1af2022-08-19 08:16:4851 EXPECT_TRUE(thread_has_run_event.Wait(TimeDelta::Seconds(1)));
Sebastian Janssonb55015e2019-04-09 11:44:0452}
53
54} // namespace
55
56TEST(SequenceCheckerTest, CallsAllowedOnSameThread) {
57 SequenceChecker sequence_checker;
58 EXPECT_TRUE(sequence_checker.IsCurrent());
59}
60
61TEST(SequenceCheckerTest, DestructorAllowedOnDifferentThread) {
Mirko Bonadei317a1f02019-09-17 15:06:1862 auto sequence_checker = std::make_unique<SequenceChecker>();
Sebastian Janssonb55015e2019-04-09 11:44:0463 RunOnDifferentThread([&] {
64 // Verify that the destructor doesn't assert when called on a different
65 // thread.
66 sequence_checker.reset();
67 });
68}
69
70TEST(SequenceCheckerTest, Detach) {
71 SequenceChecker sequence_checker;
72 sequence_checker.Detach();
73 RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
74}
75
76TEST(SequenceCheckerTest, DetachFromThreadAndUseOnTaskQueue) {
77 SequenceChecker sequence_checker;
78 sequence_checker.Detach();
79 TaskQueueForTest queue;
Danil Chapovalove519f382022-08-11 10:26:0980 queue.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
Sebastian Janssonb55015e2019-04-09 11:44:0481}
82
83TEST(SequenceCheckerTest, DetachFromTaskQueueAndUseOnThread) {
84 TaskQueueForTest queue;
Danil Chapovalove519f382022-08-11 10:26:0985 queue.SendTask([] {
86 SequenceChecker sequence_checker;
87 sequence_checker.Detach();
88 RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
89 });
Sebastian Janssonb55015e2019-04-09 11:44:0490}
91
92TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) {
93 SequenceChecker sequence_checker;
94 RunOnDifferentThread(
95 [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
96}
97
98TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) {
99 SequenceChecker sequence_checker;
100 TaskQueueForTest queue;
101 queue.SendTask(
Danil Chapovalove519f382022-08-11 10:26:09102 [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
Sebastian Janssonb55015e2019-04-09 11:44:04103}
104
105TEST(SequenceCheckerTest, DetachFromTaskQueueInDebug) {
106 SequenceChecker sequence_checker;
107 sequence_checker.Detach();
108
109 TaskQueueForTest queue1;
Danil Chapovalove519f382022-08-11 10:26:09110 queue1.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
Sebastian Janssonb55015e2019-04-09 11:44:04111
112 // IsCurrent should return false in debug builds after moving to
113 // another task queue.
114 TaskQueueForTest queue2;
115 queue2.SendTask(
Danil Chapovalove519f382022-08-11 10:26:09116 [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
Sebastian Janssonb55015e2019-04-09 11:44:04117}
118
119class TestAnnotations {
120 public:
121 TestAnnotations() : test_var_(false) {}
122
123 void ModifyTestVar() {
124 RTC_DCHECK_RUN_ON(&checker_);
125 test_var_ = true;
126 }
127
128 private:
129 bool test_var_ RTC_GUARDED_BY(&checker_);
130 SequenceChecker checker_;
131};
132
133TEST(SequenceCheckerTest, TestAnnotations) {
134 TestAnnotations annotations;
135 annotations.ModifyTestVar();
136}
137
138#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
139
140void TestAnnotationsOnWrongQueue() {
141 TestAnnotations annotations;
142 TaskQueueForTest queue;
Danil Chapovalove519f382022-08-11 10:26:09143 queue.SendTask([&] { annotations.ModifyTestVar(); });
Sebastian Janssonb55015e2019-04-09 11:44:04144}
145
146#if RTC_DCHECK_IS_ON
Tommiec3ba732020-05-17 12:33:40147// Note: Ending the test suite name with 'DeathTest' is important as it causes
148// gtest to order this test before any other non-death-tests, to avoid potential
149// global process state pollution such as shared worker threads being started
150// (e.g. a side effect of calling InitCocoaMultiThreading() on Mac causes one or
151// two additional threads to be created).
152TEST(SequenceCheckerDeathTest, TestAnnotationsOnWrongQueueDebug) {
Sebastian Janssonb55015e2019-04-09 11:44:04153 ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, "");
154}
155#else
156TEST(SequenceCheckerTest, TestAnnotationsOnWrongQueueRelease) {
157 TestAnnotationsOnWrongQueue();
158}
159#endif
160#endif // GTEST_HAS_DEATH_TEST
161} // namespace webrtc