Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 838422b3 authored by Jack He's avatar Jack He
Browse files

Cert: Improve gd/cert/run performance

For gd/cert/run:
* Remove --reuse_venv option as it does not actually install updated
  GD cert python libraries and is causing confusion
* Add --clean option, if omitted, gd/cert/run will not try to re-install
  non-GD external libraries during test setup, it will only
  - Re-compile all binaries and libraries if needed
  - Re-zip everything into bluetooth_cert_tests.zip
  - Re-create virtualenv in the same folder without removing the old one
  - Unzip bluetooth_cert_tests.zip into the same virtual environment
  - Run gd/setup.py build with --force to overwrite any GD libraries
  - Run gd/setup.py install with --force and --reuse-acts option,
    this will fail if ACTS has never been installed in the virtualenv
  - However, all Python libraries, extensions, and binaries from GD
    directory will be re-installed regardless
* Enable quiet mode when running setup.py to reduce log spam

For gd/setup.py
* Remove "develop" command as bluetooth_cert_tests.zip is an overlay
  library using generated sources and compiled native extensions. It
  is not possible to develop and debug GD Python code without
  re-compilation and re-zipping everything
* Add "--reuse-acts" option to "install" command so that developer
  can choose to re-use existing ACTS installation in an environment.
  However, gd/setup.py will validate that "acts" module can be imported
  regardless of this option. Without this option, ACTS library will
  always be re-installed
* Exclude 'acts_framework.*' correctly

Performance improvement on my machine:
* Command:
    time gd/cert/run --host --test_filter=CerSelfTest:test_skip_a_test --clean
* Use --clean (i.e. original performance without this change):
    real: 40s
* Without --clean:
    real: 17s
* Speed up: 57%

Bug: 153189503
Bug: 151989046
Test: gd/cert/run --host
Test: gd/cert/run --host --clean
Change-Id: I739c62e9be2ad8d8b04df2a267b3dd9c93f3594d
parent 7d7adde6
Loading
Loading
Loading
Loading
+27 −7
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ fi

TEST_CONFIG="$ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/android_devices_config.json"
TEST_FILTER="-tf $ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/all_cert_testcases"
REUSE_VENV=false
CLEAN_VENV=false
NUM_REPETITIONS="1"

POSITIONAL=()
@@ -45,9 +45,10 @@ case $key in
    TEST_CONFIG="${key#*=}"
    shift # past argument
    ;;
    # This will speed up the test by overwriting existing venv
    --reuse_venv)
    REUSE_VENV=true
    # This will delete the existing venv before running the test
    # If you updated external libraries such as ACTS, you need to add this flag
    --clean)
    CLEAN_VENV=true
    shift # past argument
    ;;
    # Repeat running the specified test cases by N times in one single setup
@@ -65,8 +66,16 @@ set -- "${POSITIONAL[@]}" # restore positional parameters

CERT_TEST_VENV=$ANDROID_BUILD_TOP/out/dist/bluetooth_venv

if [ "$REUSE_VENV" != true ] ; then
YELLOW="\033[1;33m"
NOCOLOR="\033[0m"

INSTALL_ARGS="--reuse-acts"
if [ "$CLEAN_VENV" == true ] ; then
  echo -e "${YELLOW}Cleaning up existing virtualenv${NOCOLOR}"
  rm -rf $CERT_TEST_VENV
  INSTALL_ARGS=""
else
  echo -e "${YELLOW}Try to reuse existing virtualenv at ${CERT_TEST_VENV}${NOCOLOR}"
fi

python3.8 -m virtualenv --python `which python3.8` $CERT_TEST_VENV
@@ -81,9 +90,15 @@ if [[ $? -ne 0 ]] ; then
    exit 1
fi

$CERT_TEST_VENV/bin/python $CERT_TEST_VENV/acts/setup.py install
$CERT_TEST_VENV/bin/python $CERT_TEST_VENV/acts/setup.py --quiet build --force
if [[ $? -ne 0 ]] ; then
    echo "Error installing GD libraries"
    echo "Error building GD Python libraries"
    exit 1
fi

$CERT_TEST_VENV/bin/python $CERT_TEST_VENV/acts/setup.py --quiet install --skip-build --force $INSTALL_ARGS
if [[ $? -ne 0 ]] ; then
    echo "Error installing GD Python libraries"
    exit 1
fi

@@ -102,3 +117,8 @@ for n in $(seq $NUM_REPETITIONS); do
      $TEST_FILTER \
      -tp $CERT_TEST_VENV/acts
done

if [ "$CLEAN_VENV" != true ] ; then
  echo -e "${YELLOW}NOTE:${NOCOLOR} Completed tests using existing external libraries in virtualenv."
  echo -e "${YELLOW}NOTE:${NOCOLOR} To update external libraries, please add --clean option."
fi
 No newline at end of file
+31 −19
Original line number Diff line number Diff line
@@ -15,10 +15,11 @@
#   limitations under the License.

from distutils import log
from distutils.errors import DistutilsModuleError
import os
from setuptools import setup, find_packages
from setuptools import find_packages
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.develop import develop
import stat
import subprocess
import sys
@@ -33,14 +34,21 @@ host_executables = [
]


# Need to verify acts is importable in a new Python context
def is_acts_importable():
    cmd = [sys.executable, '-c', 'import acts']
    completed_process = subprocess.run(cmd, cwd=os.getcwd())
    return completed_process.returncode == 0


def setup_acts_for_cmd_or_die(cmd_str):
    acts_framework_dir = os.path.abspath('acts_framework')
    acts_setup_bin = os.path.join(acts_framework_dir, 'setup.py')
    cmd = [sys.executable, acts_setup_bin, cmd_str]
    subprocess.check_call(cmd, cwd=acts_framework_dir)
    subprocess.run(cmd, cwd=acts_framework_dir, check=True)


def set_permssions_for_host_executables(outputs):
def set_permissions_for_host_executables(outputs):
    for file in outputs:
        if os.path.basename(file) in host_executables:
            current_mode = os.stat(file).st_mode
@@ -53,22 +61,26 @@ def set_permssions_for_host_executables(outputs):

class InstallLocalPackagesForInstallation(install):

    def run(self):
        self.announce('Installing ACTS for installation', log.INFO)
        setup_acts_for_cmd_or_die("install")
        self.announce('ACTS installed for installation.', log.INFO)
        install.run(self)
        set_permssions_for_host_executables(self.get_outputs())

    user_options = install.user_options + [
        ('reuse-acts', None, "Skip ACTS installation if already installed"),
    ]
    boolean_options = install.boolean_options + ['reuse-acts']

class InstallLocalPackagesForDevelopment(develop):
    def initialize_options(self):
        install.initialize_options(self)
        self.reuse_acts = False

    def run(self):
        log.log(log.INFO, 'Installing ACTS for development')
        setup_acts_for_cmd_or_die("develop")
        log.log(log.INFO, 'ACTS installed for development')
        develop.run(self)
        set_permssions_for_host_executables(self.get_outputs())
        if self.reuse_acts and is_acts_importable():
            self.announce('Reusing existing ACTS installation', log.WARN)
        else:
            self.announce('Installing ACTS for installation', log.WARN)
            setup_acts_for_cmd_or_die("install")
            self.announce('ACTS installed for installation.', log.WARN)
        if not is_acts_importable():
            raise DistutilsModuleError("Cannot import acts after installation")
        install.run(self)
        set_permissions_for_host_executables(self.get_outputs())


def main():
@@ -85,7 +97,8 @@ def main():
        description="""Bluetooth Cert Tests Package""",
        # Include root package so that bluetooth_packets_python3.so can be
        # included as well
        packages=[''] + find_packages(exclude='acts_framework'),
        packages=[''] +
        find_packages(exclude=['acts_framework', 'acts_framework.*']),
        install_requires=install_requires,
        package_data={
            '': host_executables + ['*.so', 'lib64/*.so', 'target/*'],
@@ -93,7 +106,6 @@ def main():
        },
        cmdclass={
            'install': InstallLocalPackagesForInstallation,
            'develop': InstallLocalPackagesForDevelopment,
        })