summaryrefslogtreecommitdiffstats
path: root/container-di/src/test/java/demo
diff options
context:
space:
mode:
Diffstat (limited to 'container-di/src/test/java/demo')
-rw-r--r--container-di/src/test/java/demo/Base.java66
-rw-r--r--container-di/src/test/java/demo/ComponentConfigTest.java48
-rw-r--r--container-di/src/test/java/demo/ComponentRegistryTest.java42
-rw-r--r--container-di/src/test/java/demo/ContainerTestBase.java74
-rw-r--r--container-di/src/test/java/demo/DeconstructTest.java35
-rw-r--r--container-di/src/test/java/demo/FallbackToGuiceInjectorTest.java104
6 files changed, 369 insertions, 0 deletions
diff --git a/container-di/src/test/java/demo/Base.java b/container-di/src/test/java/demo/Base.java
new file mode 100644
index 00000000000..7bc2c7b4404
--- /dev/null
+++ b/container-di/src/test/java/demo/Base.java
@@ -0,0 +1,66 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package demo;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.yahoo.component.ComponentId;
+import com.yahoo.config.ConfigInstance;
+import com.yahoo.container.di.ContainerTest;
+import com.yahoo.container.di.componentgraph.core.ComponentGraph;
+import com.yahoo.container.di.componentgraph.core.ComponentNode;
+import com.yahoo.container.di.componentgraph.core.Node;
+import com.yahoo.vespa.config.ConfigKey;
+import org.junit.Before;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author tonytv
+ * @author gjoranv
+ */
+public class Base {
+ private ComponentGraph componentGraph;
+ private Injector injector;
+ private Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs =
+ new HashMap<>();
+
+ @Before
+ public void createGraph() {
+ injector = Guice.createInjector();
+ componentGraph = new ComponentGraph(0);
+ }
+
+ public void register(Class<?> componentClass) {
+ componentGraph.add(mockComponentNode(componentClass));
+ }
+
+ public ComponentId toId(Class<?> componentClass) {
+ return ComponentId.fromString(componentClass.getName());
+ }
+
+ @SuppressWarnings("unchecked")
+ private Node mockComponentNode(Class<?> componentClass) {
+ return new ComponentNode(toId(componentClass), toId(componentClass).toString(), (Class<Object>)componentClass, null);
+ }
+
+ public <T> T getInstance(Class<T> componentClass) {
+ return componentGraph.getInstance(componentClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void complete() {
+ componentGraph.complete(injector);
+ componentGraph.setAvailableConfigs(ContainerTest.convertMap(configs));
+ }
+
+ public void setInjector(Injector injector) {
+ this.injector = injector;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void addConfig(ConfigInstance configInstance, ComponentId id) {
+ configs.put(new ConfigKey<>((Class<ConfigInstance>)configInstance.getClass(), id.toString()),
+ configInstance);
+ }
+}
diff --git a/container-di/src/test/java/demo/ComponentConfigTest.java b/container-di/src/test/java/demo/ComponentConfigTest.java
new file mode 100644
index 00000000000..5b3be2f549a
--- /dev/null
+++ b/container-di/src/test/java/demo/ComponentConfigTest.java
@@ -0,0 +1,48 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package demo;
+
+import com.yahoo.config.test.ThreadPoolConfig;
+import com.yahoo.container.di.componentgraph.Provider;
+import org.junit.Test;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.assertNotNull;
+
+
+/**
+ * @author tonytv
+ * @author gjoranv
+ */
+public class ComponentConfigTest extends Base {
+ public static class ThreadPoolExecutorProvider implements Provider<Executor> {
+ private ExecutorService executor;
+
+ public ThreadPoolExecutorProvider(ThreadPoolConfig config) {
+ executor = Executors.newFixedThreadPool(config.numThreads());
+ }
+
+ @Override
+ public Executor get() {
+ return executor;
+ }
+
+ @Override
+ public void deconstruct() {
+ executor.shutdown();
+ }
+ }
+
+ @Test
+ public void require_that_non_components_can_be_configured() {
+ register(ThreadPoolExecutorProvider.class);
+ addConfig(new ThreadPoolConfig(new ThreadPoolConfig.Builder().numThreads(4)),
+ toId(ThreadPoolExecutorProvider.class));
+ complete();
+
+ Executor executor = getInstance(Executor.class);
+ assertNotNull(executor);
+ }
+}
diff --git a/container-di/src/test/java/demo/ComponentRegistryTest.java b/container-di/src/test/java/demo/ComponentRegistryTest.java
new file mode 100644
index 00000000000..193f65048ab
--- /dev/null
+++ b/container-di/src/test/java/demo/ComponentRegistryTest.java
@@ -0,0 +1,42 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package demo;
+
+import com.yahoo.component.AbstractComponent;
+import com.yahoo.component.provider.ComponentRegistry;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+
+/**
+ * @author tonytv
+ * @author gjoranv
+ */
+public class ComponentRegistryTest extends Base {
+ public static class SearchHandler extends AbstractComponent {
+ private final ComponentRegistry<Searcher> searchers;
+
+ public SearchHandler(ComponentRegistry<Searcher> searchers) {
+ this.searchers = searchers;
+ }
+ }
+
+ public static class Searcher extends AbstractComponent {}
+
+ public static class FooSearcher extends Searcher {}
+ public static class BarSearcher extends Searcher {}
+
+ @Test
+ public void require_that_component_registry_can_be_injected() {
+ register(SearchHandler.class);
+ register(FooSearcher.class);
+ register(BarSearcher.class);
+ complete();
+
+ SearchHandler handler = getInstance(SearchHandler.class);
+
+ ComponentRegistry<Searcher> searchers = handler.searchers;
+ assertNotNull(searchers.getComponent(toId(FooSearcher.class)));
+ assertNotNull(searchers.getComponent(toId(BarSearcher.class)));
+ }
+}
diff --git a/container-di/src/test/java/demo/ContainerTestBase.java b/container-di/src/test/java/demo/ContainerTestBase.java
new file mode 100644
index 00000000000..fdc73913052
--- /dev/null
+++ b/container-di/src/test/java/demo/ContainerTestBase.java
@@ -0,0 +1,74 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package demo;
+
+import com.google.inject.Guice;
+import com.yahoo.component.ComponentSpecification;
+import com.yahoo.container.bundle.BundleInstantiationSpecification;
+import com.yahoo.config.FileReference;
+import com.yahoo.container.di.CloudSubscriberFactory;
+import com.yahoo.container.di.Container;
+import com.yahoo.container.di.ContainerTest;
+import com.yahoo.container.di.Osgi;
+import com.yahoo.container.di.componentgraph.core.ComponentGraph;
+import org.junit.Before;
+import org.osgi.framework.Bundle;
+import scala.collection.*;
+import scala.collection.immutable.*;
+import scala.collection.immutable.Set;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author tonytv
+ * @author gjoranv
+ */
+public class ContainerTestBase extends ContainerTest {
+ private ComponentGraph componentGraph;
+
+ @Before
+ public void createGraph() {
+ componentGraph = new ComponentGraph(0);
+ }
+
+ public void complete() {
+ try {
+ Container container = new Container(
+ new CloudSubscriberFactory(dirConfigSource().configSource()),
+ dirConfigSource().configId(),
+ new ContainerTest.TestDeconstructor(),
+ new Osgi() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Class<Object> resolveClass(BundleInstantiationSpecification spec) {
+ try {
+ return (Class<Object>) Class.forName(spec.classId.getName());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public BundleClasses getBundleClasses(ComponentSpecification bundle,
+ Set<String> packagesToScan) {
+ throw new UnsupportedOperationException("getBundleClasses not supported");
+ }
+
+ @Override
+ public void useBundles(Collection<FileReference> bundles) {}
+
+ @Override
+ public Bundle getBundle(ComponentSpecification spec) {
+ throw new UnsupportedOperationException("getBundle not supported.");
+ }
+ });
+ componentGraph = container.runOnce(componentGraph, Guice.createInjector());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public <T> T getInstance(Class<T> componentClass) {
+ return componentGraph.getInstance(componentClass);
+ }
+}
diff --git a/container-di/src/test/java/demo/DeconstructTest.java b/container-di/src/test/java/demo/DeconstructTest.java
new file mode 100644
index 00000000000..10e9844f6de
--- /dev/null
+++ b/container-di/src/test/java/demo/DeconstructTest.java
@@ -0,0 +1,35 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package demo;
+
+import com.yahoo.container.di.ContainerTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author tonytv
+ * @author gjoranv
+ */
+public class DeconstructTest extends ContainerTestBase {
+ public static class DeconstructableComponent extends ContainerTest.DestructableComponent {
+ private boolean isDeconstructed = false;
+
+ @Override
+ public void deconstruct() {
+ isDeconstructed = true;
+ }
+ }
+
+ @Test
+ public void require_that_unused_components_are_deconstructed() {
+ writeBootstrapConfigs("d1", DeconstructableComponent.class);
+ complete();
+
+ DeconstructableComponent d1 = getInstance(DeconstructableComponent.class);
+
+ writeBootstrapConfigs("d2", DeconstructableComponent.class);
+ complete();
+
+ assertTrue(d1.isDeconstructed);
+ }
+}
diff --git a/container-di/src/test/java/demo/FallbackToGuiceInjectorTest.java b/container-di/src/test/java/demo/FallbackToGuiceInjectorTest.java
new file mode 100644
index 00000000000..3d5550ab0a3
--- /dev/null
+++ b/container-di/src/test/java/demo/FallbackToGuiceInjectorTest.java
@@ -0,0 +1,104 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package demo;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.yahoo.component.AbstractComponent;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author tonytv
+ * @author gjoranv
+ */
+@SuppressWarnings("unused")
+public class FallbackToGuiceInjectorTest extends Base {
+ public static class MyComponent extends AbstractComponent {
+ private final String url;
+ private final Executor executor;
+
+ @Inject
+ public MyComponent(@Named("url") String url, Executor executor) {
+ this.url = url;
+ this.executor = executor;
+ }
+
+ public MyComponent() {
+ throw new RuntimeException("Constructor annotated with @Inject is preferred.");
+ }
+ }
+
+ public static class ComponentTakingDefaultString{
+ private final String injectedString;
+
+ public ComponentTakingDefaultString(String empty_string_created_by_guice) {
+ this.injectedString = empty_string_created_by_guice;
+ }
+ }
+
+ public static class ComponentThatCannotBeConstructed {
+ public ComponentThatCannotBeConstructed(Integer cannot_be_injected_because_Integer_has_no_default_ctor) { }
+ }
+
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void guice_injector_is_used_when_no_global_component_exists() {
+ setInjector(
+ Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Executor.class).toInstance(Executors.newSingleThreadExecutor());
+ bind(String.class).annotatedWith(Names.named("url")).toInstance("http://yahoo.com");
+ }
+ }));
+
+ register(MyComponent.class);
+ complete();
+
+ MyComponent component = getInstance(MyComponent.class);
+ assertThat(component.url, is("http://yahoo.com"));
+ assertNotNull(component.executor);
+ }
+
+ @Test
+ public void guice_injector_creates_a_new_instance_with_default_ctor_when_no_explicit_binding_exists() {
+ setInjector(emptyGuiceInjector());
+ register(ComponentTakingDefaultString.class);
+ complete();
+
+ ComponentTakingDefaultString component = getInstance(ComponentTakingDefaultString.class);
+ assertThat(component.injectedString, is(""));
+ }
+
+ @Test
+ public void guice_injector_fails_when_no_explicit_binding_exists_and_class_has_no_default_ctor() {
+ setInjector(emptyGuiceInjector());
+ register(ComponentThatCannotBeConstructed.class);
+
+ exception.expect(RuntimeException.class);
+ exception.expectMessage("When resolving dependencies of 'demo.FallbackToGuiceInjectorTest$ComponentThatCannotBeConstructed'");
+ complete();
+ }
+
+ private Injector emptyGuiceInjector() {
+ return Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ }
+ });
+ }
+}