diff options
author | John Cater <jcater@google.com> | 2023-09-07 13:43:09 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-09-07 13:43:41 -0700 |
commit | 91ca9f6952fab96fd54f52857f764fb7aa002552 (patch) | |
tree | 632b3e1827e65798d4e5d0ffdc9e213d8775faac /test | |
parent | 8c1dbff9cbc35f11a3ac1af909132f44809a406f (diff) | |
download | bazelbuild-rules_android-91ca9f6952fab96fd54f52857f764fb7aa002552.tar.gz |
Implement android_sdk_repository in Starlark.
Fixes https://github.com/bazelbuild/rules_android/issues/76.
PiperOrigin-RevId: 563532977
Change-Id: I1a17d21984429bf426c9ff3f8ba7cdab337c8529
Diffstat (limited to 'test')
5 files changed, 580 insertions, 0 deletions
diff --git a/test/rules/android_sdk_repository/BUILD b/test/rules/android_sdk_repository/BUILD new file mode 100644 index 0000000..72cabf9 --- /dev/null +++ b/test/rules/android_sdk_repository/BUILD @@ -0,0 +1,75 @@ +# Description: +# Tests for android_sdk_repository. + +load("@bazel_binaries//:defs.bzl", "bazel_binaries") +load( + "@rules_bazel_integration_test//bazel_integration_test:defs.bzl", + "script_test", +) + +package( + default_applicable_licenses = ["//:license"], + default_visibility = [ + "//test:__subpackages__", + ], +) + +licenses(["notice"]) + +sh_library( + name = "android_helper", + testonly = True, + srcs = ["android_helper.sh"], + data = [ + "//rules/android_sdk_repository:bzl", + ], + visibility = ["//visibility:private"], + deps = [ + "//test/bashunit", + "@bazel_tools//tools/bash/runfiles", + ], +) + +sh_library( + name = "test_lib", + testonly = True, + srcs = ["test_lib.sh"], + visibility = ["//visibility:private"], + deps = [ + ":android_helper", + "//test/bashunit", + "@bazel_tools//tools/bash/runfiles", + ], +) + +script_test( + name = "android_sdk_repository_test", + srcs = ["android_sdk_repository_test.sh"], + bazel_binaries = bazel_binaries, + bazel_version = bazel_binaries.versions.current, + deps = [ + ":test_lib", + "//test/bashunit", + "@bazel_tools//tools/bash/runfiles", + ], +) + +script_test( + name = "android_sdk_repository_platforms_test", + srcs = ["android_sdk_repository_platforms_test.sh"], + bazel_binaries = bazel_binaries, + bazel_version = bazel_binaries.versions.current, + deps = [ + ":test_lib", + "//test/bashunit", + "@bazel_tools//tools/bash/runfiles", + ], +) + +test_suite( + name = "integration_tests", + tests = [ + ":android_sdk_repository_platforms_test", + ":android_sdk_repository_test", + ], +) diff --git a/test/rules/android_sdk_repository/android_helper.sh b/test/rules/android_sdk_repository/android_helper.sh new file mode 100644 index 0000000..63a817f --- /dev/null +++ b/test/rules/android_sdk_repository/android_helper.sh @@ -0,0 +1,253 @@ +#!/bin/bash +# +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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. + +# --- 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 build_bazel_rules_android/test/bashunit/unittest.bash)" || \ + (echo >&2 "Failed to locate bashunit.sh" && exit 1) + +function set_up() { + # Clean out the repository. + rm -rf * + touch WORKSPACE + + # Clean out the test android SDK if any + rm -rf "${TEST_TMPDIR}/android_sdk" + + # Make sure the rules exist and seed the WORKSPACE. + rm -rf "${TEST_TMPDIR}/android_sdk_repository_src" + set_up_rules +} + +function set_up_rules() { + local android_revision_rule="$(rlocation build_bazel_rules_android/rules/android_revision.bzl)" + + local repo_rule="$(rlocation build_bazel_rules_android/rules/android_sdk_repository/rule.bzl)" + local repo_rule_dir="$(dirname "${repo_rule}")" + local dest_dir="${TEST_TMPDIR}/android_sdk_repository_src" + mkdir -p "${dest_dir}/rules/android_sdk_repository" + cp -r "${repo_rule_dir}"/* "${dest_dir}/rules/android_sdk_repository" + cat > "${dest_dir}/WORKSPACE" <<EOF +workspace(name = "android_sdk_repository_src") +EOF + cat > "${dest_dir}/rules/BUILD" <<EOF +exports_files(["*.bzl"]) +EOF + cp "${android_revision_rule}" "${dest_dir}/rules/" + cat > "${dest_dir}/rules/android_sdk_repository/BUILD" <<EOF +exports_files(["*.bzl"]) +EOF + + cat >> WORKSPACE <<EOF +local_repository( + name = "android_sdk_repository_src", + path = "${dest_dir}", +) +load("@android_sdk_repository_src//rules/android_sdk_repository:rule.bzl", "android_sdk_repository") +EOF +} + +function create_android_sdk() { + # Create a fake Android SDK that will be available for the repository rule. + local location="${TEST_TMPDIR}/android_sdk" + mkdir -p "${location}" + + mkdir "${location}/platform-tools" + touch "${location}/platform-tools/adb" + + echo "${location}" +} + +function add_platforms() { + local sdk_path="${1}" + shift + + # Add all requested API levels + for level in "$@"; do + local dir="${sdk_path}/platforms/android-${level}" + mkdir -p "${dir}" + touch "${dir}/android.jar" + touch "${dir}/framework.aidl" + + local system_image_dir="${sdk_path}/system-images/android-${level}" + mkdir -p "${system_image_dir}/default/arm64-v8a" + mkdir -p "${system_image_dir}/default/x86_64" + done +} + +function add_build_tools() { + local sdk_path="${1}" + shift + + # Add all requested tools + for version in "$@"; do + local dir="${sdk_path}/build-tools/${version}" + mkdir -p "${dir}/lib" + touch "${dir}/aapt" + touch "${dir}/aidl" + touch "${dir}/lib/apksigner.jar" + touch "${dir}/lib/d8.jar" + touch "${dir}/lib/dx.jar" + touch "${dir}/mainDexClasses.rules" + touch "${dir}/zipalign" + done +} + +function create_android_sdk_basic() { + local sdk_path="$(create_android_sdk)" + add_platforms "${sdk_path}" 31 + add_build_tools "${sdk_path}" 30.0.3 + echo "${sdk_path}" +} + +function create_verify() { + mkdir verify + cat > verify/BUILD <<EOF +genrule( + name = "check_sdk", + outs = ["check_sdk.log"], + cmd = select({ + "@androidsdk//:has_androidsdk": "echo sdk present > \$@", + "//conditions:default": "echo sdk missing > \$@", + }), +) +EOF + + "${BIT_BAZEL_BINARY}" build //verify:check_sdk >& $TEST_log || fail "Expected success" + cat bazel-bin/verify/check_sdk.log >$TEST_log +} + +function verify_no_android_sdk() { + create_verify + expect_log "sdk missing" +} + +function verify_android_sdk() { + create_verify + expect_log "sdk present" + "${BIT_BAZEL_BINARY}" query @androidsdk//:files >& $TEST_log || fail "Expected to exist" +} + +function write_platforms() { + mkdir -p platforms + cat > platforms/BUILD <<EOF +platform( + name = "arm64-v8a", + constraint_values = [ + "@platforms//os:android", + "@platforms//cpu:arm64", + ], +) +EOF +} + +function write_android_sdk_provider() { + mkdir -p sdk_check + cat > sdk_check/check.bzl <<EOF +def _find_api_level(android_jar): + # expected format: external/androidsdk/platforms/android-LEVEL/android.jar + if not android_jar.startswith("external/androidsdk/platforms/android-"): + return "unknown" + if not android_jar.endswith("/android.jar"): + return "unknown" + level = android_jar.removeprefix("external/androidsdk/platforms/android-") + level = level.removesuffix("/android.jar") + return level +def _show_sdk_info_impl(ctx): + print("SDK check results:") + provider = ctx.attr._android_sdk[AndroidSdkInfo] + print("build_tools_version: %s" % provider.build_tools_version) + print("api_level: %s" % _find_api_level(provider.android_jar.path)) +show_sdk_info = rule( + implementation = _show_sdk_info_impl, + attrs = { + "_android_sdk": attr.label(default = "@androidsdk//:sdk"), + }, +) +EOF +} + +function write_android_sdk_provider_platforms() { + mkdir -p sdk_check + cat > sdk_check/check.bzl <<EOF +def _find_api_level(android_jar): + # expected format: external/androidsdk/platforms/android-LEVEL/android.jar + if not android_jar.startswith("external/androidsdk/platforms/android-"): + return "unknown" + if not android_jar.endswith("/android.jar"): + return "unknown" + level = android_jar.removeprefix("external/androidsdk/platforms/android-") + level = level.removesuffix("/android.jar") + return level +def _show_sdk_info_impl(ctx): + print("SDK check results:") + toolchain = ctx.toolchains["@bazel_tools//tools/android:sdk_toolchain_type"] + if not toolchain: + print("No SDK found via toolchain") + return + provider = toolchain.android_sdk_info + print("build_tools_version: %s" % provider.build_tools_version) + print("api_level: %s" % _find_api_level(provider.android_jar.path)) +show_sdk_info = rule( + implementation = _show_sdk_info_impl, + toolchains = [ + config_common.toolchain_type( + "@bazel_tools//tools/android:sdk_toolchain_type", + mandatory = False, + ), + ], +) +EOF +} + +function check_android_sdk_provider() { + local extra_args=("$@") + + if [[ ${ENABLE_PLATFORMS:-false} == "true" ]]; then + write_platforms + write_android_sdk_provider_platforms + extra_args+=( + "--incompatible_enable_android_toolchain_resolution" + "--platforms=//platforms:arm64-v8a" + ) + else + write_android_sdk_provider + fi + + cat > sdk_check/BUILD <<EOF +load(":check.bzl", "show_sdk_info") +show_sdk_info( + name = "check", +) +EOF + + "${BIT_BAZEL_BINARY}" \ + build \ + --experimental_google_legacy_api \ + "${extra_args[@]}" \ + -- \ + //sdk_check:check >& $TEST_log || fail "Expected success" + expect_log "SDK check results" +} diff --git a/test/rules/android_sdk_repository/android_sdk_repository_platforms_test.sh b/test/rules/android_sdk_repository/android_sdk_repository_platforms_test.sh new file mode 100755 index 0000000..20eaf84 --- /dev/null +++ b/test/rules/android_sdk_repository/android_sdk_repository_platforms_test.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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. + +# --- 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 build_bazel_rules_android/test/bashunit/unittest.bash)" || \ + (echo >&2 "Failed to locate bashunit.sh" && exit 1) + +ENABLE_PLATFORMS=true + +# Source and run the actual tests from test_lib.sh +source "$(rlocation build_bazel_rules_android/test/rules/android_sdk_repository/test_lib.sh)" || \ + (echo >&2 "Failed to locate test_lib.sh" && exit 1) + +run_suite "Android integration tests for SDK (with platforms)" diff --git a/test/rules/android_sdk_repository/android_sdk_repository_test.sh b/test/rules/android_sdk_repository/android_sdk_repository_test.sh new file mode 100755 index 0000000..53d6573 --- /dev/null +++ b/test/rules/android_sdk_repository/android_sdk_repository_test.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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. + +# --- 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 build_bazel_rules_android/test/bashunit/unittest.bash)" || \ + (echo >&2 "Failed to locate bashunit.sh" && exit 1) + +ENABLE_PLATFORMS=false + +# Source and run the actual tests from test_lib.sh +source "$(rlocation build_bazel_rules_android/test/rules/android_sdk_repository/test_lib.sh)" || \ + (echo >&2 "Failed to locate test_lib.sh" && exit 1) + +run_suite "Android integration tests for SDK" diff --git a/test/rules/android_sdk_repository/test_lib.sh b/test/rules/android_sdk_repository/test_lib.sh new file mode 100644 index 0000000..f6a53af --- /dev/null +++ b/test/rules/android_sdk_repository/test_lib.sh @@ -0,0 +1,178 @@ +#!/bin/bash +# +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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. + +# --- 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 build_bazel_rules_android/test/bashunit/unittest.bash)" || \ + (echo >&2 "Failed to locate bashunit.sh" && exit 1) + +source "$(rlocation build_bazel_rules_android/test/rules/android_sdk_repository/android_helper.sh)" || \ + (echo >&2 "Failed to locate android_helper.sh" && exit 1) + +# Actual tests for Android Sdk Repository + +# Check that the empty BUILD file was created. +function test_android_sdk_repository_no_path_or_android_home() { + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", +) +EOF + + verify_no_android_sdk + "${BIT_BAZEL_BINARY}" build @androidsdk//:files >& $TEST_log && fail "Should have failed" || true + expect_log "Either the path attribute of android_sdk_repository" +} + +function test_android_sdk_repository_path_from_attribute() { + # Create android SDK + local sdk_path="$(create_android_sdk_basic)" + + # Add to repository. + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", + path = "${sdk_path}", +) +EOF + + # Verify the SDK is created correctly. + verify_android_sdk +} + +function test_android_sdk_repository_path_from_environment() { + # Create android SDK + local sdk_path="$(create_android_sdk_basic)" + + # Add to repository. + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", +) +EOF + + export ANDROID_HOME="${sdk_path}" + # Verify the SDK is created correctly. + verify_android_sdk +} + +function test_android_sdk_repository_fails_invalid_path() { + # Create an empty SDK directory. + mkdir -p "$TEST_TMPDIR/android_sdk" + + # Add to repository with the invalid path + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", + path = "$TEST_TMPDIR/android_sdk", +) +EOF + + "${BIT_BAZEL_BINARY}" query @androidsdk//:files >& $TEST_log && fail "Should have failed" || true + expect_log "No Android SDK apis found in the Android SDK" +} + +function test_build_tools_largest() { + # create several build tools + local sdk_path="$(create_android_sdk)" + add_platforms "${sdk_path}" 31 + add_build_tools "${sdk_path}" 10.1.2 20.2.3 30.3.4 + + # Add to repository. + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", + path = "${sdk_path}", +) +EOF + + check_android_sdk_provider + expect_log "build_tools_version: 30.3.4" +} + +function test_api_level_default() { + if [[ "${ENABLE_PLATFORMS:-false}" == "true" ]]; then + # TODO(katre): Fix API selection with platforms. + return + fi + # create several api levels + local sdk_path="$(create_android_sdk)" + add_platforms "${sdk_path}" 31 23 45 + add_build_tools "${sdk_path}" 30.3.4 + + # Add to repository. + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", + path = "${sdk_path}", +) +EOF + + # Should be the largest API level available + check_android_sdk_provider + expect_log "api_level: 45" +} + +function test_api_level_specific() { + if [[ "${ENABLE_PLATFORMS:-false}" == "true" ]]; then + # TODO(katre): Fix API selection with platforms. + return + fi + # create several api levels + local sdk_path="$(create_android_sdk)" + add_platforms "${sdk_path}" 31 23 45 + add_build_tools "${sdk_path}" 30.3.4 + + # Add to repository. + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", + path = "${sdk_path}", + api_level = 31, +) +EOF + + check_android_sdk_provider + expect_log "api_level: 31" +} + +function test_api_level_specific_missing() { + # create several api levels + local sdk_path="$(create_android_sdk)" + add_platforms "${sdk_path}" 31 23 45 + add_build_tools "${sdk_path}" 30.3.4 + + # Add to repository. + cat >> WORKSPACE <<EOF +android_sdk_repository( + name = "androidsdk", + path = "${sdk_path}", + api_level = 30, +) +EOF + + "${BIT_BAZEL_BINARY}" query @androidsdk//:files >& $TEST_log && fail "Should have failed" || true + expect_log "Android SDK api level 30 was requested but it is not installed" +} |