Exemplo n.º 1
0
 def setup(self):
     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"))
     # Try freeing ports and ignore results
     self.adb.remove_tcp_forward(self.grpc_port)
     self.adb.remove_tcp_forward(self.grpc_root_server_port)
     self.adb.reverse("--remove tcp:%d" % self.signal_port)
     # Set up port forwarding or reverse or die
     self.tcp_forward_or_die(self.grpc_port, self.grpc_port)
     self.tcp_forward_or_die(self.grpc_root_server_port,
                             self.grpc_root_server_port)
     self.tcp_reverse_or_die(self.signal_port, self.signal_port)
     # Puh test binaries
     self.push_or_die(
         os.path.join(get_gd_root(), "target",
                      "bluetooth_stack_with_facade"), "system/bin")
     self.push_or_die(
         os.path.join(get_gd_root(), "target", "libbluetooth_gd.so"),
         "system/lib64")
     self.push_or_die(
         os.path.join(get_gd_root(), "target", "libgrpc++_unsecure.so"),
         "system/lib64")
     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"))
     super().setup()
Exemplo n.º 2
0
    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()

        # Start root-canal if needed
        self.rootcanal_running = False
        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')
            self.rootcanal_logs = open(self.rootcanal_logpath, 'w')

            # 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
            self.rootcanal_process = subprocess.Popen(
                [
                    rootcanal,
                    str(rootcanal_test_port),
                    str(rootcanal_hci_port),
                    str(rootcanal_link_layer_port)
                ],
                cwd=get_gd_root(),
                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")

            # 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)

        # Parse and construct GD device objects
        self.register_controller(
            importlib.import_module('cert.gd_device'), builtin=True)
        self.dut = self.gd_devices[1]
        self.cert = self.gd_devices[0]
Exemplo n.º 3
0
    def setup(self):
        logging.info("Setting up device %s %s" % (self.label, self.serial_number))
        asserts.assert_true(self.adb.ensure_root(), "device %s cannot run as root", self.serial_number)

        # Try freeing ports and ignore results
        self.cleanup_port_forwarding()
        self.sync_device_time()

        # Set up port forwarding or reverse or die
        self.tcp_forward_or_die(self.grpc_port, self.grpc_port)
        self.tcp_forward_or_die(self.grpc_root_server_port, self.grpc_root_server_port)
        self.tcp_reverse_or_die(self.signal_port, self.signal_port)

        # Push test binaries
        self.ensure_verity_disabled()
        self.push_or_die(os.path.join(get_gd_root(), "target", "bluetooth_stack_with_facade"), "system/bin")
        self.push_or_die(os.path.join(get_gd_root(), "target", "libbluetooth_gd.so"), "system/lib64")
        self.push_or_die(os.path.join(get_gd_root(), "target", "libgrpc++_unsecure.so"), "system/lib64")
        self.adb.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log")
        self.ensure_no_output(self.adb.shell("svc bluetooth disable"))

        # Start logcat logging
        self.logcat_output_path = os.path.join(
            self.log_path_base, '%s_%s_%s_logcat_logs.txt' % (self.type_identifier, self.label, self.serial_number))
        self.logcat_cmd = ["adb", "-s", self.serial_number, "logcat", "-T", "1", "-v", "year", "-v", "uid"]
        logging.debug("Running %s", " ".join(self.logcat_cmd))
        self.logcat_process = subprocess.Popen(
            self.logcat_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
        asserts.assert_true(self.logcat_process, msg="Cannot start logcat_process at " + " ".join(self.logcat_cmd))
        asserts.assert_true(
            is_subprocess_alive(self.logcat_process),
            msg="logcat_process stopped immediately after running " + " ".join(self.logcat_cmd))
        self.logcat_logger = AsyncSubprocessLogger(
            self.logcat_process, [self.logcat_output_path],
            log_to_stdout=self.verbose_mode,
            tag="%s_%s" % (self.label, self.serial_number),
            color=self.terminal_color)

        # Done run parent setup
        logging.info("Done preparation for %s, starting backing process" % self.serial_number)
        super().setup()
Exemplo n.º 4
0
 def __init__(self, grpc_port: str, grpc_root_server_port: str, signal_port: str, cmd: List[str], label: str,
              type_identifier: str, name: str, verbose_mode: bool):
     super().__init__(grpc_port, grpc_root_server_port, signal_port, cmd, label, MOBLY_CONTROLLER_CONFIG_NAME, name,
                      verbose_mode)
     # Enable LLVM code coverage output for host only tests
     self.backing_process_profraw_path = pathlib.Path(self.log_path_base).joinpath(
         "%s_%s_backing_coverage.profraw" % (self.type_identifier, self.label))
     self.environment["LLVM_PROFILE_FILE"] = str(self.backing_process_profraw_path)
     llvm_binutils = pathlib.Path(get_gd_root()).joinpath("llvm_binutils").joinpath("bin")
     llvm_symbolizer = llvm_binutils.joinpath("llvm-symbolizer")
     if llvm_symbolizer.is_file():
         self.environment["ASAN_SYMBOLIZER_PATH"] = llvm_symbolizer
     else:
         logging.warning("[%s] Cannot find LLVM symbolizer at %s" % (self.label, str(llvm_symbolizer)))
Exemplo n.º 5
0
def replace_vars(string, config):
    serial_number = config.get("serial_number")
    if serial_number is None:
        serial_number = ""
    rootcanal_port = config.get("rootcanal_port")
    if rootcanal_port is None:
        rootcanal_port = ""
    if serial_number == "DUT" or serial_number == "CERT":
        raise Exception("Did you forget to configure the serial number?")
    return string.replace("$GD_ROOT", get_gd_root()) \
                 .replace("$(grpc_port)", config.get("grpc_port")) \
                 .replace("$(grpc_root_server_port)", config.get("grpc_root_server_port")) \
                 .replace("$(rootcanal_port)", rootcanal_port) \
                 .replace("$(signal_port)", config.get("signal_port")) \
                 .replace("$(serial_number)", serial_number)
Exemplo n.º 6
0
 def generate_coverage_report(self):
     if not self.backing_process_profraw_path.is_file():
         logging.info("[%s] Skip coverage report as there is no profraw file at %s" %
                      (self.label, str(self.backing_process_profraw_path)))
         return
     try:
         if self.backing_process_profraw_path.stat().st_size <= 0:
             logging.info("[%s] Skip coverage report as profraw file is empty at %s" %
                          (self.label, str(self.backing_process_profraw_path)))
             return
     except OSError:
         logging.info("[%s] Skip coverage report as profraw file is inaccessible at %s" %
                      (self.label, str(self.backing_process_profraw_path)))
         return
     llvm_binutils = pathlib.Path(get_gd_root()).joinpath("llvm_binutils").joinpath("bin")
     llvm_profdata = llvm_binutils.joinpath("llvm-profdata")
     if not llvm_profdata.is_file():
         logging.info(
             "[%s] Skip coverage report as llvm-profdata is not found at %s" % (self.label, str(llvm_profdata)))
         return
     llvm_cov = llvm_binutils.joinpath("llvm-cov")
     if not llvm_cov.is_file():
         logging.info("[%s] Skip coverage report as llvm-cov is not found at %s" % (self.label, str(llvm_cov)))
         return
     logging.info("[%s] Generating coverage report" % self.label)
     profdata_path = pathlib.Path(self.test_runner_base_path).joinpath(
         "%s_%s_backing_process_coverage.profdata" % (self.type_identifier, self.label))
     profdata_path_tmp = pathlib.Path(self.test_runner_base_path).joinpath(
         "%s_%s_backing_process_coverage_tmp.profdata" % (self.type_identifier, self.label))
     # Merge with existing profdata if possible
     profdata_cmd = [str(llvm_profdata), "merge", "-sparse", str(self.backing_process_profraw_path)]
     if profdata_path.is_file():
         profdata_cmd.append(str(profdata_path))
     profdata_cmd += ["-o", str(profdata_path_tmp)]
     result = subprocess.run(profdata_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     if result.returncode != 0:
         logging.warning("[%s] Failed to index profdata, cmd result: %r" % (self.label, result))
         profdata_path.unlink(missing_ok=True)
         return
     shutil.move(profdata_path_tmp, profdata_path)
     coverage_result_path = pathlib.Path(self.test_runner_base_path).joinpath(
         "%s_%s_backing_process_coverage.json" % (self.type_identifier, self.label))
     with coverage_result_path.open("w") as coverage_result_file:
         result = subprocess.run(
             [str(llvm_cov), "export", "--format=text", "--instr-profile", profdata_path, self.cmd[0]],
             stderr=subprocess.PIPE,
             stdout=coverage_result_file,
             cwd=os.path.join(get_gd_root()))
     if result.returncode != 0:
         logging.warning("[%s] Failed to generated coverage report, cmd result: %r" % (self.label, result))
         coverage_result_path.unlink(missing_ok=True)
         return
     coverage_summary_path = pathlib.Path(self.test_runner_base_path).joinpath(
         "%s_%s_backing_process_coverage_summary.txt" % (self.type_identifier, self.label))
     with coverage_summary_path.open("w") as coverage_summary_file:
         result = subprocess.run(
             [llvm_cov, "report", "--instr-profile", profdata_path, self.cmd[0]],
             stderr=subprocess.PIPE,
             stdout=coverage_summary_file,
             cwd=os.path.join(get_gd_root()))
     if result.returncode != 0:
         logging.warning("[%s] Failed to generated coverage summary, cmd result: %r" % (self.label, result))
         coverage_summary_path.unlink(missing_ok=True)
Exemplo n.º 7
0
    def setup(self):
        """Set up this device for test, must run before using this device
        - After calling this, teardown() must be called when test finishes
        - Should be executed after children classes' setup() methods
        :return:
        """
        # Ensure signal port is available
        # signal port is the only port that always listen on the host machine
        asserts.assert_true(
            make_ports_available([self.signal_port]), "[%s] Failed to make signal port available" % self.label)
        # Start backing process
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as signal_socket:
            # Setup signaling socket
            signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            signal_socket.bind(("localhost", self.signal_port))
            signal_socket.listen(1)
            signal_socket.settimeout(300)  # 5 minute timeout for blocking socket operations

            # Start backing process
            logging.debug("Running %s" % " ".join(self.cmd))
            self.backing_process = subprocess.Popen(
                self.cmd,
                cwd=get_gd_root(),
                env=self.environment,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                universal_newlines=True)
            asserts.assert_true(self.backing_process, msg="Cannot start backing_process at " + " ".join(self.cmd))
            asserts.assert_true(
                is_subprocess_alive(self.backing_process),
                msg="backing_process stopped immediately after running " + " ".join(self.cmd))

            # Wait for process to be ready
            logging.debug("Waiting for backing_process accept.")
            signal_socket.accept()

        self.backing_process_logger = AsyncSubprocessLogger(
            self.backing_process, [self.backing_process_log_path],
            log_to_stdout=self.verbose_mode,
            tag=self.label,
            color=self.terminal_color)

        # Setup gRPC management channels
        self.grpc_root_server_channel = grpc.insecure_channel("localhost:%d" % self.grpc_root_server_port)
        self.grpc_channel = grpc.insecure_channel("localhost:%d" % self.grpc_port)

        if self.verbose_mode:
            self.grpc_channel = grpc.intercept_channel(self.grpc_channel, LoggingClientInterceptor(self.label))

        # Establish services from facades
        self.rootservice = facade_rootservice_pb2_grpc.RootFacadeStub(self.grpc_root_server_channel)
        self.hal = hal_facade_pb2_grpc.HciHalFacadeStub(self.grpc_channel)
        self.controller_read_only_property = facade_rootservice_pb2_grpc.ReadOnlyPropertyStub(self.grpc_channel)
        self.hci = hci_facade_pb2_grpc.HciFacadeStub(self.grpc_channel)
        self.l2cap = l2cap_facade_pb2_grpc.L2capClassicModuleFacadeStub(self.grpc_channel)
        self.l2cap_le = l2cap_le_facade_pb2_grpc.L2capLeModuleFacadeStub(self.grpc_channel)
        self.iso = iso_facade_pb2_grpc.IsoModuleFacadeStub(self.grpc_channel)
        self.hci_acl_manager = acl_manager_facade_pb2_grpc.AclManagerFacadeStub(self.grpc_channel)
        self.hci_le_acl_manager = le_acl_manager_facade_pb2_grpc.LeAclManagerFacadeStub(self.grpc_channel)
        self.hci_le_initiator_address = le_initiator_address_facade_pb2_grpc.LeInitiatorAddressFacadeStub(
            self.grpc_channel)
        self.hci_controller = controller_facade_pb2_grpc.ControllerFacadeStub(self.grpc_channel)
        self.hci_controller.GetMacAddressSimple = lambda: self.hci_controller.GetMacAddress(empty_proto.Empty()).address
        self.hci_controller.GetLocalNameSimple = lambda: self.hci_controller.GetLocalName(empty_proto.Empty()).name
        self.hci_le_advertising_manager = le_advertising_manager_facade_pb2_grpc.LeAdvertisingManagerFacadeStub(
            self.grpc_channel)
        self.hci_le_scanning_manager = le_scanning_manager_facade_pb2_grpc.LeScanningManagerFacadeStub(
            self.grpc_channel)
        self.neighbor = neighbor_facade_pb2_grpc.NeighborFacadeStub(self.grpc_channel)
        self.security = security_facade_pb2_grpc.SecurityModuleFacadeStub(self.grpc_channel)
        self.shim = shim_facade_pb2_grpc.ShimFacadeStub(self.grpc_channel)
Exemplo n.º 8
0
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
    info['rootcanal_logpath'] = ""
    info['rootcanal_process'] = None
    info['rootcanal_logger'] = None
    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
Exemplo n.º 9
0
    def setup(self):
        """Set up this device for test, must run before using this device
        - After calling this, teardown() must be called when test finishes
        - Should be executed after children classes' setup() methods
        :return:
        """
        # Ensure signal port is available
        # signal port is the only port that always listen on the host machine
        asserts.assert_true(
            make_ports_available([self.signal_port]),
            "[%s] Failed to make signal port available" % self.label)
        # Start backing process
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as signal_socket:
            # Setup signaling socket
            signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            signal_socket.bind(("localhost", self.signal_port))
            signal_socket.listen(1)

            # Start backing process
            self.backing_process_logs = open(self.backing_process_log_path, 'w')
            self.backing_process = subprocess.Popen(
                self.cmd,
                cwd=get_gd_root(),
                env=self.environment,
                stdout=self.backing_process_logs,
                stderr=self.backing_process_logs)
            asserts.assert_true(
                self.backing_process,
                msg="Cannot start backing_process at " + " ".join(self.cmd))
            asserts.assert_true(
                is_subprocess_alive(self.backing_process),
                msg="backing_process stopped immediately after running " +
                " ".join(self.cmd))

            # Wait for process to be ready
            signal_socket.accept()

        # Setup gRPC management channels
        self.grpc_root_server_channel = grpc.insecure_channel(
            "localhost:%d" % self.grpc_root_server_port)
        self.grpc_channel = grpc.insecure_channel(
            "localhost:%d" % self.grpc_port)

        # Establish services from facades
        self.rootservice = facade_rootservice_pb2_grpc.RootFacadeStub(
            self.grpc_root_server_channel)
        self.hal = hal_facade_pb2_grpc.HciHalFacadeStub(self.grpc_channel)
        self.controller_read_only_property = facade_rootservice_pb2_grpc.ReadOnlyPropertyStub(
            self.grpc_channel)
        self.hci = hci_facade_pb2_grpc.HciLayerFacadeStub(self.grpc_channel)
        self.l2cap = l2cap_facade_pb2_grpc.L2capClassicModuleFacadeStub(
            self.grpc_channel)
        self.l2cap_le = l2cap_le_facade_pb2_grpc.L2capLeModuleFacadeStub(
            self.grpc_channel)
        self.hci_acl_manager = acl_manager_facade_pb2_grpc.AclManagerFacadeStub(
            self.grpc_channel)
        self.hci_le_acl_manager = le_acl_manager_facade_pb2_grpc.LeAclManagerFacadeStub(
            self.grpc_channel)
        self.hci_controller = controller_facade_pb2_grpc.ControllerFacadeStub(
            self.grpc_channel)
        self.hci_controller.GetMacAddressSimple = lambda: self.hci_controller.GetMacAddress(
            empty_proto.Empty()).address
        self.hci_controller.GetLocalNameSimple = lambda: self.hci_controller.GetLocalName(
            empty_proto.Empty()).name
        self.hci_le_advertising_manager = le_advertising_manager_facade_pb2_grpc.LeAdvertisingManagerFacadeStub(
            self.grpc_channel)
        self.hci_le_scanning_manager = le_scanning_manager_facade_pb2_grpc.LeScanningManagerFacadeStub(
            self.grpc_channel)
        self.neighbor = neighbor_facade_pb2_grpc.NeighborFacadeStub(
            self.grpc_channel)
        self.security = security_facade_pb2_grpc.SecurityModuleFacadeStub(
            self.grpc_channel)
Exemplo n.º 10
0
    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
        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")

            self.rootcanal_logger = AsyncSubprocessLogger(
                self.rootcanal_process, [self.rootcanal_logpath],
                log_to_stdout=self.verbose_mode,
                tag="rootcanal",
                color=TerminalColor.MAGENTA)

            # 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)

        # Parse and construct GD device objects
        self.register_controller(importlib.import_module('cert.gd_device'),
                                 builtin=True)
        self.dut = self.gd_devices[1]
        self.cert = self.gd_devices[0]