for (int i=0; i<threads.length; i++) threads[i].join();
TestUtilities.rethrownIfNotNull(failures.get());
/*
* Verifies the values.
*/
final Statistics beforeGC = validateStressEntries("Before GC", cache);
assertTrue("Should not have more entries than what we put in.", cache.size() <= count);
assertFalse("Some entries should be retained by strong references.", cache.isEmpty());
/*
* If verbose test output is enabled, report the number of cache hits.
* The numbers below are for tuning the test only. The output is somewhat
* random so we can not check it in a test suite. However if the test is
* properly tuned, most values should be non-zero.
*/
final PrintWriter out = CacheTest.out;
TestUtilities.printSeparator("CacheTest.stress() - testing concurrent accesses");
out.print("There is "); out.print(threads.length); out.print(" threads, each of them"
+ " fetching or creating "); out.print(count); out.println(" values.");
out.println("Number of times a new value has been created, for each thread:");
for (int i=0; i<threads.length;) {
final String n = String.valueOf(threads[i++].addCount);
out.print(CharSequences.spaces(6 - n.length()));
out.print(n);
if ((i % 10) == 0) {
out.println();
}
}
out.println();
out.println("Now observe how the background thread cleans the cache.");
long time = System.nanoTime();
for (int i=0; i<10; i++) {
final long t = System.nanoTime();
out.printf("Cache size: %4d (after %3d ms)%n", cache.size(), round((t - time) / 1E+6));
time = t;
Thread.sleep(250);
if (i >= 2) {
System.gc();
}
}
out.println();
/*
* Gets the statistics of key values after garbage collection. Most values should
* be higher, because oldest values (which should have been garbage collected first)
* have lower values. If verbose output is enabled, then we will print the statistics
* before to perform the actual check in order to allow the developer to have more
* information in case of failure.
*
* The mean value is often greater, but not always. Since we have fewer remaining values
* (100 instead of 10000), the remaining low values will have a much greater impact on
* the mean. Only the check on the minimal value is fully reliable.
*/
final Statistics afterGC = validateStressEntries("After GC", cache);
out.println("Statistics on the keys before and after garbage collection.");
out.println("The minimum value shall always be equals or greater after GC.");
out.println("The mean value is usually greater too, except by coincidence.");
final StatisticsFormat format = StatisticsFormat.getInstance();
format.setBorderWidth(1);
try {
format.format(new Statistics[] {beforeGC, afterGC}, out);
} catch (IOException e) {
throw new AssertionError(e);
}
assertTrue("Minimum key value should be greater after garbage collection.",
afterGC.minimum() >= beforeGC.minimum());
}