package org.codehaus.plexus.component.collection;
import static com.google.common.collect.Sets.newHashSet;
import junit.framework.TestCase;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.collections.LiveMap;
import org.codehaus.plexus.component.repository.exception.ComponentRepositoryException;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
public class LiveMapTest extends TestCase
{
private DefaultPlexusContainer container;
private Component unknown;
protected void setUp() throws Exception
{
super.setUp();
container = new DefaultPlexusContainer();
unknown = new Component( "Unknown" );
}
public void testEmpty() throws Exception
{
LiveMap<Component> map = new LiveMap<Component>( container, Component.class, null, null );
Map<String, Component> all = emptyMap();
// isEmpty and size
assertTrue( map.isEmpty() );
assertEquals( 0, map.size() );
// get
assertNull( map.get( "unknown" ) );
// contains
assertFalse( map.containsKey( "unknown" ) );
assertFalse( map.containsValue( unknown ) );
// keySet, values, entrySet
assertEquals( all.keySet(), map.keySet() );
assertEquals( newHashSet( all.values() ), newHashSet( map.values() ) );
assertEquals( all.entrySet(), map.entrySet() );
// hashCode, equals, and toString
assertEquals( emptyMap().hashCode(), map.hashCode() );
assertTrue( map.equals( emptyMap() ) );
assertNotNull( map.toString() );
assertTrue( map.toString().length() > 0 );
// List must be immutable
assertImmutable( map );
}
public void testSingleComponent() throws Exception
{
LiveMap<Component> map = new LiveMap<Component>( container, Component.class, null, null );
Component zero = addComponent( "zero" );
Map<String, Component> all = singletonMap( "zero", zero );
// isEmpty and size
assertFalse( map.isEmpty() );
assertEquals( 1, map.size() );
// get
assertSame( zero, map.get( "zero" ) );
assertNull( map.get( "unknown" ) );
// contains
assertTrue( map.containsKey( "zero" ) );
assertFalse( map.containsKey( "unknown" ) );
assertTrue( map.containsValue( zero ) );
assertFalse( map.containsValue( unknown ) );
// keySet, values, entrySet
assertEquals( all.keySet(), map.keySet() );
assertEquals( newHashSet( all.values() ), newHashSet( map.values() ) );
assertEquals( all.entrySet(), map.entrySet() );
// hashCode, equals and toString
assertEquals( all.hashCode(), map.hashCode() );
assertTrue( map.equals( all ) );
assertNotNull( map.toString() );
assertTrue( map.toString().length() > 0 );
// List must be immutable
assertImmutable( map );
}
public void testAllHints() throws Exception
{
// components are in the order they are added to the container
LiveMap<Component> map = new LiveMap<Component>( container, Component.class, null, null );
Map<String, Component> all = new LinkedHashMap<String, Component>();
all.put( "zero", addComponent( "zero" ) );
all.put( "one", addComponent( "one" ) );
all.put( "two", addComponent( "two" ) );
all.put( "three", addComponent( "three" ) );
all.put( "four", addComponent( "four" ) );
assertZeroToFour( all, map );
}
public void testSpecificHints() throws Exception
{
LiveMap<Component> map = new LiveMap<Component>( container,
Component.class,
asList( "zero", "one", "two", "three", "four" ),
null );
Map<String, Component> all = new LinkedHashMap<String, Component>();
all.put( "zero", addComponent( "zero" ) );
all.put( "one", addComponent( "one" ) );
all.put( "two", addComponent( "two" ) );
all.put( "three", addComponent( "three" ) );
all.put( "four", addComponent( "four" ) );
Component five = addComponent( "five" );
assertZeroToFour( all, map );
}
public void testSpecificHintsWithRelease() throws Exception
{
LiveMap<Component> map = new LiveMap<Component>( container,
Component.class,
asList( "zero", "one", "two", "three", "four" ),
null );
Map<String, Component> all = new LinkedHashMap<String, Component>();
// add each component in a child realm
ClassRealm realmZero = container.createChildRealm( "zero" );
all.put( "zero", addComponent( "zero", realmZero ) );
ClassRealm realmOne = container.createChildRealm( "one" );
all.put( "one", addComponent( "one", realmOne ) );
ClassRealm realmTwo = container.createChildRealm( "two" );
all.put( "two", addComponent( "two", realmTwo ) );
ClassRealm realmThree = container.createChildRealm( "three" );
all.put( "three", addComponent( "three", realmThree ) );
ClassRealm realmFour = container.createChildRealm( "four" );
all.put( "four", addComponent( "four", realmFour ) );
// verify we have a normal 0-4 list now
assertZeroToFour( all, map );
// remove realm 4 which contains component 4
container.removeComponentRealm( realmFour );
all.remove( "four" );
// verify we now have a 0-3 list
assertEquals( all, map );
// remove realm 2 which contains component 2
container.removeComponentRealm( realmTwo );
all.remove( "two" );
// verify we now have a 0,1,3 list
assertEquals( all, map );
// remove realm 0 which contains component 0
container.removeComponentRealm( realmZero );
all.remove( "zero" );
// verify we now have a 1,3 list
assertEquals( all, map );
// add them back
all.put( "zero", addComponent( "zero", realmZero ) );
all.put( "four", addComponent( "four", realmFour ) );
all.put( "two", addComponent( "two", realmTwo ) );
// verify we have a normal 0-4 list again
assertZeroToFour( all, map );
}
private void assertZeroToFour( Map<String, Component> expected, LiveMap<Component> map )
{
// get input values
assertEquals( 5, expected.size() );
Component zero = expected.get( "zero" );
Component one = expected.get( "one" );
Component two = expected.get( "two" );
Component three = expected.get( "three" );
Component four = expected.get( "four" );
// isEmpty and size
assertFalse( map.isEmpty() );
assertEquals( 5, map.size() );
// get
assertSame( zero, map.get( "zero" ) );
assertSame( one, map.get( "one" ) );
assertSame( two, map.get( "two" ) );
assertSame( three, map.get( "three" ) );
assertSame( four, map.get( "four" ) );
assertNull( map.get( "unknown" ) );
// contains
assertTrue( map.containsKey( "zero" ) );
assertTrue( map.containsKey( "two" ) );
assertTrue( map.containsKey( "four" ) );
assertFalse( map.containsKey( "unknown" ) );
assertTrue( map.containsValue( zero ) );
assertTrue( map.containsValue( two ) );
assertTrue( map.containsValue( four ) );
assertFalse( map.containsValue( unknown ) );
// keySet, values, entrySet
assertEquals( expected.keySet(), map.keySet() );
assertEquals( newHashSet( expected.values() ), newHashSet( map.values() ) );
assertEquals( expected.entrySet(), map.entrySet() );
// hashCode, equals and toString
assertEquals( expected.hashCode(), map.hashCode() );
assertTrue( map.equals( expected ) );
assertNotNull( map.toString() );
assertTrue( map.toString().length() > 0 );
// List must be immutable
assertImmutable( map );
}
private Component addComponent( String name )
throws ComponentRepositoryException
{
return addComponent( name, container.getContainerRealm() );
}
private Component addComponent( String name, ClassRealm containerRealm )
throws ComponentRepositoryException
{
Component component = new Component( name );
container.addComponent( component, Component.class, name, containerRealm );
return component;
}
private static void assertImmutable( ConcurrentMap<String, Component> map )
{
Component component = new Component( "component" );
Map<String, Component> all = singletonMap( "component", component );
try
{
map.put( "component", component );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.putIfAbsent( "component", component );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.putAll( all );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.remove( "component" );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.remove( "component", component );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.replace( "component", component, component );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.replace( "component", component );
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
try
{
map.clear();
fail( "Expected UnsupportedOperationException" );
}
catch ( UnsupportedOperationException expected )
{
}
}
public static class Component
{
public final String name;
public Component( String name )
{
this.name = name;
}
public String toString()
{
return name;
}
}
}