TestInternCache.java
package wstxtest.util;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import com.ctc.wstx.util.InternCache;
/**
* Unit tests for {@link InternCache}.
*/
public class TestInternCache
extends TestCase
{
public void testBasicIntern()
{
InternCache cache = InternCache.getInstance();
// Use new String() to ensure we're not passing an already-interned literal
String input = new String("http://example.com/test-ns");
String result = cache.intern(input);
// Must return the interned version
assertSame(input.intern(), result);
// Calling again with a different String instance of same value must return same reference
String input2 = new String("http://example.com/test-ns");
assertSame(result, cache.intern(input2));
}
public void testConcurrentIntern() throws Exception
{
final InternCache cache = InternCache.getInstance();
final int threadCount = 16;
final int stringsPerThread = 100;
// Create a shared set of strings that all threads will intern
final String[] sharedStrings = new String[stringsPerThread];
for (int i = 0; i < stringsPerThread; i++) {
sharedStrings[i] = "urn:concurrent-test:ns:" + i;
}
final CountDownLatch startLatch = new CountDownLatch(1);
final CountDownLatch doneLatch = new CountDownLatch(threadCount);
final String[][] results = new String[threadCount][stringsPerThread];
final List<Throwable> errors = new ArrayList<>();
for (int t = 0; t < threadCount; t++) {
final int threadIdx = t;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
startLatch.await();
for (int i = 0; i < stringsPerThread; i++) {
// Use new String() so each thread has its own instance
results[threadIdx][i] = cache.intern(new String(sharedStrings[i]));
}
} catch (Throwable e) {
synchronized (errors) {
errors.add(e);
}
} finally {
doneLatch.countDown();
}
}
});
thread.setDaemon(true);
thread.start();
}
// Release all threads at once
startLatch.countDown();
assertTrue("Threads did not complete in time", doneLatch.await(30, TimeUnit.SECONDS));
assertTrue("Unexpected errors: " + errors, errors.isEmpty());
// All threads must have gotten the exact same (identity-equal) interned String
for (int i = 0; i < stringsPerThread; i++) {
String expected = results[0][i];
assertSame("Result must be interned", sharedStrings[i].intern(), expected);
for (int t = 1; t < threadCount; t++) {
assertSame("Thread " + t + " got different instance for string " + i,
expected, results[t][i]);
}
}
}
}