/*
* Created on Mar 7, 2006
*
* 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.
*
* Copyright @2006 the original author or authors.
*/
package org.springmodules.cache.config;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.easymock.AbstractMatcher;
import org.easymock.MockControl;
import org.easymock.classextension.MockClassControl;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springmodules.cache.config.CacheSetupStrategyElementBuilder.CacheKeyGeneratorElementBuilder;
import org.springmodules.cache.config.CacheSetupStrategyElementBuilder.CachingModelElementBuilder;
import org.springmodules.cache.config.CacheSetupStrategyElementBuilder.FlushingModelElementBuilder;
import org.springmodules.cache.interceptor.caching.CachingListener;
import org.springmodules.cache.mock.MockCachingModel;
import org.springmodules.cache.mock.MockFlushingModel;
import org.springmodules.cache.provider.CacheProviderFacade;
/**
* <p>
* Unit Tests for <code>{@link AbstractCacheSetupStrategyParser}</code>.
* </p>
*
* @author Alex Ruiz
*/
public class CacheSetupStrategyParserTests
extends AbstractSchemaBasedConfigurationTestCase
{
public class CacheSetupStrategyPropertySourceMatcher
extends AbstractMatcher
{
/**
* @see AbstractMatcher#argumentMatches(Object, Object)
*/
protected boolean argumentMatches( Object expected, Object actual )
{
if ( !( expected instanceof CacheSetupStrategyPropertySource ) )
{
return expected.equals( actual );
}
if ( !( actual instanceof CacheSetupStrategyPropertySource ) )
{
return false;
}
return equals( (CacheSetupStrategyPropertySource) expected, (CacheSetupStrategyPropertySource) actual );
}
private boolean equals( CacheSetupStrategyPropertySource expected, CacheSetupStrategyPropertySource actual )
{
if ( expected == actual )
{
return true;
}
if ( !equals( (RuntimeBeanReference) expected.cacheKeyGenerator,
(RuntimeBeanReference) actual.cacheKeyGenerator ) )
{
return false;
}
if ( !equals( expected.cacheProviderFacadeReference, actual.cacheProviderFacadeReference ) )
{
return false;
}
if ( !equals( expected.cachingListeners, actual.cachingListeners ) )
{
return false;
}
if ( !ObjectUtils.nullSafeEquals( expected.cachingModelMap, actual.cachingModelMap ) )
{
return false;
}
if ( !ObjectUtils.nullSafeEquals( expected.flushingModelMap, actual.flushingModelMap ) )
{
return false;
}
return true;
}
/**
* Verifies that the given lists of <code>{@link RuntimeBeanReference}</code> are equal.
*
* @param expected the expected list of <code>RuntimeBeanReference</code>
* @param actual the actual list of <code>RuntimeBeanReference</code>
* @return <code>true</code> if the given lists are equal
*/
private boolean equals( List expected, List actual )
{
if ( !CollectionUtils.isEmpty( expected ) )
{
int count = expected.size();
if ( actual.size() != count )
{
return false;
}
for ( int i = 0; i < count; i++ )
{
if ( !equals( (RuntimeBeanReference) expected.get( i ), (RuntimeBeanReference) actual.get( i ) ) )
{
return false;
}
}
}
else if ( !CollectionUtils.isEmpty( actual ) )
{
return false;
}
return true;
}
private boolean equals( RuntimeBeanReference expected, RuntimeBeanReference actual )
{
if ( expected == actual )
{
return true;
}
if ( !ObjectUtils.nullSafeEquals( expected.getBeanName(), actual.getBeanName() ) )
{
return false;
}
return true;
}
}
protected BeanReferenceParser beanReferenceParser;
protected MockControl beanReferenceParserControl;
private CacheSetupStrategyElementBuilder elementBuilder;
private CacheModelParser modelParser;
private MockControl modelParserControl;
private AbstractCacheSetupStrategyParser strategyParser;
private MockClassControl strategyParserControl;
private CachingListenerValidator validator;
private MockControl validatorControl;
/**
* Constructor.
*
* @param name the name of the test case
*/
public CacheSetupStrategyParserTests( String name )
{
super( name );
}
public void testParse()
{
int listenerCount = 5;
int modelCount = 2;
elementBuilder.setDefaultCachingListenerElementBuilders( listenerCount );
// expectations for cache key generator.
RuntimeBeanReference cacheKeyGenerator = expectCacheKeyGeneratorParsing();
// expectations for parsing caching listeners.
List cachingListeners = new ArrayList();
for ( int i = 0; i < listenerCount; i++ )
{
String refId = elementBuilder.cachingListenerElementBuilders[i].refId;
registry.registerBeanDefinition( refId, new RootBeanDefinition( CachingListener.class ) );
Element cachingListenerElement = elementBuilder.cachingListenerElementBuilders[i].toXml();
// parse caching listener element
beanReferenceParser.parse( cachingListenerElement, parserContext, true );
RuntimeBeanReference cachingListenerReference = new RuntimeBeanReference( refId );
beanReferenceParserControl.setReturnValue( cachingListenerReference );
// validate the caching listener
validator.validate( cachingListenerReference, i, parserContext );
cachingListeners.add( cachingListenerReference );
}
registerCacheProviderFacadeDefinition();
// expectations for parsing cache models.
elementBuilder.setDefaultCachingModelElementBuilders( modelCount );
elementBuilder.setDefaultFlushingModelElementBuilders( modelCount );
Map cachingModelMap = expectCachingModelParsing();
Map flushingModelMap = expectFlushingModelParsing();
Element element = elementBuilder.toXml();
CacheSetupStrategyPropertySource propertySource =
new CacheSetupStrategyPropertySource( cacheKeyGenerator,
new RuntimeBeanReference( elementBuilder.cacheProviderId ),
cachingListeners, cachingModelMap, flushingModelMap );
strategyParser.parseCacheSetupStrategy( element, parserContext, propertySource );
strategyParserControl.setMatcher( new CacheSetupStrategyPropertySourceMatcher() );
replay();
// method to test
strategyParser.parse( element, parserContext );
verify();
}
/**
* Verifies that the method
* <code>{@link AbstractCacheSetupStrategyParser#parse(Element, org.springframework.beans.factory.xml.ParserContext)}</code>
* does not create a list of caching models if the XML element to parse does not include any "cachingListener"
* subelement.
*/
public void testParseWithoutCachingListeners()
{
int modelCount = 2;
registerCacheProviderFacadeDefinition();
elementBuilder.setDefaultCachingModelElementBuilders( modelCount );
elementBuilder.setDefaultFlushingModelElementBuilders( modelCount );
Map cachingModelMap = expectCachingModelParsing();
Map flushingModelMap = expectFlushingModelParsing();
Element element = elementBuilder.toXml();
CacheSetupStrategyPropertySource propertySource =
new CacheSetupStrategyPropertySource( null, new RuntimeBeanReference( elementBuilder.cacheProviderId ),
null, cachingModelMap, flushingModelMap );
strategyParser.parseCacheSetupStrategy( element, parserContext, propertySource );
strategyParserControl.setMatcher( new CacheSetupStrategyPropertySourceMatcher() );
replay();
// method to test
strategyParser.parse( element, parserContext );
verify();
}
public void testParseWithoutCachingModels()
{
int modelCount = 2;
registerCacheProviderFacadeDefinition();
elementBuilder.setDefaultFlushingModelElementBuilders( modelCount );
Map flushingModelMap = expectFlushingModelParsing();
Element element = elementBuilder.toXml();
CacheSetupStrategyPropertySource propertySource =
new CacheSetupStrategyPropertySource( null, new RuntimeBeanReference( elementBuilder.cacheProviderId ),
null, null, flushingModelMap );
strategyParser.parseCacheSetupStrategy( element, parserContext, propertySource );
strategyParserControl.setMatcher( new CacheSetupStrategyPropertySourceMatcher() );
replay();
// method to test
strategyParser.parse( element, parserContext );
verify();
}
public void testParseWithoutFlushingModels()
{
int modelCount = 2;
registerCacheProviderFacadeDefinition();
elementBuilder.setDefaultCachingModelElementBuilders( modelCount );
Map cachingModelMap = expectCachingModelParsing();
Element element = elementBuilder.toXml();
CacheSetupStrategyPropertySource propertySource =
new CacheSetupStrategyPropertySource( null, new RuntimeBeanReference( elementBuilder.cacheProviderId ),
null, cachingModelMap, null );
strategyParser.parseCacheSetupStrategy( element, parserContext, propertySource );
strategyParserControl.setMatcher( new CacheSetupStrategyPropertySourceMatcher() );
replay();
// method to test
strategyParser.parse( element, parserContext );
verify();
}
public void testParseWithRegistryNotHavingCacheProviderFacade()
{
replay();
try
{
DomElementStub domElementStub = new DomElementStub( "someElement" );
domElementStub.setAttribute( "providerId", "someId" );
strategyParser.parse( domElementStub, parserContext );
fail();
}
catch ( IllegalStateException exception )
{
// expecting exception
}
}
protected void onSetUp()
throws Exception
{
beanReferenceParserControl = MockControl.createControl( BeanReferenceParser.class );
beanReferenceParser = (BeanReferenceParser) beanReferenceParserControl.getMock();
setUpModelParser();
setUpValidator();
setUpStrategyParser();
elementBuilder = new CacheSetupStrategyElementBuilder();
elementBuilder.cacheProviderId = "cacheProvider";
}
private RuntimeBeanReference expectCacheKeyGeneratorParsing()
{
CacheKeyGeneratorElementBuilder builder = new CacheKeyGeneratorElementBuilder();
elementBuilder.cacheKeyGeneratorElementBuilder = builder;
RuntimeBeanReference cacheKeyGenerator = new RuntimeBeanReference( "cacheKeyGenerator" );
beanReferenceParser.parse( builder.toXml(), parserContext );
beanReferenceParserControl.setReturnValue( cacheKeyGenerator );
return cacheKeyGenerator;
}
private Map expectCachingModelParsing()
{
Map cachingModelMap = new HashMap();
int cachingModelCount = elementBuilder.cachingModelElementBuilders.length;
expectGetCacheModelKey();
for ( int i = 0; i < cachingModelCount; i++ )
{
MockCachingModel model = new MockCachingModel();
CachingModelElementBuilder builder = elementBuilder.cachingModelElementBuilders[i];
modelParser.parseCachingModel( builder.toXml() );
modelParserControl.setReturnValue( model );
cachingModelMap.put( builder.target, model );
}
return cachingModelMap;
}
private Map expectFlushingModelParsing()
{
Map flushingModelMap = new HashMap();
int flushingModelCount = elementBuilder.flushingModelElementBuilders.length;
expectGetCacheModelKey();
for ( int i = 0; i < flushingModelCount; i++ )
{
FlushingModelElementBuilder builder = elementBuilder.flushingModelElementBuilders[i];
MockFlushingModel model = new MockFlushingModel();
modelParser.parseFlushingModel( builder.toXml() );
modelParserControl.setReturnValue( model );
flushingModelMap.put( builder.target, model );
}
return flushingModelMap;
}
private void expectGetCacheModelKey()
{
strategyParser.getCacheModelKey();
strategyParserControl.setReturnValue( "target" );
}
private void registerCacheProviderFacadeDefinition()
{
RootBeanDefinition cacheProviderFacade = new RootBeanDefinition( CacheProviderFacade.class );
registry.registerBeanDefinition( elementBuilder.cacheProviderId, cacheProviderFacade );
}
private void replay()
{
beanReferenceParserControl.replay();
modelParserControl.replay();
strategyParserControl.replay();
validatorControl.replay();
}
private void setUpModelParser()
{
modelParserControl = MockControl.createControl( CacheModelParser.class );
modelParser = (CacheModelParser) modelParserControl.getMock();
}
private void setUpStrategyParser()
throws Exception
{
Class targetClass = AbstractCacheSetupStrategyParser.class;
Method getCacheModelKeyMethod = targetClass.getDeclaredMethod( "getCacheModelKey", new Class[0] );
Method parseCacheSetupStrategyMethod =
targetClass.getDeclaredMethod( "parseCacheSetupStrategy", new Class[] { Element.class, ParserContext.class,
CacheSetupStrategyPropertySource.class } );
Method[] methodsToMock = { getCacheModelKeyMethod, parseCacheSetupStrategyMethod };
strategyParserControl = MockClassControl.createControl( targetClass, null, null, methodsToMock );
strategyParser = (AbstractCacheSetupStrategyParser) strategyParserControl.getMock();
strategyParser.setBeanReferenceParser( beanReferenceParser );
strategyParser.setCacheModelParser( modelParser );
strategyParser.setCachingListenerValidator( validator );
}
private void setUpValidator()
{
Class targetClass = CachingListenerValidator.class;
validatorControl = MockControl.createControl( targetClass );
validator = (CachingListenerValidator) validatorControl.getMock();
}
private void verify()
{
beanReferenceParserControl.verify();
modelParserControl.verify();
strategyParserControl.verify();
validatorControl.verify();
}
}