/*
* Copyright 2011 Google Inc.
*
* 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 com.google.gwt.dev.util;
import junit.framework.TestCase;
/**
* Verifies that we can intern strings.
*
* @author skybrian@google.com (Brian Slesinsky)
*/
public class StringInternerTest extends TestCase {
private StringInterner interner;
protected void setUp() throws Exception {
super.setUp();
interner = StringInterner.get();
}
public void testCanInternString() throws Exception {
String firstIn = "fnord123";
String secondIn = new String(firstIn);
assertFalse(firstIn == secondIn);
String firstOut = interner.intern(firstIn);
String secondOut = interner.intern(secondIn);
assertSame(firstOut, secondOut);
}
public void testCanFreeString() throws Exception {
// Intern about a gigabyte of data.
// If we don't free any interned strings, we should run out of memory.
// (Verified that it fails using Interns.newStrongInterner().)
String prefix = repeat('a', 1000);
for (int i = 0; i < 1000 * 1000; i++) {
interner.intern(prefix + i);
}
}
public void testShardsAreSomewhatBalanced() throws Exception {
// Simulate adding a million strings. We use the production algorithm to choose the shard,
// but increment a counter instead. This avoids the WeakHashMap's nondeterministic
// behavior due to garbage collection.
int meanShardSize = 1000;
int shardSizes[] = new int[StringInterner.SHARD_COUNT];
int stringsToAdd = StringInterner.SHARD_COUNT * meanShardSize;
for (int i = 0; i < stringsToAdd; i++) {
int shardId = interner.getShardId("foo" + i);
shardSizes[shardId]++;
}
// Verify that no shards are too big. (A shard that's oversized could create lock contention.)
int expectedMaxShardSize = meanShardSize * 2;
int maxShardSize = 0;
int tooBigShardCount = 0;
for (int shardSize : shardSizes) {
maxShardSize = Math.max(maxShardSize, shardSize);
if (shardSize > expectedMaxShardSize) {
tooBigShardCount++;
}
}
if (tooBigShardCount > 0) {
fail(tooBigShardCount + " of " + shardSizes.length + " shards are too big (more than " +
expectedMaxShardSize + " entries); largest shard has " + maxShardSize + " entries.");
}
}
private static String repeat(char c, int length) {
StringBuilder buffer = new StringBuilder(length);
for (int i = 0; i < length; i++) {
buffer.append(c);
}
return buffer.toString();
}
}