1 /* 2 * Copyright (C) 2010 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import static org.junit.contrib.truth.Truth.ASSERT; 20 21 import com.google.common.testing.NullPointerTester; 22 23 import junit.framework.TestCase; 24 25 import java.lang.Thread.UncaughtExceptionHandler; 26 import java.util.concurrent.Executors; 27 import java.util.concurrent.ThreadFactory; 28 29 /** 30 * Tests for ThreadFactoryBuilder. 31 * 32 * @author Kurt Alfred Kluever 33 * @author Martin Buchholz 34 */ 35 public class ThreadFactoryBuilderTest extends TestCase { 36 private final Runnable monitoredRunnable = new Runnable() { 37 @Override public void run() { 38 completed = true; 39 } 40 }; 41 42 private static final UncaughtExceptionHandler UNCAUGHT_EXCEPTION_HANDLER = 43 new UncaughtExceptionHandler() { 44 @Override public void uncaughtException(Thread t, Throwable e) { 45 // No-op 46 } 47 }; 48 49 private ThreadFactoryBuilder builder; 50 private volatile boolean completed = false; 51 52 @Override public void setUp() { 53 builder = new ThreadFactoryBuilder(); 54 } 55 56 public void testThreadFactoryBuilder_defaults() throws InterruptedException { 57 ThreadFactory threadFactory = builder.build(); 58 Thread thread = threadFactory.newThread(monitoredRunnable); 59 checkThreadPoolName(thread, 1); 60 61 Thread defaultThread = 62 Executors.defaultThreadFactory().newThread(monitoredRunnable); 63 assertEquals(defaultThread.isDaemon(), thread.isDaemon()); 64 assertEquals(defaultThread.getPriority(), thread.getPriority()); 65 assertSame(defaultThread.getThreadGroup(), thread.getThreadGroup()); 66 assertSame(defaultThread.getUncaughtExceptionHandler(), 67 thread.getUncaughtExceptionHandler()); 68 69 assertFalse(completed); 70 thread.start(); 71 thread.join(); 72 assertTrue(completed); 73 74 // Creating a new thread from the same ThreadFactory will have the same 75 // pool ID but a thread ID of 2. 76 Thread thread2 = threadFactory.newThread(monitoredRunnable); 77 checkThreadPoolName(thread2, 2); 78 assertEquals( 79 thread.getName().substring(0, thread.getName().lastIndexOf('-')), 80 thread2.getName().substring(0, thread.getName().lastIndexOf('-'))); 81 82 // Building again should give us a different pool ID. 83 ThreadFactory threadFactory2 = builder.build(); 84 Thread thread3 = threadFactory2.newThread(monitoredRunnable); 85 checkThreadPoolName(thread3, 1); 86 ASSERT.that( 87 thread2.getName().substring(0, thread.getName().lastIndexOf('-'))) 88 .isNotEqualTo( 89 thread3.getName().substring(0, thread.getName().lastIndexOf('-'))); 90 } 91 92 private static void checkThreadPoolName(Thread thread, int threadId) { 93 assertTrue(thread.getName().matches("^pool-\\d+-thread-" + threadId + "$")); 94 } 95 96 public void testNameFormat_custom() { 97 final String NAME_FORMAT = "super duper thread #%s"; 98 ThreadFactory factory = builder.setNameFormat(NAME_FORMAT).build(); 99 for (int i = 0; i < 10; i++) { 100 assertEquals(String.format(NAME_FORMAT, i), 101 factory.newThread(monitoredRunnable).getName()); 102 } 103 } 104 105 public void testDaemon_false() { 106 ThreadFactory factory = builder.setDaemon(false).build(); 107 Thread thread = factory.newThread(monitoredRunnable); 108 assertFalse(thread.isDaemon()); 109 } 110 111 public void testDaemon_true() { 112 ThreadFactory factory = builder.setDaemon(true).build(); 113 Thread thread = factory.newThread(monitoredRunnable); 114 assertTrue(thread.isDaemon()); 115 } 116 117 public void testPriority_custom() { 118 for (int i = Thread.MIN_PRIORITY; i <= Thread.MAX_PRIORITY; i++) { 119 ThreadFactory factory = builder.setPriority(i).build(); 120 Thread thread = factory.newThread(monitoredRunnable); 121 assertEquals(i, thread.getPriority()); 122 } 123 } 124 125 public void testPriority_tooLow() { 126 try { 127 builder.setPriority(Thread.MIN_PRIORITY - 1); 128 fail(); 129 } catch (IllegalArgumentException expected) { 130 } 131 } 132 133 public void testPriority_tooHigh() { 134 try { 135 builder.setPriority(Thread.MAX_PRIORITY + 1); 136 fail(); 137 } catch (IllegalArgumentException expected) { 138 } 139 } 140 141 public void testUncaughtExceptionHandler_custom() { 142 assertEquals(UNCAUGHT_EXCEPTION_HANDLER, 143 builder.setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER).build() 144 .newThread(monitoredRunnable).getUncaughtExceptionHandler()); 145 } 146 147 public void testBuildMutateBuild() { 148 ThreadFactory factory1 = builder.setPriority(1).build(); 149 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 150 151 ThreadFactory factory2 = builder.setPriority(2).build(); 152 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 153 assertEquals(2, factory2.newThread(monitoredRunnable).getPriority()); 154 } 155 156 public void testBuildTwice() { 157 builder.build(); // this is allowed 158 builder.build(); // this is *also* allowed 159 } 160 161 public void testBuildMutate() { 162 ThreadFactory factory1 = builder.setPriority(1).build(); 163 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 164 165 builder.setPriority(2); // change the state of the builder 166 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 167 } 168 169 public void testThreadFactory() throws InterruptedException { 170 final String THREAD_NAME = "ludicrous speed"; 171 final int THREAD_PRIORITY = 1; 172 final boolean THREAD_DAEMON = false; 173 ThreadFactory backingThreadFactory = new ThreadFactory() { 174 @Override public Thread newThread(Runnable r) { 175 Thread thread = new Thread(r); 176 thread.setName(THREAD_NAME); 177 thread.setPriority(THREAD_PRIORITY); 178 thread.setDaemon(THREAD_DAEMON); 179 thread.setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER); 180 return thread; 181 } 182 }; 183 184 Thread thread = builder.setThreadFactory(backingThreadFactory).build() 185 .newThread(monitoredRunnable); 186 187 assertEquals(THREAD_NAME, thread.getName()); 188 assertEquals(THREAD_PRIORITY, thread.getPriority()); 189 assertEquals(THREAD_DAEMON, thread.isDaemon()); 190 assertSame(UNCAUGHT_EXCEPTION_HANDLER, 191 thread.getUncaughtExceptionHandler()); 192 assertSame(Thread.State.NEW, thread.getState()); 193 194 assertFalse(completed); 195 thread.start(); 196 thread.join(); 197 assertTrue(completed); 198 } 199 200 public void testNulls() throws Exception { 201 NullPointerTester npTester = new NullPointerTester(); 202 npTester.testAllPublicConstructors(ThreadFactoryBuilder.class); 203 npTester.testAllPublicStaticMethods(ThreadFactoryBuilder.class); 204 npTester.testAllPublicInstanceMethods(builder); 205 } 206 } 207