1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <utility>
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker #include "api/function_view.h"
17*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/event.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/platform_thread.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/task_queue_for_test.h"
21*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker using testing::HasSubstr;
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
27*d9f75844SAndroid Build Coastguard Worker namespace {
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker // This class is dead code, but its purpose is to make sure that
30*d9f75844SAndroid Build Coastguard Worker // SequenceChecker is compatible with the RTC_GUARDED_BY and RTC_RUN_ON
31*d9f75844SAndroid Build Coastguard Worker // attributes that are checked at compile-time.
32*d9f75844SAndroid Build Coastguard Worker class CompileTimeTestForGuardedBy {
33*d9f75844SAndroid Build Coastguard Worker public:
CalledOnSequence()34*d9f75844SAndroid Build Coastguard Worker int CalledOnSequence() RTC_RUN_ON(sequence_checker_) { return guarded_; }
35*d9f75844SAndroid Build Coastguard Worker
CallMeFromSequence()36*d9f75844SAndroid Build Coastguard Worker void CallMeFromSequence() {
37*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_);
38*d9f75844SAndroid Build Coastguard Worker guarded_ = 41;
39*d9f75844SAndroid Build Coastguard Worker }
40*d9f75844SAndroid Build Coastguard Worker
41*d9f75844SAndroid Build Coastguard Worker private:
42*d9f75844SAndroid Build Coastguard Worker int guarded_ RTC_GUARDED_BY(sequence_checker_);
43*d9f75844SAndroid Build Coastguard Worker ::webrtc::SequenceChecker sequence_checker_;
44*d9f75844SAndroid Build Coastguard Worker };
45*d9f75844SAndroid Build Coastguard Worker
RunOnDifferentThread(rtc::FunctionView<void ()> run)46*d9f75844SAndroid Build Coastguard Worker void RunOnDifferentThread(rtc::FunctionView<void()> run) {
47*d9f75844SAndroid Build Coastguard Worker rtc::Event thread_has_run_event;
48*d9f75844SAndroid Build Coastguard Worker rtc::PlatformThread::SpawnJoinable(
49*d9f75844SAndroid Build Coastguard Worker [&] {
50*d9f75844SAndroid Build Coastguard Worker run();
51*d9f75844SAndroid Build Coastguard Worker thread_has_run_event.Set();
52*d9f75844SAndroid Build Coastguard Worker },
53*d9f75844SAndroid Build Coastguard Worker "thread");
54*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(thread_has_run_event.Wait(TimeDelta::Seconds(1)));
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker
57*d9f75844SAndroid Build Coastguard Worker } // namespace
58*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,CallsAllowedOnSameThread)59*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, CallsAllowedOnSameThread) {
60*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
61*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(sequence_checker.IsCurrent());
62*d9f75844SAndroid Build Coastguard Worker }
63*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,DestructorAllowedOnDifferentThread)64*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, DestructorAllowedOnDifferentThread) {
65*d9f75844SAndroid Build Coastguard Worker auto sequence_checker = std::make_unique<SequenceChecker>();
66*d9f75844SAndroid Build Coastguard Worker RunOnDifferentThread([&] {
67*d9f75844SAndroid Build Coastguard Worker // Verify that the destructor doesn't assert when called on a different
68*d9f75844SAndroid Build Coastguard Worker // thread.
69*d9f75844SAndroid Build Coastguard Worker sequence_checker.reset();
70*d9f75844SAndroid Build Coastguard Worker });
71*d9f75844SAndroid Build Coastguard Worker }
72*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,Detach)73*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, Detach) {
74*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
75*d9f75844SAndroid Build Coastguard Worker sequence_checker.Detach();
76*d9f75844SAndroid Build Coastguard Worker RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
77*d9f75844SAndroid Build Coastguard Worker }
78*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,DetachFromThreadAndUseOnTaskQueue)79*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, DetachFromThreadAndUseOnTaskQueue) {
80*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
81*d9f75844SAndroid Build Coastguard Worker sequence_checker.Detach();
82*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue;
83*d9f75844SAndroid Build Coastguard Worker queue.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,DetachFromTaskQueueAndUseOnThread)86*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, DetachFromTaskQueueAndUseOnThread) {
87*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue;
88*d9f75844SAndroid Build Coastguard Worker queue.SendTask([] {
89*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
90*d9f75844SAndroid Build Coastguard Worker sequence_checker.Detach();
91*d9f75844SAndroid Build Coastguard Worker RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
92*d9f75844SAndroid Build Coastguard Worker });
93*d9f75844SAndroid Build Coastguard Worker }
94*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,MethodNotAllowedOnDifferentThreadInDebug)95*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) {
96*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
97*d9f75844SAndroid Build Coastguard Worker RunOnDifferentThread(
98*d9f75844SAndroid Build Coastguard Worker [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,MethodNotAllowedOnDifferentTaskQueueInDebug)101*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) {
102*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
103*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue;
104*d9f75844SAndroid Build Coastguard Worker queue.SendTask(
105*d9f75844SAndroid Build Coastguard Worker [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,DetachFromTaskQueueInDebug)108*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, DetachFromTaskQueueInDebug) {
109*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
110*d9f75844SAndroid Build Coastguard Worker sequence_checker.Detach();
111*d9f75844SAndroid Build Coastguard Worker
112*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue1;
113*d9f75844SAndroid Build Coastguard Worker queue1.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
114*d9f75844SAndroid Build Coastguard Worker
115*d9f75844SAndroid Build Coastguard Worker // IsCurrent should return false in debug builds after moving to
116*d9f75844SAndroid Build Coastguard Worker // another task queue.
117*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue2;
118*d9f75844SAndroid Build Coastguard Worker queue2.SendTask(
119*d9f75844SAndroid Build Coastguard Worker [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); });
120*d9f75844SAndroid Build Coastguard Worker }
121*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,ExpectationToString)122*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, ExpectationToString) {
123*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue1;
124*d9f75844SAndroid Build Coastguard Worker
125*d9f75844SAndroid Build Coastguard Worker SequenceChecker sequence_checker;
126*d9f75844SAndroid Build Coastguard Worker sequence_checker.Detach();
127*d9f75844SAndroid Build Coastguard Worker
128*d9f75844SAndroid Build Coastguard Worker rtc::Event blocker;
129*d9f75844SAndroid Build Coastguard Worker queue1.PostTask([&blocker, &sequence_checker]() {
130*d9f75844SAndroid Build Coastguard Worker (void)sequence_checker.IsCurrent();
131*d9f75844SAndroid Build Coastguard Worker blocker.Set();
132*d9f75844SAndroid Build Coastguard Worker });
133*d9f75844SAndroid Build Coastguard Worker
134*d9f75844SAndroid Build Coastguard Worker blocker.Wait(rtc::Event::kForever);
135*d9f75844SAndroid Build Coastguard Worker
136*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON
137*d9f75844SAndroid Build Coastguard Worker
138*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(ExpectationToString(&sequence_checker),
139*d9f75844SAndroid Build Coastguard Worker HasSubstr("# Expected: TQ:"));
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker // Test for the base class
142*d9f75844SAndroid Build Coastguard Worker webrtc_sequence_checker_internal::SequenceCheckerImpl* sequence_checker_base =
143*d9f75844SAndroid Build Coastguard Worker &sequence_checker;
144*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(ExpectationToString(sequence_checker_base),
145*d9f75844SAndroid Build Coastguard Worker HasSubstr("# Expected: TQ:"));
146*d9f75844SAndroid Build Coastguard Worker
147*d9f75844SAndroid Build Coastguard Worker #else
148*d9f75844SAndroid Build Coastguard Worker GTEST_ASSERT_EQ(ExpectationToString(&sequence_checker), "");
149*d9f75844SAndroid Build Coastguard Worker #endif
150*d9f75844SAndroid Build Coastguard Worker }
151*d9f75844SAndroid Build Coastguard Worker
152*d9f75844SAndroid Build Coastguard Worker class TestAnnotations {
153*d9f75844SAndroid Build Coastguard Worker public:
TestAnnotations()154*d9f75844SAndroid Build Coastguard Worker TestAnnotations() : test_var_(false) {}
155*d9f75844SAndroid Build Coastguard Worker
ModifyTestVar()156*d9f75844SAndroid Build Coastguard Worker void ModifyTestVar() {
157*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&checker_);
158*d9f75844SAndroid Build Coastguard Worker test_var_ = true;
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker
161*d9f75844SAndroid Build Coastguard Worker private:
162*d9f75844SAndroid Build Coastguard Worker bool test_var_ RTC_GUARDED_BY(&checker_);
163*d9f75844SAndroid Build Coastguard Worker SequenceChecker checker_;
164*d9f75844SAndroid Build Coastguard Worker };
165*d9f75844SAndroid Build Coastguard Worker
TEST(SequenceCheckerTest,TestAnnotations)166*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, TestAnnotations) {
167*d9f75844SAndroid Build Coastguard Worker TestAnnotations annotations;
168*d9f75844SAndroid Build Coastguard Worker annotations.ModifyTestVar();
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker
171*d9f75844SAndroid Build Coastguard Worker #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
172*d9f75844SAndroid Build Coastguard Worker
TestAnnotationsOnWrongQueue()173*d9f75844SAndroid Build Coastguard Worker void TestAnnotationsOnWrongQueue() {
174*d9f75844SAndroid Build Coastguard Worker TestAnnotations annotations;
175*d9f75844SAndroid Build Coastguard Worker TaskQueueForTest queue;
176*d9f75844SAndroid Build Coastguard Worker queue.SendTask([&] { annotations.ModifyTestVar(); });
177*d9f75844SAndroid Build Coastguard Worker }
178*d9f75844SAndroid Build Coastguard Worker
179*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON
180*d9f75844SAndroid Build Coastguard Worker // Note: Ending the test suite name with 'DeathTest' is important as it causes
181*d9f75844SAndroid Build Coastguard Worker // gtest to order this test before any other non-death-tests, to avoid potential
182*d9f75844SAndroid Build Coastguard Worker // global process state pollution such as shared worker threads being started
183*d9f75844SAndroid Build Coastguard Worker // (e.g. a side effect of calling InitCocoaMultiThreading() on Mac causes one or
184*d9f75844SAndroid Build Coastguard Worker // two additional threads to be created).
TEST(SequenceCheckerDeathTest,TestAnnotationsOnWrongQueueDebug)185*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerDeathTest, TestAnnotationsOnWrongQueueDebug) {
186*d9f75844SAndroid Build Coastguard Worker ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, "");
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker #else
TEST(SequenceCheckerTest,TestAnnotationsOnWrongQueueRelease)189*d9f75844SAndroid Build Coastguard Worker TEST(SequenceCheckerTest, TestAnnotationsOnWrongQueueRelease) {
190*d9f75844SAndroid Build Coastguard Worker TestAnnotationsOnWrongQueue();
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker #endif
193*d9f75844SAndroid Build Coastguard Worker #endif // GTEST_HAS_DEATH_TEST
194*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
195