/*
* Copyright (c) 2010-2014. Axon Framework
*
* 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 org.axonframework.common.caching;
import org.axonframework.common.Registration;
import org.junit.Before;
import org.junit.Test;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import static java.util.Collections.singleton;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class WeakReferenceCacheTest {
private WeakReferenceCache testSubject;
private Cache.EntryListener mockListener;
private Registration registration;
@Before
public void setUp() throws Exception {
mockListener = mock(Cache.EntryListener.class);
testSubject = new WeakReferenceCache();
registration = testSubject.registerCacheEntryListener(mockListener);
}
@Test
public void testItemPurgedWhenNoLongerReferenced() throws Exception {
// Mockito holds a reference to all parameters, preventing GC
registration.cancel();
final Set<String> expiredEntries = new CopyOnWriteArraySet<>();
testSubject.registerCacheEntryListener(new Cache.EntryListenerAdapter() {
@Override
public void onEntryExpired(Object key) {
expiredEntries.add(key.toString());
}
});
Object value = new Object();
testSubject.put("test1", value);
assertSame(value, testSubject.get("test1"));
// dereference
value = null;
// hope for a true GC
System.gc();
for (int i = 0; i < 5 && testSubject.containsKey("test1"); i++) {
// try again
System.gc();
Thread.sleep(100);
}
assertNull(testSubject.get("test1"));
// the reference is gone, but it may take a 'while' for the reference to be queued
for (int i = 0; i < 5 && !expiredEntries.contains("test1"); i++) {
testSubject.get("test1");
Thread.sleep(100);
}
assertEquals(singleton("test1"), expiredEntries);
}
@Test
public void testEntryListenerNotifiedOfCreationUpdateAndDeletion() throws Exception {
Object value = new Object();
Object value2 = new Object();
testSubject.put("test1", value);
verify(mockListener).onEntryCreated("test1", value);
testSubject.put("test1", value2);
verify(mockListener).onEntryUpdated("test1", value2);
testSubject.get("test1");
verify(mockListener).onEntryRead("test1", value2);
testSubject.remove("test1");
verify(mockListener).onEntryRemoved("test1");
assertNull(testSubject.get("test1"));
verifyNoMoreInteractions(mockListener);
}
}