In my Cucumber-jvm scripts, I need to run an external jar program before each script, interact with it using the FEST library in steps, and finally close the program to clear the slate for the next script. For a specific external program that I need, should be used System.exit()to close when closing. In turn, I can’t just exit the program in my tests, as this would end the entire virtual machine. Instead, I use the custom SecurityManager built into FEST to override the call System.exit(). However, I cannot get it to work correctly.
The code in example 1 below tries to start an external program in the Cucumber hook @Beforeand disable it in @After. It works fine with one scenario when I run mvn verify. However, in two or more scenarios, maven just hangs on the lines:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running test.acceptance.CucumberRunner
After that, nothing happens. I see that the external program starts and closes once, but the second time its launch does not close. When I close it manually, maven displays the following:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-
plugin:2.16:integration-test (default) on project acceptance-tests: Execution default of
goal org.apache.maven.plugins:maven-failsafe-plugin:2.16:integration-test failed: The
forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
- , ? , , - , NoExitSecurityManagerInstaller, . , , System.exit, . - , , , . ?
- !
, Robot, WindowFinder, cleanUp, : " (, , {@link ScreenLock}), .". frame.close(), , ! SecurityManager.
, BasicRobot.robotWithCurrentAwtHierarchy() , frame.close(). , BasicRobot.robotWithCurrentAwtHierarchy() /, , , . , robot.cleanUp ( ). , frame.close , , .
1
public class CucumberHooks {
private FrameFixture frame;
@Before
public void setup() throws InterruptedException, IOException {
Thread t = new Thread(new Runnable() {
public void run() {
File file = new File(System.getProperty("external-jar"));
URLClassLoader cl = null;
try {
cl = new URLClassLoader( new URL[]{file.toURI().toURL()} );
}
catch (MalformedURLException e) {}
Class<?> clazz = null;
try {
clazz = cl.loadClass("MainClass");
}
catch (ClassNotFoundException e) {}
Method main = null;
try {
main = clazz.getMethod("main", String[].class);
}
catch (NoSuchMethodException e) {}
try {
main.invoke(null, new Object[]{new String[]{}});
}
catch (Exception e) {}
}
});
t.start();
GenericTypeMatcher<JFrame> matcher = new GenericTypeMatcher<JFrame>(JFrame.class) {
protected boolean isMatching(JFrame frame) {
return "External Jar Title".equals(frame.getTitle()) && frame.isShowing();
}
};
frame = WindowFinder.findFrame(matcher).using(BasicRobot.robotWithCurrentAwtHierarchy());
}
@After
public void shutDown() throws InterruptedException {
NoExitSecurityManagerInstaller i = NoExitSecurityManagerInstaller.installNoExitSecurityManager();
frame.close();
i.uninstall();
}
}
2
public class CucumberHooks {
private FrameFixture frame;
private Robot robot;
@Before
public void setup() throws InterruptedException, IOException {
Thread t = new Thread(new Runnable() {
public void run() {
File file = new File(System.getProperty("external-jar"));
URLClassLoader cl = null;
try {
cl = new URLClassLoader( new URL[]{file.toURI().toURL()} );
}
catch (MalformedURLException e) {}
Class<?> clazz = null;
try {
clazz = cl.loadClass("MainClass");
}
catch (ClassNotFoundException e) {}
Method main = null;
try {
main = clazz.getMethod("main", String[].class);
}
catch (NoSuchMethodException e) {}
try {
main.invoke(null, new Object[]{new String[]{}});
}
catch (Exception e) {}
}
});
t.start();
GenericTypeMatcher<JFrame> matcher = new GenericTypeMatcher<JFrame>(JFrame.class) {
protected boolean isMatching(JFrame frame) {
return "External Jar Title".equals(frame.getTitle()) && frame.isShowing();
}
};
robot = BasicRobot.robotWithCurrentAwtHierarchy();
frame = WindowFinder.findFrame(matcher).using(robot);
}
@After
public void shutDown() {
robot.cleanUp();
}
}