package net.bytebuddy; import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; import net.bytebuddy.test.utility.ObjectPropertyAssertion; import org.junit.Test; import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.concurrent.Callable; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.CoreMatchers.is; import static org.mockito.Mockito.*; public class TypeCacheTest { @Test public void testCache() throws Exception { TypeCache<Object> typeCache = new TypeCache<Object>(TypeCache.Sort.WEAK); Object key = new Object(); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), nullValue(Class.class)); assertThat(typeCache.insert(ClassLoader.getSystemClassLoader(), key, Void.class), is((Object) Void.class)); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), is((Object) Void.class)); assertThat(typeCache.find(mock(ClassLoader.class), key), nullValue(Class.class)); typeCache.clear(); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), nullValue(Class.class)); } @Test public void testCacheInline() throws Exception { TypeCache<Object> typeCache = new TypeCache.WithInlineExpunction<Object>(TypeCache.Sort.WEAK); Object key = new Object(); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), nullValue(Class.class)); assertThat(typeCache.insert(ClassLoader.getSystemClassLoader(), key, Void.class), is((Object) Void.class)); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), is((Object) Void.class)); assertThat(typeCache.find(mock(ClassLoader.class), key), nullValue(Class.class)); typeCache.clear(); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), nullValue(Class.class)); } @Test public void testCacheNullLoader() throws Exception { TypeCache<Object> typeCache = new TypeCache<Object>(TypeCache.Sort.WEAK); Object key = new Object(); assertThat(typeCache.find(null, key), nullValue(Class.class)); assertThat(typeCache.insert(null, key, Void.class), is((Object) Void.class)); assertThat(typeCache.find(null, key), is((Object) Void.class)); assertThat(typeCache.find(mock(ClassLoader.class), key), nullValue(Class.class)); typeCache.clear(); assertThat(typeCache.find(null, key), nullValue(Class.class)); } @Test public void testCacheCollection() throws Exception { TypeCache<Object> typeCache = new TypeCache<Object>(TypeCache.Sort.WEAK); Object key = new Object(); ClassLoader classLoader = mock(ClassLoader.class); assertThat(typeCache.find(classLoader, key), nullValue(Class.class)); assertThat(typeCache.insert(classLoader, key, Void.class), is((Object) Void.class)); assertThat(typeCache.find(classLoader, key), is((Object) Void.class)); classLoader = null; // Make eligible for GC for (int index = 0; index < 2; index++) { System.gc(); Thread.sleep(50L); } typeCache.expungeStaleEntries(); assertThat(typeCache.cache.isEmpty(), is(true)); } @Test public void testCacheTypeCollection() throws Exception { TypeCache<Object> typeCache = new TypeCache<Object>(TypeCache.Sort.WEAK); Object key = new Object(); ClassLoader classLoader = mock(ClassLoader.class); assertThat(typeCache.find(classLoader, key), nullValue(Class.class)); Class<?> type = new ByteBuddy().subclass(Object.class) .make() .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); assertThat(typeCache.insert(classLoader, key, type), is((Object) type)); assertThat(typeCache.find(classLoader, key), is((Object) type)); type = null; // Make eligable for GC for (int index = 0; index < 2; index++) { System.gc(); Thread.sleep(50L); } assertThat(typeCache.find(classLoader, key), nullValue(Class.class)); assertThat(typeCache.insert(classLoader, key, Void.class), is((Object) Void.class)); assertThat(typeCache.find(classLoader, key), is((Object) Void.class)); } @Test public void testWeakReference() throws Exception { Reference<Class<?>> reference = TypeCache.Sort.WEAK.wrap(Void.class); assertThat(reference, instanceOf(WeakReference.class)); assertThat(reference.get(), is((Object) Void.class)); } @Test public void testSoftReference() throws Exception { Reference<Class<?>> reference = TypeCache.Sort.SOFT.wrap(Void.class); assertThat(reference, instanceOf(SoftReference.class)); assertThat(reference.get(), is((Object) Void.class)); } @Test @SuppressWarnings("unchecked") public void testFindOrInsert() throws Exception { TypeCache<Object> typeCache = new TypeCache<Object>(TypeCache.Sort.WEAK); Object key = new Object(); assertThat(typeCache.find(ClassLoader.getSystemClassLoader(), key), nullValue(Class.class)); Callable<Class<?>> callable = mock(Callable.class); when(callable.call()).thenReturn((Class) Void.class); assertThat(typeCache.findOrInsert(ClassLoader.getSystemClassLoader(), key, callable, new Object()), is((Object) Void.class)); verify(callable).call(); assertThat(typeCache.findOrInsert(ClassLoader.getSystemClassLoader(), key, callable), is((Object) Void.class)); assertThat(typeCache.findOrInsert(ClassLoader.getSystemClassLoader(), key, callable, new Object()), is((Object) Void.class)); verifyNoMoreInteractions(callable); } @Test(expected = IllegalArgumentException.class) @SuppressWarnings("unchecked") public void testCreationException() throws Exception { TypeCache<Object> typeCache = new TypeCache<Object>(TypeCache.Sort.WEAK); Callable<Class<?>> callable = mock(Callable.class); when(callable.call()).thenThrow(RuntimeException.class); typeCache.findOrInsert(ClassLoader.getSystemClassLoader(), new Object(), callable, new Object()); } @Test public void testObjectProperties() throws Exception { ObjectPropertyAssertion.of(TypeCache.Sort.class).apply(); final Iterator<Class<?>> iterator = Arrays.<Class<?>>asList(Object.class, String.class, Void.class, Integer.class, Long.class, Byte.class, Boolean.class, Character.class, Short.class, Float.class, Long.class).iterator(); ObjectPropertyAssertion.of(TypeCache.SimpleKey.class).create(new ObjectPropertyAssertion.Creator<Collection<Class<?>>>() { @Override public Collection<Class<?>> create() { return Collections.<Class<?>>singleton(iterator.next()); } }).create(new ObjectPropertyAssertion.Creator<Class<?>>() { @Override public Class<?> create() { return iterator.next(); } }).apply(); } }