/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.test.shell.harness; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.Properties; /** * This TestRunner runs a script. Typically the first line of the script will * be a "#!" line that says what interpreter to use. * * @author crawley@jnode.org */ class ScriptTestRunner extends TestRunnerBase implements TestRunnable { private File tempScriptFile; public ScriptTestRunner(TestSpecification spec, TestHarness harness) { super(spec, harness); } @Override public int run() throws Exception { Properties props = new Properties(); File tempDir = harness.tempDir(); props.setProperty("TEMP_DIR", tempDir.getAbsolutePath()); // (We don't put the script file in the @TEMP_DIR@ because it may interfere with // the running of testcases.) tempScriptFile = new File(System.getProperty("java.io.tmpdir"), spec.getCommand()); BufferedWriter bw = null; try { bw = new BufferedWriter(new FileWriter(tempScriptFile)); expand(props, spec.getScriptContent().toString(), bw, '@'); bw.write('\n'); } finally { bw.close(); } int rc; try { rc = getShell().runCommandFile(tempScriptFile, spec.getCommand(), spec.getArgs().toArray(new String[0])); } catch (Throwable ex) { Class<? extends Throwable> exception = spec.getException(); if (exception != null && exception.isInstance(ex)) { rc = 0; } else if (ex instanceof Error) { throw (Error) ex; } else { throw (Exception) ex; } } flush(); return check(rc) ? 0 : 1; } private boolean check(int rc) throws IOException { return harness.expect(rc, spec.getRc(), "return code") & harness.expect(outBucket.toString(), spec.getOutputContent(), "output content") & harness.expect(errBucket.toString(), spec.getErrorContent(), "err content") & checkFiles(); } @Override public void cleanup() { if (tempScriptFile != null) { tempScriptFile.delete(); } super.cleanup(); } /** * Expand a '@...@' sequences in a template, writing the result to an * Writer. A sequence '@@' turns into a single '@'. A sequence * '@name@' expands to the value of the named property if it is defined in * the property set, or the sequence '@name@' if it does not. A CR, NL or * EOF in an '@...@' sequence is an error. * * @param props the properties to be expanded * @param template is the template string * @param w the sink for the expanded template * @param marker the sequence marker character(defaults to '@') * @throws IOException * @throws TestSpecificationException */ private void expand(Properties props, String template, BufferedWriter w, char marker) throws IOException, TestSpecificationException { int ch; Reader r = new StringReader(template); while ((ch = r.read()) != -1) { if (ch == marker) { StringBuffer sb = new StringBuffer(20); while ((ch = r.read()) != marker) { switch (ch) { case -1: throw new TestSpecificationException("Encountered EOF in a " + marker + "..." + marker + " sequence in script template"); case '\n': throw new TestSpecificationException("Encountered newline in a " + marker + "..." + marker + " sequence in script template"); default: sb.append((char) ch); } } if (sb.length() == 0) { w.write(marker); } else { String name = sb.toString(); String value = props.getProperty(name); if (value == null) { w.write(marker); w.write(sb.toString().toCharArray()); w.write(marker); } else { w.write(value.toCharArray()); } } } else { w.write((char) ch); } } } }