diff options
Diffstat (limited to 'container-di/src/test/scala/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.scala')
-rw-r--r-- | container-di/src/test/scala/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.scala | 540 |
1 files changed, 0 insertions, 540 deletions
diff --git a/container-di/src/test/scala/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.scala b/container-di/src/test/scala/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.scala deleted file mode 100644 index 05194cb911b..00000000000 --- a/container-di/src/test/scala/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.scala +++ /dev/null @@ -1,540 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core - -import java.util.concurrent.{Executor, Executors} - -import com.google.inject.name.{Named, Names} -import com.google.inject.{AbstractModule, Guice, Inject, Key, Provider => GuiceProvider} -import com.yahoo.component.provider.ComponentRegistry -import com.yahoo.component.{AbstractComponent, ComponentId} -import com.yahoo.config.ConfigInstance -import com.yahoo.config.subscription.ConfigGetter -import com.yahoo.config.test.{Test2Config, TestConfig} -import com.yahoo.container.di._ -import com.yahoo.container.di.componentgraph.Provider -import com.yahoo.container.di.config.{JerseyBundlesConfig, JerseyInjectionConfig, RestApiContext} -import com.yahoo.vespa.config.ConfigKey -import org.hamcrest.CoreMatchers.{containsString, equalTo, is, not, sameInstance} -import org.hamcrest.Matcher -import org.junit.Assert._ -import org.junit.Test - -import scala.language.implicitConversions - -/** - * @author gjoranv - * @author tonytv - */ -class ComponentGraphTest { - import ComponentGraphTest._ - - private def keyAndConfig[T <: ConfigInstance](clazz: Class[T], configId: String): (ConfigKey[T], T) = { - val key = new ConfigKey(clazz, configId) - key -> ConfigGetter.getConfig(key.getConfigClass, key.getConfigId.toString) - } - - @Test - def component_taking_config_can_be_instantiated() { - val componentGraph = new ComponentGraph - val configId = "raw:stringVal \"test-value\"" - val componentNode = mockComponentNode(classOf[ComponentTakingConfig], configId) - - componentGraph.add(componentNode) - componentGraph.complete() - componentGraph.setAvailableConfigs(Map(keyAndConfig(classOf[TestConfig], configId))) - - val instance = componentGraph.getInstance(classOf[ComponentTakingConfig]) - assertNotNull(instance) - assertThat(instance.config.stringVal(), is("test-value")) - } - - @Test - def component_can_be_injected_into_another_component() { - val injectedComponent = mockComponentNode(classOf[SimpleComponent]) - val targetComponent = mockComponentNode(classOf[ComponentTakingComponent]) - targetComponent.inject(injectedComponent) - - val destroyGlobalLookupComponent = mockComponentNode(classOf[SimpleComponent]) - - val componentGraph = new ComponentGraph - componentGraph.add(injectedComponent) - componentGraph.add(targetComponent) - componentGraph.add(destroyGlobalLookupComponent) - componentGraph.complete() - - - val instance = componentGraph.getInstance(classOf[ComponentTakingComponent]) - assertNotNull(instance) - } - - @Test - def all_components_of_a_type_can_be_injected() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleDerivedComponent])) - componentGraph.add(mockComponentNode(classOf[ComponentTakingAllSimpleComponents])) - componentGraph.complete() - - val instance = componentGraph.getInstance(classOf[ComponentTakingAllSimpleComponents]) - assertThat(instance.simpleComponents.allComponents().size(), is(3)) - } - - @Test - def empty_component_registry_can_be_injected() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[ComponentTakingAllSimpleComponents])) - componentGraph.complete() - - val instance = componentGraph.getInstance(classOf[ComponentTakingAllSimpleComponents]) - assertThat(instance.simpleComponents.allComponents().size(), is(0)) - } - - @Test - def component_registry_with_wildcard_upper_bound_can_be_injected() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleDerivedComponent])) - componentGraph.add(mockComponentNode(classOf[ComponentTakingAllSimpleComponentsUpperBound])) - componentGraph.complete() - - val instance = componentGraph.getInstance(classOf[ComponentTakingAllSimpleComponentsUpperBound]) - assertThat(instance.simpleComponents.allComponents().size(), is(2)) - } - - @Test(expected = classOf[RuntimeException]) - def require_exception_when_injecting_registry_with_unknown_type_variable() { - val clazz = classOf[ComponentTakingAllComponentsWithTypeVariable[_]] - - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleDerivedComponent])) - componentGraph.add(mockComponentNode(clazz)) - componentGraph.complete() - - componentGraph.getInstance(clazz) - } - - @Test - def components_are_shared() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.complete() - - val instance1 = componentGraph.getInstance(classOf[SimpleComponent]) - val instance2 = componentGraph.getInstance(classOf[SimpleComponent]) - assertThat(instance1, sameInstance(instance2)) - } - - @Test - def singleton_components_can_be_injected() { - val componentGraph = new ComponentGraph - val configId = """raw:stringVal "test-value" """ - - componentGraph.add(mockComponentNode(classOf[ComponentTakingComponent])) - componentGraph.add(mockComponentNode(classOf[ComponentTakingConfig], configId)) - componentGraph.add(mockComponentNode(classOf[SimpleComponent2])) - componentGraph.complete() - componentGraph.setAvailableConfigs(Map(keyAndConfig(classOf[TestConfig], configId))) - - val instance = componentGraph.getInstance(classOf[ComponentTakingComponent]) - assertThat(instance.injectedComponent.asInstanceOf[ComponentTakingConfig].config.stringVal(), is("test-value")) - } - - @Test(expected = classOf[RuntimeException]) - def require_error_when_multiple_components_match_a_singleton_dependency() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[SimpleDerivedComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[ComponentTakingComponent])) - componentGraph.complete() - } - - @Test - def named_component_can_be_injected() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleComponent], key = Names.named("named-test"))) - componentGraph.add(mockComponentNode(classOf[ComponentTakingNamedComponent])) - componentGraph.complete() - } - - @Test - def config_keys_can_be_retrieved() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[ComponentTakingConfig], configId = """raw:stringVal "component1" """"")) - componentGraph.add(mockComponentNode(classOf[ComponentTakingConfig], configId = """raw:stringVal "component2" """"")) - componentGraph.add(new ComponentRegistryNode(classOf[ComponentTakingConfig])) - componentGraph.complete() - - val configKeys = componentGraph.configKeys - assertThat(configKeys.size, is(2)) - - configKeys.foreach{ key => - assertThat(key.getConfigClass, equalTo(classOf[TestConfig])) - assertThat(key.getConfigId.toString, containsString("component")) - } - } - - @Test - def providers_can_be_instantiated() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[ExecutorProvider])) - componentGraph.complete() - - assertNotNull(componentGraph.getInstance(classOf[Executor])) - } - - @Test - def providers_can_be_inherited() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[DerivedExecutorProvider])) - componentGraph.complete() - - assertNotNull(componentGraph.getInstance(classOf[Executor])) - } - - @Test - def providers_can_deliver_a_new_instance_for_each_component() { - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNode(classOf[NewIntProvider])) - componentGraph.complete() - - val instance1 = componentGraph.getInstance(classOf[Int]) - val instance2 = componentGraph.getInstance(classOf[Int]) - assertThat(instance1, not(equalTo(instance2))) - } - - @Test - def providers_can_be_injected_explicitly() { - val componentGraph = new ComponentGraph - - val componentTakingExecutor = mockComponentNode(classOf[ComponentTakingExecutor]) - val executorProvider = mockComponentNode(classOf[ExecutorProvider]) - componentTakingExecutor.inject(executorProvider) - - componentGraph.add(executorProvider) - componentGraph.add(mockComponentNode(classOf[ExecutorProvider])) - - componentGraph.add(componentTakingExecutor) - - componentGraph.complete() - assertNotNull(componentGraph.getInstance(classOf[ComponentTakingExecutor])) - } - - @Test - def global_providers_can_be_injected() { - val componentGraph = new ComponentGraph - - componentGraph.add(mockComponentNode(classOf[ComponentTakingExecutor])) - componentGraph.add(mockComponentNode(classOf[ExecutorProvider])) - componentGraph.add(mockComponentNode(classOf[IntProvider])) - componentGraph.complete() - - assertNotNull(componentGraph.getInstance(classOf[ComponentTakingExecutor])) - } - - @Test(expected = classOf[RuntimeException]) - def throw_if_multiple_global_providers_exist(): Unit = { - val componentGraph = new ComponentGraph - - componentGraph.add(mockComponentNode(classOf[ExecutorProvider])) - componentGraph.add(mockComponentNode(classOf[ExecutorProvider])) - componentGraph.add(mockComponentNode(classOf[ComponentTakingExecutor])) - componentGraph.complete() - } - - @Test - def provider_is_not_used_when_component_of_provided_class_exists() { - val componentGraph = new ComponentGraph - - componentGraph.add(mockComponentNode(classOf[SimpleComponent])) - componentGraph.add(mockComponentNode(classOf[SimpleComponentProviderThatThrows])) - componentGraph.add(mockComponentNode(classOf[ComponentTakingComponent])) - componentGraph.complete() - - val injectedComponent = componentGraph.getInstance(classOf[ComponentTakingComponent]).injectedComponent - assertNotNull(injectedComponent) - } - - //TODO: move - @Test - def check_if_annotation_is_a_binding_annotation() { - import ComponentGraph.isBindingAnnotation - - assertTrue(isBindingAnnotation(Names.named("name"))) - assertFalse(isBindingAnnotation(classOf[Named].getAnnotations.head)) - } - - @Test - def cycles_gives_exception() { - val componentGraph = new ComponentGraph - - def mockNode = mockComponentNode(classOf[ComponentCausingCycle]) - - val node1 = mockNode - val node2 = mockNode - - node1.inject(node2) - node2.inject(node1) - - componentGraph.add(node1) - componentGraph.add(node2) - - try { - componentGraph.complete() - fail("Cycle exception expected.") - } catch { - case e : Throwable => assertThat(e.getMessage, containsString("cycle")) - } - } - - @Test(expected = classOf[IllegalArgumentException]) - def abstract_classes_are_rejected() { - new ComponentNode(ComponentId.fromString("Test"), "", classOf[AbstractClass]) - } - - @Test - def inject_constructor_is_preferred() { - assertThatComponentCanBeCreated(classOf[ComponentWithInjectConstructor]) - } - - @Test - def constructor_with_most_parameters_is_preferred() { - assertThatComponentCanBeCreated(classOf[ComponentWithMultipleConstructors]) - } - - def assertThatComponentCanBeCreated(clazz: Class[AnyRef]) { - val componentGraph = new ComponentGraph - val configId = """raw:stringVal "dummy" """" - - componentGraph.add(mockComponentNode(clazz, configId)) - componentGraph.complete() - - componentGraph.setAvailableConfigs(Map( - keyAndConfig(classOf[TestConfig], configId), - keyAndConfig(classOf[Test2Config], configId))) - - assertNotNull(componentGraph.getInstance(clazz)) - } - - @Test - def require_fallback_to_child_injector() { - val componentGraph = new ComponentGraph - - componentGraph.add(mockComponentNode(classOf[ComponentTakingExecutor])) - - componentGraph.complete(singletonExecutorInjector) - assertNotNull(componentGraph.getInstance(classOf[ComponentTakingExecutor])) - } - - @Test - def child_injector_can_inject_multiple_instances_for_same_key() { - def executorProvider() = Executors.newSingleThreadExecutor() - - val (graphSize, executorA, executorB) = buildGraphWithChildInjector(() => executorProvider()) - - assertThat(graphSize, is(4)) - assertThat(executorA, not(sameInstance(executorB))) - } - - @Test - def components_injected_via_child_injector_can_be_shared() { - val commonExecutor = Executors.newSingleThreadExecutor() - val (graphSize, executorA, executorB) = buildGraphWithChildInjector(() => commonExecutor) - - assertThat(graphSize, is(3)) - assertThat(executorA, sameInstance(executorB)) - } - - def buildGraphWithChildInjector(executorProvider: () => Executor) = { - val childInjector = Guice.createInjector(new AbstractModule { - override def configure() { - bind(classOf[Executor]).toProvider(new GuiceProvider[Executor] { - def get() = executorProvider() - }) - } - }) - - val componentGraph = new ComponentGraph - - def key(name: String) = Key.get(classOf[ComponentTakingExecutor], Names.named(name)) - val keyA = key("A") - val keyB = key("B") - - componentGraph.add(mockComponentNode(keyA)) - componentGraph.add(mockComponentNode(keyB)) - - componentGraph.complete(childInjector) - - (componentGraph.size, componentGraph.getInstance(keyA).executor, componentGraph.getInstance(keyB).executor) - } - - @Test - def providers_can_be_reused() { - def createGraph() = { - val graph = new ComponentGraph() - graph.add(mockComponentNodeWithId(classOf[ExecutorProvider], "dummyId")) - graph.complete() - graph.setAvailableConfigs(Map()) - graph - } - - val oldGraph = createGraph() - val executor = oldGraph.getInstance(classOf[Executor]) - - val newGraph = createGraph() - newGraph.reuseNodes(oldGraph) - - val newExecutor = newGraph.getInstance(classOf[Executor]) - assertThat(executor, sameInstance(newExecutor)) - } - - @Test - def component_id_can_be_injected() { - val componentId: String = "myId:1.2@namespace" - - val componentGraph = new ComponentGraph - componentGraph.add(mockComponentNodeWithId(classOf[ComponentTakingComponentId], componentId)) - componentGraph.complete() - - assertThat(componentGraph.getInstance(classOf[ComponentTakingComponentId]).componentId, - is(ComponentId.fromString(componentId))) - } - - @Test - def rest_api_context_can_be_instantiated() { - val configId = """raw:"" """ - - val clazz = classOf[RestApiContext] - val jerseyNode = new JerseyNode(uniqueComponentId(clazz.getName), configId, clazz, new Osgi {}) - - val componentGraph = new ComponentGraph - componentGraph.add(jerseyNode) - componentGraph.complete() - componentGraph.setAvailableConfigs(Map(keyAndConfig(classOf[JerseyBundlesConfig], configId), - keyAndConfig(classOf[JerseyInjectionConfig], configId))) - - val restApiContext = componentGraph.getInstance(clazz) - assertNotNull(restApiContext) - assertThat(restApiContext.getBundles.size, is(0)) - } - -} - -//Note that all Components must be defined in a static context, -//otherwise their constructor will take the outer class as the first parameter. -object ComponentGraphTest { - var counter = 0 - - - class SimpleComponent extends AbstractComponent - class SimpleComponent2 extends AbstractComponent - class SimpleDerivedComponent extends SimpleComponent - - class ComponentTakingConfig(val config: TestConfig) extends SimpleComponent { - require(config != null) - } - - class ComponentTakingComponent(val injectedComponent: SimpleComponent) extends AbstractComponent { - require(injectedComponent != null) - } - - class ComponentTakingConfigAndComponent(val config: TestConfig, val injectedComponent: SimpleComponent) extends AbstractComponent { - require(config != null) - require(injectedComponent != null) - } - - class ComponentTakingAllSimpleComponents(val simpleComponents: ComponentRegistry[SimpleComponent]) extends AbstractComponent { - require(simpleComponents != null) - } - - class ComponentTakingAllSimpleComponentsUpperBound(val simpleComponents: ComponentRegistry[_ <: SimpleComponent]) - extends AbstractComponent { - - require(simpleComponents != null) - } - - class ComponentTakingAllComponentsWithTypeVariable[COMPONENT <: AbstractComponent](val simpleComponents: ComponentRegistry[COMPONENT]) - extends AbstractComponent { - - require(simpleComponents != null) - } - - class ComponentTakingNamedComponent(@Named("named-test") injectedComponent: SimpleComponent) extends AbstractComponent { - require(injectedComponent != null) - } - - class ComponentCausingCycle(component: ComponentCausingCycle) extends AbstractComponent - - class SimpleComponentProviderThatThrows extends Provider[SimpleComponent] { - def get() = throw new AssertionError("Should never be called.") - def deconstruct() {} - } - - class ExecutorProvider extends Provider[Executor] { - val executor = Executors.newSingleThreadExecutor() - def get() = executor - def deconstruct() { /*TODO */ } - } - - class DerivedExecutorProvider extends ExecutorProvider - - class IntProvider extends Provider[java.lang.Integer] { - def get() = throw new AssertionError("Should never be called.") - def deconstruct() {} - } - - class NewIntProvider extends Provider[Integer] { - var i: Int = 0 - def get() = { - i += 1 - i - } - def deconstruct() {} - } - - class ComponentTakingExecutor(val executor: Executor) extends AbstractComponent { - require(executor != null) - } - - class ComponentWithInjectConstructor private () { - def this(c: TestConfig, c2: Test2Config) = { this(); sys.error("Should not be called") } - @Inject - def this(c: Test2Config) = { this() } - } - - class ComponentWithMultipleConstructors private (dummy : Int) { - def this(c: TestConfig, c2: Test2Config) = { this(0); } - - def this() = { this(0); sys.error("Should not be called") } - def this(c: Test2Config) = { this() } - } - - class ComponentTakingComponentId(val componentId: ComponentId) - - def uniqueComponentId(className: String): ComponentId = { - counter += 1 - ComponentId.fromString(className + counter) - } - - def mockComponentNode(key: Key[_ <: AnyRef]): Node = - mockComponentNode(key.getTypeLiteral.getRawType.asInstanceOf[Class[AnyRef]], key=key.getAnnotation) - - def mockComponentNode(clazz: Class[_ <: AnyRef], configId: String = "", key: JavaAnnotation = null): Node = - new ComponentNode(uniqueComponentId(clazz.getName), configId, clazz, key) - - def mockComponentNodeWithId(clazz: Class[_ <: AnyRef], componentId: String, configId: String = "", key: JavaAnnotation = null): Node = - new ComponentNode(ComponentId.fromString(componentId), configId, clazz, key) - - val singletonExecutorInjector = Guice.createInjector(new AbstractModule { - override def configure() { - bind(classOf[Executor]).toInstance(Executors.newSingleThreadExecutor()) - } - }) - - implicit def makeMatcherCovariant[T, U >: T](matcher: Matcher[T]) : Matcher[U] = matcher.asInstanceOf[Matcher[U]] - - abstract class AbstractClass -} - |