]> mj.ucw.cz Git - moe.git/commitdiff
Added interactive testing.
authorMartin Mares <mj@ucw.cz>
Sun, 3 Jun 2001 20:35:19 +0000 (20:35 +0000)
committerMartin Mares <mj@ucw.cz>
Sun, 3 Jun 2001 20:35:19 +0000 (20:35 +0000)
Makefile
TODO
bin/lib
config
src/iwrapper.c [new file with mode: 0644]

index 9d2b0e2dabeacb7a20e907934ce0adbe4ae17733..6681c0f66cea1433cb8d550810fd519fe8dd569f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,14 @@
 #DEBUG=-ggdb
 CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Winline $(DEBUG)
 
-all: bin/box
+all: bin/box bin/iwrapper
 
 bin/box: src/box.o
        $(CC) $(LDFLAGS) -o $@ $<
 
+bin/iwrapper: src/iwrapper.o
+       $(CC) $(LDFLAGS) -o $@ $<
+
 clean:
        rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core`
-       rm -f bin/box
+       rm -f bin/box bin/iwrapper
diff --git a/TODO b/TODO
index c20c4267d5594cd5f6b76311c2b462a62bf5c10c..7187e09574d4b40cd2a694dbe382fbe980bfacb6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,6 +3,9 @@ Evaluator
 mo-install: don't copy private test data to public
 lepsi time limity
 zkopirovat *.ok i kdyz program spadne na run-time error
+submit: do real test?
+
+giant: sample input?
 
 Environment
 ~~~~~~~~~~~
diff --git a/bin/lib b/bin/lib
index aa7b4cfff04b88da71420a6d4910033cd0c1fe08..ccb0b9cf6eeccd2f673a080f3306b9e0915a6f7e 100644 (file)
--- a/bin/lib
+++ b/bin/lib
@@ -151,9 +151,16 @@ function compile
        pend "OK"
 }
 
-# Running of test program with file input/output
+# Running of test program according to current task type
 
 function test-run
+{
+       test-run-$TASK_TYPE
+}
+
+# Running of test program with file input/output
+
+function test-run-file
 {
        pcont "<init> "
        box-clean
@@ -190,6 +197,38 @@ function test-run
        cp $BOXDIR/$PROBLEM.out $TDIR/$TEST.out
 }
 
+# Running of interactive test programs
+
+function test-run-interactive
+{
+       pcont "<init> "
+       box-clean
+       echo "Executable file: $TDIR/$PROBLEM"
+       cp $TDIR/$PROBLEM $BOXDIR/
+       echo "Input: $TDIR/$PROBLEM"
+       ln $PDIR/$TEST.in $TDIR/$TEST.in
+       cp $PDIR/$TEST.in $BOXDIR/$PROBLEM.in
+       echo "Input files:"
+       ls -Al $BOXDIR
+
+       pcont "<run> "
+       echo "Timeout: $TIME_LIMIT s"
+       echo "Memory: $MEM_LIMIT KB"
+       BOXOPTS="`eval echo $TEST_SANDBOX_OPTS`"
+       echo "Sandbox options: $BOXOPTS"
+       ICCMD="`eval echo $IA_CHECK`"
+       echo "Interactive checker: $ICCMD"
+       if ! bin/iwrapper $BOXCMD $BOXOPTS -- ./$PROBLEM @@ $ICCMD 2>$TDIR/exec.out ; then
+               TEST_MSG="`cat $TDIR/exec.out`"
+               pend "$TEST_MSG"
+               echo "$TEST_MSG"
+               echo >>$PTSFILE "0 $TEST_MSG"
+               return 1
+       fi
+       cat $TDIR/exec.out
+       rm $TDIR/exec.out
+}
+
 # Syntax checks
 
 function syntax-check
@@ -209,6 +248,7 @@ function syntax-check
 
 function output-check
 {
+       [ -n "$OUTPUT_CHECK" ] || return 0
        pcont "<check> "
        ln $PDIR/$TEST.out $TDIR/$TEST.ok
        OCHECK="`eval echo $OUTPUT_CHECK`"
diff --git a/config b/config
index 50ed7005c1df0757ba2de50d239bedefdfacfdd5..84bf889b68dce056625b86d0eef75c4d1c78bc61 100644 (file)
--- a/config
+++ b/config
@@ -16,6 +16,9 @@ TEST_USER=${TEST_USER:mo-test1}
 
 ### all of the following variables can be overriden in per-task config file
 
+# Default task type (file or interactive)
+TASK_TYPE=file
+
 # Known source file extensions
 EXTENSIONS="c C cpp p pas"
 
diff --git a/src/iwrapper.c b/src/iwrapper.c
new file mode 100644 (file)
index 0000000..19435e8
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *     A Wrapper for Interactive Tests
+ *
+ *     (c) 2001 Martin Mares <mj@ucw.cz>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <time.h>
+#include <sys/wait.h>
+#include <sys/user.h>
+#include <sys/time.h>
+#include <sys/ptrace.h>
+#include <sys/signal.h>
+#include <sys/sysinfo.h>
+#include <sys/syscall.h>
+#include <sys/resource.h>
+
+#define NONRET __attribute__((noreturn))
+#define UNUSED __attribute__((unused))
+
+static void NONRET __attribute__((format(printf,1,2)))
+die(char *msg, ...)
+{
+  va_list args;
+  va_start(args, msg);
+  vfprintf(stderr, msg, args);
+  fputc('\n', stderr);
+  exit(1);
+}
+
+static void
+copy(int fd)
+{
+  char buf[4096];
+  int c;
+
+  while (c = read(fd, buf, sizeof(buf)))
+    write(2, buf, c);
+}
+
+int
+main(int argc, char **argv)
+{
+  int sep, nbox, nchk;
+  char **abox, **achk;
+  pid_t pbox, pchk;
+  int inpipe[2], outpipe[2], boxepipe[2], chkepipe[2];
+  int exited = 0, sbox, schk;
+
+  for (sep=1; sep < argc; sep++)
+    if (!strcmp(argv[sep], "@@"))
+      break;
+  if (sep >= argc - 1)
+    die("Usage: iwrapper <testee> @@ <tester>");
+  nbox = sep - 1;
+  abox = alloca((nbox+1) * sizeof(char *));
+  memcpy(abox, argv+1, nbox*sizeof(char *));
+  abox[nbox] = NULL;
+  nchk = argc - sep - 1;
+  achk = alloca((nchk+1) * sizeof(char *));
+  memcpy(achk, argv+sep+1, nchk*sizeof(char *));
+  achk[nchk] = NULL;
+
+  if (pipe(inpipe) < 0 ||
+      pipe(outpipe) < 0 ||
+      pipe(boxepipe) < 0 ||
+      pipe(chkepipe) < 0)
+    die("pipe: %m");
+
+  pbox = fork();
+  if (pbox < 0)
+    die("fork: %m");
+  if (!pbox)
+    {
+      close(inpipe[1]);
+      close(0);
+      dup(inpipe[0]);
+      close(inpipe[0]);
+      close(outpipe[0]);
+      close(1);
+      dup(outpipe[1]);
+      close(outpipe[1]);
+      close(boxepipe[0]);
+      close(2);
+      dup(boxepipe[1]);
+      close(boxepipe[1]);
+      close(chkepipe[0]);
+      close(chkepipe[1]);
+      execv(abox[0], abox);
+      die("exec: %m");
+    }
+
+  pchk = fork();
+  if (pchk < 0)
+    die("fork: %m");
+  if (!pchk)
+    {
+      close(inpipe[0]);
+      close(1);
+      dup(inpipe[1]);
+      close(inpipe[1]);
+      close(outpipe[1]);
+      close(0);
+      dup(outpipe[0]);
+      close(outpipe[0]);
+      close(chkepipe[0]);
+      close(2);
+      dup(chkepipe[1]);
+      close(chkepipe[1]);
+      close(boxepipe[0]);
+      close(boxepipe[1]);
+      execv(achk[0], achk);
+      die("exec: %m");
+    }
+
+  close(inpipe[0]);
+  close(inpipe[1]);
+  close(outpipe[0]);
+  close(outpipe[1]);
+  close(chkepipe[1]);
+  close(boxepipe[1]);
+
+  sbox = schk = 0;
+  while (exited != 3)
+    {
+      int st;
+      pid_t p = wait(&st);
+      if (p < 0)
+       die("wait: %m");
+      if (p == pbox)
+       {
+         exited |= 1;
+         sbox = st;
+       }
+      else if (p == pchk)
+       {
+         exited |= 2;
+         schk = st;
+       }
+      else
+       die("Unknown process %d died", p);
+    }
+
+  if (!WIFEXITED(sbox))
+    die("Sandbox fault, status=%x", sbox);
+  if (!WIFEXITED(schk))
+    die("Checker fault, status=%x", schk);
+  if (WEXITSTATUS(sbox))
+    {
+      copy(boxepipe[0]);
+      return 1;
+    }
+  else if (WEXITSTATUS(schk))
+    {
+      copy(chkepipe[0]);
+      return 1;
+    }
+  copy(boxepipe[0]);
+  return 0;
+}