001// Copyright 2006, 2007, 2008, 2010, 2011 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.ioc.test;
016
017import static java.lang.Thread.sleep;
018import static org.easymock.EasyMock.isA;
019
020import java.io.File;
021import java.lang.annotation.Annotation;
022import java.lang.reflect.Method;
023import java.net.URL;
024import java.util.Locale;
025
026import org.apache.tapestry5.ioc.*;
027import org.apache.tapestry5.ioc.annotations.IntermediateType;
028import org.apache.tapestry5.ioc.def.*;
029import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
030import org.apache.tapestry5.ioc.services.MasterObjectProvider;
031import org.apache.tapestry5.ioc.services.PerthreadManager;
032import org.apache.tapestry5.ioc.services.PropertyAccess;
033import org.apache.tapestry5.ioc.services.PropertyAdapter;
034import org.apache.tapestry5.ioc.services.SymbolSource;
035import org.apache.tapestry5.ioc.services.ThreadLocale;
036import org.apache.tapestry5.ioc.services.TypeCoercer;
037import org.slf4j.Logger;
038
039/**
040 * Add factory and trainer methods for the public interfaces of Tapestry IOC.
041 */
042public class IOCTestCase extends TestBase
043{
044
045    /**
046     * Builds a Registry for the provided modules; caller should shutdown the Registry when done.
047     */
048    protected final Registry buildRegistry(Class... moduleClasses)
049    {
050        RegistryBuilder builder = new RegistryBuilder();
051
052        builder.add(moduleClasses);
053
054        return builder.build();
055    }
056
057    protected final Method findMethod(Class clazz, String methodName)
058    {
059        for (Method method : clazz.getMethods())
060        {
061            if (method.getName().equals(methodName))
062                return method;
063        }
064
065        throw new IllegalArgumentException(String.format("Class %s does not provide a method named '%s'.",
066                clazz.getName(), methodName));
067    }
068
069    protected final Method findMethod(Object subject, String methodName)
070    {
071        return findMethod(subject.getClass(), methodName);
072    }
073
074    protected final Method findMethod(String methodName)
075    {
076        return findMethod(this, methodName);
077    }
078
079    /**
080     * Combines a series of lines by forming a string with a line separator after each line.
081     */
082    protected final String join(String... lines)
083    {
084        StringBuilder result = new StringBuilder();
085
086        for (String line : lines)
087        {
088            result.append(line);
089            result.append("\n");
090        }
091
092        return result.toString();
093    }
094
095    protected final AnnotationProvider mockAnnotationProvider()
096    {
097        return newMock(AnnotationProvider.class);
098    }
099
100    @SuppressWarnings("unchecked")
101    protected final <T> Configuration<T> mockConfiguration()
102    {
103        return newMock(Configuration.class);
104    }
105
106    protected final ContributionDef mockContributionDef()
107    {
108        return newMock(ContributionDef.class);
109    }
110
111    protected final DecoratorDef mockDecoratorDef()
112    {
113        return newMock(DecoratorDef.class);
114    }
115
116    protected final DecoratorDef2 mockDecoratorDef2()
117    {
118        return newMock(DecoratorDef2.class);
119    }
120
121    protected final AdvisorDef mockAdvisorDef()
122    {
123        return newMock(AdvisorDef.class);
124    }
125
126    protected final AdvisorDef2 mockAdvisorDef2()
127    {
128        return newMock(AdvisorDef2.class);
129    }
130
131    protected final Location mockLocation()
132    {
133        return newMock(Location.class);
134    }
135
136    protected final Logger mockLogger()
137    {
138        return newMock(Logger.class);
139    }
140
141    protected final void stub_isDebugEnabled(Logger logger, boolean enabled)
142    {
143        expect(logger.isDebugEnabled()).andStubReturn(enabled);
144    }
145
146    @SuppressWarnings("unchecked")
147    protected final <K, V> MappedConfiguration<K, V> mockMappedConfiguration()
148    {
149        return newMock(MappedConfiguration.class);
150    }
151
152    protected final MessageFormatter mockMessageFormatter()
153    {
154        return newMock(MessageFormatter.class);
155    }
156
157    protected final Messages mockMessages()
158    {
159        return newMock(Messages.class);
160    }
161
162    protected final ModuleDef mockModuleDef()
163    {
164        return newMock(ModuleDef.class);
165    }
166
167    protected final ModuleDef2 mockModuleDef2()
168    {
169        return newMock(ModuleDef2.class);
170    }
171
172    protected final ObjectCreator mockObjectCreator()
173    {
174        return newMock(ObjectCreator.class);
175    }
176
177    protected final ObjectProvider mockObjectProvider()
178    {
179        return newMock(ObjectProvider.class);
180    }
181
182    @SuppressWarnings("unchecked")
183    protected final <T> OrderedConfiguration<T> mockOrderedConfiguration()
184    {
185        return newMock(OrderedConfiguration.class);
186    }
187
188    protected final Resource mockResource()
189    {
190        return newMock(Resource.class);
191    }
192
193    /**
194     * Frequently used as a placeholder for an arbitrary service (but its nice and simple).
195     */
196    protected final Runnable mockRunnable()
197    {
198        return newMock(Runnable.class);
199    }
200
201    protected final ServiceBuilderResources mockServiceBuilderResources()
202    {
203        return newMock(ServiceBuilderResources.class);
204    }
205
206    protected final ServiceDecorator mockServiceDecorator()
207    {
208        return newMock(ServiceDecorator.class);
209    }
210
211    protected final ServiceDef mockServiceDef()
212    {
213        return newMock(ServiceDef.class);
214    }
215
216    protected final ObjectLocator mockObjectLocator()
217    {
218        return newMock(ObjectLocator.class);
219    }
220
221    protected final ServiceResources mockServiceResources()
222    {
223        return newMock(ServiceResources.class);
224    }
225
226    protected final SymbolSource mockSymbolSource()
227    {
228        return newMock(SymbolSource.class);
229    }
230
231    protected final ThreadLocale mockThreadLocale()
232    {
233        return newMock(ThreadLocale.class);
234    }
235
236    protected final TypeCoercer mockTypeCoercer()
237    {
238        return newMock(TypeCoercer.class);
239    }
240
241    protected final void stub_contains(Messages messages, boolean contained)
242    {
243        expect(messages.contains(isA(String.class))).andStubReturn(contained);
244    }
245
246    protected <S, T> void train_coerce(TypeCoercer coercer, S input, Class<T> expectedType, T coercedValue)
247    {
248        expect(coercer.coerce(input, expectedType)).andReturn(coercedValue);
249    }
250
251    protected final void train_contains(Messages messages, String key, boolean result)
252    {
253        expect(messages.contains(key)).andReturn(result).atLeastOnce();
254    }
255
256    protected final void train_createInterceptor(ServiceDecorator decorator, Object coreObject, Object interceptor)
257    {
258        expect(decorator.createInterceptor(coreObject)).andReturn(interceptor);
259    }
260
261    protected final void train_createObject(ObjectCreator creator, Object service)
262    {
263        expect(creator.createObject()).andReturn(service);
264    }
265
266    protected final void train_expandSymbols(SymbolSource source, String input)
267    {
268        train_expandSymbols(source, input, input);
269    }
270
271    protected final void train_expandSymbols(SymbolSource source, String input, String expanded)
272    {
273        expect(source.expandSymbols(input)).andReturn(expanded);
274    }
275
276    protected final void train_forFile(Resource resource, String relativePath, Resource file)
277    {
278        expect(resource.forFile(relativePath)).andReturn(file);
279    }
280
281    protected final void train_forLocale(Resource base, Locale locale, Resource resource)
282    {
283        expect(base.forLocale(locale)).andReturn(resource);
284    }
285
286    /**
287     * Have to put the result before the varargs.
288     */
289    protected void train_format(MessageFormatter formatter, String result, Object... arguments)
290    {
291        expect(formatter.format(arguments)).andReturn(result);
292    }
293
294    protected final void train_get(Messages messages, String key, String message)
295    {
296        expect(messages.get(key)).andReturn(message).atLeastOnce();
297    }
298
299    protected final void train_getLocale(ThreadLocale threadLocale, Locale locale)
300    {
301        expect(threadLocale.getLocale()).andReturn(locale);
302    }
303
304    protected final void train_getLogger(LoggerSource source, String serviceId, Logger logger)
305    {
306        expect(source.getLogger(serviceId)).andReturn(logger).atLeastOnce();
307    }
308
309    protected final void train_getMessageFormatter(Messages messages, String key, MessageFormatter formatter)
310    {
311        expect(messages.getFormatter(key)).andReturn(formatter).atLeastOnce();
312    }
313
314    protected final void train_getPath(Resource r, String path)
315    {
316        expect(r.getPath()).andReturn(path).atLeastOnce();
317    }
318
319    protected final <T> void train_getService(ObjectLocator locator, Class<T> serviceInterface, T service)
320    {
321        expect(locator.getService(serviceInterface)).andReturn(service);
322    }
323
324    protected final <T> void train_getService(ObjectLocator locator, String serviceId, Class<T> serviceInterface,
325            T service)
326    {
327        expect(locator.getService(serviceId, serviceInterface)).andReturn(service);
328    }
329
330    protected final void train_getServiceId(ServiceDef def, String serviceId)
331    {
332        expect(def.getServiceId()).andReturn(serviceId).atLeastOnce();
333    }
334
335    protected final void train_getServiceId(ServiceResources resources, String serviceId)
336    {
337        expect(resources.getServiceId()).andReturn(serviceId).atLeastOnce();
338    }
339
340    protected final void train_getServiceInterface(ServiceDef def, Class serviceInterface)
341    {
342        expect(def.getServiceInterface()).andReturn(serviceInterface).atLeastOnce();
343    }
344
345    protected final void train_getServiceInterface(ServiceResources resources, Class serviceInterface)
346    {
347        expect(resources.getServiceInterface()).andReturn(serviceInterface).atLeastOnce();
348    }
349
350    protected final void train_getLogger(ServiceResources resources, Logger log)
351    {
352        expect(resources.getLogger()).andReturn(log).atLeastOnce();
353    }
354
355    protected final void train_isDebugEnabled(Logger log, boolean debugEnabled)
356    {
357        expect(log.isDebugEnabled()).andReturn(debugEnabled);
358    }
359
360    protected final void train_isTraceEnabled(Logger log, boolean traceEnabled)
361    {
362        expect(log.isTraceEnabled()).andReturn(traceEnabled);
363    }
364
365    protected final void train_matches(DecoratorDef decoratorDef, ServiceDef serviceDef, boolean matches)
366    {
367        expect(decoratorDef.matches(serviceDef)).andReturn(matches);
368    }
369
370    protected final void train_matches(AdvisorDef advisorDef, ServiceDef serviceDef, boolean matches)
371    {
372        expect(advisorDef.matches(serviceDef)).andReturn(matches);
373    }
374
375    protected final <T> void train_provide(ObjectProvider provider, Class<T> objectType,
376            AnnotationProvider annotationProvider, ObjectLocator locator, T object)
377    {
378        expect(provider.provide(objectType, annotationProvider, locator)).andReturn(object);
379    }
380
381    protected final void train_toURL(Resource resource, URL url)
382    {
383        expect(resource.toURL()).andReturn(url).atLeastOnce();
384    }
385
386    protected final <T extends Annotation> void train_getAnnotation(AnnotationProvider annotationProvider,
387            Class<T> annotationClass, T annotation)
388    {
389        expect(annotationProvider.getAnnotation(annotationClass)).andReturn(annotation);
390    }
391
392    protected final MasterObjectProvider mockMasterObjectProvider()
393    {
394        return newMock(MasterObjectProvider.class);
395    }
396
397    protected final void train_value(IntermediateType it, Class value)
398    {
399        expect(it.value()).andReturn(value);
400    }
401
402    protected final IntermediateType newIntermediateType()
403    {
404        return newMock(IntermediateType.class);
405    }
406
407    protected final PropertyAdapter mockPropertyAdapter()
408    {
409        return newMock(PropertyAdapter.class);
410    }
411
412    protected final ClassPropertyAdapter mockClassPropertyAdapter()
413    {
414        return newMock(ClassPropertyAdapter.class);
415    }
416
417    protected final PropertyAccess mockPropertyAccess()
418    {
419        return newMock(PropertyAccess.class);
420    }
421
422    protected final <T> void train_autobuild(ObjectLocator locator, Class<T> beanClass, T instance)
423    {
424        expect(locator.autobuild(beanClass)).andReturn(instance);
425    }
426
427    protected final PerthreadManager mockPerthreadManager()
428    {
429        return newMock(PerthreadManager.class);
430    }
431
432    protected final ServiceResources mockServiceResources(OperationTracker tracker)
433    {
434        ServiceResources resources = mockServiceResources();
435
436        train_getTracker(resources, tracker);
437
438        return resources;
439    }
440
441    protected final void train_getTracker(ServiceResources resources, OperationTracker tracker)
442    {
443        expect(resources.getTracker()).andReturn(tracker).atLeastOnce();
444    }
445
446    protected final ServiceBuilderResources mockServiceBuilderResources(OperationTracker tracker)
447    {
448        ServiceBuilderResources resources = mockServiceBuilderResources();
449
450        train_getTracker(resources, tracker);
451
452        return resources;
453    }
454
455    protected final void train_valueForSymbol(SymbolSource symbolSource, String symbolName, String value)
456    {
457        expect(symbolSource.valueForSymbol(symbolName)).andReturn(value).atLeastOnce();
458    }
459
460    /**
461     * Touches the file, changing the last modified time to the current time.
462     * Does not return until the last modified time for the file actually changes (how long that takes
463     * is JDK, OS and file system dependent).
464     */
465    protected final void touch(File f) throws Exception
466    {
467        long startModified = f.lastModified();
468
469        int index = 0;
470
471        while (true)
472        {
473            f.setLastModified(System.currentTimeMillis());
474
475            long newModified = f.lastModified();
476
477            if (newModified != startModified)
478                return;
479
480            // Sleep an ever increasing amount, to ensure that the filesystem
481            // catches the change to the file. The Ubuntu CI Server appears
482            // to need longer waits.
483
484            sleep(50 * (2 ^ index++));
485        }
486    }
487}