public boolean ok(String out, String reference) { try { File fo = File.createTempFile("homeworkeval", ".out"); File fr = File.createTempFile("homeworkeval", ".ref"); log.fine("Running custom validator."); save(out, fo); save(reference, fr); ArrayList<String> c = new ArrayList<String>(); c.add(command); c.add(fo.getPath()); c.add(fr.getPath()); ProcessBuilder pb = new ProcessBuilder(c); Process p = pb.start(); int rc = p.waitFor(); fo.delete(); fr.delete(); log.fine("Custom validator " + command + " says " + rc); return rc == 0; } catch (Exception e) { // Assume NOK. Don't propagate info to the client. log.finer("exc: " + UtilSrv.describe(e)); return false; } }
public int run(PbTest[] tests, int timelimit, int memlimit) throws ServerException { allStdout = new ArrayList<String>(); allStderr = new ArrayList<String>(); int correct = 0; for (int i = 0; i < tests.length; ++i) { try { exec(runCmd, tests[i].in, timelimit, memlimit); allStdout.add(stdout); allStderr.add(stderr); if (!stderr.isEmpty()) { log.fine("NOK, stderr: " + stderr); continue; } if (!validator.ok(stdout, tests[i].out)) continue; log.fine("OK"); ++correct; } catch (Exception e) { // Assume incorrect. Do NOT propagate anyhing from the exception to // the client, just put it in the log. log.finer("exc: " + UtilSrv.describe(e)); } } return correct; }
/** * Executes a command as {@code user}. Saves the stdout/stderr in the corresponding fields and * returns the return code of the child process. * * @param cmd The command to execute * @param data The data to send to the stdin of the process * @param timelimt How many seconds the command can run * @param memlimit How many megabytes the command can use */ private int exec(String cmdS, String data, int timelimit, int memlimit) throws Exception { ArrayList<String> cmd = new ArrayList<String>(cmdPrefix); cmd.add("-m"); cmd.add("" + memlimit); cmd.add("-c"); cmd.add("" + timelimit); cmd.add("-w"); cmd.add("" + (3 * timelimit + 1)); cmd.add("-x"); cmd.add(cmdS); String tmp = ""; for (String cs : cmd) tmp += " \"" + cs + "\""; log.fine("exec " + tmp); ProcessBuilder pb = new ProcessBuilder(cmd); pb.directory(workDir); Process p = pb.start(); OutputStreamWriter writer = new OutputStreamWriter(p.getOutputStream()); StreamReader rOut = new StreamReader(p.getInputStream()); StreamReader rErr = new StreamReader(p.getErrorStream()); rOut.start(); rErr.start(); // TODO I think this may block for big tests. Check and Fix. // send and receive data "in parallel" writer.write(data); writer.flush(); writer.close(); rOut.join(); rErr.join(); stdout = rOut.result; stderr = rErr.result; if (rOut.exception != null) throw rOut.exception; if (rErr.exception != null) throw rErr.exception; // log.finer("out: " + stdout); // log.finer("err: " + stderr); // log.finer("done exec"); return p.waitFor(); }
public String[] getErr() { return allStderr.toArray(new String[0]); }
public String[] getOut() { return allStdout.toArray(new String[0]); }