View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.concurrent;
18  
19  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNotSame;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertSame;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.util.concurrent.ThreadFactory;
29  
30  import org.apache.commons.lang3.AbstractLangTest;
31  import org.easymock.EasyMock;
32  import org.junit.jupiter.api.BeforeEach;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   * Test class for {@code BasicThreadFactory}.
37   */
38  class BasicThreadFactoryTest extends AbstractLangTest {
39  
40      /** Constant for the test naming pattern. */
41      private static final String PATTERN = "testThread-%d";
42  
43      /** The builder for creating a thread factory. */
44      private BasicThreadFactory.Builder builder;
45  
46      /**
47       * Helper method for testing whether the daemon flag is taken into account.
48       *
49       * @param flag the value of the flag
50       */
51      private void checkDaemonFlag(final boolean flag) {
52          final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
53          final Runnable r = EasyMock.createMock(Runnable.class);
54          final Thread t = new Thread();
55          EasyMock.expect(wrapped.newThread(r)).andReturn(t);
56          EasyMock.replay(wrapped, r);
57          // @formatter:off
58          final BasicThreadFactory factory = builder
59                  .wrappedFactory(wrapped)
60                  .daemon(flag)
61                  .build();
62          // @formatter:on
63          assertSame(t, factory.newThread(r), "Wrong thread");
64          assertEquals(flag, t.isDaemon(), "Wrong daemon flag");
65          EasyMock.verify(wrapped, r);
66      }
67  
68      /**
69       * Tests the default options of a thread factory.
70       *
71       * @param factory the factory to be checked
72       */
73      private void checkFactoryDefaults(final BasicThreadFactory factory) {
74          assertNull(factory.getNamingPattern(), "Got a naming pattern");
75          assertNull(factory.getUncaughtExceptionHandler(), "Got an exception handler");
76          assertNull(factory.getPriority(), "Got a priority");
77          assertNull(factory.getDaemonFlag(), "Got a daemon flag");
78          assertNotNull(factory.getWrappedFactory(), "No wrapped factory");
79      }
80  
81      @BeforeEach
82      public void setUp() {
83          builder = BasicThreadFactory.builder();
84      }
85  
86      /**
87       * Tests the default values used by the builder.
88       */
89      @Test
90      void testBuildDefaults() {
91          final BasicThreadFactory factory = builder.build();
92          checkFactoryDefaults(factory);
93      }
94  
95      /**
96       * Tests the daemon() method of the builder.
97       */
98      @Test
99      void testBuilderDaemon() {
100         builder.daemon();
101         assertTrue(builder.build().getDaemonFlag());
102     }
103 
104     /**
105      * Tests the daemon() method of the builder.
106      */
107     @Test
108     void testBuilderDaemonBoolean() {
109         builder.daemon(true);
110         assertTrue(builder.build().getDaemonFlag());
111         builder.daemon(false);
112         assertFalse(builder.build().getDaemonFlag());
113     }
114 
115     /**
116      * Tests the reset() method of the builder.
117      */
118     @Test
119     void testBuilderReset() {
120         final ThreadFactory wrappedFactory = EasyMock.createMock(ThreadFactory.class);
121         final Thread.UncaughtExceptionHandler exHandler = EasyMock
122                 .createMock(Thread.UncaughtExceptionHandler.class);
123         EasyMock.replay(wrappedFactory, exHandler);
124         // @formatter:off
125         builder.namingPattern(PATTERN)
126             .daemon(true)
127             .priority(Thread.MAX_PRIORITY)
128             .uncaughtExceptionHandler(exHandler)
129             .wrappedFactory(wrappedFactory);
130         // @formatter:on
131         builder.reset();
132         final BasicThreadFactory factory = builder.build();
133         checkFactoryDefaults(factory);
134         assertNotSame(wrappedFactory, factory.getWrappedFactory(), "Wrapped factory not reset");
135         EasyMock.verify(wrappedFactory, exHandler);
136     }
137 
138     /**
139      * Tests whether reset() is automatically called after build().
140      */
141     @Test
142     void testBuilderResetAfterBuild() {
143         // @formatter:off
144         builder
145             .wrappedFactory(EasyMock.createNiceMock(ThreadFactory.class))
146             .namingPattern(PATTERN)
147             .daemon(true)
148             .build();
149         // @formatter:on
150         checkFactoryDefaults(builder.build());
151     }
152 
153     /**
154      * Tries to set a null naming pattern.
155      */
156     @Test
157     void testBuildNamingPatternNull() {
158         assertNullPointerException(() -> builder.namingPattern(null));
159     }
160 
161     /**
162      * Tries to set a null exception handler.
163      */
164     @Test
165     void testBuildUncaughtExceptionHandlerNull() {
166         assertNullPointerException(() -> builder.uncaughtExceptionHandler(null));
167     }
168 
169     /**
170      * Tries to set a null wrapped factory.
171      */
172     @Test
173     void testBuildWrappedFactoryNull() {
174         assertNullPointerException(() -> builder.wrappedFactory(null));
175     }
176 
177     /**
178      * Tests whether the daemon status of new threads can be turned off.
179      */
180     @Test
181     void testNewThreadDaemonFalse() {
182         checkDaemonFlag(false);
183     }
184 
185     /**
186      * Tests whether daemon threads can be created.
187      */
188     @Test
189     void testNewThreadDaemonTrue() {
190         checkDaemonFlag(true);
191     }
192 
193     /**
194      * Tests whether the exception handler is set if one is provided.
195      */
196     @Test
197     void testNewThreadExHandler() {
198         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
199         final Runnable r = EasyMock.createMock(Runnable.class);
200         final Thread.UncaughtExceptionHandler handler = EasyMock
201                 .createMock(Thread.UncaughtExceptionHandler.class);
202         final Thread t = new Thread();
203         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
204         EasyMock.replay(wrapped, r, handler);
205         final BasicThreadFactory factory = builder.wrappedFactory(wrapped)
206                 .uncaughtExceptionHandler(handler).build();
207         assertSame(t, factory.newThread(r), "Wrong thread");
208         assertEquals(handler, t.getUncaughtExceptionHandler(), "Wrong exception handler");
209         EasyMock.verify(wrapped, r, handler);
210     }
211 
212     /**
213      * Tests whether the naming pattern is applied to new threads.
214      */
215     @Test
216     void testNewThreadNamingPattern() {
217         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
218         final Runnable r = EasyMock.createMock(Runnable.class);
219         final int count = 12;
220         for (int i = 0; i < count; i++) {
221             EasyMock.expect(wrapped.newThread(r)).andReturn(new Thread());
222         }
223         EasyMock.replay(wrapped, r);
224         final BasicThreadFactory factory = builder.wrappedFactory(wrapped)
225                 .namingPattern(PATTERN).build();
226         for (int i = 0; i < count; i++) {
227             final Thread t = factory.newThread(r);
228             assertEquals(String.format(PATTERN, Long.valueOf(i + 1)), t.getName(), "Wrong thread name");
229             assertEquals(i + 1, factory.getThreadCount(), "Wrong thread count");
230         }
231         EasyMock.verify(wrapped, r);
232     }
233 
234     /**
235      * Tests whether the daemon flag is not touched on newly created threads if
236      * it is not specified.
237      */
238     @Test
239     void testNewThreadNoDaemonFlag() {
240         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
241         final Runnable r1 = EasyMock.createMock(Runnable.class);
242         final Runnable r2 = EasyMock.createMock(Runnable.class);
243         final Thread t1 = new Thread();
244         final Thread t2 = new Thread();
245         t1.setDaemon(true);
246         EasyMock.expect(wrapped.newThread(r1)).andReturn(t1);
247         EasyMock.expect(wrapped.newThread(r2)).andReturn(t2);
248         EasyMock.replay(wrapped, r1, r2);
249         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
250         assertSame(t1, factory.newThread(r1), "Wrong thread 1");
251         assertTrue(t1.isDaemon(), "No daemon thread");
252         assertSame(t2, factory.newThread(r2), "Wrong thread 2");
253         assertFalse(t2.isDaemon(), "A daemon thread");
254         EasyMock.verify(wrapped, r1, r2);
255     }
256 
257     /**
258      * Tests whether the original exception handler is not touched if none is
259      * specified.
260      */
261     @Test
262     void testNewThreadNoExHandler() {
263         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
264         final Runnable r = EasyMock.createMock(Runnable.class);
265         final Thread.UncaughtExceptionHandler handler = EasyMock
266                 .createMock(Thread.UncaughtExceptionHandler.class);
267         final Thread t = new Thread();
268         t.setUncaughtExceptionHandler(handler);
269         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
270         EasyMock.replay(wrapped, r, handler);
271         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
272         assertSame(t, factory.newThread(r), "Wrong thread");
273         assertEquals(handler, t.getUncaughtExceptionHandler(), "Wrong exception handler");
274         EasyMock.verify(wrapped, r, handler);
275     }
276 
277     /**
278      * Tests whether the thread name is not modified if no naming pattern is
279      * set.
280      */
281     @Test
282     void testNewThreadNoNamingPattern() {
283         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
284         final Runnable r = EasyMock.createMock(Runnable.class);
285         final String name = "unchangedThreadName";
286         final Thread t = new Thread(name);
287         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
288         EasyMock.replay(wrapped, r);
289         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
290         assertSame(t, factory.newThread(r), "Wrong thread");
291         assertEquals(name, t.getName(), "Name was changed");
292         EasyMock.verify(wrapped, r);
293     }
294 
295     /**
296      * Tests whether the original priority is not changed if no priority is
297      * specified.
298      */
299     @Test
300     void testNewThreadNoPriority() {
301         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
302         final Runnable r = EasyMock.createMock(Runnable.class);
303         final int orgPriority = Thread.NORM_PRIORITY + 1;
304         final Thread t = new Thread();
305         t.setPriority(orgPriority);
306         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
307         EasyMock.replay(wrapped, r);
308         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
309         assertSame(t, factory.newThread(r), "Wrong thread");
310         assertEquals(orgPriority, t.getPriority(), "Wrong priority");
311         EasyMock.verify(wrapped, r);
312     }
313 
314     /**
315      * Tests whether the priority is set on newly created threads.
316      */
317     @Test
318     void testNewThreadPriority() {
319         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
320         final Runnable r = EasyMock.createMock(Runnable.class);
321         final Thread t = new Thread();
322         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
323         EasyMock.replay(wrapped, r);
324         final int priority = Thread.NORM_PRIORITY + 1;
325         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).priority(
326                 priority).build();
327         assertSame(t, factory.newThread(r), "Wrong thread");
328         assertEquals(priority, t.getPriority(), "Wrong priority");
329         EasyMock.verify(wrapped, r);
330     }
331 }