1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @run testng AsyncShutdownNowInvokeAny
  27  * @summary A variant of AsyncShutdownNow useful for race bug hunting
  28  */
  29 
  30 // TODO: reorganize all of the AsyncShutdown tests
  31 
  32 import java.util.List;
  33 import java.util.concurrent.Callable;
  34 import java.util.concurrent.ExecutionException;
  35 import java.util.concurrent.ExecutorService;
  36 import java.util.concurrent.Executors;
  37 import java.util.concurrent.ForkJoinPool;
  38 import java.util.concurrent.Future;
  39 import java.util.concurrent.ScheduledExecutorService;
  40 import java.util.concurrent.TimeUnit;
  41 
  42 import org.testng.annotations.AfterClass;
  43 import org.testng.annotations.BeforeClass;
  44 import org.testng.annotations.Test;
  45 import static org.testng.Assert.*;
  46 
  47 public class AsyncShutdownNowInvokeAny {
  48 
  49     // long running interruptible task
  50     private static final Callable<Void> SLEEP_FOR_A_DAY = () -> {
  51         Thread.sleep(86400_000);
  52         return null;
  53     };
  54 
  55     private ScheduledExecutorService scheduledExecutor;
  56 
  57     @BeforeClass
  58     public void setup() {
  59         scheduledExecutor = Executors.newScheduledThreadPool(1);
  60     }
  61 
  62     @AfterClass
  63     public void teardown() {
  64         scheduledExecutor.shutdown();
  65     }
  66 
  67     /**
  68      * Schedule the given executor service to be shutdown abruptly after the given
  69      * delay, in seconds.
  70      */
  71     private void scheduleShutdownNow(ExecutorService executor, int delayInSeconds) {
  72         scheduledExecutor.schedule(() -> {
  73             executor.shutdownNow();
  74             return null;
  75         }, delayInSeconds, TimeUnit.SECONDS);
  76     }
  77 
  78     /**
  79      * Test shutdownNow with thread blocked in invokeAny.
  80      */
  81     @Test
  82     public void testInvokeAny() throws Exception {
  83         final int reps = 4;
  84         for (int rep = 1; rep < reps; rep++) {
  85             ExecutorService pool = new ForkJoinPool(1);
  86             scheduleShutdownNow(pool, 5);
  87             try {
  88                 try {
  89                     // execute long running tasks
  90                     pool.invokeAny(List.of(SLEEP_FOR_A_DAY, SLEEP_FOR_A_DAY));
  91                     assertTrue(false);
  92                 } catch (ExecutionException e) {
  93                     // expected
  94                 }
  95             } finally {
  96                 pool.shutdown();
  97             }
  98         }
  99     }
 100 }