YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/thread-test.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include "yb/util/thread.h"
34
35
#include <string>
36
37
#include <gtest/gtest.h>
38
39
#include "yb/gutil/bind.h"
40
#include "yb/gutil/ref_counted.h"
41
#include "yb/util/env.h"
42
#include "yb/util/status_log.h"
43
#include "yb/util/test_macros.h"
44
#include "yb/util/test_util.h"
45
#include "yb/util/thread_restrictions.h"
46
47
using std::string;
48
using namespace std::literals;
49
50
namespace yb {
51
52
class ThreadTest : public YBTest {};
53
54
// Join with a thread and emit warnings while waiting to join.
55
// This has to be manually verified.
56
1
TEST_F(ThreadTest, TestJoinAndWarn) {
57
1
  if (!AllowSlowTests()) {
58
1
    LOG(INFO) << "Skipping test in quick test mode, since this sleeps";
59
1
    return;
60
1
  }
61
62
0
  scoped_refptr<Thread> holder;
63
0
  ASSERT_OK(Thread::Create("test", "sleeper thread", usleep, 1000*1000, &holder));
64
0
  ASSERT_OK(ThreadJoiner(holder.get())
65
0
                   .warn_after(10ms)
66
0
                   .warn_every(100ms)
67
0
                   .Join());
68
0
}
69
70
1
TEST_F(ThreadTest, TestFailedJoin) {
71
1
  if (!AllowSlowTests()) {
72
1
    LOG(INFO) << "Skipping test in quick test mode, since this sleeps";
73
1
    return;
74
1
  }
75
76
0
  scoped_refptr<Thread> holder;
77
0
  ASSERT_OK(Thread::Create("test", "sleeper thread", usleep, 1000*1000, &holder));
78
0
  Status s = ThreadJoiner(holder.get())
79
0
    .give_up_after(50ms)
80
0
    .Join();
81
0
  ASSERT_STR_CONTAINS(s.ToString(), "Timed out after 50ms joining on sleeper thread");
82
0
}
83
84
1
static void TryJoinOnSelf() {
85
1
  Status s = ThreadJoiner(Thread::current_thread()).Join();
86
  // Use CHECK instead of ASSERT because gtest isn't thread-safe.
87
1
  CHECK(s.IsInvalidArgument());
88
1
}
89
90
// Try to join on the thread that is currently running.
91
1
TEST_F(ThreadTest, TestJoinOnSelf) {
92
1
  scoped_refptr<Thread> holder;
93
1
  ASSERT_OK(Thread::Create("test", "test", TryJoinOnSelf, &holder));
94
1
  holder->Join();
95
  // Actual assertion is done by the thread spawned above.
96
1
}
97
98
1
TEST_F(ThreadTest, TestDoubleJoinIsNoOp) {
99
1
  scoped_refptr<Thread> holder;
100
1
  ASSERT_OK(Thread::Create("test", "sleeper thread", usleep, 0, &holder));
101
1
  ThreadJoiner joiner(holder.get());
102
1
  ASSERT_OK(joiner.Join());
103
1
  ASSERT_OK(joiner.Join());
104
1
}
105
106
107
namespace {
108
109
2
void ExitHandler(string* s, const char* to_append) {
110
2
  *s += to_append;
111
2
}
112
113
1
void CallAtExitThread(string* s) {
114
1
  Thread::current_thread()->CallAtExit(Bind(&ExitHandler, s, Unretained("hello 1, ")));
115
1
  Thread::current_thread()->CallAtExit(Bind(&ExitHandler, s, Unretained("hello 2")));
116
1
}
117
118
} // anonymous namespace
119
120
1
TEST_F(ThreadTest, TestCallOnExit) {
121
1
  scoped_refptr<Thread> holder;
122
1
  string s;
123
1
  ASSERT_OK(Thread::Create("test", "TestCallOnExit", CallAtExitThread, &s, &holder));
124
1
  holder->Join();
125
1
  ASSERT_EQ("hello 1, hello 2", s);
126
1
}
127
128
1
TEST_F(ThreadTest, TestThreadNameWithoutPadding) {
129
1
  ThreadPtr t;
130
1
  string name = string(25, 'a');
131
1
  t = CHECK_RESULT(Thread::Make("test", name, [](){}));
132
1
  ASSERT_EQ(t->name(), name);
133
1
}
134
135
1
TEST_F(ThreadTest, TestThreadNameWithPadding) {
136
1
  ThreadPtr t;
137
1
  string name = string(5, 'a');
138
1
  t = CHECK_RESULT(Thread::Make("test", name, [](){}));
139
1
  ASSERT_EQ(t->name(), name + string(10, Thread::kPaddingChar));
140
1
}
141
142
// The following tests only run in debug mode, since thread restrictions are no-ops
143
// in release builds.
144
#ifndef NDEBUG
145
1
TEST_F(ThreadTest, TestThreadRestrictions_IO) {
146
  // Default should be to allow IO
147
1
  ThreadRestrictions::AssertIOAllowed();
148
149
1
  ThreadRestrictions::SetIOAllowed(false);
150
1
  {
151
1
    ThreadRestrictions::ScopedAllowIO allow_io;
152
1
    ASSERT_TRUE(Env::Default()->FileExists("/"));
153
1
  }
154
1
  ThreadRestrictions::SetIOAllowed(true);
155
156
  // Disallow IO - doing IO should crash the process.
157
1
  ASSERT_DEATH({
158
1
      ThreadRestrictions::SetIOAllowed(false);
159
1
      Env::Default()->FileExists("/");
160
1
    },
161
1
    "Function marked as IO-only was called from a thread that disallows IO");
162
1
}
163
164
1
TEST_F(ThreadTest, TestThreadRestrictions_Waiting) {
165
  // Default should be to allow IO
166
1
  ThreadRestrictions::AssertWaitAllowed();
167
168
1
  ThreadRestrictions::SetWaitAllowed(false);
169
1
  {
170
1
    ThreadRestrictions::ScopedAllowWait allow_wait;
171
1
    CountDownLatch l(0);
172
1
    l.Wait();
173
1
  }
174
1
  ThreadRestrictions::SetWaitAllowed(true);
175
176
  // Disallow waiting - blocking on a latch should crash the process.
177
1
  ASSERT_DEATH({
178
1
      ThreadRestrictions::SetWaitAllowed(false);
179
1
      CountDownLatch l(1);
180
1
      l.WaitFor(std::chrono::seconds(1s));
181
1
    },
182
1
    "Waiting is not allowed to be used on this thread");
183
1
}
184
#endif // NDEBUG
185
186
} // namespace yb