blob: 6ef991584381f15b872a2d04f193c003b37d7948 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.shell;
15
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000016import static org.junit.Assert.assertFalse;
17import static org.junit.Assert.assertTrue;
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000018
19import org.junit.After;
20import org.junit.Before;
21import org.junit.Test;
22import org.junit.runner.RunWith;
23import org.junit.runners.JUnit4;
24
25/**
26 * Tests of the interaction of Thread.interrupt and Command.execute.
27 *
Philipp Wollermann28f08f12015-09-21 13:42:01 +000028 * Read http://www.ibm.com/developerworks/java/library/j-jtp05236/
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000029 * for background material.
30 *
31 * NOTE: This test is dependent on thread timings. Under extreme machine load
32 * it's possible that this test could fail spuriously or intermittently. In
33 * that case, adjust the timing constants to increase the tolerance.
34 */
35@RunWith(JUnit4.class)
36public class InterruptibleTest {
37
38 private final Thread mainThread = Thread.currentThread();
39
40 // Interrupt main thread after 1 second. Hopefully by then /bin/sleep
41 // should be running.
42 private final Thread interrupter = new Thread() {
43 @Override
44 public void run() {
45 try {
46 Thread.sleep(1000); // 1 sec
47 } catch (InterruptedException e) {
48 throw new IllegalStateException("Unexpected interrupt!");
49 }
50 mainThread.interrupt();
51 }
52 };
53
54 private Command command;
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000055
Florian Weikert2c71a822015-12-02 17:22:38 +000056 @Before
57 public final void startInterrupter() throws Exception {
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000058 Thread.interrupted(); // side effect: clear interrupted status
59 assertFalse("Unexpected interruption!", mainThread.isInterrupted());
60
Han-Wen Nienhuys8c8be382015-03-05 15:28:18 +000061 // We interrupt after 1 sec, so this gives us plenty of time for the library to notice the
62 // subprocess exit.
63 this.command = new Command(new String[] { "/bin/sleep", "20" });
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000064
65 interrupter.start();
66 }
67
68 @After
Florian Weikert2c71a822015-12-02 17:22:38 +000069 public final void waitForInterrupter() throws Exception {
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000070 interrupter.join();
71 Thread.interrupted(); // Clear interrupted status, or else other tests may fail.
72 }
73
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000074 /**
75 * Test that interrupting a thread in an "uninterruptible" Command.execute
76 * preserves the thread's interruptible status, and does not terminate the
77 * subprocess.
78 */
79 @Test
80 public void testUninterruptibleCommandRunsToCompletion() throws Exception {
81 command.execute();
82
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000083 // The interrupter thread should have exited about 1000ms ago.
84 assertFalse("Interrupter thread is still alive!",
85 interrupter.isAlive());
86
87 // The interrupter thread should have set the main thread's interrupt flag.
88 assertTrue("Main thread was not interrupted during command execution!",
89 mainThread.isInterrupted());
90 }
Han-Wen Nienhuysb0e387b2015-02-12 13:27:06 +000091}