import java.util.HashSet; import java.util.Iterator; import java.util.PriorityQueue; import java.util.Random; public class TestBinHeap { static Random randgen = new Random(686585037); static int nopdone = 0; static int lastnopdone = -1; static int noperation = 0; static StringBuilder log = new StringBuilder(); static void showException(Exception e, StringBuilder log) { System.out.println("The operation on the last line of the following code causes an exception:\n"); System.out.print(log.toString()); System.out.println("\nThe exception is: " + e.toString()); System.exit(1); } static void runTest(int noperation, int interval) { log = new StringBuilder(); log.append("PrioQueue pq = new BinHeap<>(new NaturalOrderComparator());\n"); PrioQueue pq = new BinHeap<>(new NaturalOrderComparator()); PriorityQueue refpq = new PriorityQueue<>(10, new NaturalOrderComparator()); for (int j = 0; j < noperation; j++) { int whichop = randgen.nextInt(5); switch (whichop) { case 0: { // add int element = randgen.nextInt(interval); log.append("pq.add(" + element + ");\n"); try { pq.add(element); } catch (Exception e) { showException(e, log); } refpq.add(element); } break; case 1: { // peek log.append("pq.peek();"); Integer res = null; try { res = pq.peek(); } catch (Exception e) { showException(e, log); } log.append(" // result: " + res + "\n"); Integer refres = refpq.peek(); if (res != refres) { System.out.println("The result on the last line of the following code is incorrect:\n"); System.out.print(log.toString()); System.out.println("The result should be: " + refres); System.exit(1); } } break; case 2: { // poll log.append("pq.poll();"); Integer res = null; try { res = pq.poll(); } catch (Exception e) { showException(e, log); } log.append(" // result: " + res + "\n"); Integer refres = refpq.poll(); if (res != refres) { System.out.println("The result on the last line of the following code is incorrect:\n"); System.out.print(log.toString()); System.out.println("The result should be: " + refres); System.exit(1); } } break; case 3: { // iterator log.append("pq.iterator();\n"); Iterator iter = null; try { iter = pq.iterator(); } catch (Exception e) { showException(e, log); } Iterator refiter = refpq.iterator(); HashSet set = new HashSet<>(); while (iter.hasNext()) set.add(iter.next()); HashSet refset = new HashSet<>(); while (refiter.hasNext()) refset.add(refiter.next()); if (!set.equals(refset)) { System.out.println("The result on the last line of the following code is incorrect:\n"); System.out.print(log.toString()); System.out.println("The returned iterator iterates over the following set of elements:"); System.out.println(set.toString()); System.out.println("The iterator should iterate over the following set of elements:"); System.out.println(refset.toString()); System.exit(1); } } break; case 4: { // remove int element = randgen.nextInt(interval); log.append("pq.remove(" + element + ");\n"); try { pq.remove(element); } catch (Exception e) { showException(e, log); } refpq.remove(element); } break; } nopdone++; } } private static class Monitor implements Runnable { final int nsec; Monitor(int nsec) { this.nsec = nsec; } @Override public void run() { for (int secs = 0; secs < nsec; secs++) { try { Thread.sleep(1000); } catch (InterruptedException e) { return; } if (nopdone == lastnopdone) { System.out.println("No new operation completed during the last second."); System.out.println("Your program seems to loop (or be very slow) at the operation on the last line of the following code:\n"); System.out.print(log.toString()); System.exit(1); } lastnopdone = nopdone; System.out.println(nopdone + " operations executed. (No bugs found so far.)"); } System.out.println("No bugs found in " + nsec + " seconds."); System.exit(0); } } public static void main(String[] args) { if (args.length > 1) { System.out.println("The program accepts zero or one arguments."); System.out.println("If there is an argument this should be a positive number specifying the number of seconds to run the test."); System.exit(1); } int nrepetition = 5; int nsec = 5; if (args.length == 1) { try { nsec = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.out.println("The given argument is not a valid number."); System.exit(1); } } if (args.length == 0) { System.out.println("The test will run for " + nsec + " seconds or until a bug is found. (The number of seconds can be specified as an argument to the program.)"); } new Thread(new Monitor(nsec)).start(); for (int iter = 1;; iter++) { nrepetition *= 2; noperation = iter; int interval = iter; for (int i = 0; i < nrepetition; i++) { runTest(noperation, interval); } } } }