blob: eef71010afe65ab09672a00a69b34f28403b6f30 [file] [log] [blame]
Kostya Serebryany6fb47af2013-02-27 11:22:40 +00001//===-- sanitizer_linux_test.cc -------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Tests for sanitizer_linux.h
11//
12//===----------------------------------------------------------------------===//
13
Sergey Matveeva615b262013-05-14 13:19:33 +000014#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_LINUX
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000016
17#include "sanitizer_common/sanitizer_linux.h"
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000018
19#include "sanitizer_common/sanitizer_common.h"
Sergey Matveeva615b262013-05-14 13:19:33 +000020#include "gtest/gtest.h"
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000021
22#include <pthread.h>
23#include <sched.h>
Alexey Samsonovff7c14f2013-04-23 12:49:12 +000024#include <stdlib.h>
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000025
Alexey Samsonov5c217b62013-02-28 11:33:51 +000026#include <algorithm>
Alexander Potapenko32602c52013-03-14 12:06:54 +000027#include <vector>
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000028
29namespace __sanitizer {
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000030
Alexander Potapenko32602c52013-03-14 12:06:54 +000031struct TidReporterArgument {
32 TidReporterArgument() {
33 pthread_mutex_init(&terminate_thread_mutex, NULL);
34 pthread_mutex_init(&tid_reported_mutex, NULL);
35 pthread_cond_init(&terminate_thread_cond, NULL);
36 pthread_cond_init(&tid_reported_cond, NULL);
37 terminate_thread = false;
38 }
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000039
Alexander Potapenko32602c52013-03-14 12:06:54 +000040 ~TidReporterArgument() {
41 pthread_mutex_destroy(&terminate_thread_mutex);
42 pthread_mutex_destroy(&tid_reported_mutex);
43 pthread_cond_destroy(&terminate_thread_cond);
44 pthread_cond_destroy(&tid_reported_cond);
45 }
46
47 pid_t reported_tid;
48 // For signaling to spawned threads that they should terminate.
49 pthread_cond_t terminate_thread_cond;
50 pthread_mutex_t terminate_thread_mutex;
51 bool terminate_thread;
52 // For signaling to main thread that a child thread has reported its tid.
53 pthread_cond_t tid_reported_cond;
54 pthread_mutex_t tid_reported_mutex;
Alexander Potapenko3d048542013-03-14 13:15:14 +000055
56 private:
57 // Disallow evil constructors
58 TidReporterArgument(const TidReporterArgument &);
59 void operator=(const TidReporterArgument &);
Alexander Potapenko32602c52013-03-14 12:06:54 +000060};
61
62class ThreadListerTest : public ::testing::Test {
63 protected:
64 virtual void SetUp() {
65 pthread_t pthread_id;
66 pid_t tid;
67 for (uptr i = 0; i < kThreadCount; i++) {
68 SpawnTidReporter(&pthread_id, &tid);
69 pthread_ids_.push_back(pthread_id);
70 tids_.push_back(tid);
71 }
72 }
73
74 virtual void TearDown() {
75 pthread_mutex_lock(&thread_arg.terminate_thread_mutex);
76 thread_arg.terminate_thread = true;
77 pthread_cond_broadcast(&thread_arg.terminate_thread_cond);
78 pthread_mutex_unlock(&thread_arg.terminate_thread_mutex);
Alexander Potapenko3d048542013-03-14 13:15:14 +000079 for (uptr i = 0; i < pthread_ids_.size(); i++)
Alexander Potapenko32602c52013-03-14 12:06:54 +000080 pthread_join(pthread_ids_[i], NULL);
81 }
82
83 void SpawnTidReporter(pthread_t *pthread_id, pid_t *tid);
84
85 static const uptr kThreadCount = 20;
86
87 std::vector<pthread_t> pthread_ids_;
88 std::vector<pid_t> tids_;
89
90 TidReporterArgument thread_arg;
91};
92
Alexander Potapenko3d048542013-03-14 13:15:14 +000093// Writes its TID once to reported_tid and waits until signaled to terminate.
Alexander Potapenko32602c52013-03-14 12:06:54 +000094void *TidReporterThread(void *argument) {
95 TidReporterArgument *arg = reinterpret_cast<TidReporterArgument *>(argument);
96 pthread_mutex_lock(&arg->tid_reported_mutex);
97 arg->reported_tid = GetTid();
98 pthread_cond_broadcast(&arg->tid_reported_cond);
99 pthread_mutex_unlock(&arg->tid_reported_mutex);
100
101 pthread_mutex_lock(&arg->terminate_thread_mutex);
102 while (!arg->terminate_thread)
103 pthread_cond_wait(&arg->terminate_thread_cond,
104 &arg->terminate_thread_mutex);
105 pthread_mutex_unlock(&arg->terminate_thread_mutex);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000106 return NULL;
107}
108
Alexander Potapenko32602c52013-03-14 12:06:54 +0000109void ThreadListerTest::SpawnTidReporter(pthread_t *pthread_id,
110 pid_t *tid) {
111 pthread_mutex_lock(&thread_arg.tid_reported_mutex);
112 thread_arg.reported_tid = -1;
113 ASSERT_EQ(0, pthread_create(pthread_id, NULL,
114 TidReporterThread,
115 &thread_arg));
116 while (thread_arg.reported_tid == -1)
117 pthread_cond_wait(&thread_arg.tid_reported_cond,
118 &thread_arg.tid_reported_mutex);
119 pthread_mutex_unlock(&thread_arg.tid_reported_mutex);
120 *tid = thread_arg.reported_tid;
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000121}
Alexander Potapenko32602c52013-03-14 12:06:54 +0000122
Alexey Samsonov827d4ef2013-03-14 15:15:35 +0000123static std::vector<pid_t> ReadTidsToVector(ThreadLister *thread_lister) {
Alexander Potapenko32602c52013-03-14 12:06:54 +0000124 std::vector<pid_t> listed_tids;
125 pid_t tid;
Alexander Potapenko3d048542013-03-14 13:15:14 +0000126 while ((tid = thread_lister->GetNextTID()) >= 0)
Alexander Potapenko32602c52013-03-14 12:06:54 +0000127 listed_tids.push_back(tid);
Alexander Potapenko3d048542013-03-14 13:15:14 +0000128 EXPECT_FALSE(thread_lister->error());
Alexander Potapenko32602c52013-03-14 12:06:54 +0000129 return listed_tids;
130}
131
132static bool Includes(std::vector<pid_t> first, std::vector<pid_t> second) {
133 std::sort(first.begin(), first.end());
134 std::sort(second.begin(), second.end());
135 return std::includes(first.begin(), first.end(),
136 second.begin(), second.end());
137}
138
139static bool HasElement(std::vector<pid_t> vector, pid_t element) {
140 return std::find(vector.begin(), vector.end(), element) != vector.end();
141}
142
143// ThreadLister's output should include the current thread's TID and the TID of
144// every thread we spawned.
145TEST_F(ThreadListerTest, ThreadListerSeesAllSpawnedThreads) {
146 pid_t self_tid = GetTid();
147 ThreadLister thread_lister(getpid());
Alexander Potapenko3d048542013-03-14 13:15:14 +0000148 std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister);
Alexander Potapenko32602c52013-03-14 12:06:54 +0000149 ASSERT_TRUE(HasElement(listed_tids, self_tid));
150 ASSERT_TRUE(Includes(listed_tids, tids_));
151}
152
153// Calling Reset() should not cause ThreadLister to forget any threads it's
154// supposed to know about.
155TEST_F(ThreadListerTest, ResetDoesNotForgetThreads) {
156 ThreadLister thread_lister(getpid());
157
158 // Run the loop body twice, because Reset() might behave differently if called
159 // on a freshly created object.
160 for (uptr i = 0; i < 2; i++) {
161 thread_lister.Reset();
Alexander Potapenko3d048542013-03-14 13:15:14 +0000162 std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister);
Alexander Potapenko32602c52013-03-14 12:06:54 +0000163 ASSERT_TRUE(Includes(listed_tids, tids_));
164 }
165}
166
167// If new threads have spawned during ThreadLister object's lifetime, calling
168// Reset() should cause ThreadLister to recognize their existence.
169TEST_F(ThreadListerTest, ResetMakesNewThreadsKnown) {
170 ThreadLister thread_lister(getpid());
Alexander Potapenko3d048542013-03-14 13:15:14 +0000171 std::vector<pid_t> threads_before_extra = ReadTidsToVector(&thread_lister);
Alexander Potapenko32602c52013-03-14 12:06:54 +0000172
173 pthread_t extra_pthread_id;
174 pid_t extra_tid;
175 SpawnTidReporter(&extra_pthread_id, &extra_tid);
176 // Register the new thread so it gets terminated in TearDown().
177 pthread_ids_.push_back(extra_pthread_id);
178
179 // It would be very bizarre if the new TID had been listed before we even
180 // spawned that thread, but it would also cause a false success in this test,
181 // so better check for that.
182 ASSERT_FALSE(HasElement(threads_before_extra, extra_tid));
183
184 thread_lister.Reset();
185
Alexander Potapenko3d048542013-03-14 13:15:14 +0000186 std::vector<pid_t> threads_after_extra = ReadTidsToVector(&thread_lister);
Alexander Potapenko32602c52013-03-14 12:06:54 +0000187 ASSERT_TRUE(HasElement(threads_after_extra, extra_tid));
188}
189
Alexey Samsonovff7c14f2013-04-23 12:49:12 +0000190TEST(SanitizerCommon, SetEnvTest) {
191 const char kEnvName[] = "ENV_FOO";
192 SetEnv(kEnvName, "value");
193 EXPECT_STREQ("value", getenv(kEnvName));
194 unsetenv(kEnvName);
195 EXPECT_EQ(0, getenv(kEnvName));
196}
197
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800198#if (defined(__x86_64__) || defined(__i386__)) && !SANITIZER_ANDROID
Sergey Matveev4c086442013-05-29 13:07:42 +0000199void *thread_self_offset_test_func(void *arg) {
200 bool result =
201 *(uptr *)((char *)ThreadSelf() + ThreadSelfOffset()) == ThreadSelf();
202 return (void *)result;
203}
204
205TEST(SanitizerLinux, ThreadSelfOffset) {
206 EXPECT_TRUE((bool)thread_self_offset_test_func(0));
207 pthread_t tid;
208 void *result;
209 ASSERT_EQ(0, pthread_create(&tid, 0, thread_self_offset_test_func, 0));
210 ASSERT_EQ(0, pthread_join(tid, &result));
211 EXPECT_TRUE((bool)result);
212}
213
214// libpthread puts the thread descriptor at the end of stack space.
215void *thread_descriptor_size_test_func(void *arg) {
216 uptr descr_addr = ThreadSelf();
Sergey Matveev24323de2013-05-07 14:41:43 +0000217 pthread_attr_t attr;
218 pthread_getattr_np(pthread_self(), &attr);
219 void *stackaddr;
Sergey Matveev4c086442013-05-29 13:07:42 +0000220 size_t stacksize;
Sergey Matveev24323de2013-05-07 14:41:43 +0000221 pthread_attr_getstack(&attr, &stackaddr, &stacksize);
Sergey Matveev4c086442013-05-29 13:07:42 +0000222 return (void *)((uptr)stackaddr + stacksize - descr_addr);
Sergey Matveev24323de2013-05-07 14:41:43 +0000223}
224
225TEST(SanitizerLinux, ThreadDescriptorSize) {
226 pthread_t tid;
227 void *result;
Sergey Matveev4c086442013-05-29 13:07:42 +0000228 ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func, 0));
Sergey Matveev24323de2013-05-07 14:41:43 +0000229 ASSERT_EQ(0, pthread_join(tid, &result));
230 EXPECT_EQ((uptr)result, ThreadDescriptorSize());
231}
232#endif
233
Sergey Matveev3de00862013-05-14 13:24:46 +0000234TEST(SanitizerCommon, LibraryNameIs) {
235 EXPECT_FALSE(LibraryNameIs("", ""));
236
237 char full_name[256];
238 const char *paths[] = { "", "/", "/path/to/" };
239 const char *suffixes[] = { "", "-linux", ".1.2", "-linux.1.2" };
240 const char *base_names[] = { "lib", "lib.0", "lib-i386" };
241 const char *wrong_names[] = { "", "lib.9", "lib-x86_64" };
242 for (uptr i = 0; i < ARRAY_SIZE(paths); i++)
243 for (uptr j = 0; j < ARRAY_SIZE(suffixes); j++) {
244 for (uptr k = 0; k < ARRAY_SIZE(base_names); k++) {
245 internal_snprintf(full_name, ARRAY_SIZE(full_name), "%s%s%s.so",
246 paths[i], base_names[k], suffixes[j]);
247 EXPECT_TRUE(LibraryNameIs(full_name, base_names[k]))
248 << "Full name " << full_name
249 << " doesn't match base name " << base_names[k];
250 for (uptr m = 0; m < ARRAY_SIZE(wrong_names); m++)
251 EXPECT_FALSE(LibraryNameIs(full_name, wrong_names[m]))
252 << "Full name " << full_name
253 << " matches base name " << wrong_names[m];
254 }
255 }
256}
257
Stephen Hines86277eb2015-03-23 12:06:32 -0700258#if defined(__mips64)
259// Effectively, this is a test for ThreadDescriptorSize() which is used to
260// compute ThreadSelf().
261TEST(SanitizerLinux, ThreadSelfTest) {
262 ASSERT_EQ(pthread_self(), ThreadSelf());
263}
264#endif
265
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000266} // namespace __sanitizer
267
Kostya Serebryanyf931da82013-05-15 12:36:29 +0000268#endif // SANITIZER_LINUX