package rabbitescape.render;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import org.junit.Test;
import rabbitescape.render.androidlike.Bitmap;
public class TestReLruCache
{
@Test
public void Can_get_elements_that_were_added()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 10L );
Obj obj1 = new Obj( 1 );
Obj obj2 = new Obj( 1 );
cache.put( "obj1", obj1 );
cache.put( "obj2", obj2 );
// This is what we are testing: can get things out
assertThat( cache.get( "obj1" ), sameInstance( obj1 ) );
assertThat( cache.get( "obj2" ), sameInstance( obj2 ) );
}
@Test
public void When_space_is_still_free_size_is_the_sum_of_added_elements()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 100 );
cache.put( "obj1", new Obj( 14 ) );
cache.put( "obj2", new Obj( 1 ) );
// This is what we are testing: size is the total
assertThat( cache.currentSize(), is( 15L ) );
// Another object adds to the size again
cache.put( "obj3", new Obj( 3 ) );
assertThat( cache.currentSize(), is( 18L ) );
}
@Test
public void When_space_is_still_free_replacing_an_object_replaces_its_size()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 100 );
cache.put( "obj1", new Obj( 14 ) );
cache.put( "obj2", new Obj( 1 ) );
// Sanity
assertThat( cache.currentSize(), is( 15L ) );
// obj2 replaced - the size it takes changes from 1 to 3
cache.put( "obj2", new Obj( 3 ) );
assertThat( cache.currentSize(), is( 17L ) );
// obj1 replaced - the size it takes changes from 14 to 7
cache.put( "obj1", new Obj( 7 ) );
assertThat( cache.currentSize(), is( 10L ) );
}
@Test
public void When_space_overflows_last_used_object_is_removed()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 20 );
Obj obj1 = new Obj( 12 );
Obj obj2 = new Obj( 10 );
cache.put( "obj1", obj1 );
cache.put( "obj2", obj2 ); // Here we go over max size
// Sanity: obj2 is in cache
assertThat( cache.get( "obj2" ), sameInstance( obj2 ) );
assertThat( obj2.recycled, is( false ) );
// This is what we are testing: obj1 got removed
assertThat( cache.get( "obj1" ), nullValue() );
assertThat( obj1.recycled, is( true ) );
assertThat( cache.currentSize(), is( 10L ) );
}
@Test
public void When_space_overflows_last_used_object_is_removed_even_if_it_was_added_later()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 13 );
Obj obj1 = new Obj( 5 );
Obj obj2 = new Obj( 5 );
Obj obj3 = new Obj( 5 );
cache.put( "obj1", obj1 );
cache.put( "obj2", obj2 );
cache.get( "obj1" ); // Moves obj1 to front
// This is what we are testing: go over size
cache.put( "obj3", obj3 );
// obj1 is in the cache because it is more recently used
assertThat( cache.get( "obj1" ), sameInstance( obj1 ) );
assertThat( obj1.recycled, is( false ) );
// This is what we are testing: obj2 got removed
assertThat( cache.get( "obj2" ), nullValue() );
assertThat( obj2.recycled, is( true ) );
assertThat( cache.currentSize(), is( 10L ) );
}
@Test
public void Adding_an_object_makes_it_recently_used()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 13 );
Obj obj1a = new Obj( 5 );
Obj obj1b = new Obj( 5 );
Obj obj2 = new Obj( 5 );
Obj obj3 = new Obj( 5 );
cache.put( "obj1", obj1a );
cache.put( "obj2", obj2 );
cache.put( "obj1", obj1b ); // obj1 to front, even though different
// This is what we are testing: go over size
cache.put( "obj3", obj3 );
// obj1 is in the cache because it is more recently used
assertThat( cache.get( "obj1" ), sameInstance( obj1b ) );
assertThat( obj1b.recycled, is( false ) );
// This is what we are testing: obj2 got removed
assertThat( cache.get( "obj2" ), nullValue() );
assertThat( obj2.recycled, is( true ) );
assertThat( cache.currentSize(), is( 10L ) );
}
@Test
public void Adding_something_huge_stores_it()
{
ReLruCache<Obj> cache = new ReLruCache<Obj>( 13 );
Obj obj1 = new Obj( 5 );
Obj obj2 = new Obj( 5 );
Obj obj3 = new Obj( 15 );
cache.put( "obj1", obj1 );
cache.put( "obj2", obj2 );
// This is what we are testing: object overfills whole cache
cache.put( "obj3", obj3 );
// obj3 was stored, even though it's huge
assertThat( cache.get( "obj3" ), sameInstance( obj3 ) );
assertThat( obj3.recycled, is( false ) );
// obj1 and obj2 got removed
assertThat( cache.get( "obj1" ), nullValue() );
assertThat( cache.get( "obj2" ), nullValue() );
assertThat( obj1.recycled, is( true ) );
assertThat( obj2.recycled, is( true ) );
assertThat( cache.currentSize(), is( 15L ) );
}
// ---
private static class Obj implements Bitmap
{
private final int sz;
public boolean recycled = false;
public Obj( int size )
{
sz = size;
}
@Override
public String name()
{
throw new UnsupportedOperationException();
}
@Override
public int width()
{
throw new UnsupportedOperationException();
}
@Override
public int height()
{
throw new UnsupportedOperationException();
}
@Override
public long getByteCount()
{
return sz;
}
@Override
public void recycle()
{
if ( recycled )
{
throw new AssertionError( "Object recycled twice!" );
}
recycled = true;
}
}
}