/*
 * Copyright (C) 2011-2014 Chris Vest (mr.chrisvest@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package stormpot;

import org.junit.Test;
import org.junit.experimental.categories.Category;
import stormpot.slow.SlowTest;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

@Category(SlowTest.class)
public class PreciseLeakDetectorIT {
  private PreciseLeakDetector detector = new PreciseLeakDetector();

  // Note: this test takes about 3 to 4 minutes to run.
  @Test
  public void
  mustCountCorrectlyAfterRandomAddRemoveLeakAndCounts() {
    // This particular seed seems to give pretty good coverage:
    Random rng = new Random(-6406176578229504295L);
    Set<Object> objs = new HashSet<Object>();
    long leaksCreated = 0;

    // This distribution of the operations seems to give a good coverage:
    int iterations = 120000;
    for (int i = 0; i < iterations; i++) {
      int choice = rng.nextInt(100);
      if (choice < 60) {
        // Add
        Object add = new Object();
        objs.add(add);
        detector.register(add);
      } else if (choice < 80) {
        // Remove
        Object remove = removeRandom(objs);
        if (remove != null) {
          detector.unregister(remove);
        }
      } else if (choice < 90) {
        // Count
        assertThat(detector.countLeakedObjects(), is(leaksCreated));
      } else {
        // Leak
        Object obj = removeRandom(objs);
        if (obj != null) {
          //noinspection UnusedAssignment : required for System.gc()
          obj = null;
          System.gc();
          leaksCreated++;
        }
      }

      printProgress(iterations, i);
    }
    System.out.println();
    for (Object obj : objs) {
      detector.unregister(obj);
    }
    objs.clear();
    //noinspection UnusedAssignment : required for System.gc()
    objs = null;

    System.gc();
    assertThat(detector.countLeakedObjects(), is(leaksCreated));
  }

  private static void printProgress(int iterations, int i) {
    int stride = iterations / 100;
    int progress = i / stride;
    String lineReset = "\033[2K\033[G";

    if (progress * stride == i - 1) {
      System.out.printf(
          "%sNOTE: this test takes about 3 to 5 minutes to run... %s%%",
          lineReset, progress);
    }
  }

  private Object removeRandom(Set<Object> objs) {
    Iterator<Object> iterator = objs.iterator();
    if (iterator.hasNext()) {
      Object obj = iterator.next();
      iterator.remove();
      return obj;
    }
    return null;
  }
}

@@ -1071,64 +1071,8 @@
 );%0A%0A
-  // Note: this test takes about 3 to 4 minutes to run.%0A
   @T
@@ -1143,24 +1143,116 @@
 dCounts() %7B%0A
+    System.out.print(%0A        %22NOTE: this test takes about 3 to 5 minutes to run...    %22);%0A%0A
     // This 
@@ -2743,48 +2743,8 @@
 ide;
-%0A    String lineReset = %22%5C033%5B2K%5C033%5BG%22;
 %0A%0A  
@@ -2807,101 +2807,23 @@
 ntf(
-%0A          %22%25sNOTE: this test takes about 3 to 5 minutes to run... %25s%25%25%22,%0A          lineReset
+%22%5C033%5B4D%25 3d%25%25%22
 , pr

Tighten output from PreciseLeakDetectorIT