001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3.concurrent;
018
019import static org.junit.Assert.assertEquals;
020import static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertNotSame;
023import static org.junit.Assert.assertNull;
024import static org.junit.Assert.assertSame;
025import static org.junit.Assert.assertTrue;
026
027import java.util.concurrent.ThreadFactory;
028
029import org.easymock.EasyMock;
030import org.junit.Before;
031import org.junit.Test;
032
033/**
034 * Test class for {@code BasicThreadFactory}.
035 *
036 * @version $Id: BasicThreadFactoryTest.java 1436770 2013-01-22 07:09:45Z ggregory $
037 */
038public class BasicThreadFactoryTest {
039    /** Constant for the test naming pattern. */
040    private static final String PATTERN = "testThread-%d";
041
042    /** The builder for creating a thread factory. */
043    private BasicThreadFactory.Builder builder;
044
045    @Before
046    public void setUp() throws Exception {
047        builder = new BasicThreadFactory.Builder();
048    }
049
050    /**
051     * Tests the default options of a thread factory.
052     *
053     * @param factory the factory to be checked
054     */
055    private void checkFactoryDefaults(final BasicThreadFactory factory) {
056        assertNull("Got a naming pattern", factory.getNamingPattern());
057        assertNull("Got an exception handler", factory
058                .getUncaughtExceptionHandler());
059        assertNull("Got a priority", factory.getPriority());
060        assertNull("Got a daemon flag", factory.getDaemonFlag());
061        assertNotNull("No wrapped factory", factory.getWrappedFactory());
062    }
063
064    /**
065     * Tests the default values used by the builder.
066     */
067    @Test
068    public void testBuildDefaults() {
069        final BasicThreadFactory factory = builder.build();
070        checkFactoryDefaults(factory);
071    }
072
073    /**
074     * Tries to set a null naming pattern.
075     */
076    @Test(expected = NullPointerException.class)
077    public void testBuildNamingPatternNull() {
078        builder.namingPattern(null);
079    }
080
081    /**
082     * Tries to set a null wrapped factory.
083     */
084    @Test(expected = NullPointerException.class)
085    public void testBuildWrappedFactoryNull() {
086        builder.wrappedFactory(null);
087    }
088
089    /**
090     * Tries to set a null exception handler.
091     */
092    @Test(expected = NullPointerException.class)
093    public void testBuildUncaughtExceptionHandlerNull() {
094        builder.uncaughtExceptionHandler(null);
095    }
096
097    /**
098     * Tests the reset() method of the builder.
099     */
100    @Test
101    public void testBuilderReset() {
102        final ThreadFactory wrappedFactory = EasyMock.createMock(ThreadFactory.class);
103        final Thread.UncaughtExceptionHandler exHandler = EasyMock
104                .createMock(Thread.UncaughtExceptionHandler.class);
105        EasyMock.replay(wrappedFactory, exHandler);
106        builder.namingPattern(PATTERN).daemon(true).priority(
107                Thread.MAX_PRIORITY).uncaughtExceptionHandler(exHandler)
108                .wrappedFactory(wrappedFactory);
109        builder.reset();
110        final BasicThreadFactory factory = builder.build();
111        checkFactoryDefaults(factory);
112        assertNotSame("Wrapped factory not reset", wrappedFactory, factory
113                .getWrappedFactory());
114        EasyMock.verify(wrappedFactory, exHandler);
115    }
116
117    /**
118     * Tests whether reset() is automatically called after build().
119     */
120    @Test
121    public void testBuilderResetAfterBuild() {
122        builder.wrappedFactory(EasyMock.createNiceMock(ThreadFactory.class))
123                .namingPattern(PATTERN).daemon(true).build();
124        checkFactoryDefaults(builder.build());
125    }
126
127    /**
128     * Tests whether the naming pattern is applied to new threads.
129     */
130    @Test
131    public void testNewThreadNamingPattern() {
132        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
133        final Runnable r = EasyMock.createMock(Runnable.class);
134        final int count = 12;
135        for (int i = 0; i < count; i++) {
136            EasyMock.expect(wrapped.newThread(r)).andReturn(new Thread());
137        }
138        EasyMock.replay(wrapped, r);
139        final BasicThreadFactory factory = builder.wrappedFactory(wrapped)
140                .namingPattern(PATTERN).build();
141        for (int i = 0; i < count; i++) {
142            final Thread t = factory.newThread(r);
143            assertEquals("Wrong thread name", String.format(PATTERN, Long
144                    .valueOf(i + 1)), t.getName());
145            assertEquals("Wrong thread count", i + 1, factory.getThreadCount());
146        }
147        EasyMock.verify(wrapped, r);
148    }
149
150    /**
151     * Tests whether the thread name is not modified if no naming pattern is
152     * set.
153     */
154    @Test
155    public void testNewThreadNoNamingPattern() {
156        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
157        final Runnable r = EasyMock.createMock(Runnable.class);
158        final String name = "unchangedThreadName";
159        final Thread t = new Thread(name);
160        EasyMock.expect(wrapped.newThread(r)).andReturn(t);
161        EasyMock.replay(wrapped, r);
162        final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
163        assertSame("Wrong thread", t, factory.newThread(r));
164        assertEquals("Name was changed", name, t.getName());
165        EasyMock.verify(wrapped, r);
166    }
167
168    /**
169     * Helper method for testing whether the daemon flag is taken into account.
170     *
171     * @param flag the value of the flag
172     */
173    private void checkDaemonFlag(final boolean flag) {
174        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
175        final Runnable r = EasyMock.createMock(Runnable.class);
176        final Thread t = new Thread();
177        EasyMock.expect(wrapped.newThread(r)).andReturn(t);
178        EasyMock.replay(wrapped, r);
179        final BasicThreadFactory factory = builder.wrappedFactory(wrapped).daemon(
180                flag).build();
181        assertSame("Wrong thread", t, factory.newThread(r));
182        assertTrue("Wrong daemon flag", flag == t.isDaemon());
183        EasyMock.verify(wrapped, r);
184    }
185
186    /**
187     * Tests whether daemon threads can be created.
188     */
189    @Test
190    public void testNewThreadDaemonTrue() {
191        checkDaemonFlag(true);
192    }
193
194    /**
195     * Tests whether the daemon status of new threads can be turned off.
196     */
197    @Test
198    public void testNewThreadDaemonFalse() {
199        checkDaemonFlag(false);
200    }
201
202    /**
203     * Tests whether the daemon flag is not touched on newly created threads if
204     * it is not specified.
205     */
206    @Test
207    public void testNewThreadNoDaemonFlag() {
208        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
209        final Runnable r1 = EasyMock.createMock(Runnable.class);
210        final Runnable r2 = EasyMock.createMock(Runnable.class);
211        final Thread t1 = new Thread();
212        final Thread t2 = new Thread();
213        t1.setDaemon(true);
214        EasyMock.expect(wrapped.newThread(r1)).andReturn(t1);
215        EasyMock.expect(wrapped.newThread(r2)).andReturn(t2);
216        EasyMock.replay(wrapped, r1, r2);
217        final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
218        assertSame("Wrong thread 1", t1, factory.newThread(r1));
219        assertTrue("No daemon thread", t1.isDaemon());
220        assertSame("Wrong thread 2", t2, factory.newThread(r2));
221        assertFalse("A daemon thread", t2.isDaemon());
222        EasyMock.verify(wrapped, r1, r2);
223    }
224
225    /**
226     * Tests whether the priority is set on newly created threads.
227     */
228    @Test
229    public void testNewThreadPriority() {
230        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
231        final Runnable r = EasyMock.createMock(Runnable.class);
232        final Thread t = new Thread();
233        EasyMock.expect(wrapped.newThread(r)).andReturn(t);
234        EasyMock.replay(wrapped, r);
235        final int priority = Thread.NORM_PRIORITY + 1;
236        final BasicThreadFactory factory = builder.wrappedFactory(wrapped).priority(
237                priority).build();
238        assertSame("Wrong thread", t, factory.newThread(r));
239        assertEquals("Wrong priority", priority, t.getPriority());
240        EasyMock.verify(wrapped, r);
241    }
242
243    /**
244     * Tests whether the original priority is not changed if no priority is
245     * specified.
246     */
247    @Test
248    public void testNewThreadNoPriority() {
249        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
250        final Runnable r = EasyMock.createMock(Runnable.class);
251        final int orgPriority = Thread.NORM_PRIORITY + 1;
252        final Thread t = new Thread();
253        t.setPriority(orgPriority);
254        EasyMock.expect(wrapped.newThread(r)).andReturn(t);
255        EasyMock.replay(wrapped, r);
256        final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
257        assertSame("Wrong thread", t, factory.newThread(r));
258        assertEquals("Wrong priority", orgPriority, t.getPriority());
259        EasyMock.verify(wrapped, r);
260    }
261
262    /**
263     * Tests whether the exception handler is set if one is provided.
264     */
265    @Test
266    public void testNewThreadExHandler() {
267        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
268        final Runnable r = EasyMock.createMock(Runnable.class);
269        final Thread.UncaughtExceptionHandler handler = EasyMock
270                .createMock(Thread.UncaughtExceptionHandler.class);
271        final Thread t = new Thread();
272        EasyMock.expect(wrapped.newThread(r)).andReturn(t);
273        EasyMock.replay(wrapped, r, handler);
274        final BasicThreadFactory factory = builder.wrappedFactory(wrapped)
275                .uncaughtExceptionHandler(handler).build();
276        assertSame("Wrong thread", t, factory.newThread(r));
277        assertEquals("Wrong exception handler", handler, t
278                .getUncaughtExceptionHandler());
279        EasyMock.verify(wrapped, r, handler);
280    }
281
282    /**
283     * Tests whether the original exception hander is not touched if none is
284     * specified.
285     */
286    @Test
287    public void testNewThreadNoExHandler() {
288        final ThreadFactory wrapped = EasyMock.createMock(ThreadFactory.class);
289        final Runnable r = EasyMock.createMock(Runnable.class);
290        final Thread.UncaughtExceptionHandler handler = EasyMock
291                .createMock(Thread.UncaughtExceptionHandler.class);
292        final Thread t = new Thread();
293        t.setUncaughtExceptionHandler(handler);
294        EasyMock.expect(wrapped.newThread(r)).andReturn(t);
295        EasyMock.replay(wrapped, r, handler);
296        final BasicThreadFactory factory = builder.wrappedFactory(wrapped).build();
297        assertSame("Wrong thread", t, factory.newThread(r));
298        assertEquals("Wrong exception handler", handler, t
299                .getUncaughtExceptionHandler());
300        EasyMock.verify(wrapped, r, handler);
301    }
302}