| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package au.pfip;
- import com.sun.net.httpserver.HttpServer;
- import java.lang.reflect.Method;
- import java.net.InetSocketAddress;
- import java.nio.charset.StandardCharsets;
- import java.util.Random;
- import java.util.concurrent.TimeUnit;
- public class Harness2 {
- static int failures = 0;
- static void check(String name, boolean ok) {
- System.out.println((ok ? "PASS " : "FAIL ") + name);
- if (!ok) failures++;
- }
- public static void main(String[] a) throws Exception {
- Method checkUser = Main.class.getDeclaredMethod("checkUser", String.class);
- checkUser.setAccessible(true);
- HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
- final String[] body = {"0"}; final int[] status = {200};
- final java.util.List<String> queries = new java.util.concurrent.CopyOnWriteArrayList<>();
- server.createContext("/", ex -> {
- queries.add(ex.getRequestURI().toString());
- byte[] b = body[0].getBytes(StandardCharsets.UTF_8);
- ex.sendResponseHeaders(status[0], b.length);
- ex.getResponseBody().write(b); ex.close();
- });
- server.start();
- Main.PlaytimeURL = "http://127.0.0.1:" + server.getAddress().getPort() + "/timer.php";
- String me = System.getProperty("user.name"); // the student who is playing
- String other = "nobodyxyz"; // a monitored student who is not playing
- int n = 40000 + new Random().nextInt(9000);
- String game = "sleep " + n;
- Main.GamesList = new String[]{game};
- // 1. The old bug: the playing student is checked FIRST, a non-playing student LAST.
- Process p1 = new ProcessBuilder("sleep", String.valueOf(n)).start();
- Thread.sleep(300);
- body[0] = "0";
- checkUser.invoke(null, me);
- checkUser.invoke(null, other);
- check("0 minutes: playing student's game is closed even though the next student isn't playing",
- p1.waitFor(15, TimeUnit.SECONDS));
- check("server was asked about the playing student only once",
- queries.size() == 1 && queries.get(0).contains("user=" + me) && queries.get(0).contains("game=sleep+" + n));
- // 2. Minutes left: nothing is killed.
- Process p2 = new ProcessBuilder("sleep", String.valueOf(n)).start();
- Thread.sleep(300);
- body[0] = "10";
- checkUser.invoke(null, me);
- check("10 minutes left: game keeps running", p2.isAlive());
- // 3. Server problems: closed only after OfflineChecksBeforeKill failures in a row.
- settings.addSetting("OfflineChecksBeforeKill", "2");
- status[0] = 500;
- checkUser.invoke(null, me);
- check("1st failed check: game keeps running", p2.isAlive());
- status[0] = 200; body[0] = "10";
- checkUser.invoke(null, me); // a good answer resets the count
- status[0] = 500;
- checkUser.invoke(null, me);
- check("failure count was reset by a good answer: still running", p2.isAlive());
- checkUser.invoke(null, me);
- check("2 failed checks in a row: game is closed", p2.waitFor(15, TimeUnit.SECONDS));
- // 4. A text reason from the server closes the game.
- Process p3 = new ProcessBuilder("sleep", String.valueOf(n)).start();
- Thread.sleep(300);
- status[0] = 200; body[0] = "You are not within allowed play times.";
- checkUser.invoke(null, me);
- check("text reason: game is closed", p3.waitFor(15, TimeUnit.SECONDS));
- // 5. No game running: server isn't called.
- queries.clear();
- checkUser.invoke(null, me);
- check("no game running: server not called", queries.isEmpty());
- server.stop(0);
- System.out.println(failures == 0 ? "ALL PASSED" : failures + " FAILED");
- System.exit(failures == 0 ? 0 : 1);
- }
- }
|