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 com.google.common.truth.Truth.assertThat; 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 assertThat( 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 testNameFormatWithPercentS_custom() { 97 String format = "super-duper-thread-%s"; 98 ThreadFactory factory = builder.setNameFormat(format).build(); 99 for (int i = 0; i < 11; i++) { 100 assertEquals(String.format(format, i), 101 factory.newThread(monitoredRunnable).getName()); 102 } 103 } 104 105 public void testNameFormatWithPercentD_custom() { 106 String format = "super-duper-thread-%d"; 107 ThreadFactory factory = builder.setNameFormat(format).build(); 108 for (int i = 0; i < 11; i++) { 109 assertEquals(String.format(format, i), 110 factory.newThread(monitoredRunnable).getName()); 111 } 112 } 113 114 public void testDaemon_false() { 115 ThreadFactory factory = builder.setDaemon(false).build(); 116 Thread thread = factory.newThread(monitoredRunnable); 117 assertFalse(thread.isDaemon()); 118 } 119 120 public void testDaemon_true() { 121 ThreadFactory factory = builder.setDaemon(true).build(); 122 Thread thread = factory.newThread(monitoredRunnable); 123 assertTrue(thread.isDaemon()); 124 } 125 126 public void testPriority_custom() { 127 for (int i = Thread.MIN_PRIORITY; i <= Thread.MAX_PRIORITY; i++) { 128 ThreadFactory factory = builder.setPriority(i).build(); 129 Thread thread = factory.newThread(monitoredRunnable); 130 assertEquals(i, thread.getPriority()); 131 } 132 } 133 134 public void testPriority_tooLow() { 135 try { 136 builder.setPriority(Thread.MIN_PRIORITY - 1); 137 fail(); 138 } catch (IllegalArgumentException expected) { 139 } 140 } 141 142 public void testPriority_tooHigh() { 143 try { 144 builder.setPriority(Thread.MAX_PRIORITY + 1); 145 fail(); 146 } catch (IllegalArgumentException expected) { 147 } 148 } 149 150 public void testUncaughtExceptionHandler_custom() { 151 assertEquals(UNCAUGHT_EXCEPTION_HANDLER, 152 builder.setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER).build() 153 .newThread(monitoredRunnable).getUncaughtExceptionHandler()); 154 } 155 156 public void testBuildMutateBuild() { 157 ThreadFactory factory1 = builder.setPriority(1).build(); 158 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 159 160 ThreadFactory factory2 = builder.setPriority(2).build(); 161 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 162 assertEquals(2, factory2.newThread(monitoredRunnable).getPriority()); 163 } 164 165 public void testBuildTwice() { 166 builder.build(); // this is allowed 167 builder.build(); // this is *also* allowed 168 } 169 170 public void testBuildMutate() { 171 ThreadFactory factory1 = builder.setPriority(1).build(); 172 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 173 174 builder.setPriority(2); // change the state of the builder 175 assertEquals(1, factory1.newThread(monitoredRunnable).getPriority()); 176 } 177 178 public void testThreadFactory() throws InterruptedException { 179 final String THREAD_NAME = "ludicrous speed"; 180 final int THREAD_PRIORITY = 1; 181 final boolean THREAD_DAEMON = false; 182 ThreadFactory backingThreadFactory = new ThreadFactory() { 183 @Override public Thread newThread(Runnable r) { 184 Thread thread = new Thread(r); 185 thread.setName(THREAD_NAME); 186 thread.setPriority(THREAD_PRIORITY); 187 thread.setDaemon(THREAD_DAEMON); 188 thread.setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER); 189 return thread; 190 } 191 }; 192 193 Thread thread = builder.setThreadFactory(backingThreadFactory).build() 194 .newThread(monitoredRunnable); 195 196 assertEquals(THREAD_NAME, thread.getName()); 197 assertEquals(THREAD_PRIORITY, thread.getPriority()); 198 assertEquals(THREAD_DAEMON, thread.isDaemon()); 199 assertSame(UNCAUGHT_EXCEPTION_HANDLER, 200 thread.getUncaughtExceptionHandler()); 201 assertSame(Thread.State.NEW, thread.getState()); 202 203 assertFalse(completed); 204 thread.start(); 205 thread.join(); 206 assertTrue(completed); 207 } 208 209 public void testNulls() { 210 NullPointerTester npTester = new NullPointerTester(); 211 npTester.testAllPublicConstructors(ThreadFactoryBuilder.class); 212 npTester.testAllPublicStaticMethods(ThreadFactoryBuilder.class); 213 npTester.testAllPublicInstanceMethods(builder); 214 } 215 } 216