From 6bda9e887683d6c61ea596251d427d470de59f07 Mon Sep 17 00:00:00 2001 From: Ben Lee Date: Tue, 9 Jun 2026 15:44:39 -0700 Subject: [PATCH 1/4] Add more integration tests --- maven_install_test.json | 55 ++++- tests/scripts/BUILD | 25 +++ .../android_lint_aar_scenarios_test.sh | 61 ++++++ tests/scripts/android_lint_scenarios_test.sh | 21 ++ tests/scripts/lint_helper.sh | 190 ++++++++++++++++++ 5 files changed, 349 insertions(+), 3 deletions(-) create mode 100755 tests/scripts/android_lint_aar_scenarios_test.sh diff --git a/maven_install_test.json b/maven_install_test.json index 4f1f2bb..93fbf3d 100755 --- a/maven_install_test.json +++ b/maven_install_test.json @@ -1,8 +1,20 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": 278678914, - "__RESOLVED_ARTIFACTS_HASH": 428393146, + "__INPUT_ARTIFACTS_HASH": 1988574746, + "__RESOLVED_ARTIFACTS_HASH": -626215935, "artifacts": { + "com.google.auto.service:auto-service-annotations": { + "shasums": { + "jar": "16a76dd00a2650568447f5d6e3a9e2c809d9a42367d56b45215cfb89731f4d24" + }, + "version": "1.1.1" + }, + "com.slack.lint.compose:compose-lint-checks": { + "shasums": { + "jar": "1ad367bbf4794c3b2f90420bc3dc97ba9a7fbbe5f7a4f995811071daca44bb0b" + }, + "version": "1.5.2" + }, "junit:junit": { "shasums": { "jar": "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3" @@ -29,6 +41,9 @@ } }, "dependencies": { + "com.slack.lint.compose:compose-lint-checks": [ + "com.google.auto.service:auto-service-annotations" + ], "junit:junit": [ "org.hamcrest:hamcrest-core" ], @@ -37,6 +52,27 @@ ] }, "packages": { + "com.google.auto.service:auto-service-annotations": [ + "com.google.auto.service" + ], + "com.slack.lint.compose:compose-lint-checks": [ + "slack.lint.compose", + "slack.lint.compose.shaded.kotlin.metadata", + "slack.lint.compose.shaded.kotlin.metadata.internal", + "slack.lint.compose.shaded.kotlin.metadata.internal.common", + "slack.lint.compose.shaded.kotlin.metadata.internal.extensions", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata.builtins", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata.deserialization", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata.jvm", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata.jvm.deserialization", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata.jvm.serialization", + "slack.lint.compose.shaded.kotlin.metadata.internal.metadata.serialization", + "slack.lint.compose.shaded.kotlin.metadata.internal.protobuf", + "slack.lint.compose.shaded.kotlin.metadata.jvm", + "slack.lint.compose.shaded.kotlin.metadata.jvm.internal", + "slack.lint.compose.util" + ], "junit:junit": [ "junit.extensions", "junit.framework", @@ -148,18 +184,31 @@ }, "repositories": { "https://maven.google.com/": [ + "com.google.auto.service:auto-service-annotations", + "com.slack.lint.compose:compose-lint-checks", "junit:junit", "net.bytebuddy:byte-buddy", "org.assertj:assertj-core", "org.hamcrest:hamcrest-core" ], "https://repo1.maven.org/maven2/": [ + "com.google.auto.service:auto-service-annotations", + "com.slack.lint.compose:compose-lint-checks", "junit:junit", "net.bytebuddy:byte-buddy", "org.assertj:assertj-core", "org.hamcrest:hamcrest-core" ] }, - "services": {}, + "services": { + "com.slack.lint.compose:compose-lint-checks": { + "com.android.tools.lint.client.api.IssueRegistry": [ + "slack.lint.compose.ComposeLintsIssueRegistry" + ], + "slack.lint.compose.shaded.kotlin.metadata.internal.extensions.MetadataExtensions": [ + "slack.lint.compose.shaded.kotlin.metadata.jvm.internal.JvmMetadataExtensions" + ] + } + }, "version": "2" } diff --git a/tests/scripts/BUILD b/tests/scripts/BUILD index 1d9250a..6620cb8 100644 --- a/tests/scripts/BUILD +++ b/tests/scripts/BUILD @@ -2,11 +2,22 @@ load("@bazel_binaries//:defs.bzl", "bazel_binaries") load("@rules_bazel_integration_test//bazel_integration_test:defs.bzl", "script_test") load("@rules_shell//shell:sh_library.bzl", "sh_library") +# Copies the compose-lint-checks jar to a stable runfiles path so the helper can +# rlocation it without depending on rules_jvm_external's repository layout. +genrule( + name = "compose_lint_checks_jar", + testonly = True, + srcs = ["@rules_android_lint_test_deps//:com_slack_lint_compose_compose_lint_checks"], + outs = ["compose_lint_checks.jar"], + cmd = "cp $$(echo '$(SRCS)' | tr ' ' '\\n' | grep 'compose-lint-checks' | head -1) $@", +) + sh_library( name = "lint_helper", testonly = True, srcs = ["lint_helper.sh"], data = [ + ":compose_lint_checks_jar", "//rules:all_files", "//src:all_files", "//src/cli:cli_deploy.jar", @@ -27,3 +38,17 @@ script_test( "//tests/bashunit", ], ) + +script_test( + name = "android_lint_aar_scenarios_test", + size = "enormous", + srcs = ["android_lint_aar_scenarios_test.sh"], + bazel_binaries = bazel_binaries, + bazel_version = bazel_binaries.versions.current, + env_inherit = ["ANDROID_HOME"], + tags = ["exclusive"], + deps = [ + ":lint_helper", + "//tests/bashunit", + ], +) diff --git a/tests/scripts/android_lint_aar_scenarios_test.sh b/tests/scripts/android_lint_aar_scenarios_test.sh new file mode 100755 index 0000000..78f61b5 --- /dev/null +++ b/tests/scripts/android_lint_aar_scenarios_test.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Scenarios for custom lint checks embedded in AAR dependencies (lint.jar), exercising the +# collect_aar_outputs_aspect extraction and auto-discovery path. Requires ANDROID_HOME. + +# --- begin runfiles.bash initialization v2 --- +# Copy-pasted from the Bazel Bash runfiles library v2. +set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e +# --- end runfiles.bash initialization v2 --- + +source "$(rlocation rules_android_lint/tests/bashunit/unittest.bash)" || \ + (echo >&2 "Failed to locate unittest.bash" && exit 1) + +source "$(rlocation rules_android_lint/tests/scripts/lint_helper.sh)" || \ + (echo >&2 "Failed to locate lint_helper.sh" && exit 1) + +function set_up() { + rm -rf -- * .bazelrc 2>/dev/null || true + set_up_lint_workspace + enable_android_in_workspace +} + +# Skips the calling test when no Android SDK is available. +function require_android_home() { + if [[ -z "${ANDROID_HOME:-}" ]]; then + echo "ANDROID_HOME is not set; skipping AAR scenario" + return 1 + fi + return 0 +} + +function test_aar_embedded_lint_jar_flags_issue() { + require_android_home || return 0 + write_composable_annotation_stub + write_dirty_composable + write_fixture_aar + write_aar_dep_lint_targets + + "${BIT_BAZEL_BINARY}" test --test_output=all //:lib_lint_test >& "$TEST_log" \ + && fail "Expected lint test with AAR-embedded checks to fail" || true + expect_log "ComposeNamingUppercase" +} + +function test_aar_embedded_lint_jar_accepts_clean_composable() { + require_android_home || return 0 + write_composable_annotation_stub + write_clean_composable + write_fixture_aar + write_aar_dep_lint_targets + + "${BIT_BAZEL_BINARY}" test --test_output=all //:lib_lint_test >& "$TEST_log" \ + || fail "Expected lint test with AAR-embedded checks to pass" +} + +run_suite "android_lint AAR lint.jar discovery scenarios" diff --git a/tests/scripts/android_lint_scenarios_test.sh b/tests/scripts/android_lint_scenarios_test.sh index 33da346..a31649a 100755 --- a/tests/scripts/android_lint_scenarios_test.sh +++ b/tests/scripts/android_lint_scenarios_test.sh @@ -116,4 +116,25 @@ function test_worker_and_local_strategies_agree() { expect_log "DefaultLocale" } +function test_custom_rules_jar_flags_compose_issue() { + write_composable_annotation_stub + write_dirty_composable + copy_compose_lint_checks + write_custom_rules_lint_targets + + "${BIT_BAZEL_BINARY}" test --test_output=all //:lib_lint_test >& "$TEST_log" \ + && fail "Expected lint test with custom compose-lints rules to fail" || true + expect_log "ComposeNamingUppercase" +} + +function test_custom_rules_jar_accepts_clean_composable() { + write_composable_annotation_stub + write_clean_composable + copy_compose_lint_checks + write_custom_rules_lint_targets + + "${BIT_BAZEL_BINARY}" test --test_output=all //:lib_lint_test >& "$TEST_log" \ + || fail "Expected lint test with custom compose-lints rules to pass" +} + run_suite "android_lint rule behavior scenarios" diff --git a/tests/scripts/lint_helper.sh b/tests/scripts/lint_helper.sh index 83da0f8..e991ec7 100755 --- a/tests/scripts/lint_helper.sh +++ b/tests/scripts/lint_helper.sh @@ -164,3 +164,193 @@ public class Foo { } EOF } + +# Copies the compose-lint-checks jar (the custom-rule test fixture) into the CWD. +function copy_compose_lint_checks() { + cp -L "$(rlocation rules_android_lint/tests/scripts/compose_lint_checks.jar)" \ + compose_lint_checks.jar +} + +# A source-level stand-in for androidx.compose.runtime.Composable so the compose-lints +# checks can resolve the annotation without the Compose runtime on the classpath. +function write_composable_annotation_stub() { + cat > Composable.kt < Modifier.kt < Stubs.kt < MyComposables.kt < MyComposables.kt <> MODULE.bazel <> .bazelrc <', + ) + aar.writestr("classes.jar", classes.getvalue()) + aar.writestr("R.txt", "") + aar.write("compose_lint_checks.jar", "lint.jar") +PYEOF +} + +# Lint targets that depend on the fixture AAR; custom checks must be discovered from the +# AAR's embedded lint.jar rather than the custom_rules attribute. +function write_aar_dep_lint_targets() { + cat > BUILD.bazel < BUILD.bazel < Date: Tue, 9 Jun 2026 15:52:27 -0700 Subject: [PATCH 2/4] Fix --- MODULE.bazel | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MODULE.bazel b/MODULE.bazel index 34b78f7..11bbb25 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -65,6 +65,8 @@ maven_test.install( artifacts = [ "org.assertj:assertj-core:3.24.2", "junit:junit:4.13.2", + # Custom lint check used as a test fixture by //tests/scripts + "com.slack.lint.compose:compose-lint-checks:1.5.2", ], lock_file = "//:maven_install_test.json", repositories = [ From 1f177c9ea0f6d33cc5852b2083a9714ed4ee4dab Mon Sep 17 00:00:00 2001 From: Ben Lee Date: Tue, 9 Jun 2026 17:16:57 -0700 Subject: [PATCH 3/4] Don't soft-fail tests when ANDROID_HOME is not there --- tests/scripts/BUILD | 2 +- tests/scripts/android_lint_aar_scenarios_test.sh | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/scripts/BUILD b/tests/scripts/BUILD index 6620cb8..831aa57 100644 --- a/tests/scripts/BUILD +++ b/tests/scripts/BUILD @@ -43,9 +43,9 @@ script_test( name = "android_lint_aar_scenarios_test", size = "enormous", srcs = ["android_lint_aar_scenarios_test.sh"], + additional_env_inherit = ["ANDROID_HOME"], bazel_binaries = bazel_binaries, bazel_version = bazel_binaries.versions.current, - env_inherit = ["ANDROID_HOME"], tags = ["exclusive"], deps = [ ":lint_helper", diff --git a/tests/scripts/android_lint_aar_scenarios_test.sh b/tests/scripts/android_lint_aar_scenarios_test.sh index 78f61b5..03b3000 100755 --- a/tests/scripts/android_lint_aar_scenarios_test.sh +++ b/tests/scripts/android_lint_aar_scenarios_test.sh @@ -26,17 +26,7 @@ function set_up() { enable_android_in_workspace } -# Skips the calling test when no Android SDK is available. -function require_android_home() { - if [[ -z "${ANDROID_HOME:-}" ]]; then - echo "ANDROID_HOME is not set; skipping AAR scenario" - return 1 - fi - return 0 -} - function test_aar_embedded_lint_jar_flags_issue() { - require_android_home || return 0 write_composable_annotation_stub write_dirty_composable write_fixture_aar @@ -48,7 +38,6 @@ function test_aar_embedded_lint_jar_flags_issue() { } function test_aar_embedded_lint_jar_accepts_clean_composable() { - require_android_home || return 0 write_composable_annotation_stub write_clean_composable write_fixture_aar From dba2381b93acdb347abff685d2792cdd45c5dc83 Mon Sep 17 00:00:00 2001 From: Ben Lee Date: Tue, 9 Jun 2026 19:16:00 -0700 Subject: [PATCH 4/4] Fix --- src/cli/AndroidLintRunner.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/AndroidLintRunner.kt b/src/cli/AndroidLintRunner.kt index 9a7b4e3..31d7b7f 100644 --- a/src/cli/AndroidLintRunner.kt +++ b/src/cli/AndroidLintRunner.kt @@ -27,7 +27,7 @@ internal class AndroidLintRunner( val aarLintRuleJars = args.classpathAarPairs .asSequence() - .map { it.first.resolve("lint.jar") } + .map { it.second.resolve("lint.jar") } .filter { it.exists() && it.isRegularFile() } // Create the project configuration file for lint