1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.commons.lang3;
21
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertNull;
28 import static org.junit.jupiter.api.Assertions.assertSame;
29 import static org.junit.jupiter.api.Assertions.assertThrows;
30 import static org.junit.jupiter.api.Assertions.assertTrue;
31
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.Modifier;
34 import java.time.Duration;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.List;
38 import java.util.Objects;
39 import java.util.concurrent.CountDownLatch;
40 import java.util.function.Predicate;
41
42 import org.apache.commons.lang3.ThreadUtils.ThreadGroupPredicate;
43 import org.apache.commons.lang3.ThreadUtils.ThreadPredicate;
44 import org.junit.jupiter.api.Test;
45
46
47
48
49 public class ThreadUtilsTest extends AbstractLangTest {
50
51 private static final class TestThread extends Thread {
52 private final CountDownLatch latch = new CountDownLatch(1);
53
54 TestThread(final String name) {
55 super(name);
56 }
57
58 TestThread(final ThreadGroup group, final String name) {
59 super(group, name);
60 }
61
62 @Override
63 public void run() {
64 latch.countDown();
65 try {
66 synchronized (this) {
67 this.wait();
68 }
69 } catch (final InterruptedException e) {
70 Thread.currentThread().interrupt();
71 }
72 }
73
74 @Override
75 public synchronized void start() {
76 super.start();
77 try {
78 latch.await();
79 } catch (final InterruptedException e) {
80 Thread.currentThread().interrupt();
81 }
82 }
83 }
84
85 @Test
86 public void testAtLeastOneThreadExists() {
87 assertFalse(ThreadUtils.getAllThreads().isEmpty());
88 }
89
90 @Test
91 public void testAtLeastOneThreadGroupsExists() {
92 assertFalse(ThreadUtils.getAllThreadGroups().isEmpty());
93 }
94
95 @Test
96 public void testComplexThreadGroups() throws Exception {
97 final ThreadGroup threadGroup1 = new ThreadGroup("thread_group_1__");
98 final ThreadGroup threadGroup2 = new ThreadGroup("thread_group_2__");
99 final ThreadGroup threadGroup3 = new ThreadGroup(threadGroup2, "thread_group_3__");
100 final ThreadGroup threadGroup4 = new ThreadGroup(threadGroup2, "thread_group_4__");
101 final ThreadGroup threadGroup5 = new ThreadGroup(threadGroup1, "thread_group_5__");
102 final ThreadGroup threadGroup6 = new ThreadGroup(threadGroup4, "thread_group_6__");
103 final ThreadGroup threadGroup7 = new ThreadGroup(threadGroup4, "thread_group_7__");
104 final ThreadGroup threadGroup7Doubled = new ThreadGroup(threadGroup4, "thread_group_7__");
105 final List<ThreadGroup> threadGroups = Arrays.asList(threadGroup1, threadGroup2, threadGroup3, threadGroup4, threadGroup5, threadGroup6, threadGroup7,
106 threadGroup7Doubled);
107
108 final Thread t1 = new TestThread("thread1_X__");
109 final Thread t2 = new TestThread(threadGroup1, "thread2_X__");
110 final Thread t3 = new TestThread(threadGroup2, "thread3_X__");
111 final Thread t4 = new TestThread(threadGroup3, "thread4_X__");
112 final Thread t5 = new TestThread(threadGroup4, "thread5_X__");
113 final Thread t6 = new TestThread(threadGroup5, "thread6_X__");
114 final Thread t7 = new TestThread(threadGroup6, "thread7_X__");
115 final Thread t8 = new TestThread(threadGroup4, "thread8_X__");
116 final Thread t9 = new TestThread(threadGroup6, "thread9_X__");
117 final Thread t10 = new TestThread(threadGroup3, "thread10_X__");
118 final Thread t11 = new TestThread(threadGroup7, "thread11_X__");
119 final Thread t11Doubled = new TestThread(threadGroup7Doubled, "thread11_X__");
120 final List<Thread> threads = Arrays.asList(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t11Doubled);
121
122 try {
123 for (final Thread thread : threads) {
124 thread.start();
125 }
126 assertThat("getAllThreadGroups", ThreadUtils.getAllThreadGroups().size(), greaterThanOrEqualTo(7));
127 assertThat("getAllThreads", ThreadUtils.getAllThreads().size(), greaterThanOrEqualTo(11));
128 assertThat("findThreads(ThreadUtils.ALWAYS_TRUE_PREDICATE)", ThreadUtils.findThreads(ThreadUtils.ALWAYS_TRUE_PREDICATE).size(), greaterThanOrEqualTo(11));
129 assertEquals(1, ThreadUtils.findThreadsByName(t4.getName(), threadGroup3.getName()).size());
130 assertEquals(0, ThreadUtils.findThreadsByName(t4.getName(), threadGroup2.getName()).size());
131 assertEquals(2, ThreadUtils.findThreadsByName(t11.getName(), threadGroup7.getName()).size());
132 } finally {
133 for (final Thread thread : threads) {
134 thread.interrupt();
135 thread.join();
136 }
137 for (final ThreadGroup threadGroup : threadGroups) {
138 if (!threadGroup.isDestroyed()) {
139 threadGroup.destroy();
140 }
141 }
142 }
143 }
144
145 @Test
146 public void testConstructor() {
147 assertNotNull(new ThreadUtils());
148 final Constructor<?>[] cons = ThreadUtils.class.getDeclaredConstructors();
149 assertEquals(1, cons.length);
150 assertTrue(Modifier.isPublic(cons[0].getModifiers()));
151 assertTrue(Modifier.isPublic(ThreadUtils.class.getModifiers()));
152 assertFalse(Modifier.isFinal(ThreadUtils.class.getModifiers()));
153 }
154
155 @Test
156 public void testGetAllThreadGroupsDoesNotReturnNull() {
157
158 Collection<ThreadGroup> threads = ThreadUtils.getAllThreadGroups();
159 assertEquals(0, threads.stream().filter(Objects::isNull).count());
160 }
161
162 @Test
163 public void testGetAllThreadsDoesNotReturnNull() {
164
165 Collection<Thread> threads = ThreadUtils.getAllThreads();
166 assertEquals(0, threads.stream().filter(Objects::isNull).count());
167 }
168
169 @Test
170 public void testInvalidThreadId() {
171 assertThrows(IllegalArgumentException.class, () -> ThreadUtils.findThreadById(-5L));
172 }
173
174 @Test
175 public void testJoinDuration() throws InterruptedException {
176 ThreadUtils.join(new Thread(), Duration.ZERO);
177 ThreadUtils.join(new Thread(), Duration.ofMillis(1));
178 }
179
180 @Test
181 public void testNoThread() {
182 assertEquals(0, ThreadUtils.findThreadsByName("some_thread_which_does_not_exist_18762ZucTT").size());
183 }
184
185 @Test
186 public void testNoThreadGroup() {
187 assertEquals(0, ThreadUtils.findThreadGroupsByName("some_thread_group_which_does_not_exist_18762ZucTTII").size());
188 }
189
190 @Test
191 public void testNullThreadGroupName() {
192 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadGroupsByName(null));
193 }
194
195 @Test
196 public void testNullThreadName() {
197 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadsByName(null));
198 }
199
200 @Test
201 public void testNullThreadThreadGroup1() {
202 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadsByName("tname", (ThreadGroup) null));
203 }
204
205 @Test
206 public void testNullThreadThreadGroup2() {
207 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadById(1L, (ThreadGroup) null));
208 }
209
210 @Test
211 public void testNullThreadThreadGroup3() {
212 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadsByName(null, (ThreadGroup) null));
213 }
214
215 @Test
216 public void testNullThreadThreadGroupName1() {
217 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadsByName(null, "tgname"));
218 }
219
220 @Test
221 public void testNullThreadThreadGroupName2() {
222 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadsByName("tname", (String) null));
223 }
224
225 @Test
226 public void testNullThreadThreadGroupName3() {
227 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadsByName(null, (String) null));
228 }
229
230 @Test
231 public void testSleepDuration() throws InterruptedException {
232 ThreadUtils.sleep(Duration.ZERO);
233 ThreadUtils.sleep(Duration.ofMillis(1));
234 }
235
236 @Test
237 public void testSystemThreadGroupExists() {
238 final ThreadGroup systemThreadGroup = ThreadUtils.getSystemThreadGroup();
239 assertNotNull(systemThreadGroup);
240 assertNull(systemThreadGroup.getParent());
241 assertEquals("system", systemThreadGroup.getName());
242 }
243
244 @Test
245 public void testThreadGroups() throws InterruptedException {
246 final String threadGroupName = "thread_group_DDZZ99__for_testThreadGroups";
247 final ThreadGroup threadGroup = new ThreadGroup(threadGroupName);
248 final Thread t1 = new TestThread(threadGroup, "thread1_XXOOPP__");
249 final Thread t2 = new TestThread(threadGroup, "thread2_XXOOPP__");
250
251 try {
252 t1.start();
253 t2.start();
254 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__").size());
255 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__", threadGroupName).size());
256 assertEquals(1, ThreadUtils.findThreadsByName("thread2_XXOOPP__", threadGroupName).size());
257 assertEquals(0, ThreadUtils.findThreadsByName("thread1_XXOOPP__", "non_existent_thread_group_JJHHZZ__").size());
258 assertEquals(0, ThreadUtils.findThreadsByName("non_existent_thread_BBDDWW__", threadGroupName).size());
259 assertEquals(1, ThreadUtils.findThreadGroupsByName(threadGroupName).size());
260 assertEquals(0, ThreadUtils.findThreadGroupsByName("non_existent_thread_group_JJHHZZ__").size());
261 assertNotNull(ThreadUtils.findThreadById(t1.getId(), threadGroup));
262 } finally {
263 t1.interrupt();
264 t2.interrupt();
265 t1.join();
266 t2.join();
267 threadGroup.destroy();
268 }
269 }
270
271 @Test
272 public void testThreadGroupsById() throws InterruptedException {
273 final String threadGroupName = "thread_group_DDZZ99__for_testThreadGroupsById";
274 final ThreadGroup threadGroup = new ThreadGroup(threadGroupName);
275 final Thread t1 = new TestThread(threadGroup, "thread1_XXOOPP__");
276 final Thread t2 = new TestThread(threadGroup, "thread2_XXOOPP__");
277 final long nonExistingId = t1.getId() + t2.getId();
278
279 try {
280 t1.start();
281 t2.start();
282 assertSame(t1, ThreadUtils.findThreadById(t1.getId(), threadGroupName));
283 assertSame(t2, ThreadUtils.findThreadById(t2.getId(), threadGroupName));
284 assertNull(ThreadUtils.findThreadById(nonExistingId, "non_existent_thread_group_JJHHZZ__"));
285 assertNull(ThreadUtils.findThreadById(nonExistingId, threadGroupName));
286 } finally {
287 t1.interrupt();
288 t2.interrupt();
289 t1.join();
290 t2.join();
291 threadGroup.destroy();
292 }
293 }
294
295 @Test
296 public void testThreadGroupsByIdFail() {
297 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadById(Thread.currentThread().getId(), (String) null));
298 }
299
300 @Test
301 public void testThreadGroupsNullParent() {
302 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadGroups(null, true, ThreadUtils.ALWAYS_TRUE_PREDICATE));
303 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadGroups(null, false, ThreadUtils.ALWAYS_TRUE_PREDICATE));
304 }
305
306 @Test
307 public void testThreadGroupsNullPredicate() {
308 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadGroups((ThreadGroupPredicate) null));
309 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadGroups((Predicate<ThreadGroup>) null));
310 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreadGroups((Predicate) null));
311 }
312
313 @Test
314 public void testThreadGroupsRef() throws InterruptedException {
315 final ThreadGroup threadGroup = new ThreadGroup("thread_group_DDZZ99__");
316 final ThreadGroup deadThreadGroup = new ThreadGroup("dead_thread_group_MMQQSS__");
317 deadThreadGroup.destroy();
318 final Thread t1 = new TestThread(threadGroup, "thread1_XXOOPP__");
319 final Thread t2 = new TestThread(threadGroup, "thread2_XXOOPP__");
320
321 try {
322 t1.start();
323 t2.start();
324 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__").size());
325 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__", threadGroup).size());
326 assertEquals(1, ThreadUtils.findThreadsByName("thread2_XXOOPP__", threadGroup).size());
327 assertEquals(0, ThreadUtils.findThreadsByName("thread1_XXOOPP__", deadThreadGroup).size());
328 } finally {
329 t1.interrupt();
330 t2.interrupt();
331 t1.join();
332 t2.join();
333 threadGroup.destroy();
334 assertEquals(0, ThreadUtils.findThreadsByName("thread2_XXOOPP__", threadGroup).size());
335 }
336 }
337
338 @Test
339 public void testThreads() throws InterruptedException {
340 final Thread t1 = new TestThread("thread1_XXOOLL__");
341 final Thread t2 = new TestThread("thread2_XXOOLL__");
342
343 try {
344 t1.start();
345 t2.start();
346 assertEquals(1, ThreadUtils.findThreadsByName("thread2_XXOOLL__").size());
347 } finally {
348 t1.interrupt();
349 t2.interrupt();
350 t1.join();
351 t2.join();
352 }
353 }
354
355 @Test
356 public void testThreadsById() throws InterruptedException {
357 final Thread t1 = new TestThread("thread1_XXOOLL__");
358 final Thread t2 = new TestThread("thread2_XXOOLL__");
359
360 try {
361 t1.start();
362 t2.start();
363 assertSame(t1, ThreadUtils.findThreadById(t1.getId()));
364 assertSame(t2, ThreadUtils.findThreadById(t2.getId()));
365 } finally {
366 t1.interrupt();
367 t2.interrupt();
368 t1.join();
369 t2.join();
370 }
371 }
372
373 @Test
374 public void testThreadsByIdWrongGroup() throws InterruptedException {
375 final Thread t1 = new TestThread("thread1_XXOOLL__");
376 final ThreadGroup tg = new ThreadGroup("tg__HHEE22");
377
378 try {
379 t1.start();
380 assertNull(ThreadUtils.findThreadById(t1.getId(), tg));
381 } finally {
382 t1.interrupt();
383 t1.join();
384 tg.destroy();
385 }
386 }
387
388 @Test
389 public void testThreadsNullPredicate() {
390 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreads((ThreadPredicate) null));
391 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreads((Predicate<Thread>) null));
392 assertThrows(NullPointerException.class, () -> ThreadUtils.findThreads((Predicate) null));
393 }
394
395 @Test
396 public void testThreadsSameName() throws InterruptedException {
397 final Thread t1 = new TestThread("thread1_XXOOLL__");
398 final Thread alsot1 = new TestThread("thread1_XXOOLL__");
399
400 try {
401 t1.start();
402 alsot1.start();
403 assertEquals(2, ThreadUtils.findThreadsByName("thread1_XXOOLL__").size());
404 } finally {
405 t1.interrupt();
406 alsot1.interrupt();
407 t1.join();
408 alsot1.join();
409 }
410 }
411
412 }