diff --git a/build/compile_script/ark.py b/build/compile_script/ark.py index b33729390d40299d348b1992bc9fa4f2ae5a5ecd..2fd7794f2242c04be4f4d4fddffe445677405647 100755 --- a/build/compile_script/ark.py +++ b/build/compile_script/ark.py @@ -345,9 +345,9 @@ class ArkPy: cmd.append(f"--ark-frontend-binary=../../{x64_out_path}/arkcompiler/ets_frontend/es2abc") cmd.append(f"--merge-abc-binary=../../{x64_out_path}/arkcompiler/ets_frontend/merge_abc") if aot_mode: - cmd.append(f"--ark-aot-tool=../../{x64_out_path}/arkcompiler/ets_runtime/ark_aot_compiler") + cmd.append(f"--ark-aot-tool=../../{out_path}/arkcompiler/ets_runtime/ark_aot_compiler") if test_suite == "regresstest": - cmd.append(f"--stub-path=../../{x64_out_path}/gen/arkcompiler/ets_runtime/stub.an") + cmd.append(f"--stub-path=../../{out_path}/gen/arkcompiler/ets_runtime/stub.an") else: cmd.append(f"--ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc") cmd.append(f"--merge-abc-binary=../../{out_path}/arkcompiler/ets_frontend/merge_abc") @@ -496,26 +496,40 @@ class ArkPy: def build_args_to_test262_cmd(arg_list): args_to_test262_cmd = [] - disable_force_gc = [arg for arg in arg_list if "disable-force-gc" in arg] - if disable_force_gc: - args_to_test262_cmd.append("--disable-force-gc") - arg_list.remove(disable_force_gc[0]) + disable_force_gc_name = "--disable-force-gc" + disable_force_gc_value, arg_list = ArkPy.parse_bool_option( + arg_list, option_name=disable_force_gc_name, default_value=False + ) + if disable_force_gc_value: + args_to_test262_cmd.extend([disable_force_gc_name]) threads_name = "--threads" threads_value, arg_list = ArkPy.parse_option(arg_list, option_name=threads_name, default_value=None) if threads_value: args_to_test262_cmd.extend([threads_name, threads_value]) + test_list_name = "--test-list" + test_list_value, arg_list = ArkPy.parse_option(arg_list, option_name=test_list_name, default_value=None) + if test_list_value is not None: + args_to_test262_cmd.extend([test_list_name, test_list_value]) + enable_rm = [arg for arg in arg_list if "enable-rm" in arg] if enable_rm: args_to_test262_cmd.append("--enable-rm") arg_list.remove(enable_rm[0]) + skip_list_name = "--skip-list" + skip_list_value, arg_list = ArkPy.parse_option(arg_list, option_name=skip_list_name, default_value=None) + if skip_list_value is not None: + args_to_test262_cmd.extend([skip_list_name, skip_list_value]) + if len(arg_list) == 0: args_to_test262_cmd.append("--es2021 all") elif len(arg_list) == 1: arg = arg_list[0] - if ".js" in arg: + if arg == "sendable": + args_to_test262_cmd.append("--sendable sendable") + elif ".js" in arg: args_to_test262_cmd.append("--file test262/data/test_es2021/{}".format(arg)) else: args_to_test262_cmd.append("--dir test262/data/test_es2021/{}".format(arg)) @@ -529,6 +543,13 @@ class ArkPy: def build_args_to_regress_cmd(arg_list): args_to_regress_cmd = [] + disable_force_gc_name = "--disable-force-gc" + disable_force_gc_value, arg_list = ArkPy.parse_bool_option( + arg_list, option_name=disable_force_gc_name, default_value=False + ) + if disable_force_gc_value: + args_to_regress_cmd.extend([disable_force_gc_name]) + processes_name = "--processes" processes_value, arg_list = ArkPy.parse_option(arg_list, option_name=processes_name, default_value=1) args_to_regress_cmd.extend([processes_name, processes_value]) @@ -560,6 +581,18 @@ class ArkPy: option_value = default_value return option_value, arg_list + @staticmethod + def parse_bool_option(arg_list: List[str], option_name: str, default_value: bool) \ + -> Tuple[bool, List[str]]: + if option_name in arg_list: + option_index = arg_list.index(option_name) + option_value = not default_value + arg_list = arg_list[:option_index] + arg_list[option_index + 1:] + else: + option_value = default_value + + return option_value, arg_list + @staticmethod def __is_option_value_int(value: Optional[Union[str, int]]) -> Tuple[bool, Optional[int]]: if isinstance(value, int): @@ -708,7 +741,7 @@ class ArkPy: "[none or --pgo] [none or --litecg] [none, file or dir] [none or --threads=X] [option]\033[0m\n" " python3 ark.py \033[92m[os_cpu].[mode] [test262] [none or --jit] [none or --threads=X]\033[0m\n" " python3 ark.py \033[92m[os_cpu].[mode] [test262] [none or --baseline-jit] [none or --enable-rm] " \ - "[none or --threads=X]\033[0m\n" + "[none or --threads=X and/or --test-list TEST_LIST_NAME]\033[0m\n" " python3 ark.py \033[92m[os_cpu].[mode] [unittest] [option]\033[0m\n" " python3 ark.py \033[92m[os_cpu].[mode] [regresstest] [none, file or dir] " \ "[none or --processes X and/or --test-list TEST_LIST_NAME]\033[0m\n") @@ -768,7 +801,7 @@ class ArkPy: # gn command print("=== gn gen start ===") code = call_with_output( - "{0} gen {1} --args=\"{2}\"".format( + "{0} gen {1} --args=\"{2}\" --export-compile-commands".format( self.gn_binary_path, out_path, " ".join(gn_args).replace("\"", "\\\"")), build_log_path) if code != 0: @@ -841,9 +874,11 @@ class ArkPy: def build_for_suite(self, *, test_suite, test_script_name, test_script_path, out_path, gn_args: list, log_file_name, args_to_cmd: str, timeout, run_jit: bool = False, run_baseline_jit: bool = False, aot_mode: bool = False, - run_pgo: bool = False, enable_litecg: bool = False, ignore_list: Optional[str] = None): + run_pgo: bool = False, enable_litecg: bool = False, ignore_list: Optional[str] = None, + skip_compiler: bool = False): x64_out_path = self.__get_x64_out_path(out_path) - self.call_build_gn_target(gn_args, out_path, x64_out_path, test_suite, log_file_name) + if not skip_compiler: + self.call_build_gn_target(gn_args, out_path, x64_out_path, test_suite, log_file_name) cmd = self.get_build_cmd( test_suite=test_suite, test_script_name=test_script_name, @@ -876,6 +911,7 @@ class ArkPy: is_litecg, arg_list = self.__purge_arg_list("--litecg", arg_list) is_jit, arg_list = self.__purge_arg_list("--jit", arg_list) is_baseline_jit, arg_list = self.__purge_arg_list("--baseline-jit", arg_list) + is_skip_compiler, arg_list = self.__purge_arg_list("--skip-compiler", arg_list) print(f"Test262: arg_list = {arg_list}") args_to_test262_cmd = self.build_args_to_test262_cmd(arg_list) @@ -892,7 +928,8 @@ class ArkPy: run_pgo=is_pgo, run_baseline_jit=is_baseline_jit, aot_mode=is_aot_mode, - enable_litecg=is_litecg + enable_litecg=is_litecg, + skip_compiler=is_skip_compiler ) def build_for_unittest(self, out_path: str, gn_args: list, log_file_name: str): @@ -912,6 +949,7 @@ class ArkPy: is_litecg, arg_list = self.__purge_arg_list("--litecg", arg_list) is_jit, arg_list = self.__purge_arg_list("--jit", arg_list) is_baseline_jit, arg_list = self.__purge_arg_list("--baseline-jit", arg_list) + is_skip_compiler, arg_list = self.__purge_arg_list("--skip-compiler", arg_list) print(f"Regress: arg_list = {arg_list}") args_to_regress_test_cmd = self.build_args_to_regress_cmd(arg_list) @@ -929,7 +967,8 @@ class ArkPy: run_baseline_jit=is_baseline_jit, aot_mode=is_aot, enable_litecg=is_litecg, - ignore_list=ignore_list + ignore_list=ignore_list, + skip_compiler=is_skip_compiler ) def build(self, out_path: str, gn_args: list, arg_list: list): diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 7be5abe41a6be6b96466417a6e73bfe17d89a207..6f9d1fbf83b1b05c217d61cb5bc14e7254e82976 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -35,7 +35,11 @@ if (check_darwin_system_result != "") { } if (host_os == "linux") { - host_platform_dir = "linux-x86_64" + if (host_cpu == "arm64") { + host_platform_dir = "linux-aarch64" + } else { + host_platform_dir = "linux-x86_64" + } } else if (host_os == "mac") { if (host_cpu == "arm64") { host_platform_dir = "darwin-arm64" diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 1478110c1e05b0cbc0681f7a4ee94af8374c2183..cabbc862170cf82380e09e59914548aa0ea43653 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -412,7 +412,7 @@ config("compiler_cpu_abi") { if (is_clang && (is_ohos || is_android)) { ldflags += [ "-Wl,--hash-style=gnu" ] } - if (!is_android) { + if (!is_android && !is_clang) { cflags += [ "-march=$arm_arch", "-mfloat-abi=$arm_float_abi", diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index d524d63d91435a52f391bee38eb251940c67aff6..3fcfa77181c62634f2bdc15dbc169c0dca5a42be 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni @@ -28,7 +28,7 @@ declare_args() { # Linux. use_lld = is_clang && (is_win || (is_linux && current_cpu == "x64") || - (is_linux && current_cpu == "x86") || + (is_linux && (current_cpu == "x86" || current_cpu == "arm64")) || (is_ohos_or_android && (current_cpu != "arm" || arm_version >= 7))) } diff --git a/build/config/components/ets_frontend/ets_frontend_config.gni b/build/config/components/ets_frontend/ets_frontend_config.gni index 2aebf108cfe1f0bbc549aa3692f776c7a524dc16..2a3c66d98f8a8e5b7b9f54e23b1afaed1b771a40 100644 --- a/build/config/components/ets_frontend/ets_frontend_config.gni +++ b/build/config/components/ets_frontend/ets_frontend_config.gni @@ -27,10 +27,11 @@ import("$build_root/test.gni") ets_frontend_root = "//arkcompiler/ets_frontend" -toolchain_linux = "$build_root/toolchain/linux:clang_x64" if (host_cpu == "arm64") { + toolchain_linux = "$build_root/toolchain/linux:clang_arm64" toolchain_mac = "$build_root/toolchain/mac:clang_arm64" } else { + toolchain_linux = "$build_root/toolchain/linux:clang_x64" toolchain_mac = "$build_root/toolchain/mac:clang_x64" } toolchain_win = "$build_root/toolchain/mingw:mingw_x86_64" diff --git a/build/core/gn/BUILD.gn b/build/core/gn/BUILD.gn index 5483815961175acc7ce9e56ae09b356390283331..47d396ef76a742e2d198c00e511fd81efd7bf72b 100644 --- a/build/core/gn/BUILD.gn +++ b/build/core/gn/BUILD.gn @@ -79,7 +79,7 @@ group("runtime_core") { group("static_core") { deps = [ "$ark_root/static_core/assembler:libarktsassembler", - "$ark_root/static_core/bytecode_optimizer:libarktsbytecodeopt", + "$ark_root/static_core/compiler:libarktscompiler", "$ark_root/static_core/libpandabase:libarktsbase", "$ark_root/static_core/libpandafile:libarktsfile", ] diff --git a/build/prebuilts_download/prebuilts_download_config.json b/build/prebuilts_download/prebuilts_download_config.json index f427f90ed81e003c60e17876d9db9d6fbd184007..744cb72d4b82ab5ea296f3469b27269514065b75 100644 --- a/build/prebuilts_download/prebuilts_download_config.json +++ b/build/prebuilts_download/prebuilts_download_config.json @@ -48,6 +48,28 @@ "unzip_filename": "llvm" } ] + }, + "aarch64": { + "copy_config": [ + { + "unzip_dir": "prebuilts/build-tools/linux-aarch64/bin", + "unzip_filename": "gn" + }, + { + "unzip_dir": "prebuilts/build-tools/linux-aarch64/bin", + "unzip_filename": "ninja" + }, + { + "unzip_dir": "prebuilts/ark_tools", + "unzip_filename": "ark_js_prebuilts" + } + ], + "linux_copy_config": [ + { + "unzip_dir": "prebuilts/clang/ohos/linux-aarch64", + "unzip_filename": "llvm" + } + ] } }, "darwin": { diff --git a/build/templates/cxx/external_deps_handler.py b/build/templates/cxx/external_deps_handler.py index 82107af743099cb05a511846ed371f86396e46bf..6577eae412e82b24e3c19ddb805c5935f8824279 100755 --- a/build/templates/cxx/external_deps_handler.py +++ b/build/templates/cxx/external_deps_handler.py @@ -139,6 +139,11 @@ def main(): "json/dummy_bundle.json".format(args.root_src_dir)) target_name = dep.split(":")[1] deps.append(get_full_path_from_target_name(config_info, target_name)) + elif dep.startswith("protobuf"): + config_info = read_json_file("{}arkcompiler/toolchain/build/third_party_gn/" \ + "protobuf/dummy_bundle.json".format(args.root_src_dir)) + target_name = dep.split(":")[1] + deps.append(get_full_path_from_target_name(config_info, target_name)) else: print("Component in which the external_dep defined is ommited in the logic of {}!".format(__file__)) sys.exit(1) diff --git a/build/test.gni b/build/test.gni index 499f070a6a5d23b7af6bbe704cf21f901e72bbaa..85e6055279894f4e1fb50c3094ffd82ad478b89f 100644 --- a/build/test.gni +++ b/build/test.gni @@ -75,7 +75,14 @@ template("ohos_unittest") { deps += invoker.deps } - deps += - [ "//arkcompiler/toolchain/build/third_party_gn/googletest:gtest_main" ] + # Add static link library judgment logic below + + if (defined(invoker.rtti_compile_flag) && invoker.rtti_compile_flag) { + deps += [ "//arkcompiler/toolchain/build/third_party_gn/googletest:gtest_rtti_main" ] + } else { + deps += [ + "//arkcompiler/toolchain/build/third_party_gn/googletest:gtest_main", + ] + } } } diff --git a/build/third_party_gn/bounds_checking_function/BUILD.gn b/build/third_party_gn/bounds_checking_function/BUILD.gn index bdf5b5648ed6b37c1d4963d3f846a87be1308a5e..24013d17b359367f79ee4ec39308a9376702325b 100644 --- a/build/third_party_gn/bounds_checking_function/BUILD.gn +++ b/build/third_party_gn/bounds_checking_function/BUILD.gn @@ -39,7 +39,7 @@ SEC_SHARED_PART_NAME = "bounds_checking_function" ohos_shared_library("libsec_shared") { stack_protector_ret = false sources = libsec_sources - all_dependent_configs = [ ":libsec_public_config" ] + public_configs = [ ":libsec_public_config" ] cflags = [ "-D_INC_STRING_S", "-D_INC_WCHAR_S", diff --git a/build/third_party_gn/googletest/BUILD.gn b/build/third_party_gn/googletest/BUILD.gn index 04449d71e8dc6af55c9c70e0bf9c660d362fcd80..af3d901136d449a6eefd2559fde3571f0f1b0ac4 100644 --- a/build/third_party_gn/googletest/BUILD.gn +++ b/build/third_party_gn/googletest/BUILD.gn @@ -21,7 +21,7 @@ config("gtest_private_config") { config("gtest_private_config_rtti") { visibility = [ ":*" ] - include_dirs = [ "googletest" ] + include_dirs = [ "$googletest_dir" ] cflags = [ "-frtti" ] cflags_objcc = [ "-frtti" ] cflags_cc = [ "-frtti" ] @@ -36,7 +36,7 @@ config("gtest_config") { "-Wno-reorder-init-list", ] if (is_mingw) { - cflags_cc = [ + cflags_cc += [ "-Wno-unused-const-variable", "-Wno-unused-private-field", ] @@ -111,6 +111,12 @@ static_library("gtest_rtti") { configs += [ ":gtest_private_config_rtti" ] } +static_library("gtest_rtti_main") { # ADD + testonly = true + sources = [ "$googletest_dir/src/gtest_main.cc" ] + public_deps = [ ":gtest_rtti" ] +} + static_library("gtest_main") { testonly = true sources = [ "$googletest_dir/src/gtest_main.cc" ] diff --git a/build/third_party_gn/protobuf/BUILD.gn b/build/third_party_gn/protobuf/BUILD.gn index 60a1daf3b562517b97fcf6d4ed6e2916e55d3200..754fca1096d8fad8f317805792d2a9ced5bfb334 100644 --- a/build/third_party_gn/protobuf/BUILD.gn +++ b/build/third_party_gn/protobuf/BUILD.gn @@ -19,7 +19,7 @@ THIRDPARTY_PROTOBUF_PART_NAME = "protobuf" protobuf_src_root = "//third_party/protobuf/src" config("protobuf_config") { - include_dirs = [ "protobuf_src_root" ] + include_dirs = [ "$protobuf_src_root" ] } ohos_shared_library("protobuf_lite") { diff --git a/build/third_party_gn/protobuf/dummy_bundle.json b/build/third_party_gn/protobuf/dummy_bundle.json new file mode 100644 index 0000000000000000000000000000000000000000..153353bc094c2920894707148377171c99b32501 --- /dev/null +++ b/build/third_party_gn/protobuf/dummy_bundle.json @@ -0,0 +1,22 @@ +{ + "component": { + "build": { + "inner_kits": [ + { + "header": { + "header_base": "//third_party/protobuf/src/google/protobuf", + "header_files": [] + }, + "name": "//arkcompiler/toolchain/build/third_party_gn/protobuf:protobuf_lite_static" + }, + { + "header": { + "header_base": "//third_party/protobuf/src/google/protobuf", + "header_files": [] + }, + "name": "//arkcompiler/toolchain/build/third_party_gn/protobuf:protobuf_static" + } + ] + } + } +} \ No newline at end of file diff --git a/inspector/connect_inspector.cpp b/inspector/connect_inspector.cpp index fd427d309c7f6b9d894f517b66dcf12366f7be17..050ebbba12fcf95ce2094e1b76508d1c4be66938 100644 --- a/inspector/connect_inspector.cpp +++ b/inspector/connect_inspector.cpp @@ -174,12 +174,16 @@ void ResetService() } } -void StartServerForSocketPair(int socketfd) +bool StartServerForSocketPair(int socketfd) { LOGI("StartServerForSocketPair, socketfd = %{private}d", socketfd); if (g_inspector == nullptr) { g_inspector = std::make_unique(); } + if (g_inspector->connectServer_ != nullptr) { + LOGW("ConnectServer is not nullptr!"); + return true; + } g_inspector->connectServer_ = std::make_unique(socketfd, std::bind(&OnMessage, std::placeholders::_1)); @@ -188,8 +192,9 @@ void StartServerForSocketPair(int socketfd) static_cast(g_inspector->connectServer_.get())) != 0) { LOGE("pthread_create fail!"); ResetService(); - return; + return false; } + return true; } void StartServer(const std::string& componentName) diff --git a/inspector/connect_inspector.h b/inspector/connect_inspector.h index 2d0420a8dadf8afe1a6f687aef5dde960b9d23ac..acb9b62d7c1914ce6cc75f9148bf08a01fea521b 100644 --- a/inspector/connect_inspector.h +++ b/inspector/connect_inspector.h @@ -32,7 +32,7 @@ extern "C" { void StartServer(const std::string& componentName); // socketpair process. -void StartServerForSocketPair(int socketfd); +bool StartServerForSocketPair(int socketfd); void StopServer([[maybe_unused]] const std::string& componentName); diff --git a/inspector/inspector.cpp b/inspector/inspector.cpp index f684b793ff22778aa3e09e03e60d4c59c38525cb..030dbddecd2278b28dad8c3e41078af68d1ead0c 100644 --- a/inspector/inspector.cpp +++ b/inspector/inspector.cpp @@ -150,18 +150,15 @@ bool InitializeInspector( void* vm, const DebuggerPostTask& debuggerPostTask, const DebugInfo& debugInfo, int tidForSocketPair = 0) { std::unique_lock lock(g_mutex); - Inspector *newInspector = nullptr; auto iter = g_inspectors.find(vm); if (iter != g_inspectors.end()) { - newInspector = g_inspectors[vm]; - } else { - newInspector = new Inspector(); - if (!g_inspectors.emplace(vm, newInspector).second) { - delete newInspector; - return false; - } + LOGW("Inspector already exist!"); + return true; } + Inspector *newInspector = new Inspector(); + g_inspectors.emplace(vm, newInspector); + newInspector->tidForSocketPair_ = tidForSocketPair; newInspector->tid_ = pthread_self(); newInspector->vm_ = vm; diff --git a/inspector/test/connect_server_test.cpp b/inspector/test/connect_server_test.cpp index 7a2eb3dbd10cb7e22c3fd8a75970cdc130d9f842..a8540ac5a501f7b293a271fb0e7a2988edfdc424 100644 --- a/inspector/test/connect_server_test.cpp +++ b/inspector/test/connect_server_test.cpp @@ -131,7 +131,9 @@ HWTEST_F(ConnectServerTest, InspectorConnectTest, testing::ext::TestSize.Level0) #if defined(OHOS_PLATFORM) int appPid = getprocpid(); int oldProcessfd = -2; - StartServerForSocketPair(oldProcessfd); + ASSERT_TRUE(StartServerForSocketPair(oldProcessfd)); + // test ConnectServer is not nullptr + ASSERT_TRUE(StartServerForSocketPair(oldProcessfd)); StoreMessage(g_instanceId, HELLO_INSPECTOR_CLIENT); pid_t pid = fork(); if (pid == 0) { diff --git a/test/autotest/aw/__init__.py b/test/autotest/aw/__init__.py index 50005d3837a7d825fbbf51da0ade8abd2a31fb09..a8f80748600f12b82dc69637a245d712c1bccdba 100644 --- a/test/autotest/aw/__init__.py +++ b/test/autotest/aw/__init__.py @@ -24,7 +24,7 @@ from aw.taskpool import TaskPool from aw.cdp import debugger from aw.cdp import runtime from aw.cdp import heap_profiler -from aw.cdp import cpu_profiler +from aw.cdp import profiler communicate_with_debugger_server = Utils.communicate_with_debugger_server diff --git a/test/autotest/aw/api/debugger_api.py b/test/autotest/aw/api/debugger_api.py new file mode 100644 index 0000000000000000000000000000000000000000..f13d6f242c2d11be018e7c6d1e2a91e588745853 --- /dev/null +++ b/test/autotest/aw/api/debugger_api.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +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. + +Description: Python Debugger Domain Interfaces +""" + +import json +import logging + +from aw import communicate_with_debugger_server, Utils +from aw.cdp import debugger +from aw.types import ThreadConnectionInfo, ProtocolType +from aw.api.protocol_api import ProtocolImpl + + +class DebuggerImpl(ProtocolImpl): + + def __init__(self, id_generator, websocket): + super().__init__(id_generator, websocket) + self.dispatch_table = {"enable": (self.enable, ProtocolType.send), + "disable": (self.disable, ProtocolType.send), + "resume": (self.resume, ProtocolType.send), + "pause": (self.pause, ProtocolType.send), + "removeBreakpointsByUrl": (self.remove_breakpoints_by_url, ProtocolType.send), + "getPossibleAndSetBreakpointsByUrl": (self.get_possible_and_set_breakpoints_by_url, + ProtocolType.send), + "stepOver": (self.step_over, ProtocolType.send), + "stepInto": (self.step_into, ProtocolType.send), + "stepOut": (self.step_out, ProtocolType.send), + "setPauseOnExceptions": (self.set_pause_on_exceptions, ProtocolType.send), + "evaluateOnCallFrame": (self.evaluate_on_call_frame, ProtocolType.send), + "smartStepInto": (self.smart_step_into, ProtocolType.send), + "setMixedDebugEnabled": (self.set_mixed_debug_enabled, ProtocolType.send), + "replyNativeCalling": (self.reply_native_calling, ProtocolType.send), + "dropFrame": (self.drop_frame, ProtocolType.send), + "scriptParsed": (self.script_parsed, ProtocolType.recv), + "paused": (self.paused, ProtocolType.recv), + "nativeCalling": (self.native_calling, ProtocolType.recv)} + + async def connect_to_debugger_server(self, pid, is_main=True): + if is_main: + send_msg = {"type": "connected"} + await self.websocket.send_msg_to_connect_server(send_msg) + response = await self.websocket.recv_msg_of_connect_server() + response = json.loads(response) + assert response['type'] == 'addInstance' + assert response['instanceId'] == 0, logging.error('InstanceId of the main thread is not 0') + assert response['tid'] == pid + else: + response = await self.websocket.recv_msg_of_connect_server() + response = json.loads(response) + assert response['type'] == 'addInstance' + assert response['instanceId'] != 0 + assert response['tid'] != pid + assert 'workerThread_' in response['name'] + instance_id = await self.websocket.get_instance() + send_queue = self.websocket.to_send_msg_queues[instance_id] + recv_queue = self.websocket.received_msg_queues[instance_id] + connection = ThreadConnectionInfo(instance_id, send_queue, recv_queue) + return connection + + async def destroy_instance(self): + response = await self.websocket.recv_msg_of_connect_server() + response = json.loads(response) + assert response['type'] == 'destroyInstance' + return response + + async def enable(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.enable(), message_id) + while response.startswith('{"method":"Debugger.scriptParsed"'): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {"debuggerId": "0", "protocols": Utils.get_custom_protocols()}} + + async def disable(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.disable(), message_id) + while response.startswith('{"method":"Debugger.resumed"') or \ + response.startswith('{"method":"HeapProfiler.lastSeenObjectId"') or \ + response.startswith('{"method":"HeapProfiler.heapStatsUpdate"'): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def script_parsed(self, connection, params): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + return response + + async def paused(self, connection, params): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response['method'] == 'Debugger.paused' + return response + + async def resume(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.resume(), message_id) + assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def remove_breakpoints_by_url(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.remove_breakpoints_by_url(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def get_possible_and_set_breakpoints_by_url(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.get_possible_and_set_breakpoint_by_url(params), + message_id) + response = json.loads(response) + assert response['id'] == message_id + return response + + async def step_over(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.step_over(), message_id) + assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def step_out(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.step_out(), message_id) + assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def step_into(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.step_into(), message_id) + assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def set_pause_on_exceptions(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.set_pause_on_exceptions(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def evaluate_on_call_frame(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.evaluate_on_call_frame(params), message_id) + response = json.loads(response) + assert response['id'] == message_id + return response + + async def pause(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.pause(), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def smart_step_into(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.smart_step_into(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def set_mixed_debug_enabled(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.set_mixed_debug_enabled(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def native_calling(self, connection, params): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response['method'] == 'Debugger.nativeCalling' + return response + + async def reply_native_calling(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.reply_native_calling(params), message_id) + assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def drop_frame(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + debugger.drop_frame(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response \ No newline at end of file diff --git a/test/autotest/aw/api/heap_profiler_api.py b/test/autotest/aw/api/heap_profiler_api.py new file mode 100644 index 0000000000000000000000000000000000000000..799ea92198fa4be4fbdd8a0997319f5a1b22a59d --- /dev/null +++ b/test/autotest/aw/api/heap_profiler_api.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +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. + +Description: Python HeapProfiler Domain Interfaces +""" + +import json + +from aw import communicate_with_debugger_server +from aw.cdp import heap_profiler +from aw.types import ProtocolType +from aw.api.protocol_api import ProtocolImpl + + +class HeapProfilerImpl(ProtocolImpl): + + def __init__(self, id_generator, websocket): + super().__init__(id_generator, websocket) + self.dispatch_table = {"startTrackingHeapObjects": (self.start_tracking_heap_objects, ProtocolType.send), + "stopTrackingHeapObjects": (self.stop_tracking_heap_objects, ProtocolType.send), + "takeHeapSnapshot": (self.take_heap_snapshot, ProtocolType.send)} + + async def start_tracking_heap_objects(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + heap_profiler.start_tracking_heap_objects(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def stop_tracking_heap_objects(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + heap_profiler.stop_tracking_heap_objects(), message_id) + while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response + pre_response = response + while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"') or \ + response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): + if response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): + pre_response = response + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + assert pre_response.endswith(r'\n]\n}\n"}}') + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def take_heap_snapshot(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + heap_profiler.take_heap_snapshot(), message_id) + assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response + pre_response = response + while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): + pre_response = response + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + assert pre_response.endswith(r'\n]\n}\n"}}') + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response \ No newline at end of file diff --git a/test/autotest/aw/api/profiler_api.py b/test/autotest/aw/api/profiler_api.py new file mode 100644 index 0000000000000000000000000000000000000000..99d6c11173fa80864104dbb414e8f303cb64d55e --- /dev/null +++ b/test/autotest/aw/api/profiler_api.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +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. + +Description: Python Profiler Domain Interfaces +""" + +import json + +from aw import communicate_with_debugger_server +from aw.cdp import profiler +from aw.types import ProtocolType +from aw.api.protocol_api import ProtocolImpl + + +class ProfilerImpl(ProtocolImpl): + + def __init__(self, id_generator, websocket): + super().__init__(id_generator, websocket) + self.dispatch_table = {"start": (self.start, ProtocolType.send), + "stop": (self.stop, ProtocolType.send), + "setSamplingInterval": (self.set_sampling_interval, ProtocolType.send)} + + async def start(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + profiler.start(), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def stop(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + profiler.stop(), message_id) + response = json.loads(response) + assert response['id'] == message_id + assert all(i >= 0 for i in response['result']['profile']['timeDeltas']) + return response + + async def set_sampling_interval(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + profiler.set_sampling_interval(params), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response \ No newline at end of file diff --git a/test/autotest/aw/api/protocol_api.py b/test/autotest/aw/api/protocol_api.py new file mode 100644 index 0000000000000000000000000000000000000000..bf4ca9c3696a2d383fb76d75246cc0cf79d6a0c6 --- /dev/null +++ b/test/autotest/aw/api/protocol_api.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +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. + +Description: Python Protocol Domain Interfaces +""" + +from aw.types import ProtocolType + + +class ProtocolImpl(object): + + def __init__(self, id_generator, websocket): + self.id_generator = id_generator + self.class_name = self.__class__.__name__ + self.domain = self.class_name[:-4] + self.dispatch_table = {} + self.websocket = websocket + + async def send(self, protocol_name, connection, params=None): + protocol = self._check_and_parse_protocol(protocol_name) + if self.dispatch_table.get(protocol) is not None: + if self.dispatch_table.get(protocol)[1] != ProtocolType.send: + raise AssertionError("{} send ProtocolType inconsistent: Protocol {}, calling {}, should be {}" + .format(self.class_name, protocol_name, "send", + self.dispatch_table.get(protocol)[1])) + message_id = next(self.id_generator) + return await self.dispatch_table.get(protocol)[0](message_id, connection, params) + + async def recv(self, protocol_name, connection, params=None): + protocol = self._check_and_parse_protocol(protocol_name) + if self.dispatch_table.get(protocol) is not None: + if self.dispatch_table.get(protocol)[1] != ProtocolType.recv: + raise AssertionError("{} recv ProtocolType inconsistent: Protocol {}, calling {}, should be {}" + .format(self.class_name, protocol_name, "recv", + self.dispatch_table.get(protocol)[1])) + return await self.dispatch_table.get(protocol)[0](connection, params) + + def _check_and_parse_protocol(self, protocol_name): + res = protocol_name.split('.') + if len(res) != 2: + raise AssertionError("{} parse protocol name error: protocol_name {} is invalid" + .format(self.class_name, protocol_name)) + domain, protocol = res[0], res[1] + if domain != self.domain: + raise AssertionError("{} parse protocol name error: protocol_name {} has the wrong domain" + .format(self.class_name, protocol_name)) + if protocol not in self.dispatch_table: + raise AssertionError("{} parse protocol name error: protocol_name {} has not been defined" + .format(self.class_name, protocol_name)) + return protocol \ No newline at end of file diff --git a/test/autotest/aw/api/runtime_api.py b/test/autotest/aw/api/runtime_api.py new file mode 100644 index 0000000000000000000000000000000000000000..d74ec27b4cc65a8a1429948513ce298195c02b79 --- /dev/null +++ b/test/autotest/aw/api/runtime_api.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +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. + +Description: Python Runtime Domain Interfaces +""" + +import json + +from aw import communicate_with_debugger_server +from aw.cdp import runtime +from aw.types import ProtocolType +from aw.api.protocol_api import ProtocolImpl + + +class RuntimeImpl(ProtocolImpl): + + def __init__(self, id_generator, websocket): + super().__init__(id_generator, websocket) + self.dispatch_table = {"enable": (self.enable, ProtocolType.send), + "runIfWaitingForDebugger": (self.run_if_waiting_for_debugger, ProtocolType.send), + "getProperties": (self.get_properties, ProtocolType.send), + "getHeapUsage": (self.get_heap_usage, ProtocolType.send)} + + async def enable(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + runtime.enable(), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {"protocols": []}} + return response + + async def run_if_waiting_for_debugger(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + runtime.run_if_waiting_for_debugger(), message_id) + response = json.loads(response) + assert response == {"id": message_id, "result": {}} + return response + + async def get_properties(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + runtime.get_properties(params), message_id) + response = json.loads(response) + assert response["id"] == message_id + return response + + async def get_heap_usage(self, message_id, connection, params): + response = await communicate_with_debugger_server(connection.instance_id, + connection.send_msg_queue, + connection.received_msg_queue, + runtime.get_heap_usage(), message_id) + while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"') or \ + response.startswith('{"method":"HeapProfiler.heapStatsUpdate"'): + response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, + connection.received_msg_queue) + response = json.loads(response) + assert response["id"] == message_id + assert response['result']['usedSize'] > 0 + assert response['result']['totalSize'] > 0 + return response \ No newline at end of file diff --git a/test/autotest/aw/cdp/debugger.py b/test/autotest/aw/cdp/debugger.py index 470d0f96fe7ac2dc643802da17bb786a3cb44048..c1aa3466ce44165e4548aec5c62424c8bda9d102 100644 --- a/test/autotest/aw/cdp/debugger.py +++ b/test/autotest/aw/cdp/debugger.py @@ -17,27 +17,78 @@ limitations under the License. Description: Python CDP Debugger. """ -from dataclasses import dataclass +from dataclasses import dataclass, field +from enum import Enum from typing import Optional, List +@dataclass +class DropFrameParams: + dropped_depth: int = 1 + + +@dataclass +class ReplyNativeCallingParams: + user_code: bool = True + + +@dataclass +class SetMixedDebugEnabledParams: + enabled: bool + mixed_stack_enabled: bool + + +@dataclass +class SmartStepIntoParams: + url: str + line_number: int + + +@dataclass +class PauseOnExceptionsState(Enum): + ALL = 'all' + NONE = 'none' + CAUGHT = 'caught' + UNCAUGHT = 'uncaught' + + +@dataclass +class EvaluateOnCallFrameParams: + expression: str + call_frame_id: int = 0 + object_group: str = "console" + include_command_line_api: bool = True + silent: bool = True + + @dataclass class BreakLocationUrl: url: str line_number: int column_number: Optional[int] = 0 + condition: Optional[str] = None def to_json(self): json = {'url': self.url, 'lineNumber': self.line_number, 'columnNumber': self.column_number} + if self.condition is not None: + json['condition'] = self.condition return json -def enable(max_scripts_cache_size: Optional[float] = None): +@dataclass +class RemoveBreakpointsUrl: + url: str = "" + + +@dataclass +class SetBreakpointsLocations: + locations: list = field(default_factory=list) + + +def enable(): command = {'method': 'Debugger.enable'} - if max_scripts_cache_size: - command['params'] = {'maxScriptsCacheSize': max_scripts_cache_size} return command @@ -46,18 +97,18 @@ def resume(): return command -def remove_breakpoints_by_url(url: str): +def remove_breakpoints_by_url(params: RemoveBreakpointsUrl): command = {'method': 'Debugger.removeBreakpointsByUrl', - 'params': {'url': url}} + 'params': {'url': params.url}} return command -def get_possible_and_set_breakpoint_by_url(locations: List[BreakLocationUrl]): - params = {'locations': []} - for location in locations: - params['locations'].append(location.to_json()) +def get_possible_and_set_breakpoint_by_url(params: SetBreakpointsLocations): + locations = [] + for location in params.locations: + locations.append(location.to_json()) command = {'method': 'Debugger.getPossibleAndSetBreakpointByUrl', - 'params': params} + 'params': {'locations': locations}} return command @@ -78,4 +129,50 @@ def step_out(): def disable(): command = {'method': 'Debugger.disable'} + return command + + +def set_pause_on_exceptions(params: PauseOnExceptionsState): + command = {'method': 'Debugger.setPauseOnExceptions', + 'params': {'state': params.value}} + return command + + +def evaluate_on_call_frame(params: EvaluateOnCallFrameParams): + command = {'method': 'Debugger.evaluateOnCallFrame', + 'params': { + 'callFrameId': str(params.call_frame_id), + 'expression': params.expression, + 'includeCommandLineApi': params.include_command_line_api, + 'objectGroup': params.object_group, + 'silent': params.silent}} + return command + + +def pause(): + command = {'method': 'Debugger.pause'} + return command + + +def set_mixed_debug_enabled(params: SetMixedDebugEnabledParams): + command = {'method': 'Debugger.setMixedDebugEnabled', + 'params': {'enabled': params.enabled, 'mixedStackEnabled': params.mixed_stack_enabled}} + return command + + +def reply_native_calling(params: ReplyNativeCallingParams): + command = {'method': 'Debugger.replyNativeCalling', + 'params': {'userCode': params.user_code}} + return command + + +def drop_frame(params: DropFrameParams): + command = {'method': 'Debugger.dropFrame', + 'params': {'droppedDepth': params.dropped_depth}} + return command + + +def smart_step_into(params: SmartStepIntoParams): + command = {'method': 'Debugger.smartStepInto', + 'params': {'url': params.url, 'lineNumber': params.line_number}} return command \ No newline at end of file diff --git a/test/autotest/aw/cdp/heap_profiler.py b/test/autotest/aw/cdp/heap_profiler.py index 59743356be8981a598bc4fd71d86995a94190745..e2abc00d4b23335d269df1fe3986f57385f5df37 100644 --- a/test/autotest/aw/cdp/heap_profiler.py +++ b/test/autotest/aw/cdp/heap_profiler.py @@ -16,7 +16,13 @@ limitations under the License. Description: Python CDP Heap Profiler. """ -import typing + +from dataclasses import dataclass + + +@dataclass +class TrackingHeapObjectsParams: + track_allocations: bool def enable(): @@ -27,11 +33,9 @@ def disable(): return {'method': 'HeapProfiler.disable'} -def start_tracking_heap_objects(track_allocations: typing.Optional[bool] = None): - params = dict() - if track_allocations is not None: - params['trackAllocations'] = track_allocations - return {'method': 'HeapProfiler.startTrackingHeapObjects', 'params': params} +def start_tracking_heap_objects(params: TrackingHeapObjectsParams): + return {'method': 'HeapProfiler.startTrackingHeapObjects', + 'params': {'trackAllocations': params.track_allocations}} def stop_tracking_heap_objects(): diff --git a/test/autotest/aw/cdp/cpu_profiler.py b/test/autotest/aw/cdp/profiler.py similarity index 79% rename from test/autotest/aw/cdp/cpu_profiler.py rename to test/autotest/aw/cdp/profiler.py index 4e0be651cf9a39f84e840937e987c71f0dfe24fb..722da3332dc476ab908b82988d6882dbad1bf9fc 100644 --- a/test/autotest/aw/cdp/cpu_profiler.py +++ b/test/autotest/aw/cdp/profiler.py @@ -17,6 +17,13 @@ limitations under the License. Description: Python CDP CPU Profiler. """ +from dataclasses import dataclass + + +@dataclass +class SamplingInterval: + interval: int + def enable(): return {'method': 'Profiler.enable'} @@ -34,6 +41,6 @@ def stop(): return {'method': 'Profiler.stop'} -def set_sampling_interval(interval: int): +def set_sampling_interval(params: SamplingInterval): return {'method': 'Profiler.setSamplingInterval', - 'params': {'interval': interval}} \ No newline at end of file + 'params': {'interval': params.interval}} \ No newline at end of file diff --git a/test/autotest/aw/cdp/runtime.py b/test/autotest/aw/cdp/runtime.py index 37f072de8a2ed6a51c5bafb31a817ea82615cd68..efaf916d9508d048f77d1334ce252de77c45d974 100644 --- a/test/autotest/aw/cdp/runtime.py +++ b/test/autotest/aw/cdp/runtime.py @@ -17,9 +17,19 @@ limitations under the License. Description: Python CDP Runtime. """ +from dataclasses import dataclass from typing import Optional +@dataclass +class GetPropertiesParams: + object_id: str = "" + own_properties: bool = True + accessor_properties_only: bool = False + generate_preview: bool = True + non_indexed_properties_only: Optional[bool] = None + + def enable(): command = {'method': 'Runtime.enable'} return command @@ -30,22 +40,14 @@ def run_if_waiting_for_debugger(): return command -def get_properties(object_id: str, - own_properties: Optional[bool] = None, - accessor_properties_only: Optional[bool] = None, - generate_preview: Optional[bool] = None, - non_indexed_properties_only: Optional[bool] = None): - command = {'method': 'Runtime.getProperties'} - params = {'objectId': object_id} - if own_properties is not None: - params['ownProperties'] = own_properties - if accessor_properties_only is not None: - params['accessorPropertiesOnly'] = accessor_properties_only - if generate_preview is not None: - params['generatePreview'] = generate_preview - if non_indexed_properties_only is not None: - params['nonIndexedPropertiesOnly'] = non_indexed_properties_only - command['params'] = params +def get_properties(params: GetPropertiesParams): + command = {'method': 'Runtime.getProperties', + 'params': {'objectId': params.object_id, + 'ownProperties': params.own_properties, + 'accessorPropertiesOnly': params.accessor_properties_only, + 'generatePreview': params.generate_preview}} + if params.non_indexed_properties_only is not None: + command['params']['nonIndexedPropertiesOnly'] = params.non_indexed_properties_only return command diff --git a/test/autotest/aw/fport.py b/test/autotest/aw/fport.py index 7bc2dcd141c36ae5ae58f41bb61442bf56fc0a08..484ba2cd4b07a2587e7d8f2f72fd7812aee677ad 100644 --- a/test/autotest/aw/fport.py +++ b/test/autotest/aw/fport.py @@ -22,24 +22,39 @@ import subprocess class Fport(object): + retry_times = 3 + increase_step = 7 + @classmethod def fport_connect_server(cls, port, pid, bundle_name): - cmd = ['hdc', 'fport', f'tcp:{port}', f'ark:{pid}@{bundle_name}'] - logging.info('fport connect server: ' + ' '.join(cmd)) - result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - logging.info(result.stdout.strip()) - assert result.stdout.decode('utf-8').strip() == 'Forwardport result:OK' + for _ in range(Fport.retry_times): + cmd = ['hdc', 'fport', f'tcp:{port}', f'ark:{pid}@{bundle_name}'] + logging.info('fport connect server: ' + ' '.join(cmd)) + result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + logging.info(result.stdout.strip()) + if 'TCP Port listen failed' not in result.stdout.decode('utf-8'): + assert result.stdout.decode('utf-8').strip() == 'Forwardport result:OK' + return port + else: # The port is occupied + port += Fport.increase_step + return -1 @classmethod def fport_debugger_server(cls, port, pid, tid=0): - if tid == 0: - cmd = ['hdc', 'fport', f'tcp:{port}', f'ark:{pid}@Debugger'] - else: - cmd = ['hdc', 'fport', f'tcp:{port}', f'ark:{pid}@{tid}@Debugger'] - logging.info('fport_debugger_server: ' + ' '.join(cmd)) - result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - logging.info(result.stdout.strip()) - assert result.stdout.decode('utf-8').strip() == 'Forwardport result:OK' + for _ in range(Fport.retry_times): + if tid == 0: + cmd = ['hdc', 'fport', f'tcp:{port}', f'ark:{pid}@Debugger'] + else: + cmd = ['hdc', 'fport', f'tcp:{port}', f'ark:{pid}@{tid}@Debugger'] + logging.info('fport_debugger_server: ' + ' '.join(cmd)) + result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + logging.info(result.stdout.strip()) + if 'TCP Port listen failed' not in result.stdout.decode('utf-8'): + assert result.stdout.decode('utf-8').strip() == 'Forwardport result:OK' + return port + else: # The port is occupied + port += Fport.increase_step + return -1 @classmethod def clear_fport(cls): diff --git a/test/autotest/aw/types.py b/test/autotest/aw/types.py new file mode 100644 index 0000000000000000000000000000000000000000..ca3464ad48abbe92511a8a6737bcf985f53f533c --- /dev/null +++ b/test/autotest/aw/types.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +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. + +Description: Data Transferring Classes & Types. +""" + +import asyncio +from dataclasses import dataclass +from enum import Enum + + +@dataclass(init=True) +class ThreadConnectionInfo: + instance_id: int + send_msg_queue: asyncio.Queue + received_msg_queue: asyncio.Queue + + +class ProtocolType(Enum): + send = "send", + recv = "recv" \ No newline at end of file diff --git a/test/autotest/aw/utils.py b/test/autotest/aw/utils.py index 3d08f29769b35efbc9bc70667a280473329258cf..3a35897728dea838a58689fb1cbb9d8f4a9c841c 100644 --- a/test/autotest/aw/utils.py +++ b/test/autotest/aw/utils.py @@ -45,8 +45,7 @@ class Utils(object): "setNativeRange", "resetSingleStepper", "callFunctionOn", - "smartStepInto", - "callFunctionOn"] + "smartStepInto"] return protocols @classmethod diff --git a/test/autotest/aw/websocket.py b/test/autotest/aw/websocket.py index 28d2bfecb9322ecbb5153253f7c45649b3d6fa6b..d2389914f918fe8f01088a9491257d03b410bef5 100644 --- a/test/autotest/aw/websocket.py +++ b/test/autotest/aw/websocket.py @@ -90,7 +90,7 @@ class WebSocket(object): logging.info(f'[==>] Connect server send message: {message}') return True - async def main_task(self, taskpool, websocket, procedure, pid): + async def main_task(self, taskpool, procedure, pid): # the async queue must be initialized in task self.to_send_msg_queue_for_connect_server = asyncio.Queue() self.received_msg_queue_for_connect_server = asyncio.Queue() @@ -101,7 +101,7 @@ class WebSocket(object): taskpool.submit(self._receiver_of_connect_server(connect_server_client, self.received_msg_queue_for_connect_server, taskpool, pid)) - taskpool.submit(procedure(websocket)) + taskpool.submit(procedure(self)) def _connect_connect_server(self): client = connect(f'ws://localhost:{self.connect_server_port}', @@ -131,7 +131,10 @@ class WebSocket(object): num_debugger_server_client < self.debugger_server_connection_threshold): instance_id = response['instanceId'] - Fport.fport_debugger_server(self.debugger_server_port, pid, instance_id) + port = Fport.fport_debugger_server(self.debugger_server_port, pid, instance_id) + assert port > 0, logging.error('Failed to fport debugger server for 3 times, ' + 'the port is very likely occupied') + self.debugger_server_port = port debugger_server_client = await self._connect_debugger_server() logging.info(f'InstanceId: {instance_id}, port: {self.debugger_server_port}, ' f'debugger server connected') diff --git a/test/autotest/pytest.ini b/test/autotest/pytest.ini index 6b882901a00109e30b8cc6241098ad146c17a312..76ad9fd0eb22e74fdba85c8d67a4f1fe3a8893cd 100644 --- a/test/autotest/pytest.ini +++ b/test/autotest/pytest.ini @@ -3,7 +3,7 @@ log_cli = true log_level = info -log_format = [+] %(asctime)s - %(filename)s - [line:%(lineno)d] - %(levelname)s: %(message)s +log_format = [+] %(asctime)s - %(filename)s - [line:%(lineno)d] - %(levelname)s: %(message).1024s log_date_format = %Y-%m-%d %H:%M:%S markers = diff --git a/test/autotest/run.py b/test/autotest/run.py index b45b2c88b4f5ca6cc5852b8aadc090a48670d5d9..da71942017ff30e0ea5d6485fd49d87f95cc6e2b 100644 --- a/test/autotest/run.py +++ b/test/autotest/run.py @@ -50,8 +50,19 @@ def install_requirements(requirements_file=r'.\requirements.txt'): sys.exit(1) +def clear_log_handler(): + # remove all old handlers of the root logger + log = logging.getLogger() + for handler in log.handlers[:]: + log.removeHandler(handler) + + if __name__ == '__main__': check_python_version() install_requirements() - pytest.main() + clear_log_handler() + + args = sys.argv[1:] + + pytest.main(args) diff --git a/test/autotest/scenario_test/conftest.py b/test/autotest/scenario_test/conftest.py index 98822b5ffeaa5ca94111ca29ee3c6df5d94c9f3f..e2af6eee1f53952bd12a07d7b6d3964fb7b970e8 100644 --- a/test/autotest/scenario_test/conftest.py +++ b/test/autotest/scenario_test/conftest.py @@ -139,7 +139,12 @@ def launch_hap(config): config['pid'] = pid Fport.clear_fport() - Fport.fport_connect_server(config['connect_server_port'], config['pid'], config['bundle_name']) + connect_server_port = Fport.fport_connect_server(config['connect_server_port'], + config['pid'], + config['bundle_name']) + assert connect_server_port > 0, logging.error('Failed to fport connect server for 3 times, ' + 'the port is very likely occupied') + config['connect_server_port'] = connect_server_port config['websocket'] = WebSocket(config['connect_server_port'], config['debugger_server_port']) config['taskpool'] = TaskPool() \ No newline at end of file diff --git a/test/autotest/scenario_test/test_cpu_profiler_01.py b/test/autotest/scenario_test/test_cpu_profiler_01.py index 0161f3e8a3ec0811f540724b312617d2fd1fb17a..0dd15805d90b8b5539127f01cc4d2457e209edc4 100644 --- a/test/autotest/scenario_test/test_cpu_profiler_01.py +++ b/test/autotest/scenario_test/test_cpu_profiler_01.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,8 @@ import pytest from aw import Utils from aw import Application -from aw import communicate_with_debugger_server -from aw import runtime, debugger, cpu_profiler +from aw import profiler +from aw.api import debugger_api, runtime_api, profiler_api @pytest.mark.cpu_profiler @@ -79,8 +78,11 @@ class TestCpuProfiler01: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) + self.profiler_impl = profiler_api.ProfilerImpl(self.id_generator, websocket) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -90,112 +92,53 @@ class TestCpuProfiler01: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - workers_num = 2 - worker_instances_id = [] - worker_thread_to_send_queues = [] - worker_thread_received_queues = [] - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # main thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # main thread: Profiler.setSamplingInterval ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - cpu_profiler.set_sampling_interval(500), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = profiler.SamplingInterval(500) + await self.profiler_impl.send("Profiler.setSamplingInterval", main_thread, params) ################################################################################################################ # worker thread: Profiler.setSamplingInterval ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - cpu_profiler.set_sampling_interval(500), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = profiler.SamplingInterval(500) + await self.profiler_impl.send("Profiler.setSamplingInterval", worker_thread_1, params) + await self.profiler_impl.send("Profiler.setSamplingInterval", worker_thread_2, params) ################################################################################################################ # main thread: Profiler.start ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - cpu_profiler.start(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.profiler_impl.send("Profiler.start", main_thread) ################################################################################################################ # worker thread: Profiler.start ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - cpu_profiler.start(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.profiler_impl.send("Profiler.start", worker_thread_1) + await self.profiler_impl.send("Profiler.start", worker_thread_2) ################################################################################################################ # main thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.disable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.disable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_1) + await self.debugger_impl.send("Debugger.disable", worker_thread_2) ################################################################################################################ # all thread: sleep 10 seconds ################################################################################################################ @@ -203,35 +146,17 @@ class TestCpuProfiler01: ################################################################################################################ # main thread: Profiler.stop ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - cpu_profiler.stop(), message_id) - response = json.loads(response) - assert response['id'] == message_id - assert all(i >= 0 for i in response['result']['profile']['timeDeltas']) + await self.profiler_impl.send("Profiler.stop", main_thread) ################################################################################################################ # worker thread: Profiler.stop ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - cpu_profiler.stop(), message_id) - response = json.loads(response) - assert response['id'] == message_id - assert all(i >= 0 for i in response['result']['profile']['timeDeltas']) - ################################################################################################################ - # worker thread: destroy instance - ################################################################################################################ - for i in range(workers_num): - await websocket.send_msg_to_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], 'close') + await self.profiler_impl.send("Profiler.stop", worker_thread_1) + await self.profiler_impl.send("Profiler.stop", worker_thread_2) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread_1.instance_id, worker_thread_1.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread_2.instance_id, worker_thread_2.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_cpu_profiler_02.py b/test/autotest/scenario_test/test_cpu_profiler_02.py index 48b67c284c5726fc158eb66afa72e44c99066b6a..15cfbd5c950d467a6a8bb017092a3853d5228aef 100644 --- a/test/autotest/scenario_test/test_cpu_profiler_02.py +++ b/test/autotest/scenario_test/test_cpu_profiler_02.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,8 @@ import pytest from aw import Utils from aw import Application -from aw import communicate_with_debugger_server -from aw import runtime, debugger, cpu_profiler +from aw import profiler +from aw.api import debugger_api, runtime_api, profiler_api @pytest.mark.cpu_profiler @@ -81,8 +80,11 @@ class TestCpuProfiler02: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) + self.profiler_impl = profiler_api.ProfilerImpl(self.id_generator, websocket) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -92,76 +94,36 @@ class TestCpuProfiler02: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - workers_num = 2 - worker_instances_id = [] - worker_thread_to_send_queues = [] - worker_thread_received_queues = [] - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # worker thread: Profiler.setSamplingInterval ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - cpu_profiler.set_sampling_interval(500), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = profiler.SamplingInterval(500) + await self.profiler_impl.send("Profiler.setSamplingInterval", worker_thread_1, params) + await self.profiler_impl.send("Profiler.setSamplingInterval", worker_thread_2, params) ################################################################################################################ # worker thread: Profiler.start ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - cpu_profiler.start(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.profiler_impl.send("Profiler.start", worker_thread_1) + await self.profiler_impl.send("Profiler.start", worker_thread_2) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.disable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_1) + await self.debugger_impl.send("Debugger.disable", worker_thread_2) ################################################################################################################ # all thread: sleep 10 seconds ################################################################################################################ @@ -169,35 +131,17 @@ class TestCpuProfiler02: ################################################################################################################ # worker thread: Profiler.stop ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - cpu_profiler.stop(), message_id) - response = json.loads(response) - assert response['id'] == message_id - assert all(i >= 0 for i in response['result']['profile']['timeDeltas']) - ################################################################################################################ - # worker thread: destroy instance - ################################################################################################################ - for i in range(workers_num): - await websocket.send_msg_to_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], 'close') - ################################################################################################################ - # main thread: Profiler.stop - ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - cpu_profiler.stop(), message_id) - response = json.loads(response) - assert response['id'] == message_id - assert all(i >= 0 for i in response['result']['profile']['timeDeltas']) + await self.profiler_impl.send("Profiler.stop", worker_thread_1) + await self.profiler_impl.send("Profiler.stop", worker_thread_2) + ################################################################################################################ + # main thread: Profiler.stop + ################################################################################################################ + await self.profiler_impl.send("Profiler.stop", main_thread) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread_1.instance_id, worker_thread_1.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread_2.instance_id, worker_thread_2.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_debug_01.py b/test/autotest/scenario_test/test_debug_01.py index 780ef6eb6e091110442434510f9b511bd2c4cffd..c2892df9d66376c1b331f5b203be20656feda37e 100644 --- a/test/autotest/scenario_test/test_debug_01.py +++ b/test/autotest/scenario_test/test_debug_01.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,8 @@ import pytest from aw import Application from aw import Utils -from aw import communicate_with_debugger_server from aw import debugger, runtime +from aw.api import debugger_api, runtime_api @pytest.mark.debug @@ -92,8 +91,10 @@ class TestDebug01: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -103,289 +104,151 @@ class TestDebug01: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # main thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # main thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", main_thread) ################################################################################################################ # main thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) ################################################################################################################ # main thread: Debugger.scriptParsed ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) assert response['params']['url'] == self.config['file_path']['entry_ability'] assert response['params']['endLine'] == 0 ################################################################################################################ # main thread: Debugger.paused ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['entry_ability'] assert response['params']['reason'] == 'Break on start' ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # main thread: Debugger.scriptParsed ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) assert response['params']['url'] == self.config['file_path']['index'] assert response['params']['endLine'] == 0 ################################################################################################################ # main thread: Debugger.paused ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'Break on start' ################################################################################################################ # main thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.remove_breakpoints_by_url( - self.config['file_path']['index']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) ################################################################################################################ # main thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=12), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=53), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=57)] - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + main_thread, params) assert response['result']['locations'][0]['id'] == 'id:12:0:' + self.config['file_path']['index'] assert response['result']['locations'][1]['id'] == 'id:53:0:' + self.config['file_path']['index'] assert response['result']['locations'][2]['id'] == 'id:57:0:' + self.config['file_path']['index'] ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # main thread: Debugger.paused, hit breakpoint ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:12:4:' + self.config['file_path']['index']] ################################################################################################################ # main thread: Debugger.stepOut ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.step_out(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + await self.debugger_impl.send("Debugger.stepOut", main_thread) + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:12:4:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - workers_num = 2 - worker_instances_id = [] - worker_thread_to_send_queues = [] - worker_thread_received_queues = [] - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}') ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # worker thread: Debugger.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", worker_thread_1) + await self.debugger_impl.send("Debugger.enable", worker_thread_2) ################################################################################################################ # worker thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} - # worker thread: Debugger.scriptParsed - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' - assert response['params']['url'] == self.config['file_path']['worker'] - assert response['params']['endLine'] == 0 - # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' - assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] - assert response['params']['reason'] == 'Break on start' + # worker thread 1: Runtime.runIfWaitingForDebugger + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_1) + # worker thread 1: Debugger.scriptParsed + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread_1) + assert response['params']['url'] == self.config['file_path']['worker'] + assert response['params']['endLine'] == 0 + # worker thread 1: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_1) + assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] + assert response['params']['reason'] == 'Break on start' + # worker thread 2: Runtime.runIfWaitingForDebugger + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_2) + # worker thread 2: Debugger.scriptParsed + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread_2) + assert response['params']['url'] == self.config['file_path']['worker'] + assert response['params']['endLine'] == 0 + # worker thread 2: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) + assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] + assert response['params']['reason'] == 'Break on start' ################################################################################################################ # worker thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.remove_breakpoints_by_url( - self.config['file_path']['worker']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_1, params) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_2, params) ################################################################################################################ # worker thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.get_possible_and_set_breakpoint_by_url( - locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id - assert response['result']['locations'][0]['id'] == 'id:11:0:' + self.config['file_path']['worker'] + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread_1, params) + assert response['result']['locations'][0]['id'] == 'id:11:0:' + self.config['file_path']['worker'] + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread_2, params) + assert response['result']['locations'][0]['id'] == 'id:11:0:' + self.config['file_path']['worker'] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread_1) + await self.debugger_impl.send("Debugger.resume", worker_thread_2) ################################################################################################################ # main thread: click on the screen ################################################################################################################ @@ -393,51 +256,25 @@ class TestDebug01: ################################################################################################################ # main thread: Debugger.paused, hit breakpoint ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:53:16:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: destroy instance ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'destroyInstance' - if response['instanceId'] == worker_instances_id[0]: - worker_instances_id[0] = worker_instances_id[1] - worker_thread_to_send_queues[0] = worker_thread_to_send_queues[1] - worker_thread_received_queues[0] = worker_thread_received_queues[1] + # worker thread 2 destroyed + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] == worker_thread_2.instance_id ################################################################################################################ # main thread: Debugger.stepInto ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.step_into(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response)['method'] == 'Debugger.paused' + await self.debugger_impl.send("Debugger.stepInto", main_thread) + await self.debugger_impl.recv("Debugger.paused", main_thread) ################################################################################################################ # main thread: Runtime.getProperties ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.get_properties(object_id='0', - own_properties=True, - accessor_properties_only=False, - generate_preview=True), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = runtime.GetPropertiesParams('0', True, False, True) + response = await self.runtime_impl.send("Runtime.getProperties", main_thread, params) assert response['result']['result'][0]['name'] == 'set message' assert response['result']['result'][0]['value']['type'] == 'function' assert response['result']['result'][1]['name'] == 'newValue' @@ -445,155 +282,74 @@ class TestDebug01: ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # main thread: Debugger.paused, hit breakpoint ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:57:20:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instances_id[1] = await websocket.get_instance() - worker_thread_to_send_queues[1] = websocket.to_send_msg_queues[worker_instances_id[1]] - worker_thread_received_queues[1] = websocket.received_msg_queues[worker_instances_id[1]] - logging.info(f'Connect to the debugger server of instance: {worker_instances_id[1]}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # worker thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", worker_thread_2) ################################################################################################################ # worker thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_2) + # worker thread: Debugger.scriptParsed + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread_2) assert response['params']['url'] == self.config['file_path']['worker'] assert response['params']['endLine'] == 0 + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) + assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] + assert response['params']['reason'] == 'Break on start' ################################################################################################################ # worker thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.remove_breakpoints_by_url( - self.config['file_path']['worker']), - message_id) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' - assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] - assert response['params']['reason'] == 'Break on start' - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_2, params) ################################################################################################################ # worker thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread_2, params) assert response['result']['locations'][0]['id'] == 'id:11:0:' + self.config['file_path']['worker'] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread_2) ################################################################################################################ - # main thread: Debugger.resume + # main thread: Debugger.stepOut ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.stepOut", main_thread) # main thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:57:20:' + self.config['file_path']['index']] # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_1) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:11:4:' + self.config['file_path']['worker']] ################################################################################################################ # worker thread: Runtime.getProperties ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - runtime.get_properties(object_id='0', - own_properties=True, - accessor_properties_only=False, - generate_preview=True), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = runtime.GetPropertiesParams('0', True, False, True) + response = await self.runtime_impl.send("Runtime.getProperties", worker_thread_1, params) assert response['result']['result'][0]['name'] == '' assert response['result']['result'][0]['value']['type'] == 'function' assert response['result']['result'][1]['name'] == 'e' @@ -601,114 +357,51 @@ class TestDebug01: ################################################################################################################ # worker thread: Debugger.stepOut ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.step_out(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.stepOut", worker_thread_1) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.disable(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - assert json.loads(response) == {"id": message_id, "result": {}} - ################################################################################################################ - # main thread: Debugger.stepOver - ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.step_over(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_1) + ################################################################################################################ + # main thread: Debugger.stepInto + ################################################################################################################ + await self.debugger_impl.send("Debugger.stepInto", main_thread) # main thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == [] # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:11:4:' + self.config['file_path']['worker']] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread_2) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.disable(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_2) ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # worker thread: destroy instance ################################################################################################################ - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'destroyInstance' - assert response['instanceId'] in worker_instances_id + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] != self.config['pid'] + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] != self.config['pid'] ################################################################################################################ # main thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.disable(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_debug_02.py b/test/autotest/scenario_test/test_debug_02.py index e039a20975a32d25183546e193ae27000bf49fa5..32c18387c5aa9733d4c26fa02b4682df13e8bc31 100644 --- a/test/autotest/scenario_test/test_debug_02.py +++ b/test/autotest/scenario_test/test_debug_02.py @@ -26,8 +26,8 @@ import pytest from aw import Application from aw import Utils -from aw import communicate_with_debugger_server -from aw import debugger, runtime +from aw import debugger +from aw.api import debugger_api, runtime_api @pytest.mark.debug @@ -86,9 +86,11 @@ class TestDebug02: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) Application.attach(self.config['bundle_name']) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -98,122 +100,55 @@ class TestDebug02: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - workers_num = 2 - worker_instances_id = [] - worker_thread_to_send_queues = [] - worker_thread_received_queues = [] - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # worker thread: Debugger.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.enable(), message_id) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' - assert response['params']['url'] == self.config['file_path']['worker'] - assert response['params']['endLine'] == 0 - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", worker_thread_1) + await self.debugger_impl.send("Debugger.enable", worker_thread_2) ################################################################################################################ # worker thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_1) + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_2) + ################################################################################################################ + # main thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # main thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.enable(), message_id) - assert json.loads(response)['method'] == 'Debugger.scriptParsed' - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response)['method'] == 'Debugger.scriptParsed' - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", main_thread) ################################################################################################################ # main thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) ################################################################################################################ # main thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.remove_breakpoints_by_url( - self.config['file_path']['index']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) ################################################################################################################ # main thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=53), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=57)] - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + main_thread, params) assert response['result']['locations'][0]['id'] == 'id:53:0:' + self.config['file_path']['index'] assert response['result']['locations'][1]['id'] == 'id:57:0:' + self.config['file_path']['index'] ################################################################################################################ @@ -223,315 +158,149 @@ class TestDebug02: ################################################################################################################ # main thread: Debugger.paused, hit breakpoint ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:53:16:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: destroy instance ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'destroyInstance' - if response['instanceId'] == worker_instances_id[0]: - worker_instances_id[0] = worker_instances_id[1] - worker_thread_to_send_queues[0] = worker_thread_to_send_queues[1] - worker_thread_received_queues[0] = worker_thread_received_queues[1] + response = await self.debugger_impl.destroy_instance() + if response['instanceId'] == worker_thread_1.instance_id: + worker_thread_1 = worker_thread_2 ################################################################################################################ # worker thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.remove_breakpoints_by_url( - self.config['file_path']['worker']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_1, params) ################################################################################################################ # worker thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread_1, params) assert response['result']['locations'][0]['id'] == 'id:11:0:' + self.config['file_path']['worker'] ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} - ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) # main thread: Debugger.paused, hit breakpoint - ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:57:20:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instances_id[1] = await websocket.get_instance() - worker_thread_to_send_queues[1] = websocket.to_send_msg_queues[worker_instances_id[1]] - worker_thread_received_queues[1] = websocket.received_msg_queues[worker_instances_id[1]] - logging.info(f'Connect to the debugger server of instance: {worker_instances_id[1]}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # worker thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", worker_thread_2) ################################################################################################################ # worker thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_2) + # worker thread: Debugger.scriptParsed + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread_2) assert response['params']['url'] == self.config['file_path']['worker'] assert response['params']['endLine'] == 0 + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) + assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] + assert response['params']['reason'] == 'Break on start' ################################################################################################################ # worker thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.remove_breakpoints_by_url( - self.config['file_path']['worker']), - message_id) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' - assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] - assert response['params']['reason'] == 'Break on start' - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_2, params) ################################################################################################################ # worker thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread_2, params) assert response['result']['locations'][0]['id'] == 'id:11:0:' + self.config['file_path']['worker'] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread_2) ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) # main thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:57:20:' + self.config['file_path']['index']] # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_1) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] assert response['params']['reason'] == 'Break on start' assert response['params']['hitBreakpoints'] == [] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread_1) # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_1) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:11:4:' + self.config['file_path']['worker']] ################################################################################################################ # worker thread: Debugger.stepOut ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.step_out(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.stepOut", worker_thread_1) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[0], - worker_thread_to_send_queues[0], - worker_thread_received_queues[0], - debugger.disable(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[0], - worker_thread_received_queues[0]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_1) ################################################################################################################ # main thread: Debugger.stepOver ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.step_over(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.stepOver", main_thread) # main thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == [] # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:11:4:' + self.config['file_path']['worker']] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread_2) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[1], - worker_thread_to_send_queues[1], - worker_thread_received_queues[1], - debugger.disable(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[1], - worker_thread_received_queues[1]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_2) ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # worker thread: destroy instance ################################################################################################################ - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'destroyInstance' - assert response['instanceId'] in worker_instances_id + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] != self.config['pid'] + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] != self.config['pid'] ################################################################################################################ # main thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.disable(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_debug_03.py b/test/autotest/scenario_test/test_debug_03.py index 0c631b865ad4baa43b62231bf30780b67b198ec0..aa7d13d999ee96f59b3d5db984ec7d8751679f8a 100644 --- a/test/autotest/scenario_test/test_debug_03.py +++ b/test/autotest/scenario_test/test_debug_03.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,8 @@ import pytest from aw import Application from aw import Utils -from aw import communicate_with_debugger_server from aw import debugger, runtime +from aw.api import debugger_api, runtime_api @pytest.mark.debug @@ -84,8 +83,10 @@ class TestDebug03: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -95,171 +96,83 @@ class TestDebug03: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # main thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # main thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", main_thread) ################################################################################################################ # main thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) ################################################################################################################ # main thread: Debugger.scriptParsed ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) assert response['params']['url'] == self.config['file_path']['entry_ability'] assert response['params']['endLine'] == 0 ################################################################################################################ # main thread: Debugger.paused ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['entry_ability'] assert response['params']['reason'] == 'Break on start' ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # main thread: Debugger.scriptParsed ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) assert response['params']['url'] == self.config['file_path']['index'] assert response['params']['endLine'] == 0 ################################################################################################################ # main thread: Debugger.paused ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'Break on start' ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_thread_to_send_queue = websocket.to_send_msg_queues[worker_instance_id] - worker_thread_received_queue = websocket.received_msg_queues[worker_instance_id] - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}') ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread) ################################################################################################################ # worker thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", worker_thread) ################################################################################################################ # worker thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) ################################################################################################################ # main thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.remove_breakpoints_by_url( - self.config['file_path']['index']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) ################################################################################################################ # main thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + main_thread, params) assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] @@ -270,118 +183,61 @@ class TestDebug03: ################################################################################################################ # worker thread: Debugger.scriptParsed ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) assert response['params']['url'] == self.config['file_path']['index'] assert response['params']['endLine'] == 0 # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'Break on start' ################################################################################################################ # worker thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.remove_breakpoints_by_url( - self.config['file_path']['index']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) ################################################################################################################ # worker thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread, params) assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread) # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:10:14:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: Runtime.getProperties ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - runtime.get_properties(object_id='0', - own_properties=True, - accessor_properties_only=False, - generate_preview=True), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = runtime.GetPropertiesParams('0') + response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) assert response['result']['result'][0]['name'] == 'add' assert response['result']['result'][0]['value']['type'] == 'function' ################################################################################################################ # worker thread: Debugger.stepOut ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.step_out(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.stepOut", worker_thread) ################################################################################################################ # main thread: Debugger.paused, hit breakpoint ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:25:4:' + self.config['file_path']['index']] ################################################################################################################ # main thread: Runtime.getProperties ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.get_properties(object_id='0', - own_properties=True, - accessor_properties_only=False, - generate_preview=True), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = runtime.GetPropertiesParams('0') + response = await self.runtime_impl.send("Runtime.getProperties", main_thread, params) assert response['result']['result'][0]['name'] == 'taskpoolTest' assert response['result']['result'][0]['value']['type'] == 'function' assert response['result']['result'][1]['name'] == 'valueSub' @@ -392,40 +248,29 @@ class TestDebug03: ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # worker thread: Debugger.paused ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:17:14:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread) + ################################################################################################################ + # worker thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", worker_thread) + ################################################################################################################ + # main thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(worker_instance_id, worker_thread_to_send_queue, 'close') - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_debug_04.py b/test/autotest/scenario_test/test_debug_04.py index 60b68fcbfe99cd8687a9b17cab1e823c4a1ac7d1..7b69835c37884b39d3ac73979e25fcc433773cb4 100644 --- a/test/autotest/scenario_test/test_debug_04.py +++ b/test/autotest/scenario_test/test_debug_04.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,8 @@ import pytest from aw import Application from aw import Utils -from aw import communicate_with_debugger_server from aw import debugger, runtime +from aw.api import debugger_api, runtime_api @pytest.mark.debug @@ -83,9 +82,11 @@ class TestDebug04: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) Application.attach(self.config['bundle_name']) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -95,124 +96,51 @@ class TestDebug04: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_thread_to_send_queue = websocket.to_send_msg_queues[worker_instance_id] - worker_thread_received_queue = websocket.received_msg_queues[worker_instance_id] - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}') ################################################################################################################ # main thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread) ################################################################################################################ # main thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.enable(), message_id) - # main thread: Debugger.scriptParsed - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' - assert response['params']['url'] == self.config['file_path']['index'] - assert response['params']['endLine'] == 0 - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' - assert response['params']['url'] == self.config['file_path']['entry_ability'] - assert response['params']['endLine'] == 0 - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", main_thread) ################################################################################################################ # main thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) ################################################################################################################ # worker thread: Debugger.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"debuggerId": "0", - "protocols": Utils.get_custom_protocols()}} + await self.debugger_impl.send("Debugger.enable", worker_thread) ################################################################################################################ # worker thread: Runtime.runIfWaitingForDebugger ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - runtime.run_if_waiting_for_debugger(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) ################################################################################################################ # main thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.remove_breakpoints_by_url( - self.config['file_path']['index']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) ################################################################################################################ # main thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + main_thread, params) assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] @@ -223,118 +151,61 @@ class TestDebug04: ################################################################################################################ # worker thread: Debugger.scriptParsed ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.scriptParsed' + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) assert response['params']['url'] == self.config['file_path']['index'] assert response['params']['endLine'] == 0 # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'Break on start' ################################################################################################################ # worker thread: Debugger.removeBreakpointsByUrl ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.remove_breakpoints_by_url( - self.config['file_path']['index']), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) ################################################################################################################ # worker thread: Debugger.getPossibleAndSetBreakpointByUrl ################################################################################################################ - message_id = next(self.id_generator) locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.get_possible_and_set_breakpoint_by_url(locations), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", + worker_thread, params) assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread) # worker thread: Debugger.paused - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['reason'] == 'other' assert response['params']['hitBreakpoints'] == ['id:10:14:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: Runtime.getProperties ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - runtime.get_properties(object_id='0', - own_properties=True, - accessor_properties_only=False, - generate_preview=True), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = runtime.GetPropertiesParams('0') + response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) assert response['result']['result'][0]['name'] == 'add' assert response['result']['result'][0]['value']['type'] == 'function' ################################################################################################################ # worker thread: Debugger.stepOut ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.step_out(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.stepOut", worker_thread) ################################################################################################################ # main thread: Debugger.paused, hit breakpoint ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", main_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:25:4:' + self.config['file_path']['index']] ################################################################################################################ # main thread: Runtime.getProperties ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.get_properties(object_id='0', - own_properties=True, - accessor_properties_only=False, - generate_preview=True), - message_id) - response = json.loads(response) - assert response['id'] == message_id + params = runtime.GetPropertiesParams('0') + response = await self.runtime_impl.send("Runtime.getProperties", main_thread, params) assert response['result']['result'][0]['name'] == 'taskpoolTest' assert response['result']['result'][0]['value']['type'] == 'function' assert response['result']['result'][1]['name'] == 'valueSub' @@ -345,40 +216,29 @@ class TestDebug04: ################################################################################################################ # main thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", main_thread) ################################################################################################################ # worker thread: Debugger.paused ################################################################################################################ - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - response = json.loads(response) - assert response['method'] == 'Debugger.paused' + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] assert response['params']['hitBreakpoints'] == ['id:17:14:' + self.config['file_path']['index']] ################################################################################################################ # worker thread: Debugger.resume ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instance_id, - worker_thread_to_send_queue, - worker_thread_received_queue, - debugger.resume(), message_id) - assert json.loads(response) == {"method": "Debugger.resumed", "params": {}} - response = await websocket.recv_msg_of_debugger_server(worker_instance_id, - worker_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.resume", worker_thread) + ################################################################################################################ + # worker thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", worker_thread) + ################################################################################################################ + # main thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(worker_instance_id, worker_thread_to_send_queue, 'close') - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_heap_profiler_01.py b/test/autotest/scenario_test/test_heap_profiler_01.py index 438efabfc5a92ed45066422255d7a1ca7b504ec2..2a73e9fbea8207bdee52414264e880eacf6994a2 100644 --- a/test/autotest/scenario_test/test_heap_profiler_01.py +++ b/test/autotest/scenario_test/test_heap_profiler_01.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,8 @@ import pytest from aw import Application from aw import Utils -from aw import communicate_with_debugger_server -from aw import debugger, runtime, heap_profiler +from aw import heap_profiler +from aw.api import debugger_api, runtime_api, heap_profiler_api @pytest.mark.heap_profiler @@ -80,9 +79,12 @@ class TestHeapProfiler01: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) + self.heap_profiler_impl = heap_profiler_api.HeapProfilerImpl(self.id_generator, websocket) Application.attach(self.config['bundle_name']) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -92,124 +94,53 @@ class TestHeapProfiler01: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - workers_num = 2 - worker_instances_id = [] - worker_thread_to_send_queues = [] - worker_thread_received_queues = [] - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # main thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # main thread: Runtime.getHeapUsage ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.get_heap_usage(), message_id) - response = json.loads(response) - assert response['result']['usedSize'] > 0 - assert response['result']['totalSize'] > 0 + await self.runtime_impl.send("Runtime.getHeapUsage", main_thread) ################################################################################################################ # worker thread: Runtime.getHeapUsage ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.get_heap_usage(), message_id) - response = json.loads(response) - assert response['result']['usedSize'] > 0 - assert response['result']['totalSize'] > 0 + await self.runtime_impl.send("Runtime.getHeapUsage", worker_thread_1) + await self.runtime_impl.send("Runtime.getHeapUsage", worker_thread_2) ################################################################################################################ # main thread: HeapProfiler.startTrackingHeapObjects ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - heap_profiler.start_tracking_heap_objects(False), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = heap_profiler.TrackingHeapObjectsParams(False) + await self.heap_profiler_impl.send("HeapProfiler.startTrackingHeapObjects", main_thread, params) ################################################################################################################ # worker thread: HeapProfiler.startTrackingHeapObjects ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - heap_profiler.start_tracking_heap_objects(False), - message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + params = heap_profiler.TrackingHeapObjectsParams(False) + await self.heap_profiler_impl.send("HeapProfiler.startTrackingHeapObjects", worker_thread_1, params) + await self.heap_profiler_impl.send("HeapProfiler.startTrackingHeapObjects", worker_thread_2, params) ################################################################################################################ # main thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.disable(), message_id) - while not json.loads(response).get('id', None): - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.disable(), message_id) - while not json.loads(response).get('id', None): - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_1) + await self.debugger_impl.send("Debugger.disable", worker_thread_2) ################################################################################################################ # all thread: sleep 10 seconds ################################################################################################################ @@ -217,84 +148,28 @@ class TestHeapProfiler01: ################################################################################################################ # main thread: Runtime.getHeapUsage ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.get_heap_usage(), message_id) - while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - response = json.loads(response) - assert response['result']['usedSize'] > 0 - assert response['result']['totalSize'] > 0 + await self.runtime_impl.send("Runtime.getHeapUsage", main_thread) ################################################################################################################ # worker thread: Runtime.getHeapUsage ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.get_heap_usage(), message_id) - while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - response = json.loads(response) - assert response['result']['usedSize'] > 0 - assert response['result']['totalSize'] > 0 + await self.runtime_impl.send("Runtime.getHeapUsage", worker_thread_1) + await self.runtime_impl.send("Runtime.getHeapUsage", worker_thread_2) ################################################################################################################ # main thread: HeapProfiler.stopTrackingHeapObjects ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - heap_profiler.stop_tracking_heap_objects(), message_id) - while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response - pre_response = response - while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"') or\ - response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): - if response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): - pre_response = response - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert pre_response.endswith(r'\n]\n}\n"}}') - assert json.loads(response) == {"id": message_id, "result": {}} + await self.heap_profiler_impl.send("HeapProfiler.stopTrackingHeapObjects", main_thread) ################################################################################################################ # worker thread: HeapProfiler.stopTrackingHeapObjects ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - heap_profiler.stop_tracking_heap_objects(), message_id) - while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response - pre_response = response - while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"') or\ - response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): - if response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): - pre_response = response - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert pre_response.endswith(r'\n]\n}\n"}}') - assert json.loads(response) == {"id": message_id, "result": {}} - ################################################################################################################ - # worker thread: destroy instance - ################################################################################################################ - for i in range(workers_num): - await websocket.send_msg_to_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], 'close') + await self.heap_profiler_impl.send("HeapProfiler.stopTrackingHeapObjects", worker_thread_1) + await self.heap_profiler_impl.send("HeapProfiler.stopTrackingHeapObjects", worker_thread_2) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread_1.instance_id, worker_thread_1.send_msg_queue, + 'close') + await websocket.send_msg_to_debugger_server(worker_thread_2.instance_id, worker_thread_2.send_msg_queue, + 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/scenario_test/test_heap_profiler_02.py b/test/autotest/scenario_test/test_heap_profiler_02.py index 77aee0a20132c74dcd34a6f182dae1177e894190..1b5380edcefddb36bf4caa502b873e6c1f40da5c 100644 --- a/test/autotest/scenario_test/test_heap_profiler_02.py +++ b/test/autotest/scenario_test/test_heap_profiler_02.py @@ -17,7 +17,6 @@ limitations under the License. Description: Scenario test case. """ -import json import logging import os import time @@ -26,8 +25,7 @@ import pytest from aw import Application from aw import Utils -from aw import communicate_with_debugger_server -from aw import debugger, runtime, heap_profiler +from aw.api import debugger_api, runtime_api, heap_profiler_api @pytest.mark.heap_profiler @@ -79,9 +77,12 @@ class TestHeapProfiler02: websocket = self.config['websocket'] taskpool = self.config['taskpool'] pid = self.config['pid'] + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) + self.heap_profiler_impl = heap_profiler_api.HeapProfilerImpl(self.id_generator, websocket) Application.attach(self.config['bundle_name']) - taskpool.submit(websocket.main_task(taskpool, websocket, self.procedure, pid)) + taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) taskpool.await_taskpool() taskpool.task_join() if taskpool.task_exception: @@ -91,110 +92,42 @@ class TestHeapProfiler02: ################################################################################################################ # main thread: connect the debugger server ################################################################################################################ - send_msg = {"type": "connected"} - await websocket.send_msg_to_connect_server(send_msg) - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] == 0, logging.error('instance id of the main thread not equal to 0') - assert response['tid'] == self.config['pid'] - main_thread_instance_id = await websocket.get_instance() - main_thread_to_send_queue = websocket.to_send_msg_queues[main_thread_instance_id] - main_thread_received_queue = websocket.received_msg_queues[main_thread_instance_id] - logging.info(f'Connect to the debugger server of instance: {main_thread_instance_id}') + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') ################################################################################################################ # worker thread: connect the debugger server ################################################################################################################ - workers_num = 2 - worker_instances_id = [] - worker_thread_to_send_queues = [] - worker_thread_received_queues = [] - for i in range(workers_num): - response = await websocket.recv_msg_of_connect_server() - response = json.loads(response) - assert response['type'] == 'addInstance' - assert response['instanceId'] != 0 - assert response['tid'] != self.config['pid'] - assert 'workerThread_' in response['name'] - worker_instance_id = await websocket.get_instance() - worker_instances_id.append(worker_instance_id) - worker_thread_to_send_queues.append(websocket.to_send_msg_queues[worker_instance_id]) - worker_thread_received_queues.append(websocket.received_msg_queues[worker_instance_id]) - logging.info(f'Connect to the debugger server of instance: {worker_instance_id}') + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}') + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}') ################################################################################################################ # main thread: Runtime.enable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", main_thread) ################################################################################################################ # worker thread: Runtime.enable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - runtime.enable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {"protocols": []}} + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) ################################################################################################################ # main thread: Debugger.disable ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - debugger.disable(), message_id) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", main_thread) ################################################################################################################ # worker thread: Debugger.disable ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - debugger.disable(), message_id) - while not json.loads(response).get('id', None): - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert json.loads(response) == {"id": message_id, "result": {}} + await self.debugger_impl.send("Debugger.disable", worker_thread_1) + await self.debugger_impl.send("Debugger.disable", worker_thread_2) ################################################################################################################ # main thread: HeapProfiler.takeHeapSnapshot ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - heap_profiler.take_heap_snapshot(), message_id) - assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response - pre_response = response - while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): - pre_response = response - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert pre_response.endswith(r'\n]\n}\n"}}') - assert json.loads(response) == {"id": message_id, "result": {}} + await self.heap_profiler_impl.send("HeapProfiler.takeHeapSnapshot", main_thread) ################################################################################################################ # worker thread: HeapProfiler.takeHeapSnapshot ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - heap_profiler.take_heap_snapshot(), message_id) - assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response - pre_response = response - while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): - pre_response = response - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert pre_response.endswith(r'\n]\n}\n"}}') - assert json.loads(response) == {"id": message_id, "result": {}} + await self.heap_profiler_impl.send("HeapProfiler.takeHeapSnapshot", worker_thread_1) + await self.heap_profiler_impl.send("HeapProfiler.takeHeapSnapshot", worker_thread_2) ################################################################################################################ # all thread: sleep 10 seconds ################################################################################################################ @@ -202,45 +135,19 @@ class TestHeapProfiler02: ################################################################################################################ # main thread: HeapProfiler.takeHeapSnapshot ################################################################################################################ - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(main_thread_instance_id, - main_thread_to_send_queue, - main_thread_received_queue, - heap_profiler.take_heap_snapshot(), message_id) - assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response - pre_response = response - while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): - pre_response = response - response = await websocket.recv_msg_of_debugger_server(main_thread_instance_id, - main_thread_received_queue) - assert pre_response.endswith(r'\n]\n}\n"}}') - assert json.loads(response) == {"id": message_id, "result": {}} + await self.heap_profiler_impl.send("HeapProfiler.takeHeapSnapshot", main_thread) ################################################################################################################ # worker thread: HeapProfiler.takeHeapSnapshot ################################################################################################################ - for i in range(workers_num): - message_id = next(self.id_generator) - response = await communicate_with_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], - worker_thread_received_queues[i], - heap_profiler.take_heap_snapshot(), message_id) - assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response - pre_response = response - while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): - pre_response = response - response = await websocket.recv_msg_of_debugger_server(worker_instances_id[i], - worker_thread_received_queues[i]) - assert pre_response.endswith(r'\n]\n}\n"}}') - assert json.loads(response) == {"id": message_id, "result": {}} - ################################################################################################################ - # worker thread: destroy instance - ################################################################################################################ - for i in range(workers_num): - await websocket.send_msg_to_debugger_server(worker_instances_id[i], - worker_thread_to_send_queues[i], 'close') + await self.heap_profiler_impl.send("HeapProfiler.takeHeapSnapshot", worker_thread_1) + await self.heap_profiler_impl.send("HeapProfiler.takeHeapSnapshot", worker_thread_2) ################################################################################################################ # close the websocket connections ################################################################################################################ - await websocket.send_msg_to_debugger_server(main_thread_instance_id, main_thread_to_send_queue, 'close') + await websocket.send_msg_to_debugger_server(worker_thread_1.instance_id, worker_thread_1.send_msg_queue, + 'close') + await websocket.send_msg_to_debugger_server(worker_thread_2.instance_id, worker_thread_2.send_msg_queue, + 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') await websocket.send_msg_to_connect_server('close') ################################################################################################################ \ No newline at end of file diff --git a/tooling/BUILD.gn b/tooling/BUILD.gn index 9221adcba130e56a520c2ab6401c5500c13c3b22..26be1f54f6508e720f6fb5ab89c8a9f4e1b63d11 100644 --- a/tooling/BUILD.gn +++ b/tooling/BUILD.gn @@ -46,6 +46,7 @@ debugger_sources = [ "debugger_service.cpp", "dispatcher.cpp", "protocol_handler.cpp", + "utils/utils.cpp", ] if (!is_mingw && !is_mac && target_os != "ios") { debugger_sources += [ diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index e73dbb8396de3553520c4e2fb217157ebbb1a08e..2618e1b3e3257535e4645957423299f378ac5d76 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -127,6 +127,8 @@ bool DebuggerImpl::SendableScriptParsed(const std::string &fileName, const std:: // if load module, it needs to check whether clear singlestepper_ ClearSingleStepper(); + + urlFileNameMap_[url].insert(fileName); // Notify script parsed event std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); @@ -451,8 +453,7 @@ void DebuggerImpl::InitializeExtendedProtocolsList() "setNativeRange", "resetSingleStepper", "callFunctionOn", - "smartStepInto", - "callFunctionOn" + "smartStepInto" }; debuggerExtendedProtocols_ = std::move(debuggerProtocolList); } diff --git a/tooling/agent/heapprofiler_impl.cpp b/tooling/agent/heapprofiler_impl.cpp index 8774aeeb8acaad8ef8508cfb42bd7ee2eb20ecfe..f736269f8a717ca8019a6a3dcd4e928d1d295d44 100644 --- a/tooling/agent/heapprofiler_impl.cpp +++ b/tooling/agent/heapprofiler_impl.cpp @@ -324,7 +324,7 @@ DispatchResponse HeapProfilerImpl::AddInspectedHeapObject([[maybe_unused]] const DispatchResponse HeapProfilerImpl::CollectGarbage() { panda::JSNApi::TriggerGC(vm_, panda::JSNApi::TRIGGER_GC_TYPE::FULL_GC); - panda::JSNApi::TriggerGC(vm_, panda::JSNApi::TRIGGER_GC_TYPE::OLD_GC); + panda::JSNApi::TriggerGC(vm_, panda::JSNApi::TRIGGER_GC_TYPE::SHARED_FULL_GC); return DispatchResponse::Ok(); } diff --git a/tooling/base/pt_params.cpp b/tooling/base/pt_params.cpp index 23eab8b9a7f8a82d947b4e60a47f4eac5c44fbf2..293db7418b1ca93345c1f93a3454fa0572caf068 100644 --- a/tooling/base/pt_params.cpp +++ b/tooling/base/pt_params.cpp @@ -47,7 +47,9 @@ std::unique_ptr EvaluateOnCallFrameParams::Create(con std::string callFrameId; ret = params.GetString("callFrameId", &callFrameId); if (ret == Result::SUCCESS) { - paramsObject->callFrameId_ = std::stoi(callFrameId); + if (!ToolchainUtils::StrToInt32(callFrameId, paramsObject->callFrameId_)) { + error += "Failed to convert 'callFrameId' from string to int;"; + } } else { error += "Unknown or wrong type of 'callFrameId';"; } @@ -199,7 +201,9 @@ std::unique_ptr GetScriptSourceParams::Create(const PtJso std::string scriptId; ret = params.GetString("scriptId", &scriptId); if (ret == Result::SUCCESS) { - paramsObject->scriptId_ = std::stoi(scriptId); + if (!ToolchainUtils::StrToInt32(scriptId, paramsObject->scriptId_)) { + error += "Failed to convert 'scriptId' from string to int;"; + } } else { error += "Unknown or wrong type of'scriptId';"; } @@ -731,7 +735,9 @@ std::unique_ptr GetPropertiesParams::Create(const PtJson &p std::string objectId; ret = params.GetString("objectId", &objectId); if (ret == Result::SUCCESS) { - paramsObject->objectId_ = std::stoi(objectId); + if (!ToolchainUtils::StrToInt32(objectId, paramsObject->objectId_)) { + error += "Failed to convert 'objectId' from string to int;"; + } } else { error += "Unknown or wrong type of 'objectId';"; } @@ -774,7 +780,9 @@ std::unique_ptr CallFunctionOnParams::Create(const PtJson std::string callFrameId; ret = params.GetString("callFrameId", &callFrameId); if (ret == Result::SUCCESS) { - paramsObject->callFrameId_ = std::stoi(callFrameId); + if (!ToolchainUtils::StrToInt32(callFrameId, paramsObject->callFrameId_)) { + error += "Failed to convert 'callFrameId' from string to int;"; + } } else { error += "Unknown or wrong type of 'callFrameId';"; } @@ -790,7 +798,9 @@ std::unique_ptr CallFunctionOnParams::Create(const PtJson std::string objectId; ret = params.GetString("objectId", &objectId); if (ret == Result::SUCCESS) { - paramsObject->objectId_ = std::stoi(objectId); + if (!ToolchainUtils::StrToInt32(objectId, paramsObject->objectId_)) { + error += "Failed to convert 'objectId' from string to int;"; + } } else if (ret == Result::TYPE_ERROR) { error += "Wrong type of 'objectId';"; } @@ -981,7 +991,9 @@ std::unique_ptr AddInspectedHeapObjectParams::Crea std::string heapObjectId; ret = params.GetString("heapObjectId", &heapObjectId); if (ret == Result::SUCCESS) { - paramsObject->heapObjectId_ = std::stoi(heapObjectId); + if (!ToolchainUtils::StrToInt32(heapObjectId, paramsObject->heapObjectId_)) { + error += "Failed to convert 'heapObjectId' from string to int;"; + } } else { error += "Unknown or wrong type of 'heapObjectId';"; } @@ -1002,7 +1014,9 @@ std::unique_ptr GetHeapObjectIdParams::Create(const PtJso std::string objectId; ret = params.GetString("objectId", &objectId); if (ret == Result::SUCCESS) { - paramsObject->objectId_ = std::stoi(objectId); + if (!ToolchainUtils::StrToInt32(objectId, paramsObject->objectId_)) { + error += "Failed to convert 'objectId' from string to int;"; + } } else if (ret == Result::TYPE_ERROR) { error += "Wrong type of 'objectId';"; } @@ -1023,7 +1037,9 @@ std::unique_ptr GetObjectByHeapObjectIdParams::Cr std::string objectId; ret = params.GetString("objectId", &objectId); if (ret == Result::SUCCESS) { - paramsObject->objectId_ = std::stoi(objectId); + if (!ToolchainUtils::StrToInt32(objectId, paramsObject->objectId_)) { + error += "Failed to convert 'objectId' from string to int;"; + } } else if (ret == Result::TYPE_ERROR) { error += "Wrong type of 'objectId';"; } diff --git a/tooling/base/pt_types.cpp b/tooling/base/pt_types.cpp index c000ff3f432e0563fa584364aac3708667a512bb..73aab2f7e66707f8727723b08a6f0db1dbbd867d 100644 --- a/tooling/base/pt_types.cpp +++ b/tooling/base/pt_types.cpp @@ -1054,7 +1054,9 @@ std::unique_ptr RemoteObject::Create(const PtJson ¶ms) std::string objectId; ret = params.GetString("objectId", &objectId); if (ret == Result::SUCCESS) { - remoteObject->objectId_ = std::stoi(objectId); + if (!ToolchainUtils::StrToInt32(objectId, remoteObject->objectId_)) { + error += "Failed to convert 'objectId' from string to int;"; + } } else if (ret == Result::TYPE_ERROR) { error += "Wrong type of 'objectId';"; } @@ -1132,7 +1134,9 @@ std::unique_ptr ExceptionDetails::Create(const PtJson ¶ms) std::string scriptId; ret = params.GetString("scriptId", &scriptId); if (ret == Result::SUCCESS) { - exceptionDetails->scriptId_ = std::stoi(scriptId); + if (!ToolchainUtils::StrToInt32(scriptId, exceptionDetails->scriptId_)) { + error += "Failed to convert 'scriptId' from string to int;"; + } } else if (ret == Result::TYPE_ERROR) { error += "Wrong type of 'scriptId';"; } @@ -1532,7 +1536,9 @@ std::unique_ptr CallArgument::Create(const PtJson ¶ms) std::string objectId; ret = params.GetString("objectId", &objectId); if (ret == Result::SUCCESS) { - callArgument->objectId_ = std::stoi(objectId); + if (!ToolchainUtils::StrToInt32(objectId, callArgument->objectId_)) { + error += "Failed to convert 'objectId' from string to int;"; + } } else if (ret == Result::TYPE_ERROR) { // optional value error += "Wrong type of 'objectId';"; } @@ -1568,7 +1574,9 @@ std::unique_ptr Location::Create(const PtJson ¶ms) std::string scriptId; ret = params.GetString("scriptId", &scriptId); if (ret == Result::SUCCESS) { - location->scriptId_ = std::stoi(scriptId); + if (!ToolchainUtils::StrToInt32(scriptId, location->scriptId_)) { + error += "Failed to convert 'scriptId' from string to int;"; + } } else { error += "Unknown or wrong type of 'scriptId';"; } @@ -1696,7 +1704,9 @@ std::unique_ptr LocationRange::Create(const PtJson ¶ms) std::string scriptId; ret = params.GetString("scriptId", &scriptId); if (ret == Result::SUCCESS) { - locationRange->scriptId_ = std::stoi(scriptId); + if (!ToolchainUtils::StrToInt32(scriptId, locationRange->scriptId_)) { + error += "Failed to convert 'scriptId' from string to int;"; + } } else { error += "Unknown or wrong type of 'scriptId';"; } @@ -1788,7 +1798,9 @@ std::unique_ptr BreakLocation::Create(const PtJson ¶ms) std::string scriptId; ret = params.GetString("scriptId", &scriptId); if (ret == Result::SUCCESS) { - breakLocation->scriptId_ = std::stoi(scriptId); + if (!ToolchainUtils::StrToInt32(scriptId, breakLocation->scriptId_)) { + error += "Failed to convert 'scriptId' from string to int;"; + } } else { error += "Unknown or wrong type of 'scriptId';"; } @@ -1951,7 +1963,9 @@ std::unique_ptr CallFrame::Create(const PtJson ¶ms) std::string callFrameId; ret = params.GetString("callFrameId", &callFrameId); if (ret == Result::SUCCESS) { - callFrame->callFrameId_ = std::stoi(callFrameId); + if (!ToolchainUtils::StrToInt32(callFrameId, callFrame->callFrameId_)) { + error += "Failed to convert 'callFrameId' from string to int;"; + } } else { error += "Unknown or wrong type of 'callFrameId';"; } diff --git a/tooling/base/pt_types.h b/tooling/base/pt_types.h index 483a5c6716468601d3d720f277d877d6d0367b6c..03a2b66b4650aa0289d90dbd366fb8aca2e51044 100644 --- a/tooling/base/pt_types.h +++ b/tooling/base/pt_types.h @@ -22,12 +22,15 @@ #include "common/macros.h" #include "tooling/base/pt_json.h" +#include "tooling/utils/utils.h" #include "ecmascript/debugger/debugger_api.h" #include "ecmascript/dfx/cpu_profiler/samples_record.h" #include "ecmascript/dfx/hprof/heap_sampling.h" #include "libpandabase/macros.h" +using ToolchainUtils = OHOS::ArkCompiler::Toolchain::Utils; + namespace panda::ecmascript::tooling { // ========== Base types begin class PtBaseTypes { @@ -71,8 +74,12 @@ struct BreakpointDetails { std::string lineStr = id.substr(lineStart + 1, columnStart - lineStart - 1); std::string columnStr = id.substr(columnStart + 1, urlStart - columnStart - 1); std::string url = id.substr(urlStart + 1); - metaData->line_ = std::stoi(lineStr); - metaData->column_ = std::stoi(columnStr); + if (!ToolchainUtils::StrToInt32(lineStr, metaData->line_)) { + return false; + } + if (!ToolchainUtils::StrToInt32(columnStr, metaData->column_)) { + return false; + } metaData->url_ = url; return true; diff --git a/tooling/client/BUILD.gn b/tooling/client/BUILD.gn index fd96ed7e69bdce2419879f464f3cdfe72f6e38c5..80ee1c54f2862d292a7cb41c594f5455c80ab9e2 100644 --- a/tooling/client/BUILD.gn +++ b/tooling/client/BUILD.gn @@ -28,6 +28,7 @@ ohos_source_set("libark_client_set") { ] sources = [ + "../utils/utils.cpp", "domain/debugger_client.cpp", "domain/heapprofiler_client.cpp", "domain/profiler_client.cpp", @@ -42,7 +43,6 @@ ohos_source_set("libark_client_set") { "session/session.cpp", "tcpServer/tcp_server.cpp", "utils/cli_command.cpp", - "utils/utils.cpp", ] deps += [ diff --git a/tooling/client/ark_multi/BUILD.gn b/tooling/client/ark_multi/BUILD.gn index b08f3703297c012675ee8731fdf23337363a0780..d7b63e2e6d6d644817e94eab11f424f0b3cbe029 100644 --- a/tooling/client/ark_multi/BUILD.gn +++ b/tooling/client/ark_multi/BUILD.gn @@ -14,7 +14,10 @@ import("//arkcompiler/toolchain/toolchain.gni") ohos_executable("ark_multi") { - sources = [ "main.cpp" ] + sources = [ + "../../utils/utils.cpp", + "main.cpp", + ] include_dirs = [ "./", diff --git a/tooling/client/ark_multi/main.cpp b/tooling/client/ark_multi/main.cpp index 7e94fb9ad6d379d64ba38150f7577779e54a3b67..41f757af32e996fe4d135f50ba99f7086b53a47c 100644 --- a/tooling/client/ark_multi/main.cpp +++ b/tooling/client/ark_multi/main.cpp @@ -26,6 +26,7 @@ #include "ecmascript/js_runtime_options.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/platform/file.h" +#include "tooling/utils/utils.h" #ifdef PANDA_TARGET_MACOS #include #include @@ -152,7 +153,12 @@ int Main(const int argc, const char **argv) } std::string countStr = argv[1]; - g_threadCount = std::min(std::stoi(countStr), MAX_THREAD); + int32_t count; + if (!Utils::StrToInt32(countStr, count)) { + std::cerr << "The argument about the number of threads is incorrect." << std::endl; + return -1; + } + g_threadCount = std::min(count, MAX_THREAD); std::string filePath = argv[2]; std::string realPath; diff --git a/tooling/client/domain/heapprofiler_client.cpp b/tooling/client/domain/heapprofiler_client.cpp index bb224ad2871fc677fce6463ddf084fbfcbaad1a3..69b0cdf0fe88c9d4bad43dfbe63299e78fd3883c 100644 --- a/tooling/client/domain/heapprofiler_client.cpp +++ b/tooling/client/domain/heapprofiler_client.cpp @@ -15,7 +15,7 @@ #include "tooling/client/domain/heapprofiler_client.h" #include "common/log_wrapper.h" -#include "tooling/client/utils/utils.h" +#include "tooling/utils/utils.h" #include "tooling/client/session/session.h" #include diff --git a/tooling/client/domain/profiler_client.cpp b/tooling/client/domain/profiler_client.cpp index 1f0a22cb97789e3032593015c020f6b77c5bf931..6b98d7a4334b84725c91e9206801a18dd4342d54 100644 --- a/tooling/client/domain/profiler_client.cpp +++ b/tooling/client/domain/profiler_client.cpp @@ -16,7 +16,7 @@ #include "tooling/client/domain/profiler_client.h" #include "tooling/base/pt_types.h" #include "common/log_wrapper.h" -#include "tooling/client/utils/utils.h" +#include "tooling/utils/utils.h" #include "tooling/client/session/session.h" #include diff --git a/tooling/client/domain/runtime_client.cpp b/tooling/client/domain/runtime_client.cpp index 85f1123650fe6a5598ad1255cbfa314ab2a43f74..1e26b8e131f56a3ae709e62b3057f406ce6688ec 100644 --- a/tooling/client/domain/runtime_client.cpp +++ b/tooling/client/domain/runtime_client.cpp @@ -20,6 +20,7 @@ #include "tooling/client/manager/watch_manager.h" #include "tooling/base/pt_json.h" #include "tooling/client/session/session.h" +#include "tooling/utils/utils.h" using PtJson = panda::ecmascript::tooling::PtJson; namespace OHOS::ArkCompiler::Toolchain { @@ -256,10 +257,15 @@ void RuntimeClient::HandleGetProperties(std::unique_ptr json, const int variableManager.ClearVariableInfo(); variableManager.InitializeTree(treeInfo); } - std::string requestObjectId = GetRequestObjectIdById(id); + std::string requestObjectIdStr = GetRequestObjectIdById(id); TreeNode *node = nullptr; if (!isInitializeTree_) { - node = variableManager.FindNodeWithObjectId(std::stoi(requestObjectId)); + int32_t requestObjectId; + if (!Utils::StrToInt32(requestObjectIdStr, requestObjectId)) { + LOGE("arkdb: convert 'requestObjectId' from string to int error"); + return; + } + node = variableManager.FindNodeWithObjectId(requestObjectId); } else { node = variableManager.FindNodeObjectZero(); } diff --git a/tooling/client/manager/breakpoint_manager.cpp b/tooling/client/manager/breakpoint_manager.cpp index 8109d154552db9785c816d00760787ce7eede581..58e294888b1dc8f95943fd62e4e19ee227d34fc7 100644 --- a/tooling/client/manager/breakpoint_manager.cpp +++ b/tooling/client/manager/breakpoint_manager.cpp @@ -16,7 +16,7 @@ #include "tooling/client/manager/breakpoint_manager.h" #include "common/log_wrapper.h" -#include "tooling/client/utils/utils.h" +#include "tooling/utils/utils.h" #include "tooling/client/session/session.h" using PtJson = panda::ecmascript::tooling::PtJson; diff --git a/tooling/client/session/session.cpp b/tooling/client/session/session.cpp index d6569947ea748688aed8d794ba35280acd2db016..1069ad9d4eae33601fb0b2efad90595e3a2850b0 100755 --- a/tooling/client/session/session.cpp +++ b/tooling/client/session/session.cpp @@ -18,7 +18,7 @@ #include "common/log_wrapper.h" #include "tooling/client/manager/message_manager.h" #include "tooling/base/pt_json.h" -#include "tooling/client/utils/utils.h" +#include "tooling/utils/utils.h" #include diff --git a/tooling/client/tcpServer/tcp_server.cpp b/tooling/client/tcpServer/tcp_server.cpp index e3a0155a40b9e5a6ffab3d334a6a3b8e317895ac..6db3829273b063465ac804af5607795bd65e2bb9 100644 --- a/tooling/client/tcpServer/tcp_server.cpp +++ b/tooling/client/tcpServer/tcp_server.cpp @@ -14,7 +14,7 @@ */ #include "tooling/client/tcpServer/tcp_server.h" -#include "tooling/client/utils/utils.h" +#include "tooling/utils/utils.h" namespace OHOS::ArkCompiler::Toolchain { uv_async_t* g_inputSignal; diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 8e8f594d8b443079334ba269052dc291604e629e..8fb86ac215f221356b7b714759bec684caf79e30 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -26,7 +26,6 @@ #include "tooling/client/manager/stack_manager.h" #include "tooling/client/manager/variable_manager.h" #include "tooling/client/session/session.h" -#include "tooling/client/utils/utils.h" namespace OHOS::ArkCompiler::Toolchain { const std::string HELP_MSG = "usage: \n" diff --git a/tooling/client/utils/cli_command.h b/tooling/client/utils/cli_command.h index b69293119e8658f734fc8fefe74ecfbf3c6fdccd..2720521dba37a3b7abc275e9e415a96d1e77c63b 100644 --- a/tooling/client/utils/cli_command.h +++ b/tooling/client/utils/cli_command.h @@ -25,7 +25,7 @@ #include "tooling/client/domain/heapprofiler_client.h" #include "tooling/client/domain/profiler_client.h" #include "tooling/client/manager/domain_manager.h" -#include "tooling/client/utils/utils.h" +#include "tooling/utils/utils.h" #include "tooling/client/session/session.h" namespace OHOS::ArkCompiler::Toolchain { diff --git a/tooling/client/utils/utils.cpp b/tooling/utils/utils.cpp similarity index 82% rename from tooling/client/utils/utils.cpp rename to tooling/utils/utils.cpp index 7e806f45216496cc16c65360a1c6360987ee51fd..9ede2c6be9ffebd2eb49935125a8eeb360b338e3 100644 --- a/tooling/client/utils/utils.cpp +++ b/tooling/utils/utils.cpp @@ -13,13 +13,13 @@ * limitations under the License. */ -#include "common/log_wrapper.h" -#include "tooling/client/utils/utils.h" #include #include #include #include -#include "utils.h" + +#include "common/log_wrapper.h" +#include "tooling/utils/utils.h" namespace OHOS::ArkCompiler::Toolchain { bool Utils::GetCurrentTime(char *date, char *tim, size_t size) @@ -68,6 +68,30 @@ bool Utils::StrToUInt(const char *content, uint32_t *result) return true; } +bool Utils::StrToInt32(const std::string &str, int32_t &result) +{ + const int dec = 10; + char *endPtr = nullptr; + long long num = std::strtoll(str.c_str(), &endPtr, dec); + if (endPtr == str.c_str() || *endPtr != '\0' || num > INT_MAX || num < INT_MIN) { + return false; + } + result = static_cast(num); + return true; +} + +bool Utils::StrToInt32(const std::string &str, std::optional &result) +{ + const int dec = 10; + char *endPtr = nullptr; + long long num = std::strtoll(str.c_str(), &endPtr, dec); + if (endPtr == str.c_str() || *endPtr != '\0' || num > INT_MAX || num < INT_MIN) { + return false; + } + result = static_cast(num); + return true; +} + std::vector Utils::SplitString(const std::string &str, const std::string &delimiter) { std::size_t strIndex = 0; @@ -134,4 +158,4 @@ bool Utils::IsNumber(const std::string &str) return true; } -} // OHOS::ArkCompiler::Toolchain +} // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/utils/utils.h b/tooling/utils/utils.h similarity index 87% rename from tooling/client/utils/utils.h rename to tooling/utils/utils.h index 9f96a1d73c56553fabda2c44072a02a060f11aae..13ddc0093dcf75b8a80ae0667b6588d798dc1c7d 100644 --- a/tooling/client/utils/utils.h +++ b/tooling/utils/utils.h @@ -18,6 +18,7 @@ #include #include +#include namespace OHOS::ArkCompiler::Toolchain { class Utils { @@ -25,6 +26,8 @@ public: static bool RealPath(const std::string &path, std::string &realPath, bool readOnly = true); static bool GetCurrentTime(char *date, char *tim, size_t size); static bool StrToUInt(const char *content, uint32_t *result); + static bool StrToInt32(const std::string &str, int32_t &result); + static bool StrToInt32(const std::string &str, std::optional &result); static std::vector SplitString(const std::string &str, const std::string &delimiter); static bool IsNumber(const std::string &str); };