Migrate Dagger's factory tests to Kotlin sources.
RELNOTES=N/A
PiperOrigin-RevId: 493672279
diff --git a/javatests/dagger/functional/kotlinsrc/factory/AbstractModule.kt b/javatests/dagger/functional/kotlinsrc/factory/AbstractModule.kt
new file mode 100644
index 0000000..5dec18d
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/AbstractModule.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import dagger.Module
+import dagger.Provides
+
+@Module
+object AbstractModule {
+ @Provides fun provideString(): String = "foo"
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/BUILD b/javatests/dagger/functional/kotlinsrc/factory/BUILD
new file mode 100644
index 0000000..f4a0328
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/BUILD
@@ -0,0 +1,44 @@
+# Copyright (C) 2022 The Dagger Authors.
+#
+# 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.
+
+# Description:
+# Functional tests for Dagger factories
+
+load(
+ "//:build_defs.bzl",
+ "DOCLINT_HTML_AND_SYNTAX",
+ "DOCLINT_REFERENCES",
+ "JAVA_RELEASE_MIN",
+)
+load("//:test_defs.bzl", "GenJavaTests")
+
+package(default_visibility = ["//:src"])
+
+GenJavaTests(
+ name = "factory",
+ srcs = glob(["*.kt"]),
+ javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
+ lib_javacopts = JAVA_RELEASE_MIN,
+ deps = [
+ "//:dagger_with_compiler",
+ "//third_party/java/auto:factory",
+ "//third_party/java/guava/base",
+ "//third_party/java/guava/collect",
+ "//third_party/java/guava/util/concurrent",
+ "//third_party/java/jsr305_annotations",
+ "//third_party/java/jsr330_inject",
+ "//third_party/java/junit",
+ "//third_party/java/truth",
+ ],
+)
diff --git a/javatests/dagger/functional/kotlinsrc/factory/ConcreteModuleThatCouldBeAbstract.kt b/javatests/dagger/functional/kotlinsrc/factory/ConcreteModuleThatCouldBeAbstract.kt
new file mode 100644
index 0000000..20193b5
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/ConcreteModuleThatCouldBeAbstract.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import dagger.Module
+import dagger.Provides
+
+@Suppress("ClassShouldBeObject")
+@Module
+class ConcreteModuleThatCouldBeAbstract {
+ companion object {
+ @Provides fun provideDouble(): Double = 42.0
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/Dependency.kt b/javatests/dagger/functional/kotlinsrc/factory/Dependency.kt
new file mode 100644
index 0000000..4061e29
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/Dependency.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+class Dependency {
+ fun someObject(): Any = "bar"
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/FactoryBindsInstanceTest.kt b/javatests/dagger/functional/kotlinsrc/factory/FactoryBindsInstanceTest.kt
new file mode 100644
index 0000000..9e82292
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/FactoryBindsInstanceTest.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests for component factories with [BindsInstance] parameters. */
+@RunWith(JUnit4::class)
+class FactoryBindsInstanceTest {
+ @Component
+ internal interface BindsInstanceComponent {
+ fun string(): String
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance string: String): BindsInstanceComponent
+ }
+ }
+
+ @Test
+ fun bindsInstance() {
+ val component = DaggerFactoryBindsInstanceTest_BindsInstanceComponent.factory().create("baz")
+ assertThat(component.string()).isEqualTo("baz")
+ }
+
+ @Target(AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER)
+ @Retention(AnnotationRetention.BINARY)
+ internal annotation class Nullable
+
+ @Component
+ internal interface NullableBindsInstanceComponent {
+ @Nullable fun string(): String?
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance @Nullable string: String?): NullableBindsInstanceComponent
+ }
+ }
+
+ @Test
+ fun nullableBindsInstance_doesNotFailOnNull() {
+ val component =
+ DaggerFactoryBindsInstanceTest_NullableBindsInstanceComponent.factory().create(null)
+ assertThat(component.string()).isEqualTo(null)
+ }
+
+ @Component
+ internal interface PrimitiveBindsInstanceComponent {
+ val int: Int
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance i: Int): PrimitiveBindsInstanceComponent
+ }
+ }
+
+ @Test
+ fun primitiveBindsInstance() {
+ val component =
+ DaggerFactoryBindsInstanceTest_PrimitiveBindsInstanceComponent.factory().create(1)
+ assertThat(component.int).isEqualTo(1)
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/FactoryDependenciesTest.kt b/javatests/dagger/functional/kotlinsrc/factory/FactoryDependenciesTest.kt
new file mode 100644
index 0000000..884a476
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/FactoryDependenciesTest.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import com.google.common.truth.Truth.assertThat
+import dagger.Component
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests for factories for components with a dependency. */
+@RunWith(JUnit4::class)
+class FactoryDependenciesTest {
+ @Component(dependencies = [Dependency::class])
+ internal interface DependencyComponent {
+ fun someObject(): Any
+
+ @Component.Factory
+ interface Factory {
+ fun create(dependency: Dependency?): DependencyComponent
+ }
+ }
+
+ @Test
+ fun dependency() {
+ val component = DaggerFactoryDependenciesTest_DependencyComponent.factory().create(Dependency())
+ assertThat(component.someObject()).isEqualTo("bar")
+ }
+
+ @Test
+ fun dependency_failsOnNull() {
+ try {
+ DaggerFactoryDependenciesTest_DependencyComponent.factory().create(null)
+ fail()
+ } catch (expected: NullPointerException) {}
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/FactoryImplicitModulesTest.kt b/javatests/dagger/functional/kotlinsrc/factory/FactoryImplicitModulesTest.kt
new file mode 100644
index 0000000..52e1fe0
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/FactoryImplicitModulesTest.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import com.google.common.truth.Truth.assertThat
+import dagger.Component
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/**
+ * Tests for factories for components with modules that do not require an instance to be passed to
+ * the factory. Includes both tests where the module does not have a corresponding parameter in the
+ * factory method and where it does have a parameter, for cases where that's allowed.
+ */
+@RunWith(JUnit4::class)
+class FactoryImplicitModulesTest {
+ @Component(modules = [AbstractModule::class])
+ internal interface AbstractModuleComponent {
+ fun string(): String
+
+ @Component.Factory
+ interface Factory {
+ fun create(): AbstractModuleComponent
+ }
+ }
+
+ @Test
+ fun abstractModule() {
+ val component = DaggerFactoryImplicitModulesTest_AbstractModuleComponent.factory().create()
+ assertThat(component.string()).isEqualTo("foo")
+ }
+
+ @Component(modules = [InstantiableConcreteModule::class])
+ internal interface InstantiableConcreteModuleComponent {
+ val int: Int
+
+ @Component.Factory
+ interface Factory {
+ fun create(): InstantiableConcreteModuleComponent
+ }
+ }
+
+ @Test
+ fun instantiableConcreteModule() {
+ val component =
+ DaggerFactoryImplicitModulesTest_InstantiableConcreteModuleComponent.factory().create()
+ assertThat(component.int).isEqualTo(42)
+ }
+
+ @Component(modules = [InstantiableConcreteModule::class])
+ internal interface InstantiableConcreteModuleWithFactoryParameterComponent {
+ val int: Int
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ module: InstantiableConcreteModule?
+ ): InstantiableConcreteModuleWithFactoryParameterComponent
+ }
+ }
+
+ @Test
+ fun instantiableConcreteModule_withFactoryParameter() {
+ val component =
+ DaggerFactoryImplicitModulesTest_InstantiableConcreteModuleWithFactoryParameterComponent
+ .factory()
+ .create(InstantiableConcreteModule())
+ assertThat(component.int).isEqualTo(42)
+ }
+
+ @Test
+ fun instantiableConcreteModule_withFactoryParameter_failsOnNull() {
+ try {
+ DaggerFactoryImplicitModulesTest_InstantiableConcreteModuleWithFactoryParameterComponent
+ .factory()
+ .create(null)
+ fail()
+ } catch (expected: NullPointerException) {}
+ }
+
+ @Component(modules = [ConcreteModuleThatCouldBeAbstract::class])
+ internal interface ConcreteModuleThatCouldBeAbstractComponent {
+ val double: Double
+
+ @Component.Factory
+ interface Factory {
+ fun create(): ConcreteModuleThatCouldBeAbstractComponent
+ }
+ }
+
+ @Test
+ fun concreteModuleThatCouldBeAbstract() {
+ val component =
+ DaggerFactoryImplicitModulesTest_ConcreteModuleThatCouldBeAbstractComponent.factory().create()
+ assertThat(component.double).isEqualTo(42.0)
+ }
+
+ @Component(modules = [ConcreteModuleThatCouldBeAbstract::class])
+ internal interface ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent {
+ val double: Double
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ module: ConcreteModuleThatCouldBeAbstract?
+ ): ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent
+ }
+ }
+
+ @Test
+ fun concreteModuleThatCouldBeAbstract_withFactoryParameter() {
+ val component: ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent =
+ DaggerFactoryImplicitModulesTest_ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent
+ .factory()
+ .create(ConcreteModuleThatCouldBeAbstract())
+ assertThat(component.double).isEqualTo(42.0)
+ }
+
+ @Test
+ fun concreteModuleThatCouldBeAbstract_withFactoryParameter_failsOnNull() {
+ // This matches what builders do when there's a setter for such a module; the setter checks that
+ // the argument is not null but otherwise ignores it.
+ // It's possible that we shouldn't even allow such a parameter for a factory, since unlike a
+ // builder, where the setter can just not be called, a factory doesn't give the option of not
+ // passing *something* for the unused parameter.
+ try {
+ DaggerFactoryImplicitModulesTest_ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent
+ .factory()
+ .create(null)
+ fail()
+ } catch (expected: NullPointerException) {}
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/FactoryMixedParametersTest.kt b/javatests/dagger/functional/kotlinsrc/factory/FactoryMixedParametersTest.kt
new file mode 100644
index 0000000..a4fda0e
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/FactoryMixedParametersTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import java.util.Random
+import javax.inject.Provider
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests for component factories with multiple parameters. */
+@RunWith(JUnit4::class)
+class FactoryMixedParametersTest {
+ @Component(
+ modules =
+ [
+ AbstractModule::class,
+ UninstantiableConcreteModule::class,
+ InstantiableConcreteModule::class
+ ],
+ dependencies = [Dependency::class]
+ )
+ internal interface MixedArgComponent {
+ fun getString(): String
+ val getInt: Int
+ val getLong: Long
+ fun getSomeObject(): Any
+ val getDouble: Double
+ fun getRandomProvider(): Provider<Random>
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance d: Double,
+ dependency: Dependency,
+ module: UninstantiableConcreteModule,
+ @BindsInstance random: Random
+ ): MixedArgComponent
+ }
+ }
+
+ @Test
+ fun mixedArgComponent() {
+ val random = Random()
+ val component =
+ DaggerFactoryMixedParametersTest_MixedArgComponent.factory()
+ .create(3.0, Dependency(), UninstantiableConcreteModule(2L), random)
+ assertThat(component.getString()).isEqualTo("foo")
+ assertThat(component.getInt).isEqualTo(42)
+ assertThat(component.getDouble).isEqualTo(3.0)
+ assertThat(component.getSomeObject()).isEqualTo("bar")
+ assertThat(component.getLong).isEqualTo(2L)
+ assertThat(component.getRandomProvider().get()).isSameInstanceAs(random)
+ assertThat(component.getRandomProvider().get()).isSameInstanceAs(random)
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/FactoryRequiredModulesTest.kt b/javatests/dagger/functional/kotlinsrc/factory/FactoryRequiredModulesTest.kt
new file mode 100644
index 0000000..45d0280
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/FactoryRequiredModulesTest.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import com.google.common.truth.Truth.assertThat
+import dagger.Component
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/**
+ * Tests for factories for components that have a module that must have an instance provided by the
+ * user.
+ */
+@RunWith(JUnit4::class)
+class FactoryRequiredModulesTest {
+ @Component(modules = [UninstantiableConcreteModule::class])
+ internal interface UninstantiableConcreteModuleComponent {
+ val long: Long
+
+ @Component.Factory
+ interface Factory {
+ fun create(module: UninstantiableConcreteModule?): UninstantiableConcreteModuleComponent
+ }
+ }
+
+ @Test
+ fun uninstantiableConcreteModule() {
+ val component =
+ DaggerFactoryRequiredModulesTest_UninstantiableConcreteModuleComponent.factory()
+ .create(UninstantiableConcreteModule(42L))
+ assertThat(component.long).isEqualTo(42L)
+ }
+
+ @Test
+ fun uninstantiableConcreteModule_failsOnNull() {
+ try {
+ DaggerFactoryRequiredModulesTest_UninstantiableConcreteModuleComponent.factory().create(null)
+ fail()
+ } catch (expected: NullPointerException) {}
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/InstantiableConcreteModule.kt b/javatests/dagger/functional/kotlinsrc/factory/InstantiableConcreteModule.kt
new file mode 100644
index 0000000..a5be07a
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/InstantiableConcreteModule.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import dagger.Module
+import dagger.Provides
+
+// intentionally non-static
+@Module
+class InstantiableConcreteModule {
+ @Provides fun provideInt(): Int = 42
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/SubcomponentFactoryTest.kt b/javatests/dagger/functional/kotlinsrc/factory/SubcomponentFactoryTest.kt
new file mode 100644
index 0000000..9cdbb7c
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/SubcomponentFactoryTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import dagger.Module
+import dagger.Provides
+import dagger.Subcomponent
+import javax.inject.Inject
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/**
+ * Tests for [subcomponent factories][Subcomponent.Factory].
+ *
+ * Most things are tested in `FactoryTest`; this is just intended to test some things like injecting
+ * subcomponent factories and returning them from component methods.
+ */
+@RunWith(JUnit4::class)
+class SubcomponentFactoryTest {
+ @Component
+ internal interface ParentWithSubcomponentFactory {
+ fun subcomponentFactory(): Sub.Factory
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance i: Int): ParentWithSubcomponentFactory
+ }
+ }
+
+ @Subcomponent
+ internal interface Sub {
+ fun i(): Int
+ fun s(): String
+
+ @Subcomponent.Factory
+ interface Factory {
+ fun create(@BindsInstance s: String): Sub
+ }
+ }
+
+ @Test
+ fun parentComponentWithSubcomponentFactoryEntryPoint() {
+ val parent = DaggerSubcomponentFactoryTest_ParentWithSubcomponentFactory.factory().create(3)
+ val subcomponent = parent.subcomponentFactory().create("foo")
+ assertThat(subcomponent.i()).isEqualTo(3)
+ assertThat(subcomponent.s()).isEqualTo("foo")
+ }
+
+ @Module(subcomponents = [Sub::class])
+ internal object ModuleWithSubcomponent {
+ @Provides fun provideInt(): Int = 42
+ }
+
+ internal class UsesSubcomponentFactory @Inject constructor(private val subFactory: Sub.Factory) {
+ fun getSubcomponent(s: String): Sub {
+ return subFactory.create(s)
+ }
+ }
+
+ @Component(modules = [ModuleWithSubcomponent::class])
+ internal interface ParentWithModuleWithSubcomponent {
+ fun usesSubcomponentFactory(): UsesSubcomponentFactory
+ }
+
+ @Test
+ fun parentComponentWithModuleWithSubcomponent() {
+ val parent = DaggerSubcomponentFactoryTest_ParentWithModuleWithSubcomponent.create()
+ val usesSubcomponentFactory = parent.usesSubcomponentFactory()
+ val subcomponent1 = usesSubcomponentFactory.getSubcomponent("foo")
+ assertThat(subcomponent1.i()).isEqualTo(42)
+ assertThat(subcomponent1.s()).isEqualTo("foo")
+ val subcomponent2 = usesSubcomponentFactory.getSubcomponent("bar")
+ assertThat(subcomponent2.i()).isEqualTo(42)
+ assertThat(subcomponent2.s()).isEqualTo("bar")
+ }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/factory/UninstantiableConcreteModule.kt b/javatests/dagger/functional/kotlinsrc/factory/UninstantiableConcreteModule.kt
new file mode 100644
index 0000000..d6533a9
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/factory/UninstantiableConcreteModule.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Dagger Authors.
+ *
+ * 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 dagger.functional.kotlinsrc.factory
+
+import dagger.Module
+import dagger.Provides
+
+@Module
+class UninstantiableConcreteModule(private val l: Long) {
+ @Provides fun provideLong(): Long = l
+}