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

Commit 82f1b9f2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I44f2e73a,I1755c0c4,Iee69245a,Ie7f4e084

* changes:
  Cert: make test setup more robust to binary failures
  Cert: use "git checkout" instead of "git co"
  Cert: Add required host libraries to test ZIP
  Cert: Handle None filter function in FilteringStream
parents 25834f06 52c2097b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -11,9 +11,15 @@ bluetooth_cert_test_file_list := $(addprefix $(LOCAL_PATH)/,$(bluetooth_cert_tes
bluetooth_cert_test_file_list += \
    $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \
    $(HOST_OUT_SHARED_LIBRARIES)/bluetooth_packets_python3.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libbase.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libc++.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libchrome.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libevent-host.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \
    $(HOST_OUT_SHARED_LIBRARIES)/liblog.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libz-host.so \
    $(HOST_OUT_SHARED_LIBRARIES)/libprotobuf-cpp-full.so \
    $(TARGET_OUT_EXECUTABLES)/bluetooth_stack_with_facade \
    $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \
    $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \
+9 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ import time
from mobly import asserts
from datetime import datetime, timedelta
from acts.base_test import BaseTestClass
from cert.event_stream import EventStream
from cert.event_stream import EventStream, FilteringEventStream
from cert.truth import assertThat

# Test packet nesting
@@ -386,3 +386,11 @@ class CertSelfTest(BaseTestClass):
            logging.debug(e)
            return True  # Failed as expected
        return False

    def test_filtering_event_stream_none_filter_function(self):
        with EventStream(FetchEvents(events=[1, 2, 3],
                                     delay_ms=50)) as event_stream:
            filtered_event_stream = FilteringEventStream(event_stream, None)
            assertThat(filtered_event_stream)\
                .emits(lambda data: data.value_ == 1)\
                .then(lambda data: data.value_ == 3)
+3 −2
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ class IEventStream(ABC):
class FilteringEventStream(IEventStream):

    def __init__(self, stream, filter_fn):
        self.filter_fn = filter_fn
        self.filter_fn = filter_fn if filter_fn else lambda x: x
        self.event_queue = SimpleQueue()
        self.stream = stream

@@ -264,11 +264,12 @@ def NOT_FOR_YOU_assert_event_occurs(
        try:
            current_event = istream.get_event_queue().get(
                timeout=remaining.total_seconds())
            logging.debug("current_event: %s", current_event)
            if match_fn(current_event):
                event_list.append(current_event)
        except Empty:
            continue
    logging.debug("Done waiting for event")
    logging.debug("Done waiting for event, received %d", len(event_list))
    asserts.assert_true(
        len(event_list) >= at_least_times,
        msg=("Expected at least %d events, but got %d" % (at_least_times,
+15 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#   See the License for the specific language governing permissions and
#   limitations under the License.

from acts import asserts
from acts.base_test import BaseTestClass
from facade import rootservice_pb2 as facade_rootservice

@@ -24,6 +25,14 @@ import signal
import subprocess


def is_subprocess_alive(process, timeout_seconds=1):
    try:
        process.wait(timeout=timeout_seconds)
        return False
    except subprocess.TimeoutExpired as exp:
        return True


class GdFacadeOnlyBaseTestClass(BaseTestClass):

    def setup_class(self, dut_module, cert_module):
@@ -54,9 +63,14 @@ class GdFacadeOnlyBaseTestClass(BaseTestClass):
                env=os.environ.copy(),
                stdout=self.rootcanal_logs,
                stderr=self.rootcanal_logs)
            asserts.assert_true(
                self.rootcanal_process,
                msg="Cannot start root-canal at " + str(rootcanal))
            asserts.assert_true(
                is_subprocess_alive(self.rootcanal_process),
                msg="root-canal stopped immediately after running")
            for gd_device in gd_devices:
                gd_device["rootcanal_port"] = rootcanal_hci_port

        self.register_controller(
            importlib.import_module('cert.gd_device'), builtin=True)

+124 −15
Original line number Diff line number Diff line
@@ -23,18 +23,21 @@ import socket
import subprocess
import time

from acts import asserts
from acts import context
from acts.controllers.adb import AdbProxy
from acts.controllers.adb import AdbProxy, AdbError

import grpc

from cert.environment_provider import PRODUCT_DEVICE
from cert.gd_base_test_facade_only import is_subprocess_alive

ANDROID_PRODUCT_OUT = os.path.join(
    os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product",
    PRODUCT_DEVICE)

WAIT_CHANNEL_READY_TIMEOUT = 10
WAIT_FOR_DEVICE_TIMEOUT = 180


def replace_vars(string, config):
@@ -77,26 +80,31 @@ class GdDeviceBase:

        self.serial_number = serial_number
        if self.serial_number:
            self.ad = AdbProxy(serial_number)
            self.ad.shell("date " + time.strftime("%m%d%H%M%Y.%S"))
            self.ad.tcp_forward(int(grpc_port), int(grpc_port))
            self.ad.tcp_forward(
            self.adb = AdbProxy(self.serial_number)
            self.ensure_verity_disabled()
            asserts.assert_true(
                self.adb.ensure_root(),
                msg="device %s cannot run as root after enabling verity" %
                self.serial_number)
            self.adb.shell("date " + time.strftime("%m%d%H%M%Y.%S"))
            self.adb.tcp_forward(int(grpc_port), int(grpc_port))
            self.adb.tcp_forward(
                int(grpc_root_server_port), int(grpc_root_server_port))
            self.ad.reverse("tcp:%s tcp:%s" % (signal_port, signal_port))
            self.ad.push(
            self.adb.reverse("tcp:%s tcp:%s" % (signal_port, signal_port))
            self.push_or_die(
                os.path.join(ANDROID_PRODUCT_OUT,
                             "system/bin/bluetooth_stack_with_facade"),
                "system/bin")
            self.ad.push(
            self.push_or_die(
                os.path.join(ANDROID_PRODUCT_OUT,
                             "system/lib64/libbluetooth_gd.so"), "system/lib64")
            self.ad.push(
            self.push_or_die(
                os.path.join(ANDROID_PRODUCT_OUT,
                             "system/lib64/libgrpc++_unsecure.so"),
                "system/lib64")
            self.ad.shell("logcat -c")
            self.ad.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log")
            self.ad.shell("svc bluetooth disable")
            self.ensure_no_output(self.adb.shell("logcat -c"))
            self.adb.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log")
            self.ensure_no_output(self.adb.shell("svc bluetooth disable"))

        tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
@@ -111,6 +119,13 @@ class GdDeviceBase:
            env=os.environ.copy(),
            stdout=self.backing_process_logs,
            stderr=self.backing_process_logs)
        asserts.assert_true(
            self.backing_process,
            msg="Cannot start backing_process at " + " ".join(cmd))
        asserts.assert_true(
            is_subprocess_alive(self.backing_process),
            msg="backing_process stopped immediately after running " +
            " ".join(cmd))
        tester_signal_socket.accept()
        tester_signal_socket.close()

@@ -131,11 +146,11 @@ class GdDeviceBase:
                          (self.label, backing_process_return_code))

        if self.serial_number:
            self.ad.shell("logcat -d -f /data/misc/bluetooth/logs/system_log")
            self.ad.pull(
            self.adb.shell("logcat -d -f /data/misc/bluetooth/logs/system_log")
            self.adb.pull(
                "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join(
                    self.log_path_base, "%s_btsnoop_hci.log" % self.label))
            self.ad.pull(
            self.adb.pull(
                "/data/misc/bluetooth/logs/system_log %s" % os.path.join(
                    self.log_path_base, "%s_system_log" % self.label))

@@ -145,3 +160,97 @@ class GdDeviceBase:
            future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT)
        except grpc.FutureTimeoutError:
            logging.error("wait channel ready timeout")

    def ensure_no_output(self, result):
        """
        Ensure a command has not output
        """
        asserts.assert_true(
            result is None or len(result) == 0,
            msg="command returned something when it shouldn't: %s" % result)

    def push_or_die(self, src_file_path, dst_file_path, push_timeout=300):
        """Pushes a file to the Android device

        Args:
            src_file_path: The path to the file to install.
            dst_file_path: The destination of the file.
            push_timeout: How long to wait for the push to finish in seconds
        """
        try:
            self.adb.ensure_root()
            self.ensure_verity_disabled()
            out = self.adb.push(
                '%s %s' % (src_file_path, dst_file_path), timeout=push_timeout)
            if 'error' in out:
                asserts.fail('Unable to push file %s to %s due to %s' %
                             (src_file_path, dst_file_path, out))
        except Exception as e:
            asserts.fail(
                msg='Unable to push file %s to %s due to %s' %
                (src_file_path, dst_file_path, e),
                extras=e)

    def ensure_verity_disabled(self):
        """Ensures that verity is enabled.

        If verity is not enabled, this call will reboot the phone. Note that
        this only works on debuggable builds.
        """
        logging.debug("Disabling verity and remount for %s", self.serial_number)
        asserts.assert_true(self.adb.ensure_root(),
                            "device %s cannot run as root", self.serial_number)
        # The below properties will only exist if verity has been enabled.
        system_verity = self.adb.getprop('partition.system.verified')
        vendor_verity = self.adb.getprop('partition.vendor.verified')
        if system_verity or vendor_verity:
            self.adb.disable_verity()
            self.reboot()
        self.adb.remount()
        self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT)

    def reboot(self, timeout_minutes=15.0):
        """Reboots the device.

        Reboot the device, wait for device to complete booting.
        """
        logging.debug("Rebooting %s", self.serial_number)
        self.adb.reboot()

        timeout_start = time.time()
        timeout = timeout_minutes * 60
        # Android sometimes return early after `adb reboot` is called. This
        # means subsequent calls may make it to the device before the reboot
        # goes through, return false positives for getprops such as
        # sys.boot_completed.
        while time.time() < timeout_start + timeout:
            try:
                self.adb.get_state()
                time.sleep(.1)
            except AdbError:
                # get_state will raise an error if the device is not found. We
                # want the device to be missing to prove the device has kicked
                # off the reboot.
                break
        minutes_left = timeout_minutes - (time.time() - timeout_start) / 60.0
        self.wait_for_boot_completion(timeout_minutes=minutes_left)

    def wait_for_boot_completion(self, timeout_minutes=15.0):
        """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
        """
        timeout_start = time.time()
        timeout = timeout_minutes * 60

        self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT)
        while time.time() < timeout_start + timeout:
            try:
                completed = self.adb.getprop("sys.boot_completed")
                if completed == '1':
                    return
            except AdbError:
                # adb shell calls may fail during certain period of booting
                # process, which is normal. Ignoring these errors.
                pass
            time.sleep(5)
        asserts.fail(msg='Device %s booting process timed out.' %
                     self.serial_number)
Loading