OSDN Git Service

Unbind gd_base_test from ACTS
authorJizheng Chu <jizhengchu@google.com>
Tue, 23 Feb 2021 02:49:36 +0000 (18:49 -0800)
committerJizheng Chu <jizhengchu@google.com>
Tue, 23 Feb 2021 05:54:52 +0000 (21:54 -0800)
Test: gd/cert/run
Change-Id: If09e5ef2296e8964217e9542c1269549eb5e1b93

gd/cert/gd_base_test.py
gd/cert/gd_base_test_lib.py [new file with mode: 0644]

index b69efdc..b382e6a 100644 (file)
@@ -36,6 +36,11 @@ from cert.os_utils import make_ports_available
 from cert.os_utils import TerminalColor
 from cert.gd_device import MOBLY_CONTROLLER_CONFIG_NAME as CONTROLLER_CONFIG_NAME
 from facade import rootservice_pb2 as facade_rootservice
+from cert.gd_base_test_lib import setup_class_core
+from cert.gd_base_test_lib import teardown_class_core
+from cert.gd_base_test_lib import setup_test_core
+from cert.gd_base_test_lib import teardown_test_core
+from cert.gd_base_test_lib import dump_crashes_core
 
 
 class GdBaseTestClass(BaseTestClass):
@@ -43,59 +48,37 @@ class GdBaseTestClass(BaseTestClass):
     SUBPROCESS_WAIT_TIMEOUT_SECONDS = 10
 
     def setup_class(self, dut_module, cert_module):
-        self.dut_module = dut_module
-        self.cert_module = cert_module
         self.log_path_base = get_current_context().get_full_output_path()
         self.verbose_mode = bool(self.user_params.get('verbose_mode', False))
         for config in self.controller_configs[CONTROLLER_CONFIG_NAME]:
             config['verbose_mode'] = self.verbose_mode
 
-        # Start root-canal if needed
-        self.rootcanal_running = False
+        self.info = setup_class_core(
+            dut_module=dut_module,
+            cert_module=cert_module,
+            verbose_mode=self.verbose_mode,
+            log_path_base=self.log_path_base,
+            controller_configs=self.controller_configs)
+        self.dut_module = self.info['dut_module']
+        self.cert_module = self.info['cert_module']
+        self.rootcanal_running = self.info['rootcanal_running']
+        self.rootcanal_logpath = self.info['rootcanal_logpath']
+        self.rootcanal_process = self.info['rootcanal_process']
+
         if 'rootcanal' in self.controller_configs:
-            self.rootcanal_running = True
-            # Get root canal binary
-            rootcanal = os.path.join(get_gd_root(), "root-canal")
-            asserts.assert_true(os.path.isfile(rootcanal), "Root canal does not exist at %s" % rootcanal)
-
-            # Get root canal log
-            self.rootcanal_logpath = os.path.join(self.log_path_base, 'rootcanal_logs.txt')
-            # Make sure ports are available
-            rootcanal_config = self.controller_configs['rootcanal']
-            rootcanal_test_port = int(rootcanal_config.get("test_port", "6401"))
-            rootcanal_hci_port = int(rootcanal_config.get("hci_port", "6402"))
-            rootcanal_link_layer_port = int(rootcanal_config.get("link_layer_port", "6403"))
-            asserts.assert_true(
-                make_ports_available((rootcanal_test_port, rootcanal_hci_port, rootcanal_link_layer_port)),
-                "Failed to make root canal ports available")
-
-            # Start root canal process
-            rootcanal_cmd = [
-                rootcanal, str(rootcanal_test_port),
-                str(rootcanal_hci_port),
-                str(rootcanal_link_layer_port)
-            ]
-            self.log.debug("Running %s" % " ".join(rootcanal_cmd))
-            self.rootcanal_process = subprocess.Popen(
-                rootcanal_cmd,
-                cwd=get_gd_root(),
-                env=os.environ.copy(),
-                stdout=subprocess.PIPE,
-                stderr=subprocess.STDOUT,
-                universal_newlines=True)
-            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")
+            asserts.assert_true(self.info['rootcanal_exist'],
+                                "Root canal does not exist at %s" % self.info['rootcanal'])
+            asserts.assert_true(self.info['make_rootcanal_ports_available'],
+                                "Failed to make root canal ports available")
 
-            self.rootcanal_logger = AsyncSubprocessLogger(
-                self.rootcanal_process, [self.rootcanal_logpath],
-                log_to_stdout=self.verbose_mode,
-                tag="rootcanal",
-                color=TerminalColor.MAGENTA)
+            self.log.debug("Running %s" % " ".join(self.info['rootcanal_cmd']))
+            asserts.assert_true(
+                self.info['is_rootcanal_process_started'],
+                msg="Cannot start root-canal at " + str(self.info['rootcanal']))
+            asserts.assert_true(self.info['is_subprocess_alive'], msg="root-canal stopped immediately after running")
 
-            # Modify the device config to include the correct root-canal port
-            for gd_device_config in self.controller_configs.get("GdDevice"):
-                gd_device_config["rootcanal_port"] = str(rootcanal_hci_port)
+            self.rootcanal_logger = self.info['rootcanal_logger']
+            self.controller_configs = self.info['controller_configs']
 
         # Parse and construct GD device objects
         self.register_controller(importlib.import_module('cert.gd_device'), builtin=True)
@@ -103,38 +86,17 @@ class GdBaseTestClass(BaseTestClass):
         self.cert = self.gd_devices[0]
 
     def teardown_class(self):
-        if self.rootcanal_running:
-            stop_signal = signal.SIGINT
-            self.rootcanal_process.send_signal(stop_signal)
-            try:
-                return_code = self.rootcanal_process.wait(timeout=self.SUBPROCESS_WAIT_TIMEOUT_SECONDS)
-            except subprocess.TimeoutExpired:
-                logging.error("Failed to interrupt root canal via SIGINT, sending SIGKILL")
-                stop_signal = signal.SIGKILL
-                self.rootcanal_process.kill()
-                try:
-                    return_code = self.rootcanal_process.wait(timeout=self.SUBPROCESS_WAIT_TIMEOUT_SECONDS)
-                except subprocess.TimeoutExpired:
-                    logging.error("Failed to kill root canal")
-                    return_code = -65536
-            if return_code != 0 and return_code != -stop_signal:
-                logging.error("rootcanal stopped with code: %d" % return_code)
-            self.rootcanal_logger.stop()
+        teardown_class_core(
+            rootcanal_running=self.rootcanal_running,
+            rootcanal_process=self.rootcanal_process,
+            rootcanal_logger=self.rootcanal_logger,
+            subprocess_wait_timeout_seconds=self.SUBPROCESS_WAIT_TIMEOUT_SECONDS)
 
     def setup_test(self):
-        self.dut.rootservice.StartStack(
-            facade_rootservice.StartStackRequest(
-                module_under_test=facade_rootservice.BluetoothModule.Value(self.dut_module),))
-        self.cert.rootservice.StartStack(
-            facade_rootservice.StartStackRequest(
-                module_under_test=facade_rootservice.BluetoothModule.Value(self.cert_module),))
-
-        self.dut.wait_channel_ready()
-        self.cert.wait_channel_ready()
+        setup_test_core(dut=self.dut, cert=self.cert, dut_module=self.dut_module, cert_module=self.cert_module)
 
     def teardown_test(self):
-        self.cert.rootservice.StopStack(facade_rootservice.StopStackRequest())
-        self.dut.rootservice.StopStack(facade_rootservice.StopStackRequest())
+        teardown_test_core(cert=self.cert, dut=self.dut)
 
     def __getattribute__(self, name):
         attr = super().__getattribute__(name)
@@ -160,29 +122,12 @@ class GdBaseTestClass(BaseTestClass):
 
     def __dump_crashes(self):
         """
-        :return: formatted stack traces if found, or last few lines of log
+        return: formatted stack traces if found, or last few lines of log
         """
-        dut_crash, dut_log_tail = self.dut.get_crash_snippet_and_log_tail()
-        cert_crash, cert_log_tail = self.cert.get_crash_snippet_and_log_tail()
-        rootcanal_crash = None
-        rootcanal_log_tail = None
-        if self.rootcanal_running and not is_subprocess_alive(self.rootcanal_process):
-            rootcanal_crash, roocanal_log_tail = read_crash_snippet_and_log_tail(self.rootcanal_logpath)
-
-        crash_detail = ""
-        if dut_crash or cert_crash or rootcanal_crash:
-            if rootcanal_crash:
-                crash_detail += "rootcanal crashed:\n\n%s\n\n" % rootcanal_crash
-            if dut_crash:
-                crash_detail += "dut stack crashed:\n\n%s\n\n" % dut_crash
-            if cert_crash:
-                crash_detail += "cert stack crashed:\n\n%s\n\n" % cert_crash
-        else:
-            if rootcanal_log_tail:
-                crash_detail += "rootcanal log tail:\n\n%s\n\n" % rootcanal_log_tail
-            if dut_log_tail:
-                crash_detail += "dut log tail:\n\n%s\n\n" % dut_log_tail
-            if cert_log_tail:
-                crash_detail += "cert log tail:\n\n%s\n\n" % cert_log_tail
-
+        crash_detail = dump_crashes_core(
+            dut=self.dut,
+            cert=self.cert,
+            rootcanal_running=self.rootcanal_running,
+            rootcanal_process=self.rootcanal_process,
+            rootcanal_logpath=self.rootcanal_logpath)
         return crash_detail
diff --git a/gd/cert/gd_base_test_lib.py b/gd/cert/gd_base_test_lib.py
new file mode 100644 (file)
index 0000000..19b83f1
--- /dev/null
@@ -0,0 +1,163 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import importlib
+import logging
+import os
+import signal
+import subprocess
+import traceback
+
+from functools import wraps
+from grpc import RpcError
+
+from cert.async_subprocess_logger import AsyncSubprocessLogger
+from cert.os_utils import get_gd_root
+from cert.os_utils import read_crash_snippet_and_log_tail
+from cert.os_utils import is_subprocess_alive
+from cert.os_utils import make_ports_available
+from cert.os_utils import TerminalColor
+from cert.gd_device import MOBLY_CONTROLLER_CONFIG_NAME as CONTROLLER_CONFIG_NAME
+from facade import rootservice_pb2 as facade_rootservice
+
+
+def setup_class_core(dut_module, cert_module, verbose_mode, log_path_base, controller_configs):
+    info = {}
+    info['dut_module'] = dut_module
+    info['cert_module'] = cert_module
+    info['controller_configs'] = controller_configs
+
+    # Start root-canal if needed
+    info['rootcanal_running'] = False
+    if 'rootcanal' in info['controller_configs']:
+        info['rootcanal_running'] = True
+        # Get root canal binary
+        rootcanal = os.path.join(get_gd_root(), "root-canal")
+        info['rootcanal'] = rootcanal
+        info['rootcanal_exist'] = os.path.isfile(rootcanal)
+        if not os.path.isfile(rootcanal):
+            return info
+
+        # Get root canal log
+        rootcanal_logpath = os.path.join(log_path_base, 'rootcanal_logs.txt')
+        info['rootcanal_logpath'] = rootcanal_logpath
+        # Make sure ports are available
+        rootcanal_config = info['controller_configs']['rootcanal']
+        rootcanal_test_port = int(rootcanal_config.get("test_port", "6401"))
+        rootcanal_hci_port = int(rootcanal_config.get("hci_port", "6402"))
+        rootcanal_link_layer_port = int(rootcanal_config.get("link_layer_port", "6403"))
+
+        info['make_rootcanal_ports_available'] = make_ports_available((rootcanal_test_port, rootcanal_hci_port,
+                                                                       rootcanal_link_layer_port))
+        if not make_ports_available((rootcanal_test_port, rootcanal_hci_port, rootcanal_link_layer_port)):
+            return info
+
+        # Start root canal process
+        rootcanal_cmd = [rootcanal, str(rootcanal_test_port), str(rootcanal_hci_port), str(rootcanal_link_layer_port)]
+        info['rootcanal_cmd'] = rootcanal_cmd
+
+        rootcanal_process = subprocess.Popen(
+            rootcanal_cmd,
+            cwd=get_gd_root(),
+            env=os.environ.copy(),
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+            universal_newlines=True)
+
+        info['rootcanal_process'] = rootcanal_process
+        if rootcanal_process:
+            info['is_rootcanal_process_started'] = True
+        else:
+            info['is_rootcanal_process_started'] = False
+            return info
+        info['is_subprocess_alive'] = is_subprocess_alive(rootcanal_process)
+        if not is_subprocess_alive(rootcanal_process):
+            info['is_subprocess_alive'] = False
+            return info
+
+        info['rootcanal_logger'] = AsyncSubprocessLogger(
+            rootcanal_process, [rootcanal_logpath],
+            log_to_stdout=verbose_mode,
+            tag="rootcanal",
+            color=TerminalColor.MAGENTA)
+
+        # Modify the device config to include the correct root-canal port
+        for gd_device_config in info['controller_configs'].get("GdDevice"):
+            gd_device_config["rootcanal_port"] = str(rootcanal_hci_port)
+
+    return info
+
+
+def teardown_class_core(rootcanal_running, rootcanal_process, rootcanal_logger, subprocess_wait_timeout_seconds):
+    if rootcanal_running:
+        stop_signal = signal.SIGINT
+        rootcanal_process.send_signal(stop_signal)
+        try:
+            return_code = rootcanal_process.wait(timeout=subprocess_wait_timeout_seconds)
+        except subprocess.TimeoutExpired:
+            logging.error("Failed to interrupt root canal via SIGINT, sending SIGKILL")
+            stop_signal = signal.SIGKILL
+            rootcanal_process.kill()
+            try:
+                return_code = rootcanal_process.wait(timeout=subprocess_wait_timeout_seconds)
+            except subprocess.TimeoutExpired:
+                logging.error("Failed to kill root canal")
+                return_code = -65536
+        if return_code != 0 and return_code != -stop_signal:
+            logging.error("rootcanal stopped with code: %d" % return_code)
+        rootcanal_logger.stop()
+
+
+def setup_test_core(dut, cert, dut_module, cert_module):
+    dut.rootservice.StartStack(
+        facade_rootservice.StartStackRequest(module_under_test=facade_rootservice.BluetoothModule.Value(dut_module),))
+    cert.rootservice.StartStack(
+        facade_rootservice.StartStackRequest(module_under_test=facade_rootservice.BluetoothModule.Value(cert_module),))
+
+    dut.wait_channel_ready()
+    cert.wait_channel_ready()
+
+
+def teardown_test_core(cert, dut):
+    cert.rootservice.StopStack(facade_rootservice.StopStackRequest())
+    dut.rootservice.StopStack(facade_rootservice.StopStackRequest())
+
+
+def dump_crashes_core(dut, cert, rootcanal_running, rootcanal_process, rootcanal_logpath):
+    dut_crash, dut_log_tail = dut.get_crash_snippet_and_log_tail()
+    cert_crash, cert_log_tail = cert.get_crash_snippet_and_log_tail()
+    rootcanal_crash = None
+    rootcanal_log_tail = None
+    if rootcanal_running and not is_subprocess_alive(rootcanal_process):
+        rootcanal_crash, roocanal_log_tail = read_crash_snippet_and_log_tail(rootcanal_logpath)
+
+    crash_detail = ""
+    if dut_crash or cert_crash or rootcanal_crash:
+        if rootcanal_crash:
+            crash_detail += "rootcanal crashed:\n\n%s\n\n" % rootcanal_crash
+        if dut_crash:
+            crash_detail += "dut stack crashed:\n\n%s\n\n" % dut_crash
+        if cert_crash:
+            crash_detail += "cert stack crashed:\n\n%s\n\n" % cert_crash
+    else:
+        if rootcanal_log_tail:
+            crash_detail += "rootcanal log tail:\n\n%s\n\n" % rootcanal_log_tail
+        if dut_log_tail:
+            crash_detail += "dut log tail:\n\n%s\n\n" % dut_log_tail
+        if cert_log_tail:
+            crash_detail += "cert log tail:\n\n%s\n\n" % cert_log_tail
+
+    return crash_detail