Emberveil sourcetests/ClientCloseCheck.java
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.nio.file.*;
import java.util.concurrent.*;
public final class ClientCloseCheck {
static final Path proof=Paths.get("runtime/client-close-check.txt");
static class Fixture extends RSApplet {
@Override void cleanUpForQuit(){try{Files.write(proof,"cleanup completed".getBytes("UTF-8"),StandardOpenOption.APPEND);Thread.sleep(300);}catch(Exception e){throw new RuntimeException(e);}}
}
public static void main(String[] args)throws Exception {
if(args.length>0) {
Fixture app=new Fixture();app.myWidth=765;app.myHeight=503;app.setPreferredSize(new Dimension(765,503));app.gameFrame=new RSFrame(app);
EventQueue.invokeAndWait(()->{long start=System.nanoTime();app.windowClosing(new WindowEvent(app.gameFrame,WindowEvent.WINDOW_CLOSING));long millis=TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-start);
try{Files.write(proof,("windowHidden="+!app.gameFrame.isVisible()+" eventMillis="+millis+"\n").getBytes("UTF-8"));}catch(Exception e){throw new RuntimeException(e);}
if(millis>300)throw new AssertionError("close event blocked interface");
});
EventQueue.invokeAndWait(()->{try{Files.write(proof,"interface responsive\n".getBytes("UTF-8"),StandardOpenOption.APPEND);}catch(Exception e){throw new RuntimeException(e);}});
return;
}
Files.deleteIfExists(proof);
Process p=new ProcessBuilder(System.getProperty("java.home")+"/bin/java","-cp",System.getProperty("java.class.path"),"ClientCloseCheck","child").inheritIO().start();
if(!p.waitFor(8,TimeUnit.SECONDS)){p.destroy();throw new AssertionError("client did not exit after cleanup");}
String text=new String(Files.readAllBytes(proof),"UTF-8");
if(p.exitValue()!=0||!text.contains("windowHidden=true")||!text.contains("interface responsive")||!text.contains("cleanup completed"))throw new AssertionError(text);
System.out.println("PASS immediate window hiding, responsive interface and completed shutdown: "+text.replace('\n',' '));
}
}