blob: 008e2cacd27e023f49e92032014e0418b27e29d6 [file] [log] [blame]
Ewout van Bekkuma082d7f2021-04-15 14:36:37 -07001// Copyright 2021 The Pigweed Authors
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -08002//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080015#include "gtest/gtest.h"
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080016#include "pw_sync/binary_semaphore.h"
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080017#include "pw_thread/id.h"
18#include "pw_thread/test_threads.h"
19#include "pw_thread/thread.h"
20
21using pw::thread::test::TestOptionsThread0;
22using pw::thread::test::TestOptionsThread1;
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080023using pw::thread::test::WaitUntilDetachedThreadsCleanedUp;
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080024
25namespace pw::thread {
26namespace {
27
28TEST(Thread, DefaultIds) {
29 Thread not_executing_thread;
30 EXPECT_EQ(not_executing_thread.get_id(), Id());
31}
32
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080033static void ReleaseBinarySemaphore(void* arg) {
34 static_cast<sync::BinarySemaphore*>(arg)->release();
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080035}
36
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080037#if PW_THREAD_JOINING_ENABLED
38TEST(Thread, Join) {
39 Thread thread;
40 EXPECT_FALSE(thread.joinable());
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080041 sync::BinarySemaphore thread_ran_sem;
42 thread =
43 Thread(TestOptionsThread0(), ReleaseBinarySemaphore, &thread_ran_sem);
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080044 EXPECT_TRUE(thread.joinable());
45 thread.join();
46 EXPECT_EQ(thread.get_id(), Id());
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080047 EXPECT_TRUE(thread_ran_sem.try_acquire());
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080048}
49#endif // PW_THREAD_JOINING_ENABLED
50
51TEST(Thread, Detach) {
52 Thread thread;
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080053 sync::BinarySemaphore thread_ran_sem;
54 thread =
55 Thread(TestOptionsThread0(), ReleaseBinarySemaphore, &thread_ran_sem);
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080056 EXPECT_NE(thread.get_id(), Id());
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080057 EXPECT_TRUE(thread.joinable());
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080058 thread.detach();
59 EXPECT_EQ(thread.get_id(), Id());
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080060 EXPECT_FALSE(thread.joinable());
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080061 thread_ran_sem.acquire();
62
63 WaitUntilDetachedThreadsCleanedUp();
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080064}
65
66TEST(Thread, SwapWithoutExecution) {
67 Thread thread_0;
68 Thread thread_1;
69
70 // Make sure we can swap threads which are not associated with any execution.
71 thread_0.swap(thread_1);
72}
73
74TEST(Thread, SwapWithOneExecuting) {
75 Thread thread_0;
76 EXPECT_EQ(thread_0.get_id(), Id());
77
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080078 sync::BinarySemaphore thread_ran_sem;
79 Thread thread_1(
80 TestOptionsThread1(), ReleaseBinarySemaphore, &thread_ran_sem);
81
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080082 EXPECT_NE(thread_1.get_id(), Id());
83
84 thread_0.swap(thread_1);
85 EXPECT_NE(thread_0.get_id(), Id());
86 EXPECT_EQ(thread_1.get_id(), Id());
87
88 thread_0.detach();
89 EXPECT_EQ(thread_0.get_id(), Id());
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080090
91 thread_ran_sem.acquire();
92 WaitUntilDetachedThreadsCleanedUp();
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -080093}
94
95TEST(Thread, SwapWithTwoExecuting) {
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -080096 sync::BinarySemaphore thread_a_ran_sem;
97 Thread thread_0(
98 TestOptionsThread0(), ReleaseBinarySemaphore, &thread_a_ran_sem);
99 sync::BinarySemaphore thread_b_ran_sem;
100 Thread thread_1(
101 TestOptionsThread1(), ReleaseBinarySemaphore, &thread_b_ran_sem);
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800102 const Id thread_a_id = thread_0.get_id();
103 EXPECT_NE(thread_a_id, Id());
104 const Id thread_b_id = thread_1.get_id();
105 EXPECT_NE(thread_b_id, Id());
106 EXPECT_NE(thread_a_id, thread_b_id);
107
108 thread_0.swap(thread_1);
109 EXPECT_EQ(thread_1.get_id(), thread_a_id);
110 EXPECT_EQ(thread_0.get_id(), thread_b_id);
111
112 thread_0.detach();
113 EXPECT_EQ(thread_0.get_id(), Id());
114 thread_1.detach();
115 EXPECT_EQ(thread_1.get_id(), Id());
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -0800116
117 thread_a_ran_sem.acquire();
118 thread_b_ran_sem.acquire();
119 WaitUntilDetachedThreadsCleanedUp();
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800120}
121
122TEST(Thread, MoveOperator) {
123 Thread thread_0;
124 EXPECT_EQ(thread_0.get_id(), Id());
125
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -0800126 sync::BinarySemaphore thread_ran_sem;
127 Thread thread_1(
128 TestOptionsThread1(), ReleaseBinarySemaphore, &thread_ran_sem);
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800129 EXPECT_NE(thread_1.get_id(), Id());
130
131 thread_0 = std::move(thread_1);
132 EXPECT_NE(thread_0.get_id(), Id());
Prashanth Swaminathanbaacfe32021-03-05 09:32:42 -0800133#ifndef __clang_analyzer__
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800134 EXPECT_EQ(thread_1.get_id(), Id());
Prashanth Swaminathanbaacfe32021-03-05 09:32:42 -0800135#endif // ignore use-after-move
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800136
137 thread_0.detach();
138 EXPECT_EQ(thread_0.get_id(), Id());
Ewout van Bekkumae6c03a2021-01-19 14:53:19 -0800139
140 thread_ran_sem.acquire();
141 WaitUntilDetachedThreadsCleanedUp();
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800142}
143
Ewout van Bekkuma082d7f2021-04-15 14:36:37 -0700144class SemaphoreReleaser : public ThreadCore {
145 public:
146 pw::sync::BinarySemaphore& semaphore() { return semaphore_; }
147
148 private:
149 void Run() override { semaphore_.release(); }
150
151 sync::BinarySemaphore semaphore_;
152};
153
154TEST(Thread, ThreadCore) {
155 SemaphoreReleaser semaphore_releaser;
156 Thread thread(TestOptionsThread0(), semaphore_releaser);
157 EXPECT_NE(thread.get_id(), Id());
158 EXPECT_TRUE(thread.joinable());
159 thread.detach();
160 EXPECT_EQ(thread.get_id(), Id());
161 EXPECT_FALSE(thread.joinable());
162 semaphore_releaser.semaphore().acquire();
163
164 WaitUntilDetachedThreadsCleanedUp();
165}
Ewout van Bekkum0f3901e2020-12-22 12:00:18 -0800166} // namespace
167} // namespace pw::thread