1 /* 2 * Copyright (C) 2023 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.functional.kotlinsrc.subcomponent.multibindings 18 19 import com.google.common.collect.ImmutableMap 20 import com.google.common.collect.ImmutableSet 21 import com.google.common.truth.Truth.assertThat 22 import dagger.functional.kotlinsrc.subcomponent.multibindings.MultibindingSubcomponents.* 23 import org.junit.Before 24 import org.junit.Test 25 import org.junit.runner.RunWith 26 import org.junit.runners.JUnit4 27 28 @RunWith(JUnit4::class) 29 class SubcomponentMultibindingsTest { 30 private lateinit var parentWithoutProvisionHasChildWithoutProvision: 31 ParentWithoutProvisionHasChildWithoutProvision 32 private lateinit var parentWithoutProvisionHasChildWithProvision: 33 ParentWithoutProvisionHasChildWithProvision 34 private lateinit var parentWithProvisionHasChildWithoutProvision: 35 ParentWithProvisionHasChildWithoutProvision 36 private lateinit var parentWithProvisionHasChildWithProvision: 37 ParentWithProvisionHasChildWithProvision 38 @Before setUpnull39 fun setUp() { 40 parentWithoutProvisionHasChildWithoutProvision = 41 DaggerMultibindingSubcomponents_ParentWithoutProvisionHasChildWithoutProvision.create() 42 parentWithoutProvisionHasChildWithProvision = 43 DaggerMultibindingSubcomponents_ParentWithoutProvisionHasChildWithProvision.create() 44 parentWithProvisionHasChildWithoutProvision = 45 DaggerMultibindingSubcomponents_ParentWithProvisionHasChildWithoutProvision.create() 46 parentWithProvisionHasChildWithProvision = 47 DaggerMultibindingSubcomponents_ParentWithProvisionHasChildWithProvision.create() 48 } 49 50 @Test testParentWithoutProvisionHasChildWithoutProvisionnull51 fun testParentWithoutProvisionHasChildWithoutProvision() { 52 // Child 53 assertThat( 54 parentWithoutProvisionHasChildWithoutProvision 55 .childWithoutProvision() 56 .grandchild() 57 .requiresMultibindingsBoundInParent() 58 ) 59 .isEqualTo(BOUND_IN_PARENT) 60 61 // Grandchild 62 assertThat( 63 parentWithoutProvisionHasChildWithoutProvision 64 .childWithoutProvision() 65 .grandchild() 66 .requiresMultibindingsBoundInParentAndChild() 67 ) 68 .isEqualTo(BOUND_IN_PARENT_AND_CHILD) 69 70 assertThat( 71 parentWithoutProvisionHasChildWithoutProvision 72 .childWithoutProvision() 73 .grandchild() 74 .requiresMultibindingsBoundInChild() 75 ) 76 .isEqualTo(BOUND_IN_CHILD) 77 78 // Even though the multibinding for Set<RequiresMultiboundObjects> does not itself have a 79 // contribution from the child, it must be pushed down to (not duplicated in) the child because 80 // its contribution depends on multibindings that have one contribution from the parent and one 81 // from the child (see b/22821341). 82 assertThat( 83 parentWithoutProvisionHasChildWithoutProvision 84 .childWithoutProvision() 85 .grandchild() 86 .setOfRequiresMultibindingsInParentAndChild() 87 ) 88 .containsExactly(BOUND_IN_PARENT_AND_CHILD) 89 } 90 91 @Test testParentWithoutProvisionHasChildWithProvisionnull92 fun testParentWithoutProvisionHasChildWithProvision() { 93 // Child 94 assertThat( 95 parentWithoutProvisionHasChildWithProvision 96 .childWithProvision() 97 .grandchild() 98 .requiresMultibindingsBoundInParent() 99 ) 100 .isEqualTo(BOUND_IN_PARENT) 101 102 // Grandchild 103 assertThat( 104 parentWithoutProvisionHasChildWithProvision 105 .childWithProvision() 106 .grandchild() 107 .requiresMultibindingsBoundInParentAndChild() 108 ) 109 .isEqualTo(BOUND_IN_PARENT_AND_CHILD) 110 111 assertThat( 112 parentWithoutProvisionHasChildWithProvision 113 .childWithProvision() 114 .grandchild() 115 .requiresMultibindingsBoundInChild() 116 ) 117 .isEqualTo(BOUND_IN_CHILD) 118 119 // Even though the multibinding for Set<RequiresMultiboundObjects> does not itself have a 120 // contribution from the child, it must be pushed down to (not duplicated in) the child because 121 // its contribution depends on multibindings that have one contribution from the parent and one 122 // from the child (see b/22821341). 123 assertThat( 124 parentWithoutProvisionHasChildWithProvision 125 .childWithProvision() 126 .grandchild() 127 .setOfRequiresMultibindingsInParentAndChild() 128 ) 129 .containsExactly(BOUND_IN_PARENT_AND_CHILD) 130 } 131 132 @Test testParentWithProvisionHasChildWithoutProvisionnull133 fun testParentWithProvisionHasChildWithoutProvision() { 134 // Parent 135 assertThat(parentWithProvisionHasChildWithoutProvision.requiresMultibindingsBoundInParent()) 136 .isEqualTo(BOUND_IN_PARENT) 137 assertThat( 138 parentWithProvisionHasChildWithoutProvision.requiresMultibindingsBoundInParentAndChild() 139 ) 140 .isEqualTo(BOUND_IN_PARENT_AND_CHILD_PROVIDED_BY_PARENT) 141 142 // Grandchild 143 assertThat( 144 parentWithProvisionHasChildWithoutProvision 145 .childWithoutProvision() 146 .grandchild() 147 .requiresMultibindingsBoundInParent() 148 ) 149 .isEqualTo(BOUND_IN_PARENT) 150 assertThat( 151 parentWithProvisionHasChildWithoutProvision 152 .childWithoutProvision() 153 .grandchild() 154 .requiresMultibindingsBoundInChild() 155 ) 156 .isEqualTo(BOUND_IN_CHILD) 157 158 assertThat( 159 parentWithProvisionHasChildWithoutProvision 160 .childWithoutProvision() 161 .grandchild() 162 .requiresMultibindingsBoundInParentAndChild() 163 ) 164 .isEqualTo(BOUND_IN_PARENT_AND_CHILD) 165 166 // Even though the multibinding for Set<RequiresMultiboundObjects> does not itself have a 167 // contribution from the child, it must be pushed down to (not duplicated in) the child because 168 // its contribution depends on multibindings that have one contribution from the parent and one 169 // from the child (see b/22821341). 170 assertThat( 171 parentWithProvisionHasChildWithoutProvision 172 .childWithoutProvision() 173 .grandchild() 174 .setOfRequiresMultibindingsInParentAndChild() 175 ) 176 .containsExactly(BOUND_IN_PARENT_AND_CHILD) 177 } 178 179 @Test testParentWithProvisionHasChildWithProvisionnull180 fun testParentWithProvisionHasChildWithProvision() { 181 // Parent 182 assertThat(parentWithProvisionHasChildWithProvision.requiresMultibindingsBoundInParent()) 183 .isEqualTo(BOUND_IN_PARENT) 184 185 // Child 186 assertThat( 187 parentWithProvisionHasChildWithProvision 188 .childWithProvision() 189 .requiresMultibindingsBoundInParent() 190 ) 191 .isEqualTo(BOUND_IN_PARENT) 192 assertThat( 193 parentWithProvisionHasChildWithProvision 194 .childWithProvision() 195 .requiresMultibindingsBoundInChild() 196 ) 197 .isEqualTo(BOUND_IN_CHILD) 198 assertThat( 199 parentWithProvisionHasChildWithProvision 200 .childWithProvision() 201 .requiresMultibindingsBoundInParentAndChild() 202 ) 203 .isEqualTo(BOUND_IN_PARENT_AND_CHILD) 204 205 // https://github.com/google/dagger/issues/401 206 assertThat( 207 DaggerMultibindingSubcomponents_ParentWithProvisionHasChildWithBinds.create() 208 .childWithBinds() 209 .requiresMultibindingsBoundInParentAndChild() 210 ) 211 .isEqualTo(BOUND_IN_PARENT_AND_CHILD) 212 213 // Even though the multibinding for Set<RequiresMultiboundObjects> does not itself have a 214 // contribution from the child, it must be pushed down to (not duplicated in) the child because 215 // its contribution depends on multibindings that have one contribution from the parent and one 216 // from the child (see b/22821341). 217 assertThat( 218 parentWithProvisionHasChildWithProvision 219 .childWithProvision() 220 .setOfRequiresMultibindingsInParentAndChild() 221 ) 222 .containsExactly(BOUND_IN_PARENT_AND_CHILD) 223 224 // Grandchild 225 assertThat( 226 parentWithProvisionHasChildWithProvision 227 .childWithProvision() 228 .grandchild() 229 .requiresMultibindingsBoundInParent() 230 ) 231 .isEqualTo(BOUND_IN_PARENT) 232 233 assertThat( 234 parentWithProvisionHasChildWithProvision 235 .childWithProvision() 236 .grandchild() 237 .requiresMultibindingsBoundInChild() 238 ) 239 .isEqualTo(BOUND_IN_CHILD) 240 241 assertThat( 242 parentWithProvisionHasChildWithProvision 243 .childWithProvision() 244 .grandchild() 245 .requiresMultibindingsBoundInParentAndChild() 246 ) 247 .isEqualTo(BOUND_IN_PARENT_AND_CHILD) 248 249 // Even though the multibinding for Set<RequiresMultiboundObjects> does not itself have a 250 // contribution from the child, it must be pushed down to (not duplicated in) the child because 251 // its contribution depends on multibindings that have one contribution from the parent and one 252 // from the child (see b/22821341). 253 assertThat( 254 parentWithProvisionHasChildWithProvision 255 .childWithProvision() 256 .grandchild() 257 .setOfRequiresMultibindingsInParentAndChild() 258 ) 259 .containsExactly(BOUND_IN_PARENT_AND_CHILD) 260 } 261 262 companion object { 263 private val BOUND_IN_PARENT = 264 RequiresMultibindings( 265 ImmutableSet.of(BoundInParent.INSTANCE), 266 ImmutableMap.of("parent key", BoundInParent.INSTANCE) 267 ) 268 private val BOUND_IN_CHILD = 269 RequiresMultibindings( 270 ImmutableSet.of(BoundInChild.INSTANCE), 271 ImmutableMap.of("child key", BoundInChild.INSTANCE) 272 ) 273 private val BOUND_IN_PARENT_AND_CHILD = 274 RequiresMultibindings( 275 ImmutableSet.of(BoundInParentAndChild.IN_PARENT, BoundInParentAndChild.IN_CHILD), 276 ImmutableMap.of( 277 "parent key", 278 BoundInParentAndChild.IN_PARENT, 279 "child key", 280 BoundInParentAndChild.IN_CHILD 281 ) 282 ) 283 private val BOUND_IN_PARENT_AND_CHILD_PROVIDED_BY_PARENT = 284 RequiresMultibindings( 285 ImmutableSet.of(BoundInParentAndChild.IN_PARENT), 286 ImmutableMap.of("parent key", BoundInParentAndChild.IN_PARENT) 287 ) 288 } 289 } 290