blob: db86e637f2811120395ac9a0c8d5f2c48884a3df [file] [log] [blame]
/*
* Copyright 2000-2014 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 org.junit.Test;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import static org.junit.Assert.*;
public class WeakListTest {
private static final String HARD_REFERENCED = "xxx";
private final WeakList<Object> myWeakList = new WeakList<Object>();
private final List<Object> myHolder = new ArrayList<Object>();
@Test
public void testCompresses() {
fillWithObjects(20);
assertEquals(20, myWeakList.listSize());
addElement(HARD_REFERENCED);
assertEquals(21, myWeakList.listSize());
myHolder.clear();
while (myWeakList.toStrongList().size() == 21) {
synchronized (myWeakList) {
gc();
}
}
synchronized (myWeakList) {
boolean processed = myWeakList.processQueue();
assertTrue(processed); // some refs must be in the queue
}
//HARD_REFERENCED is held there
assertEquals(1, myWeakList.listSize());
}
@Test
public void testClear() {
fillWithObjects(20);
assertEquals(20, myWeakList.listSize());
myHolder.clear();
gc();
myWeakList.clear();
assertFalse(myWeakList.iterator().hasNext());
}
@Test
public void testIterator() {
int N = 10;
fillWithInts(N);
gc();
Iterator<?> iterator = myWeakList.iterator();
for (int i = 0; i < N; i++) {
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
int element = (Integer)iterator.next();
assertEquals(i, element);
}
assertFalse(iterator.hasNext());
int elementCount = 0;
for (Object element : myWeakList) {
assertEquals(elementCount, element);
elementCount++;
}
assertEquals(N, elementCount);
}
@Test
public void testRemoveViaIterator() {
addElement(new Object());
addElement(new Object());
addElement(new Object());
Iterator<Object> iterator = myWeakList.iterator();
assertSame(myHolder.get(0), iterator.next());
iterator.remove();
gc();
assertEquals(2, myWeakList.toStrongList().size());
iterator.next();
gc();
assertEquals(2, myWeakList.toStrongList().size());
assertSame(myHolder.get(2), iterator.next());
assertFalse(iterator.hasNext());
myHolder.remove(1);
}
@Test
public void testRemoveAllViaIterator() {
int N = 10;
fillWithInts(N);
gc();
Iterator<Object> iterator = myWeakList.iterator();
for (int i = 0; i < N; i++) {
assertTrue(iterator.hasNext());
int element = (Integer)iterator.next();
assertEquals(i, element);
iterator.remove();
}
assertFalse(iterator.hasNext());
assertTrue(myWeakList.toStrongList().isEmpty());
}
@Test
public void testRemoveLastViaIterator() {
addElement(new Object());
addElement(new Object());
Iterator<Object> iterator = myWeakList.iterator();
iterator.next();
assertTrue(iterator.hasNext());
iterator.next();
assertFalse(iterator.hasNext());
iterator.remove();
}
@Test
public void testIteratorKeepsFirstElement() {
addElement(new Object());
addElement(new Object());
Iterator<Object> iterator = myWeakList.iterator();
assertTrue(iterator.hasNext());
myHolder.clear();
gc();
assertNotNull(iterator.next());
assertFalse(iterator.hasNext());
}
@Test
public void testIteratorKeepsNextElement() {
addElement(new Object());
addElement(new Object());
addElement(new Object());
Iterator<Object> iterator = myWeakList.iterator();
iterator.next();
assertTrue(iterator.hasNext());
myHolder.clear();
gc();
assertNotNull(iterator.next());
assertFalse(iterator.hasNext());
}
@Test
public void testIteratorRemoveEmpty() {
Iterator<Object> iterator = myWeakList.iterator();
assertFalse(iterator.hasNext());
try {
iterator.next();
fail("must not allow to next");
}
catch (NoSuchElementException ignored) {
}
try {
iterator.remove();
fail("must not allow to remove");
}
catch (NoSuchElementException ignored) {
}
}
@Test
public void testElementGetsCollectedInTheMiddleAndListRebuildsItself() {
int N = 200;
fillWithObjects(N);
String x = new String("xxx");
addElement(x);
fillWithObjects(N);
gc();
assertEquals(N + 1 + N, myWeakList.listSize());
myHolder.clear();
while (myWeakList.toStrongList().size() == N + 1 + N) {
synchronized (myWeakList) {
gc();
}
}
boolean removed = myWeakList.remove("zzz");
assertFalse(removed);
assertEquals(1, myWeakList.listSize());
Object element = myWeakList.iterator().next();
assertSame(x, element);
}
@Test
public void testIsEmpty() {
assertTrue(myWeakList.isEmpty());
addElement(new Object());
assertFalse(myWeakList.isEmpty());
myHolder.clear();
gc();
assertEquals(1, myWeakList.listSize());
assertTrue(myWeakList.isEmpty());
}
private void addElement(Object element) {
myWeakList.add(element);
myHolder.add(element);
}
private void fillWithObjects(int n) {
for (int i = n - 1; i >= 0; i--) {
addElement(new Object());
}
}
private void fillWithInts(int n) {
for (int i = 0; i < n; i++) {
addElement(i);
}
}
private static void gc() {
ConcurrentMapsTest.tryGcSoftlyReachableObjects();
WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
do {
System.gc();
}
while (weakReference.get() != null);
}
}