1#! /bin/bash
2
3YELLOW="\033[1;33m"
4NOCOLOR="\033[0m"
5BLUE="\033[1;34m"
6RED="\033[1;91m"
7
8function happy_hedgehog {
9    echo -e "\t${BLUE}"
10    echo -e "\t       ___------__"
11    echo -e "\t |\__-- /\       _-"
12    echo -e "\t |/_   __      -"
13    echo -e "\t // \ /  \    /__"
14    echo -e "\t | 0 |  0 |__     --_        Gotta go fast!"
15    echo -e "\t \\____-- __ \   ___-"
16    echo -e "\t ( @    __/  / /_"
17    echo -e "\t    -_____---   --_"
18    echo -e "\t     //  \ \\   ___-"
19    echo -e "\t   //|\__/  \\  \\"
20    echo -e "\t   \_-\_____/  \-\\"
21    echo -e "\t        // \\--\|"
22    echo -e "\t   ${RED}____${BLUE}//  ||${RED}_"
23    echo -e "\t${RED}  /_____\ /___\\"
24    echo -e "${NOCOLOR}"
25}
26
27function sad_hedgehog {
28    echo -e "\t${BLUE}"
29    echo -e "\t       ___------__"
30    echo -e "\t |\__-- /\       _-"
31    echo -e "\t |/_    __      -"
32    echo -e "\t // \  /  \    /__"
33    echo -e "\t | 0 |  0 |__     --_        Gotta go sllloowwww!"
34    echo -e "\t \\____-- __ \   ___-"
35    echo -e "\t ( @    __   / /_"
36    echo -e "\t    -_____---   --_"
37    echo -e "\t     //  \ \\   ___-"
38    echo -e "\t   //|\__/  \\  \\"
39    echo -e "\t   \_-\_____/  \-\\"
40    echo -e "\t        // \\--\|"
41    echo -e "\t  ${RED} ____${BLUE}//  ||${RED}_"
42    echo -e "\t${RED}  /_____\ /___\\"
43    echo -e "{$NOCOLOR}"
44}
45
46function check_environment {
47    if [[ -z "${ANDROID_BUILD_TOP}" ]] || [[ -z "${ANDROID_HOST_OUT}" ]] ; then
48      echo -e "${RED}ANDROID_BUILD_TOP${NOCOLOR} or ${RED}ANDROID_HOST_OUT${NOCOLOR} is not set for host run"
49      echo -e "Navigate to android root and run:"
50      echo -e "${YELLOW}"
51      echo -e ". build/envsetup.sh"
52      echo -e "lunch <fish>"
53      echo -e "${NOCOLOR}"
54      echo
55      exit 1
56    fi
57    if ! [ -x "$(command -v python3.8)" ] ; then
58      echo -e "${RED}You must have python 3.8 installed${NOCOLOR}"
59      exit 1
60    fi
61}
62
63ASHMEM_OUT="/dev/shm/out"
64ASHMEM_DIST="${ASHMEM_OUT}/dist"
65ASHMEM_VENV="${ASHMEM_DIST}/bluetooth_venv"
66ASHMEM_GOTTA_GO_FAST="/dev/shm/gottagofast"
67ASHMEM_HOST_LOGS="${ASHMEM_GOTTA_GO_FAST}/logs"
68ASHMEM_OUT_TARGET="${ASHMEM_GOTTA_GO_FAST}/target"
69ASHMEM_SOONG="${ASHMEM_GOTTA_GO_FAST}/out/soong"
70CERT_HOST_LOGS="/tmp/logs/HostOnlyCert"
71CERT_DEVICE_LOGS="TODO: Add this"
72CERT_TEST_VENV=${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv
73OUT_TARGET="${ANDROID_BUILD_TOP}/out/target"
74TEST_CONFIG="${ANDROID_BUILD_TOP}/system/bt/gd/cert/android_devices_config.json"
75TEST_FILTER="-tf ${ANDROID_BUILD_TOP}/system/bt/gd/cert/all_cert_testcases"
76
77CLEAN_VENV=false
78GOTTA_GO_FAST=false
79NUM_REPETITIONS="1"
80SKIP_SOONG_BUILD=false
81USE_ASHMEM_VENV=true
82VERBOSE_MODE=false
83
84# Used for position arguments needed for later
85POSITIONAL=()
86function parse_options {
87    while [[ $# -gt 0 ]]
88    do
89    key="$1"
90    case $key in
91        # This will delete the existing venv before running the test
92        # If you updated external libraries such as ACTS, you need to add this flag
93        --clean)
94        CLEAN_VENV=true
95        shift # past argument
96        ;;
97        --help)
98        echo
99        echo -e "${YELLOW}Help menu${NOCOLOR}"
100        echo -e "==================================="
101        echo -e "${BLUE}  --clean${NOCOLOR}"
102        echo -e "    Clean the virtul environment; use if ACTS has been updated."
103        echo -e "${BLUE}  --disable-ashmem-venv${NOCOLOR}"
104        echo -e "    Places the virtual environment on disk rather than in ashmem which is default."
105        echo -e "${BLUE}  --gotta-go-fast${NOCOLOR}"
106        echo -e "    Makes use of ashmem as best as possible for targeted speed increases."
107        echo -e "${BLUE}  --host${NOCOLOR}"
108        echo -e "    Run the test on the host machine [i.e. simulated]."
109        echo -e "${BLUE}  --repeat=<N>${NOCOLOR}"
110        echo -e "    Repeat the test sequence N (int) number of times."
111        echo -e "${BLUE}  --skip-soong-build${NOCOLOR}"
112        echo -e "    Skips building soong targets. Use when you are just modifying simple python files."
113        echo -e "${BLUE}  --test_config=<configfile>${NOCOLOR}"
114        echo -e "    Override default test configuration."
115        echo -e "${BLUE}  --verbose${NOCOLOR}"
116        echo -e "    Displays device logs and test logs to output."
117        echo
118        echo -e "Usage: $0 [--clean|--host|--repeat=<N>|--test_config=<config>] [TestGroupName[:IndividualTestName]]"
119        echo -e "        ${YELLOW}e.g."
120        echo -e "         $0 --host --clean SecurityTest"
121        echo -e "         $0 --host --verbose SecurityTest:test_dut_initiated_display_only_display_only ${NOCOLOR}"
122        echo
123        shift
124        exit 0
125        ;;
126        # This will cause the bluetooth_venv to be created in ashmem
127        # Increases --clean build times by 40% (~21 seconds on my machine)
128        --disable-ashmem-venv)
129        USE_ASHMEM_VENV=false
130        shift # past argument
131        ;;
132        --gotta-go-fast)
133        GOTTA_GO_FAST=true
134        shift # past argument
135        ;;
136        --host)
137        TEST_CONFIG=$ANDROID_BUILD_TOP/system/bt/gd/cert/host_config.json
138        shift # past argument
139        ;;
140        # Repeat running the specified test cases by N times in one single setup
141        --repeat=*)
142        NUM_REPETITIONS="${key#*=}"
143        shift # past argument
144        ;;
145        --skip-soong-build)
146        SKIP_SOONG_BUILD=true
147        shift
148        ;;
149        --test_config=*)
150        TEST_CONFIG="${key#*=}"
151        shift # past argument
152        ;;
153        # This will log everything to both log file and stdout
154        --verbose)
155        VERBOSE_MODE=true
156        shift # past argument
157        ;;
158        *)    # unknown option
159        POSITIONAL+=("$1") # save it in an array for later
160        shift # past argument
161        ;;
162    esac
163    done
164    set -- "${POSITIONAL[@]}" # restore positional parameters
165
166    # Set the test filter
167    if [[ -n "$1" ]] ; then
168      TEST_FILTER="-tc $1"
169    fi
170
171    INSTALL_ARGS="--reuse-acts"
172    if [ "$CLEAN_VENV" == true ] ; then
173      echo -e "${YELLOW}Cleaning up existing virtualenv${NOCOLOR}"
174      rm -rf $CERT_TEST_VENV/*
175      rm -rf $CERT_TEST_VENV
176      mkdir -p ${CERT_TEST_VENV}
177      INSTALL_ARGS=""
178    else
179      echo -e "${YELLOW}Try to reuse existing virtualenv at ${CERT_TEST_VENV}${NOCOLOR}"
180    fi
181
182}
183
184function soong_build {
185    $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --build-mode --"modules-in-a-dir" --dir="${ANDROID_BUILD_TOP}/system/bt/gd" dist bluetooth_stack_with_facade
186    if [[ $? -ne 0 ]] ; then
187        echo "Failed to build bluetooth_stack_with_facade"
188        exit 1
189    fi
190}
191
192function setup_venv {
193    # Make venv in memory, decreases --clean build times by 40%
194    # Caveat is you lose the venv if the computer reboots
195    if [ "${USE_ASHMEM_VENV}" == true ] ; then
196        echo -e "${BLUE}Using ashmem virtual environment.${NOCOLOR}"
197        if [[ ! -L ${CERT_TEST_VENV} ]] ; then
198            echo -e "${BLUE}"
199            echo -ne "Creating ashmem dist folder..."
200            mkdir -p "${ASHMEM_VENV}"
201            # Ensure the directory doesn't exist
202            rm -rf "${CERT_TEST_VENV}"
203            echo -e "Done"
204            echo -ne "Sym linking ${ASHMEM_VENV} to ${CERT_TEST_VENV}..."
205            ln -s "${ASHMEM_VENV}" "${CERT_TEST_VENV}"
206            echo -e "Done"
207            echo -e "${NOCOLOR}"
208        fi
209    else
210        echo -e "${RED}Not using ashmem virtual environment.${NOCOLOR}"
211        if [[ -L ${CERT_TEST_VENV} ]] ; then
212            echo -e "${RED}"
213            echo -en "Removing sym link from ${ASHMEM_VENV} to ${CERT_TEST_VENV}..."
214            rm -rf ""${ASHMEM_VENV} "${CERT_TEST_VENV}"
215            echo -e "Done"
216            echo -en "Cleaning up memory..."
217            rm -rf "${ASHMEM_VENV}"
218            echo -e "Done"
219            echo -e "${NOCOLOR}"
220        fi
221    fi
222    python3.8 -m virtualenv --python `which python3.8` "${CERT_TEST_VENV}"
223    if [[ $? -ne 0 ]] ; then
224        echo "Error setting up virtualenv"
225        exit 1
226    fi
227
228    unzip -o -q "${ANDROID_BUILD_TOP}/out/dist/bluetooth_cert_tests.zip" -d "${CERT_TEST_VENV}/acts"
229    if [[ $? -ne 0 ]] ; then
230        echo "Error unzipping bluetooth_cert_tests.zip"
231        exit 1
232    fi
233
234    $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/acts/setup.py" --quiet build --force)
235    if [[ $? -ne 0 ]] ; then
236        echo "Error building GD Python libraries"
237        exit 1
238    fi
239
240    $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/acts/setup.py" --quiet install --skip-build --force "${INSTALL_ARGS}")
241    if [[ $? -ne 0 ]] ; then
242        echo "Error installing GD Python libraries"
243        exit 1
244    fi
245
246"${CERT_TEST_VENV}/bin/python" -c "
247import bluetooth_packets_python3 as bp3
248bp3.BaseStruct
249"
250if [[ $? -ne 0 ]] ; then
251  echo "Setup failed as bluetooth_packets_python3 cannot be imported"
252  exit 1
253fi
254
255if [ "${VERBOSE_MODE}" == true ] ; then
256  TEMP_CONFIG=/tmp/temp_acts_config.json
257  cat "${TEST_CONFIG}" | "${CERT_TEST_VENV}/bin/python" -c "
258import sys
259import json
260from acts import keys
261config = json.load(sys.stdin)
262config['verbose_mode'] = True
263print(json.dumps(config))
264  " > "${TEMP_CONFIG}"
265  TEST_CONFIG="${TEMP_CONFIG}"
266  if [[ $? -ne 0 ]] ; then
267    echo "Setup failed as verbose mode is chosen but cannot be enabled"
268    exit 1
269  fi
270fi
271
272}
273
274function gotta_go_fast {
275    if [ "${GOTTA_GO_FAST}" == true ] ; then
276        # Call here to explicitly note the flag is in use
277        happy_hedgehog
278        if [[ ! -L "${CERT_HOST_LOGS}" ]] ; then
279            rm -rf "${CERT_HOST_LOGS}"
280            mkdir -p "${ASHMEM_HOST_LOGS}"
281            ln -s "${ASHMEM_HOST_LOGS}" "${CERT_HOST_LOGS}"
282        fi
283
284        if [[ ! -L "${OUT_TARGET}" ]] ; then
285            rm -rf "${OUT_TARGET}"
286            mkdir -p "${ASHMEM_OUT_TARGET}"
287            ln -s  "${ASHMEM_OUT_TARGET}" "${OUT_TARGET}"
288        fi
289    else
290        if [[ -L "${CERT_HOST_LOGS}" ]] ; then
291            # Call here so we don't spam anyone not using the flag
292            sad_hedgehog
293            rm -rf "${CERT_HOST_LOGS}"
294            rm -rf "${ASHMEM_HOST_LOGS}"
295        fi
296
297        if [[ -L "${OUT_TARGET}" ]] ; then
298            rm -rf "${OUT_TARGET}"
299            rm -rf "${ASHMEM_OUT_TARGET}"
300        fi
301    fi
302}
303
304function run_tests {
305    for n in $(seq "${NUM_REPETITIONS}"); do
306      $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/bin/act.py" \
307          -c "${TEST_CONFIG}" \
308          "${TEST_FILTER}" \
309          -tp "${CERT_TEST_VENV}"/acts)
310    done
311
312    if [ "${CLEAN_VENV}" != true ] ; then
313      echo -e "${YELLOW}NOTE:${NOCOLOR} Completed tests using existing external libraries in virtualenv."
314      echo -e "${YELLOW}NOTE:${NOCOLOR} To update external libraries, please add --clean option."
315    fi
316}
317
318function main {
319    check_environment
320    parse_options $@
321    if [[ "${SKIP_SOONG_BUILD}" != true ]] ; then
322        soong_build
323    fi
324    setup_venv
325    gotta_go_fast
326    run_tests
327}
328
329main $@
330