/* * JBoss, Home of Professional Open Source * Copyright 2010, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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. */ package org.jboss.arquillian.impl; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import junit.framework.Assert; import org.jboss.arquillian.impl.core.ManagerBuilder; import org.jboss.arquillian.impl.core.ManagerImpl; import org.jboss.arquillian.impl.core.UncheckedThrow; import org.jboss.arquillian.impl.core.context.ClassContextImpl; import org.jboss.arquillian.impl.core.context.ContainerContextImpl; import org.jboss.arquillian.impl.core.context.DeploymentContextImpl; import org.jboss.arquillian.impl.core.context.SuiteContextImpl; import org.jboss.arquillian.impl.core.context.TestContextImpl; import org.jboss.arquillian.impl.core.spi.Manager; import org.jboss.arquillian.impl.core.spi.context.ClassContext; import org.jboss.arquillian.impl.core.spi.context.ContainerContext; import org.jboss.arquillian.impl.core.spi.context.Context; import org.jboss.arquillian.impl.core.spi.context.DeploymentContext; import org.jboss.arquillian.impl.core.spi.context.SuiteContext; import org.jboss.arquillian.impl.core.spi.context.TestContext; import org.jboss.arquillian.spi.core.Injector; import org.jboss.arquillian.spi.core.Instance; import org.jboss.arquillian.spi.core.InstanceProducer; import org.jboss.arquillian.spi.core.annotation.ApplicationScoped; import org.jboss.arquillian.spi.core.annotation.Inject; import org.jboss.arquillian.spi.core.annotation.Observes; import org.junit.After; import org.junit.Before; /** * AbstractManagerTestBase * * @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a> * @version $Revision: $ */ public abstract class AbstractManagerTestBase { private ManagerImpl manager; @Before public final void create() { ManagerBuilder builder = ManagerBuilder.from(); addContexts(builder); builder.extension(EventRegisterObserver.class); addExtensions(builder); manager = builder.create(); manager.resolve(Injector.class).inject(this); startContexts(manager); } @After public final void destory() { manager.shutdown(); } public ManagerImpl getManager() { return manager; } //-------------------------------------------------------------------------------------|| // Assertions and Helper operations ----------------------------------------------------|| //-------------------------------------------------------------------------------------|| public final void fire(Object event) { manager.fire(event); } public final <T> void bind(Class<? extends Annotation> scope, Class<T> type, T instance) { manager.bind(scope, type, instance); } public final void assertEventFired(Class<?> type) { Assert.assertNotNull( "Event " + type.getName() + " should have been fired", manager.resolve(EventRegister.class).getCount(type)); } public final void assertEventFired(Class<?> type, Integer count) { Assert.assertEquals( "The event of exact type " + type.getName() + " should have been fired", count, manager.resolve(EventRegister.class).getCount(type)); } public final void assertEventFiredTyped(Class<?> type, Integer count) { Assert.assertEquals( "The event of assiganble type to " + type.getName() + " should have been fired", count, manager.resolve(EventRegister.class).getCountTyped(type)); } public final void assertEventFiredInContext(Class<?> type, Class<? extends Context> activeContext) { Assert.assertTrue( "Event " + type.getName() + " should have been fired within context " + activeContext.getName(), manager.resolve(EventRegister.class).wasActive(type, activeContext)); } //-------------------------------------------------------------------------------------|| // Extendables ------------------------------------------------------------------------|| //-------------------------------------------------------------------------------------|| protected void addContexts(ManagerBuilder builder) { builder.context(SuiteContextImpl.class) .context(ClassContextImpl.class) .context(TestContextImpl.class) .context(ContainerContextImpl.class) .context(DeploymentContextImpl.class); } protected abstract void addExtensions(ManagerBuilder builder); protected void startContexts(Manager manager) { manager.getContext(SuiteContext.class).activate(); manager.getContext(ClassContext.class).activate(super.getClass()); manager.getContext(TestContext.class).activate(this); } //-------------------------------------------------------------------------------------|| // Internal Helpers - Track events ----------------------------------------------------|| //-------------------------------------------------------------------------------------|| public static class EventRegisterObserver { @Inject @ApplicationScoped private InstanceProducer<EventRegister> register; @Inject private Instance<SuiteContext> suiteContext; @Inject private Instance<ClassContext> classContext; @Inject private Instance<TestContext> testContext; @Inject private Instance<ContainerContext> containerContext; @Inject private Instance<DeploymentContext> deploymentContext; public void register(@Observes Object event) { if(register.get() == null) { register.set(new EventRegister()); } EventRegister reg = register.get(); reg.add( event.getClass(), new EventRecording() .add(SuiteContext.class, suiteContext.get().isActive()) .add(ClassContext.class, classContext.get().isActive()) .add(TestContext.class, testContext.get().isActive()) .add(ContainerContext.class, containerContext.get().isActive()) .add(DeploymentContext.class, deploymentContext.get().isActive())); if(event instanceof Throwable) { // we are listening to Object which is not really a good thing, so throw exceptions if found. UncheckedThrow.throwUnchecked((Throwable)event); } } } public static class EventRegister { private Map<Class<?>, List<EventRecording>> events; public EventRegister() { events = new HashMap<Class<?>, List<EventRecording>>(); } public void add(Class<?> type, EventRecording recording) { if(events.get(type) == null) { List<EventRecording> recordings = new ArrayList<EventRecording>(); recordings.add(recording); events.put(type, recordings); } else { events.get(type).add(recording); } } /** * Get the count of a assignable count. * * @param type The assignable event type * @return Number of times fired */ public Integer getCountTyped(Class<?> type) { int count = 0; for(Map.Entry<Class<?>, List<EventRecording>> recordingEntry : events.entrySet()) { if(type.isAssignableFrom(recordingEntry.getKey())) { count += recordingEntry.getValue().size(); } } return count; } /** * Get the count of a specific type. * * @param type The exact event type * @return Number of times fired */ public Integer getCount(Class<?> type) { return events.containsKey(type) ? events.get(type).size():0; } public Boolean wasActive(Class<?> type, Class<? extends Context> context) { if(getCount(type) == 0) { return false; } for(EventRecording recording : events.get(type)) { if(!recording.wasActive(context)) { return false; } } return true; } } private static class EventRecording { private Map<Class<? extends Context>, Boolean> activeContexts; public EventRecording() { activeContexts = new HashMap<Class<? extends Context>, Boolean>(); } public EventRecording add(Class<? extends Context> context, Boolean isActive) { activeContexts.put(context, isActive); return this; } public Boolean wasActive(Class<? extends Context> context) { if(activeContexts.get(context) != null) { return activeContexts.get(context); } return false; } } }