1#!/bin/bash 2 3# This script creates temporary workspaces and generates `rust-project.json` 4# files unique to the set of targets defined in the generated workspace. 5 6set -euo pipefail 7 8if [[ -z "${BUILD_WORKSPACE_DIRECTORY:-}" ]]; then 9 >&2 echo "This script should be run under Bazel" 10 exit 1 11fi 12 13PACKAGE_NAME="$1" 14if [[ -z "${PACKAGE_NAME:-}" ]]; then 15 >&2 echo "The first argument should be the package name of the test target" 16 exit 1 17fi 18 19function generate_workspace() { 20 local temp_dir="$(mktemp -d -t rules_rust_test_rust_analyzer-XXXXXXXXXX)" 21 local new_workspace="${temp_dir}/rules_rust_test_rust_analyzer" 22 23 mkdir -p "${new_workspace}" 24 cat <<EOF >"${new_workspace}/WORKSPACE.bazel" 25workspace(name = "rules_rust_test_rust_analyzer") 26local_repository( 27 name = "rules_rust", 28 path = "${BUILD_WORKSPACE_DIRECTORY}", 29) 30load("@rules_rust//rust:repositories.bzl", "rust_repositories") 31rust_repositories() 32load("@rules_rust//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies") 33rust_analyzer_dependencies() 34 35load("@rules_rust//test/3rdparty/crates:crates.bzl", test_crate_repositories = "crate_repositories") 36 37test_crate_repositories() 38EOF 39 40 cat <<EOF >"${new_workspace}/.bazelrc" 41build --keep_going 42test --test_output=errors 43# The 'strict' config is used to ensure extra checks are run on the test 44# targets that would otherwise not run due to them being tagged as "manual". 45# Note that that tag is stripped for this test. 46build:strict --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect 47build:strict --output_groups=+rustfmt_checks 48build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect 49build:strict --output_groups=+clippy_checks 50EOF 51 52 echo "${new_workspace}" 53} 54 55function rust_analyzer_test() { 56 local source_dir="$1" 57 local workspace="$2" 58 local generator_arg="$3" 59 60 echo "Testing '$(basename "${source_dir}")'" 61 rm -f "${workspace}"/*.rs "${workspace}"/*.json "${workspace}"/*.bzl "${workspace}/BUILD.bazel" "${workspace}/BUILD.bazel-e" 62 cp -r "${source_dir}"/* "${workspace}" 63 64 # Drop the 'manual' tags 65 if [ "$(uname)" == "Darwin" ]; then 66 SEDOPTS=(-i '' -e) 67 else 68 SEDOPTS=(-i) 69 fi 70 sed ${SEDOPTS[@]} 's/"manual"//' "${workspace}/BUILD.bazel" 71 72 pushd "${workspace}" &>/dev/null 73 echo "Generating rust-project.json..." 74 if [[ -n "${generator_arg}" ]]; then 75 bazel run "@rules_rust//tools/rust_analyzer:gen_rust_project" -- "${generator_arg}" 76 else 77 bazel run "@rules_rust//tools/rust_analyzer:gen_rust_project" 78 fi 79 echo "Building..." 80 bazel build //... 81 echo "Testing..." 82 bazel test //... 83 echo "Building with Aspects..." 84 bazel build //... --config=strict 85 popd &>/dev/null 86} 87 88function cleanup() { 89 local workspace="$1" 90 pushd "${workspace}" &>/dev/null 91 bazel clean --async 92 popd &>/dev/null 93 rm -rf "${workspace}" 94} 95 96function run_test_suite() { 97 local temp_workspace="$(generate_workspace)" 98 echo "Generated workspace: ${temp_workspace}" 99 100 for test_dir in "${BUILD_WORKSPACE_DIRECTORY}/${PACKAGE_NAME}"/*; do 101 # Skip everything but directories 102 if [[ ! -d "${test_dir}" ]]; then 103 continue 104 fi 105 106 # Some tests have arguments that need to be passed to the rust-project.json generator. 107 if [[ "${test_dir}" = "aspect_traversal_test" ]]; then 108 test_arg="//mylib_test" 109 elif [[ "${test_dir}" = "merging_crates_test" ]]; then 110 test_arg="//mylib_test" 111 else 112 test_arg="" 113 fi 114 115 rust_analyzer_test "${test_dir}" "${temp_workspace}" "${test_arg}" 116 done 117 118 echo "Done" 119 cleanup "${temp_workspace}" 120} 121 122run_test_suite 123