/**
* Copyright (C) 2008 Progress Software, Inc. All rights reserved.
* http://fusesource.com
*
* The software in this package is published under the terms of the AGPL license
* a copy of which has been included with this distribution in the license.txt file.
*/
package org.fusesource.cloudmix.agent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import junit.framework.TestCase;
import com.sun.jna.Platform;
public class PidUtilsTest extends TestCase {
public void testGetPid() {
int pid = PidUtils.getPid();
assertTrue("Pid Utils should return a meaningful pid", pid > 0);
assertEquals("The pid should remain the same", pid, PidUtils.getPid());
}
public void testKillPid() throws IOException, InterruptedException, ExecutionException, TimeoutException {
// Launch the PidUtilsTestMain class as a child process.
String cp = getClassPathOf(PidUtilsTestMain.class);
final Process exec = Runtime.getRuntime().exec(new String[] {
"java", "-cp", cp, PidUtilsTestMain.class.getName()
});
new Thread() {
public void run() {
try {
InputStream is = exec.getErrorStream();
int c;
while ((c = is.read()) >= 0) {
System.err.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
} .start();
// Setup a thread to wait for the child's exit code.
FutureTask<Integer> exitCode = new FutureTask<Integer>(new Callable<Integer>() {
public Integer call() throws Exception {
return exec.waitFor();
}
});
new Thread(exitCode).start();
try {
exitCode.get(500, TimeUnit.MILLISECONDS);
System.out
.println("Cannot run the rest of the test.. could not execute the child process properly.");
return;
} catch (TimeoutException expected) {
//ignore
}
// The child will let us know it's pid.
BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
String line = reader.readLine();
int childPid = Integer.parseInt(line);
assertTrue(childPid > 0);
assertTrue(PidUtils.isPidRunning(childPid));
// Kill it..
PidUtils.killPid(childPid, 9, 5);
int rc = exitCode.get(3, TimeUnit.SECONDS);
if (Platform.isWindows()) {
// On windows we can actually say what the exit code should be.
assert rc == 5;
} else {
assertTrue(rc != 0);
}
assertFalse(PidUtils.isPidRunning(childPid));
}
/**
* Gives you back the classpath that you can use to load up the specified Class.
*
* @param clazz
* @return
*/
private String getClassPathOf(Class<? extends Object> clazz) {
List<String> path = new ArrayList<String>();
buildClassPath(path, clazz.getClassLoader());
StringBuilder rc = new StringBuilder();
boolean first = true;
for (String file : path) {
if (!first) {
rc.append(File.pathSeparator);
}
rc.append(file);
first = false;
}
return rc.toString();
}
/**
* Adds all the file paths in the provided ClassLoader into the provided ArrayList.
*
* @param path
* @param classLoader
*/
private void buildClassPath(List<String> path, ClassLoader classLoader) {
if (classLoader.getParent() != null) {
buildClassPath(path, classLoader.getParent());
}
if (classLoader instanceof URLClassLoader) {
URLClassLoader ulc = (URLClassLoader)classLoader;
URL[] urls = ulc.getURLs();
if (urls == null) {
return;
}
for (URL url : urls) {
if ("file".equals(url.getProtocol())) {
File f;
try {
f = new File(url.toURI());
} catch (URISyntaxException e) {
f = new File(url.getPath());
}
path.add(f.getAbsolutePath());
} else {
System.out.println("Unknown url: " + url);
}
}
} else {
System.out.println("Unknown cl: " + classLoader);
}
}
}