1#!/bin/bash
2
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18# Run ART APEX tests.
19
20SCRIPT_DIR=$(dirname $0)
21
22# Status of whole test script.
23exit_status=0
24# Status of current test suite.
25test_status=0
26
27function say {
28  echo "$0: $*"
29}
30
31function die {
32  echo "$0: $*"
33  exit 1
34}
35
36function setup_die {
37  die "You need to run lunch, banchan, or tapas before you can use this script."
38}
39
40[[ -n "$ANDROID_BUILD_TOP" ]] || setup_die
41[[ -n "$ANDROID_PRODUCT_OUT" ]] || setup_die
42[[ -n "$ANDROID_HOST_OUT" ]] || setup_die
43
44flattened_apex_p=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash \
45    --dumpvar-mode TARGET_FLATTEN_APEX) \
46  || setup_die
47
48compressed_apex_p=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash \
49    --dumpvar-mode PRODUCT_COMPRESSED_APEX) \
50  || setup_die
51
52# Switch the build system to unbundled mode in the reduced manifest branch.
53if [ ! -d $ANDROID_BUILD_TOP/frameworks/base ]; then
54  export TARGET_BUILD_UNBUNDLED=true
55fi
56
57have_deapexer_p=false
58if $flattened_apex_p; then :; else
59  if [ ! -e "$ANDROID_HOST_OUT/bin/deapexer" -o ! -e "$ANDROID_HOST_OUT/bin/debugfs_static" ] ; then
60    say "Could not find deapexer and/or debugfs_static, building now."
61    build/soong/soong_ui.bash --make-mode deapexer debugfs_static-host || \
62      die "Cannot build deapexer and debugfs_static"
63  fi
64  have_deapexer_p=true
65fi
66
67# Fail early.
68set -e
69
70build_apex_p=true
71list_image_files_p=false
72print_image_tree_p=false
73print_file_sizes_p=false
74
75function usage {
76  cat <<EOF
77Usage: $0 [OPTION] [apexes...]
78Build (optional) and run tests on ART APEX package (on host). Defaults to all
79applicable APEXes if none is given on the command line.
80
81  -B, --skip-build    skip the build step
82  -l, --list-files    list the contents of the ext4 image (\`find\`-like style)
83  -t, --print-tree    list the contents of the ext4 image (\`tree\`-like style)
84  -s, --print-sizes   print the size in bytes of each file when listing contents
85  -h, --help          display this help and exit
86
87EOF
88  exit
89}
90
91apex_modules=()
92
93while [[ $# -gt 0 ]]; do
94  case "$1" in
95    (-B|--skip-build)  build_apex_p=false;;
96    (-l|--list-files)  list_image_files_p=true;;
97    (-t|--print-tree)  print_image_tree_p=true;;
98    (-s|--print-sizes) print_file_sizes_p=true;;
99    (-h|--help) usage;;
100    (-*) die "Unknown option: '$1'
101Try '$0 --help' for more information.";;
102    (*) apex_modules+=($1);;
103  esac
104  shift
105done
106
107# build_apex APEX_MODULES
108# -----------------------
109# Build APEX packages APEX_MODULES.
110function build_apex {
111  if $build_apex_p; then
112    say "Building $@" && build/soong/soong_ui.bash --make-mode "$@" || die "Cannot build $@"
113  fi
114}
115
116# maybe_list_apex_contents_apex APEX TMPDIR [other]
117function maybe_list_apex_contents_apex {
118  local print_options=()
119  if $print_file_sizes_p; then
120    print_options+=(--size)
121  fi
122
123  # List the contents of the apex in list form.
124  if $list_image_files_p; then
125    say "Listing image files"
126    $SCRIPT_DIR/art_apex_test.py --list ${print_options[@]} $@
127  fi
128
129  # List the contents of the apex in tree form.
130  if $print_image_tree_p; then
131    say "Printing image tree"
132    $SCRIPT_DIR/art_apex_test.py --tree ${print_options[@]} $@
133  fi
134}
135
136function fail_check {
137  echo "$0: FAILED: $*"
138  test_status=1
139  exit_status=1
140}
141
142if [ ${#apex_modules[@]} -eq 0 ]; then
143  # Test as many modules as possible.
144  apex_modules=(
145    "com.android.art"
146    "com.android.art.debug"
147    "com.android.art.testing"
148  )
149  if [[ "$HOST_PREFER_32_BIT" = true ]]; then
150    say "Skipping com.android.art.host, as \`HOST_PREFER_32_BIT\` equals \`true\`"
151  else
152    apex_modules+=("com.android.art.host")
153  fi
154fi
155
156# Build the APEX packages (optional).
157build_apex ${apex_modules[@]}
158
159# Clean-up.
160function cleanup {
161  rm -rf "$work_dir"
162}
163
164# Garbage collection.
165function finish {
166  # Don't fail early during cleanup.
167  set +e
168  cleanup
169}
170
171for apex_module in ${apex_modules[@]}; do
172  test_status=0
173  say "Checking APEX package $apex_module"
174  work_dir=$(mktemp -d)
175  trap finish EXIT
176
177  art_apex_test_args="--tmpdir $work_dir"
178  test_only_args=""
179  if [[ $apex_module = *.host ]]; then
180    apex_path="$ANDROID_HOST_OUT/apex/${apex_module}.zipapex"
181    art_apex_test_args="$art_apex_test_args --host"
182    test_only_args="--flavor debug"
183  else
184    if $flattened_apex_p; then
185      apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}"
186      art_apex_test_args="$art_apex_test_args --flattened"
187    else
188      # Note: The Testing ART APEX is never built as a Compressed APEX.
189      if $compressed_apex_p && [[ $apex_module != *.testing ]]; then
190        apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.capex"
191      else
192        apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.apex"
193      fi
194    fi
195    if $have_deapexer_p; then
196      art_apex_test_args="$art_apex_test_args --deapexer $ANDROID_HOST_OUT/bin/deapexer"
197      art_apex_test_args="$art_apex_test_args --debugfs $ANDROID_HOST_OUT/bin/debugfs_static"
198    fi
199    case $apex_module in
200      (*.debug)   test_only_args="--flavor debug";;
201      (*.testing) test_only_args="--flavor testing";;
202      (*)         test_only_args="--flavor release";;
203    esac
204  fi
205  say "APEX package path: $apex_path"
206
207  # List the contents of the APEX image (optional).
208  maybe_list_apex_contents_apex $art_apex_test_args $apex_path
209
210  # Run tests on APEX package.
211  $SCRIPT_DIR/art_apex_test.py $art_apex_test_args $test_only_args $apex_path \
212    || fail_check "Checks failed on $apex_module"
213
214  # Clean up.
215  trap - EXIT
216  cleanup
217
218  [[ "$test_status" = 0 ]] && say "$apex_module tests passed"
219  echo
220done
221
222[[ "$exit_status" = 0 ]] && say "All ART APEX tests passed"
223
224exit $exit_status
225