/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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.intellij.util.containers;
import java.lang.ref.WeakReference;
public class WeakReferenceArrayTest extends WeaksTestCase {
public void testCorpseCounter() {
addElements(5);
checkForAliveCount(5);
checkSameElements(null);
myHolder.remove(3);
gc();
checkForAliveCount(4);
myCollection.remove(3);
checkSameNotNulls(null);
checkForAliveCount(4);
myCollection.remove(2);
checkForAliveCount(3);
myHolder.remove(2);
gc();
checkSameNotNulls(null);
checkForAliveCount(3);
}
public void testAddRemove() {
myHolder.add("1");
myHolder.add("2");
checkForSize(0, false);
myCollection.add(myHolder.get(0));
checkForSize(1, false);
myCollection.add(myHolder.get(1));
checkSameElements(null);
assertSame(myHolder.get(0), myCollection.remove(0));
checkForSize(2, false);
assertNull(myCollection.remove(0));
}
public void testRemoveDead() {
myCollection.add(new Object());
myCollection.add(this);
gc();
checkForSize(2, false);
checkForAliveCount(1);
assertNull(myCollection.remove(0));
checkForAliveCount(1);
}
public void testCompress() {
addElements(5);
checkSameElements(null);
myHolder.remove(0);
myHolder.remove(0);
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.compress(-1);
}
});
checkForAliveCount(3);
}
public void testCompressTrackingLastSurvived() {
myCollection.add(new Object());
addElement(new Object());
myCollection.add(new Object());
addElement(new Object());
myCollection.add(new Object());
gc();
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.compress(-1);
}
});
}
public void testAddingManyElement() {
int initialCapacity = fullCollection();
assertEquals(initialCapacity, myCollection.getCapacity());
assertTrue(initialCapacity > 3); // Need to go on
myHolder.remove(0);
myHolder.remove(0);
gc();
checkSameNotNulls(null);
addElement(new Object());
assertEquals(initialCapacity, myCollection.getCapacity());
checkSameElements(null);
}
public void testReduceSize() {
int initialCapacity = fullCollection();
assertEquals(initialCapacity, myCollection.getCapacity());
addElement(new Object());
int grownCapacity = 2 * initialCapacity;
assertEquals(grownCapacity, myCollection.getCapacity());
checkSameElements(null);
myCollection.reduceCapacity(-1);
assertEquals(grownCapacity, myCollection.getCapacity());
myHolder.remove(0);
gc();
myCollection.reduceCapacity(-1);
assertEquals(grownCapacity, myCollection.getCapacity());
myHolder.remove(0);
for (int i = 0; i < grownCapacity; i++) addElement(new Object());
for (int i = 0; i < grownCapacity; i++) myHolder.remove(0);
final int lastCapacity = myCollection.getCapacity();
gc();
checkSameNotNulls(null);
myCollection.reduceCapacity(-1);
assertTrue(lastCapacity > myCollection.getCapacity());
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.reduceCapacity(-1);
}
});
myHolder.clear();
gc();
checkForSize(0, true);
addElement(new Object());
checkSameElements(null);
}
public void testReduceCapacityOfAliveCollection() {
myCollection = new WeakReferenceArray<Object>(WeakReferenceArray.MINIMUM_CAPACITY * 3);
addElement(new Object());
myCollection.reduceCapacity(-1);
checkForAliveCount(1);
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.reduceCapacity(-1);
}
});
}
public void testRemoveAlives() {
addElement(new Object());
addElement(new Object());
addElement(new Object());
WeakReference[] references = copyReferences();
assertTrue(references.length >= 3);
myCollection.remove(1);
myCollection.remove(0);
checkForAliveCount(1);
myHolder.remove(0);
myHolder.remove(0);
checkSameNotNulls(null);
gc();
checkForAliveCount(1);
}
private WeakReference[] copyReferences() {
WeakReference[] references = new WeakReference[myCollection.getCapacity()];
System.arraycopy(myCollection.getReferences(), 0, references, 0, references.length);
return references;
}
public void testRemoveEnqueuedReference() {
addElement(new Object());
WeakReference reference = myCollection.getReferences()[0];
assertSame(reference.get(), myHolder.get(0));
myHolder.clear();
reference.enqueue();
myCollection.remove(0);
gc();
checkForAliveCount(0);
myCollection.getCorpseCount();
reference = null;
gc();
checkForAliveCount(0);
}
public void testRemoveNotEnqueuedReference() {
addElement(new Object());
WeakReference reference = myCollection.getReferences()[0];
myCollection.remove(0);
gc();
myHolder.clear();
reference.enqueue();
gc();
checkForAliveCount(0);
}
public void testOutofboundsReferences() {
for (int i = 0; i < 400; i++) addElement(new Object());
WeakReference[] references = copyReferences();
for (int i = 0; i < 100; i++) references[i].clear();
for (int i = 100; i < 395; i++) myCollection.remove(i);
myCollection.reduceCapacity(-1);
assertEquals(210, myCollection.getCapacity());
checkForSize(5, true);
checkForAliveCount(5);
for (int i = 0; i < 100; i++) assertFalse(String.valueOf(i), references[i].enqueue());
for (int i = 0; i < myCollection.getCapacity() - 20; i++) addElement(new Object());
for (int i = 0; i < myCollection.getCapacity() - 20; i++) myCollection.remove(i);
myCollection.reduceCapacity(-1);
for (int i = 0; i < 100; i++) assertFalse(references[i].enqueue());
myCollection.reduceCapacity(-1);
}
public void testRemoveAliveReference() {
Object obj = new Object();
myCollection.add(obj);
WeakReference[] references = copyReferences();
assertSame(obj, references[0].get());
assertTrue(myCollection.removeReference(0));
assertTrue(references[0].isEnqueued());
assertNull(references[0].get());
checkForAliveCount(0);
assertNull(myCollection.getReferences()[0]);
}
public void testRemoveDeadReference() {
Object obj = new Object();
myCollection.add(obj);
WeakReference[] references = copyReferences();
references[0].clear();
references[0].enqueue();
assertFalse(myCollection.removeReference(0));
checkForAliveCount(0);
assertNull(myCollection.getReferences()[0]);
}
public void testRemoveRemovedReference() {
Object obj = new Object();
myCollection.add(obj);
myCollection.remove(0);
checkForAliveCount(0);
assertFalse(myCollection.removeReference(0));
checkForAliveCount(0);
}
public void testCompacting() {
addElements(20);
removeEven(1);
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.reduceCapacity(-1);
}
});
addElements(19);
removeEven(1);
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.compress(-1);
}
});
addElements(19);
removeEven(0);
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.reduceCapacity(-1);
}
});
addElements(19);
removeEven(0);
checkSameElements(new Runnable() {
@Override
public void run() {
myCollection.compress(-1);
}
});
}
private void removeEven(int remainder) {
for (int i = 0; i < myCollection.size(); i++) {
if (i % 4 != remainder) myHolder.remove(myCollection.remove(i));
}
}
private int fullCollection() {
int initialCapacity = myCollection.getCapacity();
for (int i = 0; i < initialCapacity; i++) {
addElement(new Object());
}
return initialCapacity;
}
private void addElements(int count) {
for (int i = 0; i < count; i++) {
addElement(new Object());
}
}
private void addElement(Object o) {
addElement(o, myCollection);
}
}