Skip to content

Commit

Permalink
Fixes issue with using EarlyEntryPoints being dropped when using `ena…
Browse files Browse the repository at this point in the history
…bleAggregatingTask`.

Due to the missing package in the aggregated packages list, the Hilt Gradle plugin was silently dropping `EarlyEntryPoint` metadata when `enableAggregatingTask = true`.
See #2789

Added a new Gradle module as a regression test.

Fixes #2789

RELNOTES=Fix #2789: Fixes issue with using EarlyEntryPoints being dropped when using `enableAggregatingTask`
PiperOrigin-RevId: 387850463
  • Loading branch information
bcorso authored and Dagger Team committed Jul 30, 2021
1 parent 5dec3cf commit 38db196
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 1 deletion.
Expand Up @@ -91,8 +91,10 @@ abstract class AggregatedPackagesTransform : TransformAction<TransformParameters
}

companion object {
// TODO(b/195125455): Make this more robust when adding new metadata.
// The list packages for generated classes used to pass information between compilation units.
val AGGREGATED_PACKAGES = listOf(
"dagger/hilt/android/internal/earlyentrypoint/codegen",
"dagger/hilt/android/internal/uninstallmodules/codegen",
"dagger/hilt/internal/aggregatedroot/codegen",
"dagger/hilt/internal/processedrootsentinel/codegen",
Expand Down
@@ -0,0 +1,67 @@
plugins {
id 'com.android.library'
id 'dagger.hilt.android.plugin'
}

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"

defaultConfig {
minSdkVersion 15
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
testOptions {
unitTests.includeAndroidResources = true
}
}

hilt {
enableTransformForLocalTests = true
enableAggregatingTask = true
}

// This is a regression test for https://github.com/google/dagger/issues/2789.
// Reproducing this issue requires that we don't have unexpected tests, so this
// check validates that. In particular, if we accidentally add a test with no
// test-specific bindings the EarlyEntryPoints will use the component for that
// test instead of generating a component just for the EarlyEntryPoints, which
// causes this issue.
task checkSourceSetTask(){
sourceSets {
test {
def expectedSrcs = [
'EarlyEntryPointWithBindValueTest.java',
'EarlyEntryPointWithBindValueObjects.java'
]
if (!allSource.files.name.equals(expectedSrcs)) {
throw new StopExecutionException(
'Unexpected test sources: ' + allSource.files.name)
}
}
}
}

gradle.projectsEvaluated {
preBuild.dependsOn checkSourceSetTask
}

dependencies {
implementation "com.google.dagger:hilt-android:$dagger_version"
annotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"

testImplementation 'com.google.truth:truth:1.0.1'
testImplementation 'junit:junit:4.13'
testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
testImplementation 'androidx.core:core:1.3.2'
testImplementation 'androidx.test.ext:junit:1.1.2'
testImplementation 'androidx.test:runner:1.3.0'
testImplementation "com.google.dagger:hilt-android-testing:$dagger_version"
testAnnotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
}
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 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.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dagger.hilt.android.simple.earlyentrypoint">

</manifest>
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 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.hilt.android.simple;

import dagger.hilt.InstallIn;
import dagger.hilt.android.EarlyEntryPoint;
import dagger.hilt.components.SingletonComponent;
import javax.inject.Inject;
import javax.inject.Singleton;

// This is defined outside of the tests since EarlyEntryPoint cannot be nested in tests.
public final class EarlyEntryPointWithBindValueObjects {
private EarlyEntryPointWithBindValueObjects() {}

@Singleton
public static final class Foo {
@Inject
Foo() {}
}

/** Used to test {@link EarlyEntryPoint} */
@EarlyEntryPoint
@InstallIn(SingletonComponent.class)
public interface FooEarlyEntryPoint {
Foo getEarlyFoo();
}
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2021 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.hilt.android.simple;

import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;

import android.content.Context;
import android.os.Build;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import dagger.hilt.EntryPoint;
import dagger.hilt.EntryPoints;
import dagger.hilt.InstallIn;
import dagger.hilt.android.EarlyEntryPoints;
import dagger.hilt.android.simple.EarlyEntryPointWithBindValueObjects.Foo;
import dagger.hilt.android.simple.EarlyEntryPointWithBindValueObjects.FooEarlyEntryPoint;
import dagger.hilt.android.testing.BindValue;
import dagger.hilt.android.testing.HiltAndroidRule;
import dagger.hilt.android.testing.HiltAndroidTest;
import dagger.hilt.android.testing.HiltTestApplication;
import dagger.hilt.components.SingletonComponent;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;

@HiltAndroidTest
@RunWith(AndroidJUnit4.class)
// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
@Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
public final class EarlyEntryPointWithBindValueTest {
@EntryPoint
@InstallIn(SingletonComponent.class)
interface FooEntryPoint {
Foo foo();
}

@Rule public HiltAndroidRule rule = new HiltAndroidRule(this);

@BindValue String bindString = "TestValue";

@Test
public void testBindValue() throws Exception {
rule.inject();
assertThat(bindString).isNotNull();
assertThat(bindString).isEqualTo("TestValue");
}

@Test
public void testEarlyEntryPoint() throws Exception {
Context appContext = getApplicationContext();

// Assert that all scoped Foo instances from EarlyEntryPoint are equal
Foo earlyFoo1 = EarlyEntryPoints.get(appContext, FooEarlyEntryPoint.class).getEarlyFoo();
Foo earlyFoo2 = EarlyEntryPoints.get(appContext, FooEarlyEntryPoint.class).getEarlyFoo();
assertThat(earlyFoo1).isNotNull();
assertThat(earlyFoo2).isNotNull();
assertThat(earlyFoo1).isEqualTo(earlyFoo2);

// Assert that all scoped Foo instances from EntryPoint are equal
Foo foo1 = EntryPoints.get(appContext, FooEntryPoint.class).foo();
Foo foo2 = EntryPoints.get(appContext, FooEntryPoint.class).foo();
assertThat(foo1).isNotNull();
assertThat(foo2).isNotNull();
assertThat(foo1).isEqualTo(foo2);

// Assert that scoped Foo instances from EarlyEntryPoint and EntryPoint are not equal
assertThat(foo1).isNotEqualTo(earlyFoo1);
}
}
3 changes: 2 additions & 1 deletion javatests/artifacts/hilt-android/simple/settings.gradle
Expand Up @@ -3,4 +3,5 @@ include ':app'
include ':feature'
include ':lib'
include ':deep-android-lib'
include ':deep-lib'
include ':deep-lib'
include ':earlyentrypoint'

0 comments on commit 38db196

Please sign in to comment.