/** * Copyright (C) 2013 Kametic <epo.jemba@kametic.com> * * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007; * or any later version * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/lgpl-3.0.txt * * 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.nuunframework.kernel; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.nuunframework.kernel.Kernel.AliasMap; import org.nuunframework.kernel.context.ContextInternal; import org.nuunframework.kernel.plugin.AbstractPlugin; import org.nuunframework.kernel.plugin.Plugin; import org.nuunframework.kernel.plugin.dummy1.Bean6; import org.nuunframework.kernel.plugin.dummy1.Bean9; import org.nuunframework.kernel.plugin.dummy1.BeanWithCustomSuffix; import org.nuunframework.kernel.plugin.dummy1.BeanWithParentType; import org.nuunframework.kernel.plugin.dummy1.DummyMarker; import org.nuunframework.kernel.plugin.dummy1.DummyPlugin; import org.nuunframework.kernel.plugin.dummy1.MarkerSample4; import org.nuunframework.kernel.plugin.dummy1.ParentClassWithCustomSuffix; import org.nuunframework.kernel.plugin.dummy1.ParentInterfaceWithCustomSuffix; import org.nuunframework.kernel.plugin.dummy23.DummyPlugin2; import org.nuunframework.kernel.plugin.dummy23.DummyPlugin3; import org.nuunframework.kernel.plugin.dummy4.DummyPlugin4; import org.nuunframework.kernel.plugin.dummy4.Pojo1; import org.nuunframework.kernel.plugin.dummy4.Pojo2; import org.nuunframework.kernel.plugin.dummy5.DescendantFromClass; import org.nuunframework.kernel.plugin.dummy5.DummyPlugin5; import org.nuunframework.kernel.plugin.dummy5.ParentClass; import org.nuunframework.kernel.plugin.dummy5.ToFind; import org.nuunframework.kernel.plugin.dummy5.ToFind2; import org.nuunframework.kernel.sample.DummyMethod; import org.nuunframework.kernel.sample.Holder; import org.nuunframework.kernel.sample.HolderForBeanWithParentType; import org.nuunframework.kernel.sample.HolderForContext; import org.nuunframework.kernel.sample.HolderForInterface; import org.nuunframework.kernel.sample.HolderForPlugin; import org.nuunframework.kernel.sample.HolderForPrefixWithName; import org.nuunframework.kernel.sample.ModuleInError; import org.nuunframework.kernel.sample.ModuleInterface; import org.powermock.reflect.Whitebox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.AbstractModule; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.matcher.Matchers; import com.google.inject.name.Named; import com.google.inject.name.Names; /** * @author Epo Jemba * */ public class KernelTest { static Logger logger = LoggerFactory.getLogger(KernelTest.class); Injector injector; static Kernel underTest; static DummyPlugin4 plugin4 = new DummyPlugin4(); static long start; static long end; @SuppressWarnings("unchecked") @BeforeClass public static void init() { start = System.currentTimeMillis(); // underTest = Kernel.createKernel(DummyPlugin.ALIAS_DUMMY_PLUGIN1 , "WAZAAAA", DummyPlugin.NUUNROOTALIAS , "").build(); underTest = Kernel.createKernel(DummyPlugin.ALIAS_DUMMY_PLUGIN1 , "WAZAAAA", DummyPlugin.NUUNROOTALIAS , "internal,"+KernelTest.class.getPackage().getName()).build(); try { underTest.init(); assertThat(true).as("Should Get a Kernel Exeption for dependency problem").isFalse(); } catch (KernelException ke) { assertThat(ke.getMessage()).isEqualTo("plugin dummyPlugin misses the following plugin/s as dependency/ies [class org.nuunframework.kernel.plugin.dummy23.DummyPlugin2]"); underTest.addPlugins( DummyPlugin2.class); try { underTest.init(); assertThat(true).as("Should Get a Kernel Exeption for dependency problem").isFalse(); } catch (KernelException ke2) { assertThat(ke2.getMessage()).isEqualTo("plugin dummyPlugin2 misses the following plugin/s as dependency/ies [class org.nuunframework.kernel.plugin.dummy23.DummyPlugin3]"); underTest.addPlugins( DummyPlugin3.class); underTest.addPlugins( plugin4); underTest.addPlugins( DummyPlugin5.class); underTest.init(); } } underTest.start(); } static class DummyInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.err.println("inside " + DummyInterceptor.class); return invocation.proceed(); } } @Before public void before() { Module aggregationModule = new AbstractModule() { @Override protected void configure() { bind(Holder.class); bind(HolderForPlugin.class); bind(HolderForContext.class); bind(HolderForPrefixWithName.class); bind(HolderForBeanWithParentType.class); bindInterceptor(Matchers.any(), Matchers.annotatedWith(DummyMethod.class), new DummyInterceptor()); } }; injector = underTest.getMainInjector().createChildInjector(aggregationModule); } public Module m = new AbstractModule() { @Override protected void configure() { bind(Key.get(String.class, Names.named("epo1"))).toInstance("epo1"); bindConstant().annotatedWith(Names.named("epo2")).to("epo2"); } }; @Test public void logger_should_be_injected() { Holder holder = injector.getInstance(Holder.class); assertThat(holder.getLogger()).isNotNull(); holder.getLogger().error("MESSAGE FROM LOGGER."); } @Test public void logger_should_be_injected_with_metaannotation() { Holder holder = injector.getInstance(Holder.class); assertThat(holder.getLogger2()).isNotNull(); holder.getLogger().error("MESSAGE FROM LOGGER2."); } @Test public void plugin_shoud_be_detected() { HolderForPlugin holder = injector.getInstance(HolderForPlugin.class); // assertThat(holder.value).isNotNull(); // assertThat(holder.value).isEqualTo("lorem ipsum"); assertThat(holder.dummyService).isNotNull(); assertThat(holder.dummyService.dummy()).isEqualTo("dummyserviceinternal"); assertThat(holder.bean6).isNotNull(); assertThat(holder.bean6.sayHi()).isEqualTo("dummyserviceinternal2"); assertThat(holder.bean9).isNotNull(); assertThat(holder.bean9.value).isEqualTo("lorem ipsum"); } @Test(expected = CreationException.class) public void plugin_shoud_be_detected_error_case() { // Bean7 is not bound to the env because of @Ignore injector.createChildInjector(new ModuleInError()); } @Test public void injector_should_retrieve_context() { HolderForContext holder = injector.getInstance(HolderForContext.class); assertThat(holder.context).isNotNull(); assertThat(holder.context instanceof ContextInternal).isTrue(); ContextInternal contextInternal = (ContextInternal) holder.context; assertThat(contextInternal.mainInjector).isNotNull(); assertThat(holder.context.getClassAnnotatedWith(MarkerSample4.class)).isNotEmpty(); assertThat(holder.context.getClassAnnotatedWith(MarkerSample4.class)).hasSize(1); assertThat(holder.context.getClassAnnotatedWith(MarkerSample4.class)).containsOnly(Bean6.class); // TODO : faire pareil que pour les scans rechecher par regex assertThat(holder.context.getClassAnnotatedWithRegex(".*MarkerSample3")).isNotEmpty(); assertThat(holder.context.getClassAnnotatedWithRegex(".*MarkerSample3")).hasSize(1); assertThat(holder.context.getClassAnnotatedWithRegex(".*MarkerSample3")).containsOnly(Bean9.class); // TODO : aussi rajouter parent type by regex assertThat(holder.context.getClassWithParentType(DummyMarker.class)).isNotEmpty(); assertThat(holder.context.getClassWithParentType(DummyMarker.class)).hasSize(1); assertThat(holder.context.getClassWithParentType(DummyMarker.class)).containsOnly(BeanWithParentType.class); // TODO : faire pareil que pour les scans rechecher par regex assertThat(holder.context.getClassTypeByRegex(".*WithCustomSuffix")).isNotEmpty(); assertThat(holder.context.getClassTypeByRegex(".*WithCustomSuffix")).hasSize(3); // was 2 assertThat(holder.context.getClassTypeByRegex(".*WithCustomSuffix")).containsOnly(BeanWithCustomSuffix.class, ParentClassWithCustomSuffix.class, ParentInterfaceWithCustomSuffix.class); } @Test public void classpath_scan_by_specification_should_work() { assertThat(plugin4.collection).isNotNull(); assertThat(plugin4.collection).isNotEmpty(); assertThat(plugin4.collection).hasSize(1); assertThat(plugin4.collection).containsOnly(Pojo1.class); } @Test public void binding_by_specification_should_work () { assertThat( injector.getInstance(Pojo2.class) ).isNotNull(); // we check for the scope assertThat(injector.getInstance(Pojo2.class)).isEqualTo(injector.getInstance(Pojo2.class)); try { assertThat( injector.getInstance(Pojo1.class) ).isNull(); fail("Pojo1 should not be injector"); } catch (ConfigurationException ce) { String nl = System.getProperty("line.separator"); assertThat(ce.getMessage()).isEqualTo("Guice configuration errors:"+nl +nl +"1) Explicit bindings are required and org.nuunframework.kernel.plugin.dummy4.Pojo1 is not explicitly bound."+nl + " while locating org.nuunframework.kernel.plugin.dummy4.Pojo1"+nl +nl +"1 error" ); } } @Test public void binding_by_metaannotation_should_work () { ToFind tofind = injector.getInstance(ToFind.class); assertThat( tofind).isNotNull (); // singleton assertThat( tofind).isEqualTo(injector.getInstance(ToFind.class)); } @Test public void binding_by_metaannotationregex_should_work () { ToFind2 tofind = injector.getInstance(ToFind2.class); assertThat( tofind).isNotNull (); // singleton assertThat( tofind).isEqualTo(injector.getInstance(ToFind2.class)); } @Test public void binding_by_ancestor_should_work () { ParentClass instance = injector.getInstance(ParentClass.class); DescendantFromClass instance2 = injector.getInstance(DescendantFromClass.class); assertThat( instance).isNotNull (); assertThat( instance2).isNotNull (); // scope SINGLETON has been registered assertThat( instance).isEqualTo(injector.getInstance(ParentClass.class)); assertThat( instance2).isEqualTo(injector.getInstance(DescendantFromClass.class)); // assertThat( injector.getInstance(ParentInterface.class)).isNotNull (); // assertThat( injector.getInstance(DescendantFromInterface.class)).isNotNull (); try { assertThat( injector.getInstance(Pojo1.class) ).isNull(); fail("Pojo1 should not be injector"); } catch (ConfigurationException ce) { String nl = System.getProperty("line.separator"); assertThat(ce.getMessage()).isEqualTo("Guice configuration errors:"+nl +nl +"1) Explicit bindings are required and org.nuunframework.kernel.plugin.dummy4.Pojo1 is not explicitly bound."+nl + " while locating org.nuunframework.kernel.plugin.dummy4.Pojo1"+nl +nl +"1 error" ); } } @Test public void bean_should_be_bind_by_name() { HolderForPrefixWithName holder = injector.getInstance(HolderForPrefixWithName.class); assertThat(holder.customBean).isNotNull(); assertThat(holder.customBean.name()).isNotNull(); assertThat(holder.customBean.name()).isEqualTo("I am John"); } @Test public void bean_should_be_bind_by_parent_type() { HolderForBeanWithParentType holder = injector.getInstance(HolderForBeanWithParentType.class); assertThat(holder.beanWithParentType).isNotNull(); assertThat(holder.beanWithParentType.name()).isNotNull(); assertThat(holder.beanWithParentType.name()).isEqualTo("I am Jane"); } @Test public void interface_can_be_injected_without_instance_if_declared_nullable() { Injector createChildInjector = injector.createChildInjector(new ModuleInterface()); HolderForInterface holder = createChildInjector.getInstance(HolderForInterface.class); assertThat(holder.customBean).isNull(); } @Test public void plugin_sort_algo () throws Exception { ArrayList<Plugin> plugins = new ArrayList<Plugin>() , plugins2 = null; p1 e1 = new p1(); plugins.add(e1); p2 e2 = new p2(); plugins.add(e2); // -> 13 p3 e3 = new p3(); plugins.add(e3); p4 e4 = new p4(); plugins.add(e4); p5 e5 = new p5(); plugins.add(e5); p6 e6 = new p6(); plugins.add(e6); p7 e7 = new p7(); plugins.add(e7); // -> 11 p8 e8 = new p8(); plugins.add(e8); p9 e9 = new p9(); plugins.add(e9); p10 e10 = new p10(); plugins.add(e10); p11 e11 = new p11(); plugins.add(e11); p12 e12 = new p12(); plugins.add(e12); // -> 6 p13 e13 = new p13(); plugins.add(e13); // -> 11 plugins2 = Whitebox.invokeMethod(underTest, "sortPlugins", plugins); assertThat(plugins2).isNotNull(); assertThat(plugins2).containsOnly ( e1 , e2 , e3 , e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 ); assertThat(plugins2).containsSequence ( e11 , e13 , e6 , e12 , e10 ); } static abstract class AbstractTestPlugin extends AbstractPlugin{ public Collection<Class<? extends Plugin>> dep(Class<? extends Plugin> klazz) { Collection<Class<? extends Plugin>> plugins = new ArrayList<Class<? extends Plugin>>(); plugins.add(klazz); return plugins; } } static class p1 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p2 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } public Collection<Class<? extends Plugin>> requiredPlugins() {return dep(p13.class); } } static class p3 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p4 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p5 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p6 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p7 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } public Collection<Class<? extends Plugin>> requiredPlugins() {return dep(p11.class); } } static class p8 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p9 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p10 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p11 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } } static class p12 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } public Collection<Class<? extends Plugin>> requiredPlugins() {return dep(p6.class); } } static class p13 extends AbstractTestPlugin { public String name() {return this.getClass().getName(); } public Collection<Class<? extends Plugin>> requiredPlugins() {return dep(p11.class); } } public Plugin createPlugin (final String name , final Class<? extends Plugin> dependency) { return new AbstractPlugin () { @Override public String name() { return name; } @Override public Collection<Class<? extends Plugin>> requiredPlugins() { if (dependency != null) { Set<Class <? extends Plugin>> plugins = new HashSet<Class<? extends Plugin>>(); plugins.add(dependency); return plugins; } else { return Collections.EMPTY_SET; } } }; } @Test public void AliasMap_should_work() { AliasMap map = new AliasMap(); map.putAlias("realkey1", "alias1"); map.putAlias("realkey2", "alias2"); Object object1 = new Object(); Object object2 = new Object(); map.put("realkey1", object1.toString()); map.put("realkey2", object2.toString()); assertThat(map.get("alias1")).isEqualTo(object1.toString()); assertThat(map.get("alias2")).isEqualTo(object2.toString()); assertThat(map.containsKey("alias1")).isTrue(); assertThat(map.containsKey("alias2")).isTrue(); } @AfterClass public static void clear() { underTest.stop(); end = System.currentTimeMillis(); logger.info("Test took " + (end - start) + " ms."); } }