Harness2.java 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package au.pfip;
  2. import com.sun.net.httpserver.HttpServer;
  3. import java.lang.reflect.Method;
  4. import java.net.InetSocketAddress;
  5. import java.nio.charset.StandardCharsets;
  6. import java.util.Random;
  7. import java.util.concurrent.TimeUnit;
  8. public class Harness2 {
  9. static int failures = 0;
  10. static void check(String name, boolean ok) {
  11. System.out.println((ok ? "PASS " : "FAIL ") + name);
  12. if (!ok) failures++;
  13. }
  14. public static void main(String[] a) throws Exception {
  15. Method checkUser = Main.class.getDeclaredMethod("checkUser", String.class);
  16. checkUser.setAccessible(true);
  17. HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
  18. final String[] body = {"0"}; final int[] status = {200};
  19. final java.util.List<String> queries = new java.util.concurrent.CopyOnWriteArrayList<>();
  20. server.createContext("/", ex -> {
  21. queries.add(ex.getRequestURI().toString());
  22. byte[] b = body[0].getBytes(StandardCharsets.UTF_8);
  23. ex.sendResponseHeaders(status[0], b.length);
  24. ex.getResponseBody().write(b); ex.close();
  25. });
  26. server.start();
  27. Main.PlaytimeURL = "http://127.0.0.1:" + server.getAddress().getPort() + "/timer.php";
  28. String me = System.getProperty("user.name"); // the student who is playing
  29. String other = "nobodyxyz"; // a monitored student who is not playing
  30. int n = 40000 + new Random().nextInt(9000);
  31. String game = "sleep " + n;
  32. Main.GamesList = new String[]{game};
  33. // 1. The old bug: the playing student is checked FIRST, a non-playing student LAST.
  34. Process p1 = new ProcessBuilder("sleep", String.valueOf(n)).start();
  35. Thread.sleep(300);
  36. body[0] = "0";
  37. checkUser.invoke(null, me);
  38. checkUser.invoke(null, other);
  39. check("0 minutes: playing student's game is closed even though the next student isn't playing",
  40. p1.waitFor(15, TimeUnit.SECONDS));
  41. check("server was asked about the playing student only once",
  42. queries.size() == 1 && queries.get(0).contains("user=" + me) && queries.get(0).contains("game=sleep+" + n));
  43. // 2. Minutes left: nothing is killed.
  44. Process p2 = new ProcessBuilder("sleep", String.valueOf(n)).start();
  45. Thread.sleep(300);
  46. body[0] = "10";
  47. checkUser.invoke(null, me);
  48. check("10 minutes left: game keeps running", p2.isAlive());
  49. // 3. Server problems: closed only after OfflineChecksBeforeKill failures in a row.
  50. settings.addSetting("OfflineChecksBeforeKill", "2");
  51. status[0] = 500;
  52. checkUser.invoke(null, me);
  53. check("1st failed check: game keeps running", p2.isAlive());
  54. status[0] = 200; body[0] = "10";
  55. checkUser.invoke(null, me); // a good answer resets the count
  56. status[0] = 500;
  57. checkUser.invoke(null, me);
  58. check("failure count was reset by a good answer: still running", p2.isAlive());
  59. checkUser.invoke(null, me);
  60. check("2 failed checks in a row: game is closed", p2.waitFor(15, TimeUnit.SECONDS));
  61. // 4. A text reason from the server closes the game.
  62. Process p3 = new ProcessBuilder("sleep", String.valueOf(n)).start();
  63. Thread.sleep(300);
  64. status[0] = 200; body[0] = "You are not within allowed play times.";
  65. checkUser.invoke(null, me);
  66. check("text reason: game is closed", p3.waitFor(15, TimeUnit.SECONDS));
  67. // 5. No game running: server isn't called.
  68. queries.clear();
  69. checkUser.invoke(null, me);
  70. check("no game running: server not called", queries.isEmpty());
  71. server.stop(0);
  72. System.out.println(failures == 0 ? "ALL PASSED" : failures + " FAILED");
  73. System.exit(failures == 0 ? 0 : 1);
  74. }
  75. }