1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  */
  22 
  23 /*
  24  * This file is available under and governed by the GNU General Public
  25  * License version 2 only, as published by the Free Software Foundation.
  26  * However, the following notice accompanied the original version of this
  27  * file:
  28  *
  29  * Written by Martin Buchholz and Doug Lea with assistance from
  30  * members of JCP JSR-166 Expert Group and released to the public
  31  * domain, as explained at
  32  * http://creativecommons.org/publicdomain/zero/1.0/
  33  */
  34 
  35 /*
  36  * @test
  37  * @summary Should be able to shutdown a pool when worker creation failed.
  38  * @library /test/lib
  39  */
  40 
  41 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  42 
  43 import java.util.concurrent.LinkedBlockingQueue;
  44 import java.util.concurrent.ThreadFactory;
  45 import java.util.concurrent.ThreadPoolExecutor;
  46 import java.util.concurrent.TimeUnit;
  47 import jdk.test.lib.Utils;
  48 
  49 public class FlakyThreadFactory {
  50     static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
  51 
  52     void test(String[] args) throws Throwable {
  53         test(NullPointerException.class,
  54              new ThreadFactory() {
  55                 public Thread newThread(Runnable r) {
  56                     throw new NullPointerException();
  57                 }});
  58         test(OutOfMemoryError.class,
  59              new ThreadFactory() {
  60                  @SuppressWarnings("DeadThread")
  61                  public Thread newThread(Runnable r) {
  62                      // We expect this to throw OOME, but ...
  63                      new Thread(null, r, "a natural OOME", 1L << 60);
  64                      // """On some platforms, the value of the stackSize
  65                      // parameter may have no effect whatsoever."""
  66                      throw new OutOfMemoryError("artificial OOME");
  67                  }});
  68         test(null,
  69              new ThreadFactory() {
  70                 public Thread newThread(Runnable r) {
  71                     return null;
  72                 }});
  73     }
  74 
  75     void test(final Class<?> exceptionClass,
  76               final ThreadFactory failingThreadFactory)
  77             throws Throwable {
  78         ThreadFactory flakyThreadFactory = new ThreadFactory() {
  79             int seq = 0;
  80             public Thread newThread(Runnable r) {
  81                 if (seq++ < 4)
  82                     return new Thread(r);
  83                 else
  84                     return failingThreadFactory.newThread(r);
  85             }};
  86         ThreadPoolExecutor pool =
  87             new ThreadPoolExecutor(10, 10,
  88                                    0L, TimeUnit.SECONDS,
  89                                    new LinkedBlockingQueue(),
  90                                    flakyThreadFactory);
  91         try {
  92             for (int i = 0; i < 8; i++)
  93                 pool.submit(new Runnable() { public void run() {} });
  94             check(exceptionClass == null);
  95         } catch (Throwable t) {
  96             /* t.printStackTrace(); */
  97             check(exceptionClass.isInstance(t));
  98         }
  99         pool.shutdown();
 100         check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 101     }
 102 
 103     //--------------------- Infrastructure ---------------------------
 104     volatile int passed = 0, failed = 0;
 105     void pass() {passed++;}
 106     void fail() {failed++; Thread.dumpStack();}
 107     void fail(String msg) {System.err.println(msg); fail();}
 108     void unexpected(Throwable t) {failed++; t.printStackTrace();}
 109     void check(boolean cond) {if (cond) pass(); else fail();}
 110     void equal(Object x, Object y) {
 111         if (x == null ? y == null : x.equals(y)) pass();
 112         else fail(x + " not equal to " + y);}
 113     public static void main(String[] args) throws Throwable {
 114         new FlakyThreadFactory().instanceMain(args);}
 115     public void instanceMain(String[] args) throws Throwable {
 116         try {test(args);} catch (Throwable t) {unexpected(t);}
 117         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 118         if (failed > 0) throw new AssertionError("Some tests failed");}
 119 }