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