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      /** Constant for the test naming pattern. */
40      private static final String PATTERN = "testThread-%d";
41  
42      /** The builder for creating a thread factory. */
43      private BasicThreadFactory.Builder builder;
44  
45      /**
46       * Helper method for testing whether the daemon flag is taken into account.
47       *
48       * @param flag the value of the flag
49       */
50      private void checkDaemonFlag(final boolean flag) {
51          final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
52          final Runnable r = EasyMock.createMock(Runnable.class);
53          final Thread t = new Thread();
54          EasyMock.expect(wrapped.newThread(r)).andReturn(t);
55          EasyMock.replay(wrapped, r);
56          // @formatter:off
57          final BasicThreadFactory factory = builder
58                  .wrappedFactory(wrapped)
59                  .daemon(flag)
60                  .build();
61          // @formatter:on
62          assertSame(t, factory.newThread(r), "Wrong thread");
63          assertEquals(flag, t.isDaemon(), "Wrong daemon flag");
64          EasyMock.verify(wrapped, r);
65      }
66  
67      /**
68       * Tests the default options of a thread factory.
69       *
70       * @param factory the factory to be checked
71       */
72      private void checkFactoryDefaults(final BasicThreadFactory factory) {
73          assertNull(factory.getNamingPattern(), "Got a naming pattern");
74          assertNull(factory.getUncaughtExceptionHandler(), "Got an exception handler");
75          assertNull(factory.getPriority(), "Got a priority");
76          assertNull(factory.getDaemonFlag(), "Got a daemon flag");
77          assertNotNull(factory.getWrappedFactory(), "No wrapped factory");
78      }
79  
80      @BeforeEach
81      public void setUp() {
82          builder = BasicThreadFactory.builder();
83      }
84  
85      /**
86       * Tests the default values used by the builder.
87       */
88      @Test
89      void testBuildDefaults() {
90          final BasicThreadFactory factory = builder.build();
91          checkFactoryDefaults(factory);
92      }
93  
94      /**
95       * Tests the daemon() method of the builder.
96       */
97      @Test
98      void testBuilderDaemon() {
99          builder.daemon();
100         assertTrue(builder.build().getDaemonFlag());
101     }
102 
103     /**
104      * Tests the daemon() method of the builder.
105      */
106     @Test
107     void testBuilderDaemonBoolean() {
108         builder.daemon(true);
109         assertTrue(builder.build().getDaemonFlag());
110         builder.daemon(false);
111         assertFalse(builder.build().getDaemonFlag());
112     }
113 
114     /**
115      * Tests the reset() method of the builder.
116      */
117     @Test
118     void testBuilderReset() {
119         final ThreadFactory wrappedFactory = EasyMock.createMock(ThreadFactory.class);
120         final Thread.UncaughtExceptionHandler exHandler = EasyMock
121                 .createMock(Thread.UncaughtExceptionHandler.class);
122         EasyMock.replay(wrappedFactory, exHandler);
123         // @formatter:off
124         builder.namingPattern(PATTERN)
125             .daemon(true)
126             .priority(Thread.MAX_PRIORITY)
127             .uncaughtExceptionHandler(exHandler)
128             .wrappedFactory(wrappedFactory);
129         // @formatter:on
130         builder.reset();
131         final BasicThreadFactory factory = builder.build();
132         checkFactoryDefaults(factory);
133         assertNotSame(wrappedFactory, factory.getWrappedFactory(), "Wrapped factory not reset");
134         EasyMock.verify(wrappedFactory, exHandler);
135     }
136 
137     /**
138      * Tests whether reset() is automatically called after build().
139      */
140     @Test
141     void testBuilderResetAfterBuild() {
142         // @formatter:off
143         builder
144             .wrappedFactory(EasyMock.createNiceMock(ThreadFactory.class))
145             .namingPattern(PATTERN)
146             .daemon(true)
147             .build();
148         // @formatter:on
149         checkFactoryDefaults(builder.build());
150     }
151 
152     /**
153      * Tries to set a null naming pattern.
154      */
155     @Test
156     void testBuildNamingPatternNull() {
157         assertNullPointerException(() -> builder.namingPattern(null));
158     }
159 
160     /**
161      * Tries to set a null exception handler.
162      */
163     @Test
164     void testBuildUncaughtExceptionHandlerNull() {
165         assertNullPointerException(() -> builder.uncaughtExceptionHandler(null));
166     }
167 
168     /**
169      * Tries to set a null wrapped factory.
170      */
171     @Test
172     void testBuildWrappedFactoryNull() {
173         assertNullPointerException(() -> builder.wrappedFactory(null));
174     }
175 
176     /**
177      * Tests whether the daemon status of new threads can be turned off.
178      */
179     @Test
180     void testNewThreadDaemonFalse() {
181         checkDaemonFlag(false);
182     }
183 
184     /**
185      * Tests whether daemon threads can be created.
186      */
187     @Test
188     void testNewThreadDaemonTrue() {
189         checkDaemonFlag(true);
190     }
191 
192     /**
193      * Tests whether the exception handler is set if one is provided.
194      */
195     @Test
196     void testNewThreadExHandler() {
197         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
198         final Runnable r = EasyMock.createMock(Runnable.class);
199         final Thread.UncaughtExceptionHandler handler = EasyMock
200                 .createMock(Thread.UncaughtExceptionHandler.class);
201         final Thread t = new Thread();
202         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
203         EasyMock.replay(wrapped, r, handler);
204         final BasicThreadFactory factory = builder.wrappedFactory(wrapped)
205                 .uncaughtExceptionHandler(handler).build();
206         assertSame(t, factory.newThread(r), "Wrong thread");
207         assertEquals(handler, t.getUncaughtExceptionHandler(), "Wrong exception handler");
208         EasyMock.verify(wrapped, r, handler);
209     }
210 
211     /**
212      * Tests whether the naming pattern is applied to new threads.
213      */
214     @Test
215     void testNewThreadNamingPattern() {
216         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
217         final Runnable r = EasyMock.createMock(Runnable.class);
218         final int count = 12;
219         for (int i = 0; i < count; i++) {
220             EasyMock.expect(wrapped.newThread(r)).andReturn(new Thread());
221         }
222         EasyMock.replay(wrapped, r);
223         final BasicThreadFactory factory = builder.wrappedFactory(wrapped)
224                 .namingPattern(PATTERN).build();
225         for (int i = 0; i < count; i++) {
226             final Thread t = factory.newThread(r);
227             assertEquals(String.format(PATTERN, Long.valueOf(i + 1)), t.getName(), "Wrong thread name");
228             assertEquals(i + 1, factory.getThreadCount(), "Wrong thread count");
229         }
230         EasyMock.verify(wrapped, r);
231     }
232 
233     /**
234      * Tests whether the daemon flag is not touched on newly created threads if
235      * it is not specified.
236      */
237     @Test
238     void testNewThreadNoDaemonFlag() {
239         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
240         final Runnable r1 = EasyMock.createMock(Runnable.class);
241         final Runnable r2 = EasyMock.createMock(Runnable.class);
242         final Thread t1 = new Thread();
243         final Thread t2 = new Thread();
244         t1.setDaemon(true);
245         EasyMock.expect(wrapped.newThread(r1)).andReturn(t1);
246         EasyMock.expect(wrapped.newThread(r2)).andReturn(t2);
247         EasyMock.replay(wrapped, r1, r2);
248         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
249         assertSame(t1, factory.newThread(r1), "Wrong thread 1");
250         assertTrue(t1.isDaemon(), "No daemon thread");
251         assertSame(t2, factory.newThread(r2), "Wrong thread 2");
252         assertFalse(t2.isDaemon(), "A daemon thread");
253         EasyMock.verify(wrapped, r1, r2);
254     }
255 
256     /**
257      * Tests whether the original exception handler is not touched if none is
258      * specified.
259      */
260     @Test
261     void testNewThreadNoExHandler() {
262         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
263         final Runnable r = EasyMock.createMock(Runnable.class);
264         final Thread.UncaughtExceptionHandler handler = EasyMock
265                 .createMock(Thread.UncaughtExceptionHandler.class);
266         final Thread t = new Thread();
267         t.setUncaughtExceptionHandler(handler);
268         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
269         EasyMock.replay(wrapped, r, handler);
270         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
271         assertSame(t, factory.newThread(r), "Wrong thread");
272         assertEquals(handler, t.getUncaughtExceptionHandler(), "Wrong exception handler");
273         EasyMock.verify(wrapped, r, handler);
274     }
275 
276     /**
277      * Tests whether the thread name is not modified if no naming pattern is
278      * set.
279      */
280     @Test
281     void testNewThreadNoNamingPattern() {
282         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
283         final Runnable r = EasyMock.createMock(Runnable.class);
284         final String name = "unchangedThreadName";
285         final Thread t = new Thread(name);
286         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
287         EasyMock.replay(wrapped, r);
288         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
289         assertSame(t, factory.newThread(r), "Wrong thread");
290         assertEquals(name, t.getName(), "Name was changed");
291         EasyMock.verify(wrapped, r);
292     }
293 
294     /**
295      * Tests whether the original priority is not changed if no priority is
296      * specified.
297      */
298     @Test
299     void testNewThreadNoPriority() {
300         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
301         final Runnable r = EasyMock.createMock(Runnable.class);
302         final int orgPriority = Thread.NORM_PRIORITY + 1;
303         final Thread t = new Thread();
304         t.setPriority(orgPriority);
305         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
306         EasyMock.replay(wrapped, r);
307         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
308         assertSame(t, factory.newThread(r), "Wrong thread");
309         assertEquals(orgPriority, t.getPriority(), "Wrong priority");
310         EasyMock.verify(wrapped, r);
311     }
312 
313     /**
314      * Tests whether the priority is set on newly created threads.
315      */
316     @Test
317     void testNewThreadPriority() {
318         final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
319         final Runnable r = EasyMock.createMock(Runnable.class);
320         final Thread t = new Thread();
321         EasyMock.expect(wrapped.newThread(r)).andReturn(t);
322         EasyMock.replay(wrapped, r);
323         final int priority = Thread.NORM_PRIORITY + 1;
324         final BasicThreadFactory factory = builder.wrappedFactory(wrapped).priority(
325                 priority).build();
326         assertSame(t, factory.newThread(r), "Wrong thread");
327         assertEquals(priority, t.getPriority(), "Wrong priority");
328         EasyMock.verify(wrapped, r);
329     }
330 }