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.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
23 import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
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.assertTrue;
30
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.Modifier;
33 import java.time.Duration;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.List;
37 import java.util.Objects;
38 import java.util.concurrent.CountDownLatch;
39 import java.util.function.Predicate;
40
41 import org.apache.commons.lang3.ThreadUtils.ThreadGroupPredicate;
42 import org.apache.commons.lang3.ThreadUtils.ThreadPredicate;
43 import org.apache.commons.lang3.function.Predicates;
44 import org.junit.jupiter.api.Test;
45
46
47
48
49 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 void testAtLeastOneThreadExists() {
87 assertFalse(ThreadUtils.getAllThreads().isEmpty());
88 }
89
90 @Test
91 void testAtLeastOneThreadGroupsExists() {
92 assertFalse(ThreadUtils.getAllThreadGroups().isEmpty());
93 }
94
95 @Test
96 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 assertTrue(ThreadUtils.getAllThreadGroups().size() >= 7, "getAllThreadGroups");
127 assertTrue(ThreadUtils.getAllThreads().size() >= 11, "getAllThreads");
128 assertTrue(ThreadUtils.findThreads(Predicates.truePredicate()).size() >= 11, "findThreads(ThreadUtils.truePredicate())");
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 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 @SuppressWarnings("deprecation")
156 @Test
157 void testDepreacted() {
158 assertNotNull(ThreadUtils.ALWAYS_TRUE_PREDICATE);
159 final ThreadPredicate tp = ThreadUtils.ALWAYS_TRUE_PREDICATE;
160 assertTrue(tp.test(null));
161 assertTrue(tp.test(new Thread()));
162 final ThreadGroupPredicate tgp = ThreadUtils.ALWAYS_TRUE_PREDICATE;
163 assertTrue(tgp.test(null));
164 assertTrue(tgp.test(new ThreadGroup("")));
165 }
166
167 @Test
168 void testGetAllThreadGroupsDoesNotReturnNull() {
169
170 final Collection<ThreadGroup> threads = ThreadUtils.getAllThreadGroups();
171 assertEquals(0, threads.stream().filter(Objects::isNull).count());
172 }
173
174 @Test
175 void testGetAllThreadsDoesNotReturnNull() {
176
177 final Collection<Thread> threads = ThreadUtils.getAllThreads();
178 assertEquals(0, threads.stream().filter(Objects::isNull).count());
179 }
180
181 @Test
182 void testInvalidThreadId() {
183 assertIllegalArgumentException(() -> ThreadUtils.findThreadById(-5L));
184 }
185
186 @Test
187 void testJoinDuration() throws InterruptedException {
188 ThreadUtils.join(new Thread(), Duration.ZERO);
189 ThreadUtils.join(new Thread(), Duration.ofMillis(1));
190 }
191
192 @Test
193 void testNoThread() {
194 assertEquals(0, ThreadUtils.findThreadsByName("some_thread_which_does_not_exist_18762ZucTT").size());
195 }
196
197 @Test
198 void testNoThreadGroup() {
199 assertEquals(0, ThreadUtils.findThreadGroupsByName("some_thread_group_which_does_not_exist_18762ZucTTII").size());
200 }
201
202 @Test
203 void testNullThreadGroupName() {
204 assertNullPointerException(() -> ThreadUtils.findThreadGroupsByName(null));
205 }
206
207 @Test
208 void testNullThreadName() {
209 assertNullPointerException(() -> ThreadUtils.findThreadsByName(null));
210 }
211
212 @Test
213 void testNullThreadThreadGroup1() {
214 assertNullPointerException(() -> ThreadUtils.findThreadsByName("tname", (ThreadGroup) null));
215 }
216
217 @Test
218 void testNullThreadThreadGroup2() {
219 assertNullPointerException(() -> ThreadUtils.findThreadById(1L, (ThreadGroup) null));
220 }
221
222 @Test
223 void testNullThreadThreadGroup3() {
224 assertNullPointerException(() -> ThreadUtils.findThreadsByName(null, (ThreadGroup) null));
225 }
226
227 @Test
228 void testNullThreadThreadGroupName1() {
229 assertNullPointerException(() -> ThreadUtils.findThreadsByName(null, "tgname"));
230 }
231
232 @Test
233 void testNullThreadThreadGroupName2() {
234 assertNullPointerException(() -> ThreadUtils.findThreadsByName("tname", (String) null));
235 }
236
237 @Test
238 void testNullThreadThreadGroupName3() {
239 assertNullPointerException(() -> ThreadUtils.findThreadsByName(null, (String) null));
240 }
241
242 @Test
243 void testSleepDuration() throws InterruptedException {
244 ThreadUtils.sleep(Duration.ZERO);
245 ThreadUtils.sleep(Duration.ofMillis(1));
246 }
247
248 @Test
249 void testSystemThreadGroupExists() {
250 final ThreadGroup systemThreadGroup = ThreadUtils.getSystemThreadGroup();
251 assertNotNull(systemThreadGroup);
252 assertNull(systemThreadGroup.getParent());
253 assertEquals("system", systemThreadGroup.getName());
254 }
255
256 @Test
257 void testThreadGroups() throws InterruptedException {
258 final String threadGroupName = "thread_group_DDZZ99__for_testThreadGroups";
259 final ThreadGroup threadGroup = new ThreadGroup(threadGroupName);
260 final Thread t1 = new TestThread(threadGroup, "thread1_XXOOPP__");
261 final Thread t2 = new TestThread(threadGroup, "thread2_XXOOPP__");
262
263 try {
264 t1.start();
265 t2.start();
266 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__").size());
267 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__", threadGroupName).size());
268 assertEquals(1, ThreadUtils.findThreadsByName("thread2_XXOOPP__", threadGroupName).size());
269 assertEquals(0, ThreadUtils.findThreadsByName("thread1_XXOOPP__", "non_existent_thread_group_JJHHZZ__").size());
270 assertEquals(0, ThreadUtils.findThreadsByName("non_existent_thread_BBDDWW__", threadGroupName).size());
271 assertEquals(1, ThreadUtils.findThreadGroupsByName(threadGroupName).size());
272 assertEquals(0, ThreadUtils.findThreadGroupsByName("non_existent_thread_group_JJHHZZ__").size());
273 assertNotNull(ThreadUtils.findThreadById(t1.getId(), threadGroup));
274 } finally {
275 t1.interrupt();
276 t2.interrupt();
277 t1.join();
278 t2.join();
279 threadGroup.destroy();
280 }
281 }
282
283 @Test
284 void testThreadGroupsById() throws InterruptedException {
285 final String threadGroupName = "thread_group_DDZZ99__for_testThreadGroupsById";
286 final ThreadGroup threadGroup = new ThreadGroup(threadGroupName);
287 final Thread t1 = new TestThread(threadGroup, "thread1_XXOOPP__");
288 final Thread t2 = new TestThread(threadGroup, "thread2_XXOOPP__");
289 final long nonExistingId = t1.getId() + t2.getId();
290
291 try {
292 t1.start();
293 t2.start();
294 assertSame(t1, ThreadUtils.findThreadById(t1.getId(), threadGroupName));
295 assertSame(t2, ThreadUtils.findThreadById(t2.getId(), threadGroupName));
296 assertNull(ThreadUtils.findThreadById(nonExistingId, "non_existent_thread_group_JJHHZZ__"));
297 assertNull(ThreadUtils.findThreadById(nonExistingId, threadGroupName));
298 } finally {
299 t1.interrupt();
300 t2.interrupt();
301 t1.join();
302 t2.join();
303 threadGroup.destroy();
304 }
305 }
306
307 @Test
308 void testThreadGroupsByIdFail() {
309 assertNullPointerException(() -> ThreadUtils.findThreadById(Thread.currentThread().getId(), (String) null));
310 }
311
312 @Test
313 void testThreadGroupsNullParent() {
314 assertNullPointerException(() -> ThreadUtils.findThreadGroups(null, true, Predicates.truePredicate()));
315 assertNullPointerException(() -> ThreadUtils.findThreadGroups(null, false, Predicates.truePredicate()));
316 }
317
318 @Test
319 void testThreadGroupsNullPredicate() {
320 assertNullPointerException(() -> ThreadUtils.findThreadGroups((ThreadGroupPredicate) null));
321 assertNullPointerException(() -> ThreadUtils.findThreadGroups((Predicate<ThreadGroup>) null));
322 assertNullPointerException(() -> ThreadUtils.findThreadGroups((Predicate) null));
323 }
324
325 @Test
326 void testThreadGroupsRef() throws InterruptedException {
327 final ThreadGroup threadGroup = new ThreadGroup("thread_group_DDZZ99__");
328 final ThreadGroup deadThreadGroup = new ThreadGroup("dead_thread_group_MMQQSS__");
329 deadThreadGroup.destroy();
330 final Thread t1 = new TestThread(threadGroup, "thread1_XXOOPP__");
331 final Thread t2 = new TestThread(threadGroup, "thread2_XXOOPP__");
332
333 try {
334 t1.start();
335 t2.start();
336 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__").size());
337 assertEquals(1, ThreadUtils.findThreadsByName("thread1_XXOOPP__", threadGroup).size());
338 assertEquals(1, ThreadUtils.findThreadsByName("thread2_XXOOPP__", threadGroup).size());
339 assertEquals(0, ThreadUtils.findThreadsByName("thread1_XXOOPP__", deadThreadGroup).size());
340 } finally {
341 t1.interrupt();
342 t2.interrupt();
343 t1.join();
344 t2.join();
345 threadGroup.destroy();
346 assertEquals(0, ThreadUtils.findThreadsByName("thread2_XXOOPP__", threadGroup).size());
347 }
348 }
349
350 @Test
351 void testThreads() throws InterruptedException {
352 final Thread t1 = new TestThread("thread1_XXOOLL__");
353 final Thread t2 = new TestThread("thread2_XXOOLL__");
354
355 try {
356 t1.start();
357 t2.start();
358 assertEquals(1, ThreadUtils.findThreadsByName("thread2_XXOOLL__").size());
359 } finally {
360 t1.interrupt();
361 t2.interrupt();
362 t1.join();
363 t2.join();
364 }
365 }
366
367 @Test
368 void testThreadsById() throws InterruptedException {
369 final Thread t1 = new TestThread("thread1_XXOOLL__");
370 final Thread t2 = new TestThread("thread2_XXOOLL__");
371
372 try {
373 t1.start();
374 t2.start();
375 assertSame(t1, ThreadUtils.findThreadById(t1.getId()));
376 assertSame(t2, ThreadUtils.findThreadById(t2.getId()));
377 } finally {
378 t1.interrupt();
379 t2.interrupt();
380 t1.join();
381 t2.join();
382 }
383 }
384
385 @Test
386 void testThreadsByIdWrongGroup() throws InterruptedException {
387 final Thread t1 = new TestThread("thread1_XXOOLL__");
388 final ThreadGroup tg = new ThreadGroup("tg__HHEE22");
389
390 try {
391 t1.start();
392 assertNull(ThreadUtils.findThreadById(t1.getId(), tg));
393 } finally {
394 t1.interrupt();
395 t1.join();
396 tg.destroy();
397 }
398 }
399
400 @Test
401 void testThreadsNullPredicate() {
402 assertNullPointerException(() -> ThreadUtils.findThreads((ThreadPredicate) null));
403 assertNullPointerException(() -> ThreadUtils.findThreads((Predicate<Thread>) null));
404 assertNullPointerException(() -> ThreadUtils.findThreads((Predicate) null));
405 }
406
407 @Test
408 void testThreadsSameName() throws InterruptedException {
409 final Thread t1 = new TestThread("thread1_XXOOLL__");
410 final Thread alsot1 = new TestThread("thread1_XXOOLL__");
411
412 try {
413 t1.start();
414 alsot1.start();
415 assertEquals(2, ThreadUtils.findThreadsByName("thread1_XXOOLL__").size());
416 } finally {
417 t1.interrupt();
418 alsot1.interrupt();
419 t1.join();
420 alsot1.join();
421 }
422 }
423
424 }