/*
* 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();
@Test
public void
mustCountCorrectlyAfterRandomAddRemoveLeakAndCounts() {
System.out.print(
"NOTE: this test takes about 3 to 5 minutes to run... ");
// This particular seed seems to give pretty good coverage:
Random rng = new Random(-6406176578229504295L);
Set<Object> objs = new HashSet<>();
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;
if (progress * stride == i - 1) {
System.out.printf("\033[4D% 3d%%", 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;
}
}