1 /* 2 * Copyright (C) 2017 The Android Open Source Project 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.android.tradefed.util; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import org.junit.After; 25 import org.junit.Before; 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 import org.junit.runners.JUnit4; 29 30 import java.io.ByteArrayInputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.OutputStream; 34 35 /** 36 * Test cases for {@link ProcessHelper}. 37 */ 38 @RunWith(JUnit4.class) 39 public class ProcessHelperTest { 40 private ProcessHelper mProcessHelper; 41 42 /** 43 * Return a mock process. 44 */ createMockProcess( String stdout, String stderr, int exitValue, long executionTimeMsecs)45 private Process createMockProcess( 46 String stdout, String stderr, int exitValue, long executionTimeMsecs) { 47 // No need to close OutputStream and ByteArrayInputStream because doing so has no effect. 48 OutputStream stdinStream = new OutputStream() { 49 @Override 50 public void write(int b) throws IOException {} 51 }; 52 InputStream stdoutStream = new ByteArrayInputStream(stdout.getBytes()); 53 InputStream stderrStream = new ByteArrayInputStream(stderr.getBytes()); 54 long endTime = System.currentTimeMillis() + executionTimeMsecs; 55 56 return new Process() { 57 private boolean destroyed = false; 58 59 private boolean isRunning() { 60 return System.currentTimeMillis() <= endTime && !destroyed; 61 } 62 63 @Override 64 public void destroy() { 65 destroyed = true; 66 } 67 68 @Override 69 public int exitValue() { 70 if (isRunning()) { 71 throw new IllegalThreadStateException(); 72 } 73 return exitValue; 74 } 75 76 @Override 77 public InputStream getInputStream() { 78 return stdoutStream; 79 } 80 81 @Override 82 public OutputStream getOutputStream() { 83 return stdinStream; 84 } 85 86 @Override 87 public InputStream getErrorStream() { 88 return stderrStream; 89 } 90 91 @Override 92 public int waitFor() throws InterruptedException { 93 while (isRunning()) { 94 Thread.sleep(50); 95 } 96 return exitValue; 97 } 98 }; 99 } 100 101 /** 102 * Reset the ProcessHelper. 103 */ 104 @Before setUp()105 public void setUp() { 106 mProcessHelper = null; 107 } 108 109 /** 110 * Terminate the process, join threads and close IO streams. 111 */ 112 @After tearDown()113 public void tearDown() { 114 if (mProcessHelper != null) { 115 mProcessHelper.cleanUp(); 116 } 117 } 118 119 /** 120 * Test running a process that returns zero. 121 */ 122 @Test testSuccess()123 public void testSuccess() { 124 mProcessHelper = new ProcessHelper(createMockProcess("123\n", "456\n", 0, 10)); 125 CommandStatus status = mProcessHelper.waitForProcess(10000); 126 assertEquals(CommandStatus.SUCCESS, status); 127 assertFalse(mProcessHelper.isRunning()); 128 assertTrue(mProcessHelper.getStdout().equals("123\n")); 129 assertTrue(mProcessHelper.getStderr().equals("456\n")); 130 } 131 132 /** 133 * Test running a process that returns non-zero. 134 */ 135 @Test testFailure()136 public void testFailure() { 137 mProcessHelper = new ProcessHelper(createMockProcess("123\n", "456\n", 1, 10)); 138 CommandStatus status = mProcessHelper.waitForProcess(10000); 139 assertEquals(CommandStatus.FAILED, status); 140 assertFalse(mProcessHelper.isRunning()); 141 assertTrue(mProcessHelper.getStdout().equals("123\n")); 142 assertTrue(mProcessHelper.getStderr().equals("456\n")); 143 } 144 145 /** 146 * Test running a process that times out. 147 */ 148 @Test testTimeout()149 public void testTimeout() { 150 mProcessHelper = new ProcessHelper(createMockProcess("", "", 1, 10000)); 151 CommandStatus status = mProcessHelper.waitForProcess(100); 152 assertEquals(CommandStatus.TIMED_OUT, status); 153 assertTrue(mProcessHelper.isRunning()); 154 } 155 156 /** 157 * Test running a process and being interrupted. 158 */ 159 @Test testInterrupt()160 public void testInterrupt() throws InterruptedException { 161 mProcessHelper = new ProcessHelper(createMockProcess("", "", 1, 10000)); 162 IRunUtil runUtil = RunUtil.getDefault(); 163 Thread testThread = Thread.currentThread(); 164 165 Thread timer = new Thread() { 166 @Override 167 public void run() { 168 try { 169 Thread.sleep(50); 170 } catch (InterruptedException e) { 171 fail(); 172 } 173 runUtil.interrupt(testThread, "unit test"); 174 } 175 }; 176 177 runUtil.allowInterrupt(true); 178 timer.start(); 179 try { 180 mProcessHelper.waitForProcess(100); 181 fail(); 182 } catch (RunInterruptedException e) { 183 assertTrue(mProcessHelper.isRunning()); 184 } finally { 185 timer.join(1000); 186 } 187 } 188 } 189