# HG changeset patch # User Jiri Vanek # Date 1333623137 -7200 # Node ID 79b3ded39c1f10ffa2b9aa70cb7b573f8cad9d5b # Parent 9c0e0aec8ac8d93af063575ba57cdbcbab238b6b fixed bugs in jnlp testing engine diff -r 9c0e0aec8ac8 -r 79b3ded39c1f ChangeLog --- a/ChangeLog Mon Apr 02 11:26:17 2012 -0400 +++ b/ChangeLog Thu Apr 05 12:52:17 2012 +0200 @@ -1,3 +1,20 @@ +2012-04-05 Jiri Vanek + + Fixing issue when process was not launched at all and when was killed but + left behind living/hanging, fixing mime-types + * tests/netx/jnlp_testsengine/net/sourceforge/jnlp/ServerAccess.java: + (getContentOfStream) this method overloaded with possibility to specify + encoding (I needed to set it to ASCII in one test) + (deadlyException) field introduced in ThreadedProcess to record exception + caused by impassibility of launching the process. And so process have + been null without any sign why. + (TinyHttpdImpl) now correctly returns known mime types + (ProcessAssasin) can now skip or smoothly (and finally correctly) + destroy its process, and all his logging messages were done null-proof + (as deadlyException now allows) + Asynchronous (ContentReader) have been silenced when complaining about + closed streams by Assassin. + 2012-03-30 Danesh Dadachanji Certificate start dates are not being checked, they are still verified diff -r 9c0e0aec8ac8 -r 79b3ded39c1f tests/netx/jnlp_testsengine/net/sourceforge/jnlp/ServerAccess.java --- a/tests/netx/jnlp_testsengine/net/sourceforge/jnlp/ServerAccess.java Mon Apr 02 11:26:17 2012 -0400 +++ b/tests/netx/jnlp_testsengine/net/sourceforge/jnlp/ServerAccess.java Thu Apr 05 12:52:17 2012 +0200 @@ -209,7 +209,7 @@ @Test public void testsProcessResultFiltering() throws Exception { - ProcessResult pn = new ProcessResult(null, null, null, true, 0); + ProcessResult pn = new ProcessResult(null, null, null, true, 0, null); Assert.assertNull(pn.notFilteredStdout); Assert.assertNull(pn.stdout); Assert.assertNull(pn.stderr); @@ -228,12 +228,12 @@ "test stage 1\n" + "test stage 2\n" + "test stage 3\n"; - ProcessResult p2 = new ProcessResult(fakeOut2, fakeOut2, null, true, 0); + ProcessResult p2 = new ProcessResult(fakeOut2, fakeOut2, null, true, 0, null); Assert.assertEquals(p2.notFilteredStdout, fakeOut2); Assert.assertEquals(p2.stdout, filteredOut2); Assert.assertEquals(p2.stderr, fakeOut2); fakeOut2+="\n"; - p2 = new ProcessResult(fakeOut2, fakeOut2, null, true, 0); + p2 = new ProcessResult(fakeOut2, fakeOut2, null, true, 0, null); Assert.assertEquals(p2.notFilteredStdout, fakeOut2); Assert.assertEquals(p2.stdout, filteredOut2); Assert.assertEquals(p2.stderr, fakeOut2); @@ -255,13 +255,13 @@ + "test stage 2\n" + "test stage 3\n" + "test ends"; - ProcessResult p = new ProcessResult(fakeOut, fakeOut, null, true, 0); + ProcessResult p = new ProcessResult(fakeOut, fakeOut, null, true, 0, null); Assert.assertEquals(p.notFilteredStdout, fakeOut); Assert.assertEquals(p.stdout, filteredOut); Assert.assertEquals(p.stderr, fakeOut); fakeOut+="\n"; filteredOut+="\n"; - p = new ProcessResult(fakeOut, fakeOut, null, true, 0); + p = new ProcessResult(fakeOut, fakeOut, null, true, 0, null); Assert.assertEquals(p.notFilteredStdout, fakeOut); Assert.assertEquals(p.stdout, filteredOut); Assert.assertEquals(p.stderr, fakeOut); @@ -421,9 +421,9 @@ * @return stream as string * @throws IOException if connection cant be established or resource do not exists */ - public static String getContentOfStream(InputStream is) throws IOException { + public static String getContentOfStream(InputStream is,String encoding) throws IOException { try { - BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8")); + BufferedReader br = new BufferedReader(new InputStreamReader(is, encoding)); StringBuilder sb = new StringBuilder(); while (true) { String s = br.readLine(); @@ -441,6 +441,18 @@ } /** + * utility method which can read from any stream as one long String + * + * @param input stream + * @return stream as string + * @throws IOException if connection cant be established or resource do not exists + */ + public static String getContentOfStream(InputStream is) throws IOException { + return getContentOfStream(is, "UTF-8"); + + } + + /** * utility method which can read bytes of resource from any url * * @param resource to be located on any url @@ -601,9 +613,13 @@ ProcessAssasin pa = new ProcessAssasin(t, PROCESS_TIMEOUT); pa.start(); t.start(); - while (t.getP() == null) { + while (t.getP() == null && t.deadlyException == null) { Thread.sleep(100); } + if (t.deadlyException != null) { + pa.setCanRun(false); + return new ProcessResult("", "", null, true, Integer.MIN_VALUE, t.deadlyException); + } ContentReader crs = new ContentReader(t.getP().getInputStream()); ContentReader cre = new ContentReader(t.getP().getErrorStream()); @@ -617,10 +633,14 @@ while (t.isRunning()) { Thread.sleep(100); } + + while (!t.isDestoyed()) { + Thread.sleep(100); + } pa.setCanRun(false); // System.out.println(t.getP().exitValue()); when process is killed, this throws exception - return new ProcessResult(crs.getContent(), cre.getContent(), t.getP(), pa.wasTerminated(), t.getExitCode()); + return new ProcessResult(crs.getContent(), cre.getContent(), t.getP(), pa.wasTerminated(), t.getExitCode(), null); } /** @@ -635,6 +655,20 @@ Integer exitCode; Boolean running; File dir; + Throwable deadlyException = null; + /* + * before removing this "useless" variable + * check DeadLockTestTest.testDeadLockTestTerminated2 + */ + private boolean destoyed = false; + + public boolean isDestoyed() { + return destoyed; + } + + public void setDestoyed(boolean destoyed) { + this.destoyed = destoyed; + } public Boolean isRunning() { return running; @@ -683,12 +717,21 @@ }else{ p = r.exec(args.toArray(new String[0]),new String[0], dir); } - exitCode = p.waitFor(); + try { + exitCode = p.waitFor(); + Thread.sleep(500);//this is giving to fastly done proecesses's e/o readers time to read all. I would like to know better solution :-/ + } finally { + destoyed = true; + } } catch (Exception ex) { if (ex instanceof InterruptedException) { //add to the set of terminated threadedproceses + deadlyException = ex; terminated.add(this); } else { + //happens when nonexisting process is launched, is causing p null! + terminated.add(this); + deadlyException = ex; throw new RuntimeException(ex); } } finally { @@ -828,8 +871,17 @@ byte[] b = new byte[l]; FileInputStream f = new FileInputStream(pp); f.read(b); + String content = ""; + String ct = "Content-Type: "; + if (p.toLowerCase().endsWith(".jnlp")) { + content = ct + "application/x-java-jnlp-file\n"; + } else if (p.toLowerCase().endsWith(".html")) { + content = ct + "text/html\n"; + } else if (p.toLowerCase().endsWith(".jar")) { + content = ct + "application/x-jar\n"; + } o.writeBytes("HTTP/1.0 200 OK\nConten" - + "t-Length:" + l + "\n\n"); + + "t-Length:" + l + "\n" + content + "\n"); o.write(b, 0, l); } } @@ -855,6 +907,13 @@ //false == is disabled:( private boolean canRun = true; private boolean wasTerminated = false; + /** + * if this is true, then process is not destroyed after timeout, but just left to its own destiny. + * Its stdout/err is no longer recorded, and it is leaking system resources until it dies by itself + * The contorl is returned to main thread with all informations recorded untill now. + * You will be able to listen to std out from listeners still + */ + private boolean skipInstedOfDesroy = false; /** * @@ -868,9 +927,25 @@ } + public ProcessAssasin(ThreadedProcess p, long timeout, boolean skipInstedOfDesroy) { + this.p = (p); + this.timeout = timeout; + this.skipInstedOfDesroy = skipInstedOfDesroy; + + + } + public void setCanRun(boolean canRun) { this.canRun = canRun; - System.err.println("Stopping assasin for" + p.toString() + " " + p.getP().toString() + " " + p.getCommandLine() + ": "); + if (p != null) { + if (p.getP() != null) { + System.err.println("Stopping assassin for" + p.toString() + " " + p.getP().toString() + " " + p.getCommandLine() + ": "); + } else { + System.err.println("Stopping assassin for" + p.toString() + " " + p.getCommandLine() + ": "); + } + } else { + System.err.println("Stopping assassin for null job: "); + } System.err.flush(); } @@ -882,6 +957,14 @@ return wasTerminated; } + public void setSkipInstedOfDesroy(boolean skipInstedOfDesroy) { + this.skipInstedOfDesroy = skipInstedOfDesroy; + } + + public boolean isSkipInstedOfDesroy() { + return skipInstedOfDesroy; + } + @Override public void run() { @@ -893,16 +976,44 @@ //System.out.println(time - startTime); //System.out.println((time - startTime) > timeout); if ((time - startTime) > timeout) { - System.err.println("Timeouted " + p.toString() + " " + p.getP().toString() + " .. killing " + p.getCommandLine() + ": "); - System.err.flush(); - wasTerminated = true; - p.interrupt(); - while (!terminated.contains(p)) { - Thread.sleep(100); + try { + if (p != null) { + if (p.getP() != null) { + System.err.println("Timed out " + p.toString() + " " + p.getP().toString() + " .. killing " + p.getCommandLine() + ": "); + } else { + System.err.println("Timed out " + p.toString() + " " + "null .. killing " + p.getCommandLine() + ": "); + } + System.err.flush(); + wasTerminated = true; + p.interrupt(); + while (!terminated.contains(p)) { + Thread.sleep(100); + } + if (p.getP() != null) { + try { + if (!skipInstedOfDesroy) { + p.getP().destroy(); + } + } catch (Throwable ex) { + if (p.deadlyException == null) { + p.deadlyException = ex; + } + ex.printStackTrace(); + } + } + if (p.getP() != null) { + System.err.println("Timed out " + p.toString() + " " + p.getP().toString() + " .. killed " + p.getCommandLine()); + } else { + System.err.println("Timed out " + p.toString() + " null .. killed " + p.getCommandLine()); + } + System.err.flush(); + } else { + System.err.println("Timed out null job"); + } + break; + } finally { + p.setDestoyed(true); } - System.err.println("Timeouted " + p.toString() + " " + p.getP().toString() + " .. killed " + p.getCommandLine()); - System.err.flush(); - break; } @@ -911,7 +1022,15 @@ ex.printStackTrace(); } } - System.err.println("assasin for" + p.toString() + " " + p.getP().toString() + " .. done " + p.getCommandLine() + " termination " + wasTerminated); + if (p != null) { + if (p.getP() != null) { + System.err.println("assassin for" + p.toString() + " " + p.getP().toString() + " .. done " + p.getCommandLine() + " termination " + wasTerminated); + } else { + System.err.println("assassin for" + p.toString() + " null .. done " + p.getCommandLine() + " termination " + wasTerminated); + } + } else { + System.err.println("assassin for non exisitng job termination " + wasTerminated); + } System.err.flush(); } } @@ -927,8 +1046,12 @@ public final Process process; public final Integer returnValue; public final boolean wasTerminated; + /* + * possible exception which caused Process not to be launched + */ + public final Throwable deadlyException; - public ProcessResult(String stdout, String stderr, Process process, boolean wasTerminated, Integer r) { + public ProcessResult(String stdout, String stderr, Process process, boolean wasTerminated, Integer r, Throwable deadlyException) { this.notFilteredStdout = stdout; if (stdout == null) { this.stdout = null; @@ -939,6 +1062,7 @@ this.process = process; this.wasTerminated = wasTerminated; this.returnValue = r; + this.deadlyException = deadlyException; } } @@ -991,8 +1115,10 @@ } //do not want to bother output with terminations + //mostly compaling when assassin kill the process about StreamClosed } catch (Exception ex) { - //ex.printStackTrace(); + // ex.printStackTrace(); + // System.err.flush(); } finally { try { is.close();