aboutsummaryrefslogtreecommitdiff
path: root/tests/lib.sh
blob: f337c7457d3b1daa5f225bfe0f3d6d3e7d0c1fe9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/bin/bash -eu

set -o pipefail

HARDWIRED_MOCK_TOP=
# Uncomment this to be able to view the source tree after a test is run
# HARDWIRED_MOCK_TOP=/tmp/td

REAL_TOP="$(readlink -f "$(dirname "$0")"/../../..)"

if [[ -n "$HARDWIRED_MOCK_TOP" ]]; then
  MOCK_TOP="$HARDWIRED_MOCK_TOP"
else
  MOCK_TOP=$(mktemp -t -d st.XXXXX)
  trap cleanup_mock_top EXIT
fi

WARMED_UP_MOCK_TOP=$(mktemp -t soong_integration_tests_warmup.XXXXXX.tar.gz)
trap 'rm -f "$WARMED_UP_MOCK_TOP"' EXIT

function warmup_mock_top {
  info "Warming up mock top ..."
  info "Mock top warmup archive: $WARMED_UP_MOCK_TOP"
  cleanup_mock_top
  mkdir -p "$MOCK_TOP"
  cd "$MOCK_TOP"

  create_mock_soong
  run_soong
  tar czf "$WARMED_UP_MOCK_TOP" *
}

function cleanup_mock_top {
  cd /
  rm -fr "$MOCK_TOP"
}

function info {
  echo -e "\e[92;1m[TEST HARNESS INFO]\e[0m" "$*"
}

function fail {
  echo -e "\e[91;1mFAILED:\e[0m" "$*"
  exit 1
}

function copy_directory {
  local dir="$1"
  local -r parent="$(dirname "$dir")"

  mkdir -p "$MOCK_TOP/$parent"
  cp -R "$REAL_TOP/$dir" "$MOCK_TOP/$parent"
}

function delete_directory {
  rm -rf "$MOCK_TOP/$1"
}

function symlink_file {
  local file="$1"

  mkdir -p "$MOCK_TOP/$(dirname "$file")"
  ln -s "$REAL_TOP/$file" "$MOCK_TOP/$file"
}

function symlink_directory {
  local dir="$1"

  mkdir -p "$MOCK_TOP/$dir"
  # We need to symlink the contents of the directory individually instead of
  # using one symlink for the whole directory because finder.go doesn't follow
  # symlinks when looking for Android.bp files
  for i in "$REAL_TOP/$dir"/*; do
    i=$(basename "$i")
    local target="$MOCK_TOP/$dir/$i"
    local source="$REAL_TOP/$dir/$i"

    if [[ -e "$target" ]]; then
      if [[ ! -d "$source" || ! -d "$target" ]]; then
        fail "Trying to symlink $dir twice"
      fi
    else
      ln -s "$REAL_TOP/$dir/$i" "$MOCK_TOP/$dir/$i";
    fi
  done
}

function create_mock_soong {
  create_mock_bazel
  copy_directory build/blueprint
  copy_directory build/soong
  copy_directory build/make

  symlink_directory prebuilts/sdk
  symlink_directory prebuilts/go
  symlink_directory prebuilts/build-tools
  symlink_directory prebuilts/clang/host
  symlink_directory external/compiler-rt
  symlink_directory external/go-cmp
  symlink_directory external/golang-protobuf
  symlink_directory external/licenseclassifier
  symlink_directory external/starlark-go
  symlink_directory external/python
  symlink_directory external/sqlite
  symlink_directory external/spdx-tools
  symlink_directory libcore

  # TODO: b/286872909 - Remove these when the blocking bug is completed
  symlink_directory external/libavc
  symlink_directory external/libaom
  symlink_directory external/libvpx
  symlink_directory frameworks/base/libs/androidfw
  symlink_directory external/libhevc
  symlink_directory external/libexif
  symlink_directory external/libopus
  symlink_directory external/libmpeg2
  symlink_directory external/expat
  symlink_directory external/flac
  symlink_directory system/extras/toolchain-extras

  touch "$MOCK_TOP/Android.bp"
}

function setup {
  cleanup_mock_top
  mkdir -p "$MOCK_TOP"

  echo
  echo ----------------------------------------------------------------------------
  info "Running test case \e[96;1m${FUNCNAME[1]}\e[0m"
  cd "$MOCK_TOP"

  tar xzf "$WARMED_UP_MOCK_TOP" --warning=no-timestamp
}

# shellcheck disable=SC2120
function run_soong {
  USE_RBE=false build/soong/soong_ui.bash --make-mode --skip-ninja --skip-config --soong-only --skip-soong-tests "$@"
}

function create_mock_bazel {
  copy_directory build/bazel
  copy_directory build/bazel_common_rules

  # This requires pulling more tools into the mock top to build partitions
  delete_directory build/bazel/examples/partitions

  symlink_directory packages/modules/common/build
  symlink_directory prebuilts/bazel
  symlink_directory prebuilts/clang
  symlink_directory prebuilts/jdk
  symlink_directory external/bazel-skylib
  symlink_directory external/bazelbuild-rules_android
  symlink_directory external/bazelbuild-rules_go
  symlink_directory external/bazelbuild-rules_license
  symlink_directory external/bazelbuild-kotlin-rules
  symlink_directory external/bazelbuild-rules_java

  symlink_file WORKSPACE
  symlink_file BUILD
}

function run_bazel {
  # Remove the ninja_build output marker file to communicate to buildbot that this is not a regular Ninja build, and its
  # output should not be parsed as such.
  rm -rf out/ninja_build

  build/bazel/bin/bazel "$@"
}

function run_ninja {
  build/soong/soong_ui.bash --make-mode --skip-config --soong-only --skip-soong-tests "$@"
}

info "Starting Soong integration test suite $(basename "$0")"
info "Mock top: $MOCK_TOP"


export ALLOW_MISSING_DEPENDENCIES=true
export ALLOW_BP_UNDER_SYMLINKS=true
warmup_mock_top

function scan_and_run_tests {
  # find all test_ functions
  # NB "declare -F" output is sorted, hence test order is deterministic
  readarray -t test_fns < <(declare -F | sed -n -e 's/^declare -f \(test_.*\)$/\1/p')
  info "Found ${#test_fns[*]} tests"
  if [[ ${#test_fns[*]} -eq 0 ]]; then
    fail "No tests found"
  fi
  for f in ${test_fns[*]}; do
    $f
    info "Completed test case \e[96;1m$f\e[0m"
  done
}