diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000000000000000000000000000000000..2640e9ee703646a287d88784f57f0b38fd4e7400 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 1676253958656 + + + + + + + \ No newline at end of file diff --git a/localCoverage/__init__.py b/localCoverage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/localCoverage/all_subsystem_config.json b/localCoverage/all_subsystem_config.json new file mode 100644 index 0000000000000000000000000000000000000000..b4a228566a4544adc115b6bbecf4453300d42b29 --- /dev/null +++ b/localCoverage/all_subsystem_config.json @@ -0,0 +1,1238 @@ +{ + "bundle_framework": { + "name": "bundle_framework", + "path": [ + "foundation/bundlemanager/bundle_framework" + ] + }, + "bundle_framework_lite": { + "name": "bundle_framework_lite", + "path": [ + "foundation/bundlemanager/bundle_framework_lite" + ] + }, + "packing_tool": { + "name": "packing_tool", + "path": [ + "developtools/packing_tool" + ] + }, + "appverify": { + "name": "appverify", + "path": [ + "base/security/appverify" + ] + }, + "zlib": { + "name": "zlib", + "path": [ + "third_party/zlib" + ] + }, + "ability_lite": { + "name": "ability_lite", + "path": [ + "foundation/ability/ability_lite" + ] + }, + "ability_base": { + "name": "ability_base", + "path": [ + "foundation/ability/ability_base" + ] + }, + "ability_runtime": { + "name": "ability_runtime", + "path": [ + "foundation/ability/ability_runtime" + ] + }, + "ability_tool": { + "name": "ability_tool", + "path": [ + "foundation/ability/ability_runtime/tools" + ] + }, + "idl_tool": { + "name": "idl_tool", + "path": [ + "foundation/ability/idl_tool" + ] + }, + "form_fwk": { + "name": "form_fwk", + "path": [ + "foundation/ability/form_fwk" + ] + }, + "wms": { + "name": "wms", + "path": [ + "foundation/graphic/wms" + ] + }, + "ui": { + "name": "ui", + "path": [ + "foundation/graphic/ui" + ] + }, + "graphic_utils": { + "name": "graphic_utils", + "path": [ + "foundation/graphic/utils" + ] + }, + "graphic_2d": { + "name": "graphic_2d", + "path": [ + "foundation/graphic/graphic_2d" + ] + }, + "multimedia_image_framework": { + "name": "multimedia_image_framework", + "path": [ + "foundation/multimedia/image_framework" + ] + }, + "background_task_mgr": { + "name": "background_task_mgr", + "path": [ + "foundation/resourceschedule/background_task_mgr" + ] + }, + "work_scheduler": { + "name": "work_scheduler", + "path": [ + "foundation/resourceschedule/work_scheduler" + ] + }, + "device_usage_statistics": { + "name": "device_usage_statistics", + "path": [ + "foundation/resourceschedule/device_usage_statistics" + ] + }, + "resource_schedule_service": { + "name": "resource_schedule_service", + "path": [ + "foundation/resourceschedule/resource_schedule_service" + ] + }, + "schedule_ext": { + "name": "schedule_ext", + "path": [ + "foundation/resourceschedule/resource_schedule_service/schedule_ext" + ] + }, + "efficiency_manager": { + "name": "efficiency_manager", + "path": [ + "foundation/resourceschedule/efficiency_manager" + ] + }, + "efficiency_manager_ext": { + "name": "efficiency_manager_ext", + "path": [ + "foundation/resourceschedule/efficiency_manager_ext" + ] + }, + "preferences": { + "name": "preferences", + "path": [ + "foundation/distributeddatamgr/preferences" + ] + }, + "relational_store": { + "name": "relational_store", + "path": [ + "foundation/distributeddatamgr/relational_store" + ] + }, + "data_share": { + "name": "data_share", + "path": [ + "foundation/distributeddatamgr/data_share" + ] + }, + "kv_store": { + "name": "kv_store", + "path": [ + "foundation/distributeddatamgr/kv_store" + ] + }, + "datamgr_service": { + "name": "datamgr_service", + "path": [ + "foundation/distributeddatamgr/distributeddatamgr" + ] + }, + "data_object": { + "name": "data_object", + "path": [ + "foundation/distributeddatamgr/data_object" + ] + }, + "pasteboard": { + "name": "pasteboard", + "path": [ + "foundation/distributeddatamgr/pasteboard" + ] + }, + "ipc": { + "name": "ipc", + "path": [ + "foundation/communication/ipc" + ] + }, + "dsoftbus_standard": { + "name": "dsoftbus_standard", + "path": [ + "foundation/communication/dsoftbus" + ] + }, + "device_manager": { + "name": "device_manager", + "path": [ + "foundation/distributedhardware/device_manager" + ] + }, + "distributed_hardware_fwk": { + "name": "distributed_hardware_fwk", + "path": [ + "foundation/distributedhardware/distributed_hardware_fwk" + ] + }, + "distributed_camera": { + "name": "distributed_camera", + "path": [ + "foundation/distributedhardware/distributed_camera" + ] + }, + "distributed_audio": { + "name": "distributed_audio", + "path": [ + "foundation/distributedhardware/distributed_audio" + ] + }, + "distributed_screen": { + "name": "distributed_screen", + "path": [ + "foundation/distributedhardware/distributed_screen" + ] + }, + "distributed_input": { + "name": "distributed_input", + "path": [ + "foundation/distributedhardware/distributed_input" + ] + }, + "input": { + "name": "input", + "path": [ + "foundation/multimodalinput/input" + ] + }, + "multimedia_audio_framework": { + "name": "multimedia_audio_framework", + "path": [ + "foundation/multimedia/audio_framework" + ] + }, + "audio_manager_lite": { + "name": "audio_manager_lite", + "path": [ + "foundation/multimedia/audio_lite" + ] + }, + "camera_lite": { + "name": "camera_lite", + "path": [ + "foundation/multimedia/camera_lite" + ] + }, + "camera_framework": { + "name": "camera_framework", + "path": [ + "foundation/multimedia/camera_standard" + ] + }, + "media_lite": { + "name": "media_lite", + "path": [ + "foundation/multimedia/media_lite" + ] + }, + "multimedia_av_session": { + "name": "multimedia_av_session", + "path": [ + "foundation/multimedia/av_session" + ] + }, + "utils": { + "name": "utils", + "path": [ + "foundation/multimedia/utils" + ] + }, + "omx_adapter": { + "name": "omx_adapter", + "path": [ + "foundation/multimedia/omx_adapter" + ] + }, + "multimedia_histreamer": { + "name": "multimedia_histreamer", + "path": [ + "foundation/multimedia/histreamer" + ] + }, + "multimedia_player_framework": { + "name": "multimedia_player_framework", + "path": [ + "foundation/multimedia/player_framework" + ] + }, + "neural_network_runtime": { + "name": "neural_network_runtime", + "path": [ + "foundation/ai/neural_network_runtime" + ] + }, + "ai_engine": { + "name": "ai_engine", + "path": [ + "foundation/ai/ai_engine" + ] + }, + "decision": { + "name": "decision", + "path": [ + "foundation/ai/decision" + ] + }, + "mindspore": { + "name": "mindspore", + "path": [ + "third_party/mindspore" + ] + }, + "core_service": { + "name": "core_service", + "path": [ + "base/telephony/core_service" + ] + }, + "call_manager": { + "name": "call_manager", + "path": [ + "base/telephony/call_manager" + ] + }, + "data_storage": { + "name": "data_storage", + "path": [ + "base/telephony/data_storage" + ] + }, + "sms_mms": { + "name": "sms_mms", + "path": [ + "base/telephony/sms_mms" + ] + }, + "cellular_call": { + "name": "cellular_call", + "path": [ + "base/telephony/cellular_call" + ] + }, + "cellular_data": { + "name": "cellular_data", + "path": [ + "base/telephony/cellular_data" + ] + }, + "state_registry": { + "name": "state_registry", + "path": [ + "base/telephony/state_registry" + ] + }, + "ril_adapter": { + "name": "ril_adapter", + "path": [ + "base/telephony/ril_adapter" + ] + }, + "ims_service": { + "name": "ims_service", + "path": [ + "vendor/huawei/base/telephony/ims_service" + ] + }, + "ril_adapter_ext": { + "name": "ril_adapter_ext", + "path": [ + "vendor/huawei/base/telephony/ril_adapter_ext" + ] + }, + "certificate_manager": { + "name": "certificate_manager", + "path": [ + "base/security/certificate_manager" + ] + }, + "crypto_framework": { + "name": "crypto_framework", + "path": [ + "base/security/crypto_framework" + ] + }, + "dataclassification": { + "name": "dataclassification", + "path": [ + "base/security/dataclassification" + ] + }, + "device_auth": { + "name": "device_auth", + "path": [ + "base/security/device_auth" + ] + }, + "device_security_level": { + "name": "device_security_level", + "path": [ + "base/security/device_security_level" + ] + }, + "device_threat_detection": { + "name": "device_threat_detection", + "path": [ + "base/security/device_threat_detection" + ] + }, + "hapsigner": { + "name": "hapsigner", + "path": [ + "developtools/hapsigner" + ] + }, + "huks": { + "name": "huks", + "path": [ + "base/security/huks" + ] + }, + "appspawn": { + "name": "appspawn", + "path": [ + "base/startup/appspawn" + ] + }, + "bootstrap_lite": { + "name": "bootstrap_lite", + "path": [ + "base/startup/bootstrap_lite" + ] + }, + "init": { + "name": "init", + "path": [ + "base/startup/init" + ] + }, + "notification": { + "name": "notification", + "path": [ + "base/notification/common_event_service", + "base/notification/distributed_notification_service", + "base/notification/eventhandler" + ] + }, + "hilog": { + "name": "hilog", + "path": [ + "base/hiviewdfx/hilog" + ] + }, + "hilog_lite": { + "name": "hilog_lite", + "path": [ + "base/hiviewdfx/hilog_lite" + ] + }, + "hitrace": { + "name": "hitrace", + "path": [ + "base/hiviewdfx/hitrace" + ] + }, + "hiview": { + "name": "hiview", + "path": [ + "base/hiviewdfx/hiview/adapter", + "base/hiviewdfx/hiview/build", + "base/hiviewdfx/hiview/base", + "base/hiviewdfx/hiview/core", + "base/hiviewdfx/hiview/figures", + "base/hiviewdfx/hiview/include", + "base/hiviewdfx/hiview/service", + "base/hiviewdfx/hiview/utility", + "base/hiviewdfx/hiview/test", + "base/hiviewdfx/hiview/plugins/eventlogger", + "base/hiviewdfx/hiview/plugins/eventservice", + "base/hiviewdfx/hiview/plugins/faultlogger", + "base/hiviewdfx/hiview/plugins/freeze_detector", + "base/hiviewdfx/hiview/plugins/hicollie_collector", + "base/hiviewdfx/hiview/plugins/usage_event_report", + "base/hiviewdfx/hiview/plugins/huawei_proprietary/leak_detectors", + "base/hiviewdfx/hiview/plugins/huawei_proprietary/test" + ] + }, + "hiview_lite": { + "name": "hiview_lite", + "path": [ + "base/hiviewdfx/hiview_lite" + ] + }, + "hichecker": { + "name": "hichecker", + "path": [ + "base/hiviewdfx/hichecker" + ] + }, + "hicollie": { + "name": "hicollie", + "path": [ + "base/hiviewdfx/hicollie" + ] + }, + "hiappevent": { + "name": "hiappevent", + "path": [ + "base/hiviewdfx/hiappevent" + ] + }, + "hisysevent": { + "name": "hisysevent", + "path": [ + "base/hiviewdfx/hisysevent" + ] + }, + "hievent_lite": { + "name": "hievent_lite", + "path": [ + "base/hiviewdfx/hievent_lite" + ] + }, + "faultloggerd": { + "name": "faultloggerd", + "path": [ + "base/hiviewdfx/faultloggerd" + ] + }, + "profiler": { + "name": "profiler", + "path": [ + "developtools/profiler" + ] + }, + "hiperf": { + "name": "hiperf", + "path": [ + "developtools/hiperf" + ] + }, + "bytrace": { + "name": "bytrace", + "path": [ + "developtools/bytrace" + ] + }, + "hidumper_lite": { + "name": "hidumper_lite", + "path": [ + "base/hiviewdfx/hidumper_lite" + ] + }, + "blackbox": { + "name": "blackbox", + "path": [ + "base/hiviewdfx/blackbox" + ] + }, + "hidumper": { + "name": "hidumper", + "path": [ + "base/hiviewdfx/hidumper" + ] + }, + "bluetooth": { + "name": "bluetooth", + "path": [ + "foundation/communication/bluetooth" + ] + }, + "nfc": { + "name": "nfc", + "path": [ + "foundation/communication/nfc/nfc_core" + ] + }, + "connected_tag": { + "name": "connected_tag", + "path": [ + "foundation/communication/nfc/connected_tag" + ] + }, + "wifi": { + "name": "wifi", + "path": [ + "foundation/communication/wifi/wifi" + ] + }, + "dhcp": { + "name": "dhcp", + "path": [ + "foundation/communication/wifi/dhcp" + ] + }, + "wifi_aware": { + "name": "wifi_aware", + "path": [ + "foundation/communication/wifi_aware" + ] + }, + "wifi_lite": { + "name": "wifi_lite", + "path": [ + "foundation/communication/wifi_lite" + ] + }, + "algorithm": { + "name": "algorithm", + "path": [ + "base/msdp/algorithm" + ] + }, + "geofence": { + "name": "geofence", + "path": [ + "base/msdp/geofence" + ] + }, + "motion": { + "name": "motion", + "path": [ + "base/msdp/motion" + ] + }, + "movement": { + "name": "movement", + "path": [ + "base/msdp/movement" + ] + }, + "spatial_awareness": { + "name": "spatial_awareness", + "path": [ + "base/msdp/spatial_awareness" + ] + }, + "timeline": { + "name": "timeline", + "path": [ + "base/msdp/timeline" + ] + }, + "device_status": { + "name": "device_status", + "path": [ + "base/msdp/device_status" + ] + }, + "os_account": { + "name": "os_account", + "path": [ + "base/account/os_account" + ] + }, + "i18n": { + "name": "i18n", + "path": [ + "base/global/i18n" + ] + }, + "i18n_lite": { + "name": "i18n_lite", + "path": [ + "base/global/i18n_lite" + ] + }, + "system_resources": { + "name": "system_resources", + "path": [ + "utils/system_resources" + ] + }, + "jsoncpp": { + "name": "jsoncpp", + "path": [ + "third_party/jsoncpp" + ] + }, + "libxml2": { + "name": "libxml2", + "path": [ + "third_party/libxml2" + ] + }, + "global_resource_tool": { + "name": "global_resource_tool", + "path": [ + "developtools/global_resource_tool" + ] + }, + "resource_management": { + "name": "resource_management", + "path": [ + "base/global/resource_management" + ] + }, + "resource_management_lite": { + "name": "resource_management_lite", + "path": [ + "base/global/resource_management_lite" + ] + }, + "time_zone": { + "name": "time_zone", + "path": [ + "base/global/time_zone" + ] + }, + "accessibility": { + "name": "accessibility", + "path": [ + "foundation/barrierfree/accessibility" + ] + }, + "time_service": { + "name": "time_service", + "path": [ + "base/time/time_service" + ] + }, + "imf": { + "name": "imf", + "path": [ + "base/inputmethod/imf" + ] + }, + "theme": { + "name": "theme", + "path": [ + "base/theme" + ] + }, + "request": { + "name": "request", + "path": [ + "base/request" + ] + }, + "battery_manager": { + "name": "battery_manager", + "path": [ + "base/powermgr/battery_manager" + ] + }, + "display_manager": { + "name": "display_manager", + "path": [ + "base/powermgr/display_manager" + ] + }, + "powermgr_lite": { + "name": "powermgr_lite", + "path": [ + "base/powermgr/powermgr_lite" + ] + }, + "battery_lite": { + "name": "battery_lite", + "path": [ + "base/powermgr/battery_lite" + ] + }, + "battery_statistics": { + "name": "battery_statistics", + "path": [ + "base/powermgr/battery_statistics" + ] + }, + "power_manager": { + "name": "power_manager", + "path": [ + "base/powermgr/power_manager" + ] + }, + "thermal_manager": { + "name": "thermal_manager", + "path": [ + "base/powermgr/thermal_manager" + ] + }, + "sensor": { + "name": "sensor", + "path": [ + "base/sensors/sensor" + ] + }, + "miscdevice": { + "name": "miscdevice", + "path": [ + "base/sensors/miscdevice" + ] + }, + "sensor_lite": { + "name": "sensor_lite", + "path": [ + "base/sensors/sensor_lite" + ] + }, + "miscdevice_lite": { + "name": "miscdevice_lite", + "path": [ + "base/sensors/miscdevice_lite" + ] + }, + "start": { + "name": "start", + "path": [ + "base/sensors/start" + ] + }, + "user_auth_framework": { + "name": "user_auth_framework", + "path": [ + "base/useriam/user_auth_framework" + ] + }, + "pin_auth": { + "name": "pin_auth", + "path": [ + "base/useriam/pin_auth" + ] + }, + "face_auth": { + "name": "face_auth", + "path": [ + "base/useriam/face_auth" + ] + }, + "fingerprint_auth": { + "name": "fingerprint_auth", + "path": [ + "base/useriam/fingerprint_auth" + ] + }, + "peripheral": { + "name": "peripheral", + "path": [ + "drivers/peripheral/pin_auth", + "drivers/peripheral/face_auth", + "drivers/peripheral/user_auth", + "drivers/peripheral/fingerprint_auth" + ] + }, + "location": { + "name": "location", + "path": [ + "base/location" + ] + }, + "usb_manager": { + "name": "usb_manager", + "path": [ + "base/usb/usb_manager" + ] + }, + "build": { + "name": "build", + "path": [ + "build" + ] + }, + "gn": { + "name": "gn", + "path": [ + "third_party/gn" + ] + }, + "ninja": { + "name": "ninja", + "path": [ + "third_party/ninja" + ] + }, + "hidl_adapter": { + "name": "hidl_adapter", + "path": [ + "drivers/peripheral/adapter/activity_recognition", + "drivers/peripheral/adapter/audio", + "drivers/peripheral/adapter/camera", + "drivers/peripheral/adapter/gralloc", + "drivers/peripheral/adapter/hwc", + "drivers/peripheral/adapter/input", + "drivers/peripheral/adapter/motion", + "drivers/peripheral/adapter/sensor", + "drivers/peripheral/adapter/thermal" + ] + }, + "hdf_core": { + "name": "hdf_core", + "path": [ + "drivers/hdf_core/adapter/uhdf2", + "drivers/hdf_core/framework/core/common", + "drivers/hdf_core/framework/core/host", + "drivers/hdf_core/framework/core/manager", + "drivers/hdf_core/framework/core/shared", + "drivers/hdf_core/framework/support/posix/" + ] + }, + "filemanagement_app_file_service": { + "name": "filemanagement_app_file_service", + "path": [ + "foundation/filemanagement/app_file_service" + ] + }, + "filemanagement_backup": { + "name": "filemanagement_backup", + "path": [ + "foundation/filemanagement/backup" + ] + }, + "filemanagement_dfs_service": { + "name": "filemanagement_dfs_service", + "path": [ + "foundation/filemanagement/dfs_service" + ] + }, + "filemanagement_file_api": { + "name": "filemanagement_file_api", + "path": [ + "foundation/filemanagement/file_api" + ] + }, + "filemanagement_storage_service": { + "name": "filemanagement_storage_service", + "path": [ + "foundation/filemanagement/storage_service" + ] + }, + "filemanagement_user_file_service": { + "name": "filemanagement_user_file_service", + "path": [ + "foundation/filemanagement/user_file_service" + ] + }, + "media_library": { + "name": "media_library", + "path": [ + "foundation/multimedia/media_library" + ] + }, + "netmanager_base": { + "name": "netmanager_base", + "path": [ + "foundation/communication/netmanager_base" + ] + }, + "netmanager_ext": { + "name": "netmanager_ext", + "path": [ + "foundation/communication/netmanager_ext" + ] + }, + "netstack": { + "name": "netstack", + "path": [ + "foundation/communication/netstack" + ] + }, + "webview": { + "name": "webview", + "path": [ + "base/web/webview/ohos_adapter", + "base/web/webview/ohos_nweb" + ] + }, + "tee_client": { + "name": "tee_client", + "path": [ + "base/tee/tee_client" + ] + }, + "tee_os_framework": { + "name": "tee_os_framework", + "path": [ + "base/tee/tee_os_framework" + ] + }, + "tee_dev_kit": { + "name": "tee_dev_kit", + "path": [ + "base/tee/tee_dev_kit" + ] + }, + "tee_tzdriver": { + "name": "tee_tzdriver", + "path": [ + "base/tee/tee_tzdriver" + ] + }, + "tee_os_kernel": { + "name": "tee_os_kernel", + "path": [ + "base/tee/tee_os_kernel" + ] + }, + "device_info_manager": { + "name": "device_info_manager", + "path": [ + "foundation/deviceprofile" + ] + }, + "enterprise_device_management": { + "name": "enterprise_device_management", + "path": [ + "base/customization/enterprise_device_management" + ] + }, + "config_policy": { + "name": "config_policy", + "path": [ + "base/customization/config_policy" + ] + }, + "toolchain": { + "name": "toolchain", + "path": [ + "arkcompiler/toolchain" + ] + }, + "runtime_core": { + "name": "runtime_core", + "path": [ + "arkcompiler/runtime_core" + ] + }, + "ets_frontend": { + "name": "ets_frontend", + "path": [ + "arkcompiler/ets_frontend" + ] + }, + "ets_runtime": { + "name": "ets_runtime", + "path": [ + "arkcompiler/ets_runtime" + ] + }, + "jerryscript": { + "name": "jerryscript", + "path": [ + "third_party/jerryscript" + ] + }, + "safwk": { + "name": "safwk", + "path": [ + "foundation/systemabilitymgr/safwk" + ] + }, + "safwk_lite": { + "name": "safwk_lite", + "path": [ + "foundation/systemabilitymgr/safwk_lite" + ] + }, + "samgr_lite": { + "name": "samgr_lite", + "path": [ + "foundation/systemabilitymgr/samgr_lite" + ] + }, + "samgr": { + "name": "samgr", + "path": [ + "foundation/systemabilitymgr/samgr" + ] + }, + "dmsfwk": { + "name": "dmsfwk", + "path": [ + "foundation/ability/dmsfwk" + ] + }, + "dmsfwk_lite": { + "name": "dmsfwk_lite", + "path": [ + "foundation/ability/dmsfwk_lite" + ] + }, + "window": { + "name": "window", + "path": [ + "foundation/window/window_manager" + ] + }, + "utils_lite": { + "name": "utils_lite", + "path": [ + "commonlibrary/utils_lite" + ] + }, + "c_utils": { + "name": "c_utils", + "path": [ + "commonlibrary/c_utils" + ] + }, + "ets_utils": { + "name": "ets_utils", + "path": [ + "commonlibrary/ets_utils" + ] + }, + "selinux": { + "name": "selinux", + "path": [ + "base/security/selinux" + ] + }, + "access_token": { + "name": "access_token", + "path": [ + "base/security/access_token" + ] + }, + "permission_lite": { + "name": "permission_lite", + "path": [ + "base/security/permission_lite" + ] + }, + "dlp_permission_service": { + "name": "dlp_permission_service", + "path": [ + "base/security/dlp_permission_service" + ] + }, + "dlp_credential_service": { + "name": "dlp_credential_service", + "path": [ + "base/security/dlp_credential_service" + ] + }, + "memmgr": { + "name": "memmgr", + "path": [ + "foundation/resourceschedule/memmgr_plugin" + ] + }, + "utils_memory": { + "name": "utils_memory", + "path": [ + "utils/memory" + ] + }, + "frame_aware_sched": { + "name": "frame_aware_sched", + "path": [ + "foundation/resourceschedule/frame_aware_sched" + ] + }, + "sys_installer": { + "name": "sys_installer", + "path": [ + "base/update/sys_installer" + ] + }, + "updater": { + "name": "updater", + "path": [ + "base/update/updater" + ] + }, + "dupdate_engine": { + "name": "dupdate_engine", + "path": [ + "base/update/dupdate_engine" + ] + }, + "memory_utils": { + "name": "memory_utils", + "path": [ + "commonlibrary/memory_utils" + ] + }, + "resourceschedule_ffrt_core": { + "name": "resourceschedule_ffrt_core", + "path": [ + "foundation/resourceschedule/ffrt_core" + ] + }, + "resourceschedule_ffrt_sched_override": { + "name": "resourceschedule_ffrt_sched_override", + "path": [ + "vendor/huawei/foundation/resourceschedule/ffrt_sched_override" + ] + }, + "ace_engine": { + "name": "ace_engine", + "path": [ + "foundation/arkui/ace_engine/frameworks/base/geometry", + "foundation/arkui/ace_engine/frameworks/base/json", + "foundation/arkui/ace_engine/frameworks/base/utils", + "foundation/arkui/ace_engine/frameworks/bridge/card_frontend", + "foundation/arkui/ace_engine/frameworks/bridge/common/manifest", + "foundation/arkui/ace_engine/frameworks/bridge/common/media_query", + "foundation/arkui/ace_engine/frameworks/bridge/common/plugin_adapter", + "foundation/arkui/ace_engine/frameworks/bridge/common/utils", + "foundation/arkui/ace_engine/frameworks/bridge/plugin_frontend", + "foundation/arkui/ace_engine/interfaces" + ] + }, + "ace_engine_core": { + "name": "ace_engine_core", + "path": [ + "foundation/arkui/ace_engine/frameworks/core/accessibility", + "foundation/arkui/ace_engine/frameworks/core/common", + "foundation/arkui/ace_engine/frameworks/core/components_ng", + "foundation/arkui/ace_engine/frameworks/core/pipeline_ng" + ] + } +} + + + + + + + + + + + + + + + + + + + diff --git a/localCoverage/codeCoverage/__init__.py b/localCoverage/codeCoverage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/localCoverage/codeCoverage/codeCoverage_gcov_lcov.py b/localCoverage/codeCoverage/codeCoverage_gcov_lcov.py new file mode 100644 index 0000000000000000000000000000000000000000..e70b144586c7f3857f4a0ba44ba2b39cb49bf128 --- /dev/null +++ b/localCoverage/codeCoverage/codeCoverage_gcov_lcov.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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. +# + + +import os +import json +import shutil +import shlex +import subprocess + + +# 代码根目录 +root_path = os.getcwd() +CODEPATH = root_path.split("/test/testfwk/developer_test")[0] +# 子系统json目录 +SYSTEM_JSON = "build/subsystem_config.json" +# 覆盖率gcda +COVERAGE_GCDA_RESULTS = "test/localCoverage/codeCoverage/results/coverage/data/cxx" +# 报告路径 +REPORT_PATH = "test/localCoverage/codeCoverage/results/coverage/reports/cxx" +# llvm-gcov.sh +LLVM_GCOV = "test/localCoverage/codeCoverage/llvm-gcov.sh" +# 编译生成的out路径 +OUTPUT = "out/baltimore" +# 屏蔽列表 +FILTEROUT_DIRS = ["unittest", "third_party", "test"] + + +def call(cmd_list, is_show_cmd=False, out=None, err=None): + return_flag = False + try: + if is_show_cmd: + print("execute command: {}".format(" ".join(cmd_list))) + if 0 == subprocess.call(cmd_list, shell=False, stdout=out, stderr=err): + return_flag = True + except Exception: + print("Error : command {} execute faild!".format(cmd_list)) + return_flag = False + return return_flag + + +def execute_command(command, printflag=False): + try: + cmd_list = shlex.split(command) + with open("coverage.log", 'a') as fd: + call(cmd_list, printflag, fd, fd) + except IOError as err: + print("Error: Exception occur in open: %s", err.message) + + +def get_subsystem_config_info(): + subsystem_info_dic = {} + subsystem_config_filepath = os.path.join(CODEPATH, SYSTEM_JSON) + if os.path.exists(subsystem_config_filepath): + data = None + with open(subsystem_config_filepath, 'r') as f: + data = json.load(f) + if not data: + print("subsystem config file error.") + for value in data.values(): + subsystem_name = value.get('name') + subsystem_dir = value.get('dir') + subsystem_path = value.get('path') + subsystem_project = value.get('project') + subsystem_rootpath = os.path.join(CODEPATH, subsystem_path) + subsystem_info_dic[subsystem_name] = [ + subsystem_project, subsystem_dir, + subsystem_path, subsystem_rootpath + ] + return subsystem_info_dic + + +def get_subsystem_name_list(): + subsystem_name_list = [] + subsystem_info_dic = get_subsystem_config_info() + for key in subsystem_info_dic.keys(): + subsystem_rootpath = subsystem_info_dic[key][3] + if os.path.exists(subsystem_rootpath): + subsystem_name_list.append(key) + return subsystem_name_list + + +def get_subsystem_rootpath(subsystem_name): + subsystem_path = "" + subsystem_rootpath = "" + subsystem_info_dic = get_subsystem_config_info() + for key in subsystem_info_dic.keys(): + if key == subsystem_name: + subsystem_path = subsystem_info_dic[key][2] + subsystem_rootpath = subsystem_info_dic[key][3] + break + return subsystem_path, subsystem_rootpath + + +def is_filterout_dir(ignore_prefix, check_path): + for dir in FILTEROUT_DIRS: + check_list = check_path[len(ignore_prefix):].split("/") + if dir in check_list: + return True + return False + + +def rm_unnecessary_dir(cov_path): + topdir = os.path.join(cov_path, "obj") + for root, dirs, files in os.walk(topdir): + if is_filterout_dir(topdir, root): + shutil.rmtree(root) + + +def get_files_from_dir(find_path, postfix=None): + names = os.listdir(find_path) + file_list = [] + for fn in names: + if not os.path.isfile(os.path.join(find_path, fn)): + continue + if postfix is not None: + if fn.endswith(postfix): + file_list.append(fn) + else: + file_list.append(fn) + return file_list + + +def get_gcno_files(cov_path, dir_name): + gcda_strip_path = dir_name[len(cov_path) + 1:] + gcda_list = get_files_from_dir(dir_name, ".gcda") + for file_name in gcda_list: + gcno_name = os.path.splitext(file_name)[0] + ".gcno" + gcno_path = os.path.join(os.path.join(CODEPATH, OUTPUT), + gcda_strip_path, gcno_name) + if os.path.exists(gcno_path): + if os.path.exists(gcno_path): + shutil.copy(gcno_path, dir_name) + else: + print("%s not exists!", gcno_path) + + +def get_module_gcno_files(cov_path, dir_name): + for root, dirs, files in os.walk(dir_name): + get_gcno_files(cov_path, root) + + +def gen_subsystem_trace_info(subsystem, data_dir, test_dir): + src_dir = os.path.join(CODEPATH, OUTPUT) + single_info_path = os.path.join(CODEPATH, REPORT_PATH, + "single_test", test_dir) + if not os.path.exists(single_info_path): + os.makedirs(single_info_path) + output_name = os.path.join(CODEPATH, single_info_path, + subsystem +"_output.info") + if not os.path.exists(src_dir): + print("Sours path %s not exist!", src_dir) + return + cmd = "lcov -c -b {} -d {} --gcov-tool {} -o {} --ignore-errors source,gcov" \ + .format(src_dir, data_dir, os.path.join( + CODEPATH, LLVM_GCOV), output_name) + print("single_test**" + cmd) + execute_command(cmd) + + +def cut_info(subsystem, test_dir): + trace_file = os.path.join( + CODEPATH, REPORT_PATH, "single_test", + test_dir, subsystem + "_output.info") + output_name = os.path.join( + CODEPATH, REPORT_PATH, "single_test", + test_dir, subsystem + "_strip.info") + remove = r"'*/unittest/*' '*/third_party/*' 'sdk/android-arm64/*'" + if not os.path.exists(trace_file): + print("Error: trace file %s not exisit!", trace_file) + return + cmd = "lcov --remove {} {} -o {}".format(trace_file, remove, output_name) + execute_command(cmd) + + +def gen_info(cov_path, test_dir, subsystem_list): + if len(subsystem_list) == 0: + return + for subsystem in subsystem_list: + (subsystem_path, subsystem_rootpath) = get_subsystem_rootpath(subsystem) + subsystem_data_abspath = os.path.join(cov_path, "obj", subsystem_path) + if not os.path.exists(subsystem_data_abspath): + continue + get_module_gcno_files(cov_path, subsystem_data_abspath) + gen_subsystem_trace_info(subsystem, subsystem_data_abspath, test_dir) + cut_info(subsystem, test_dir) + + +def gen_all_test_info(subsystem_list=[]): + cov_path = os.path.join(CODEPATH, COVERAGE_GCDA_RESULTS) + single_test_dir_list = [] + for root, dirs, files in os.walk(cov_path): + single_test_dir_list = dirs + break + for index, cur_test_dir in enumerate(single_test_dir_list): + cur_test_abs_dir = os.path.join(cov_path, cur_test_dir) + rm_unnecessary_dir(cur_test_abs_dir) + gen_info(cur_test_abs_dir, cur_test_dir, subsystem_list) + + +def merge_subsystem_info_from_all_test(subsystem): + single_test_info_path = os.path.join(CODEPATH, REPORT_PATH, "single_test") + subsystem_info_list = [] + subsystem_info_name = subsystem + "_strip.info" + for root, dirs, files in os.walk(single_test_info_path): + if subsystem_info_name in files: + subsystem_info_path_tmp = os.path.join( + single_test_info_path, root, subsystem_info_name) + subsystem_info_list.append(subsystem_info_path_tmp) + if len(subsystem_info_list) == 0: + return + info_output_name = os.path.join( + CODEPATH, REPORT_PATH, subsystem_info_name) + cmd = "lcov -a {} -o {}".format( + " -a ".join(subsystem_info_list), info_output_name) + execute_command(cmd) + + +def merge_all_test_subsystem_info(subsystem_list): + single_test_info_path = os.path.join( + CODEPATH, REPORT_PATH, "single_test") + if not os.path.exists(single_test_info_path): + print("Error: the single test info path %s not exist", + single_test_info_path) + return + for subsystem in subsystem_list: + print("Merging all %s info from test data......", subsystem) + merge_subsystem_info_from_all_test(subsystem) + + +def merge_info(report_dir): + if not os.path.exists(report_dir): + print("Error: report dir %s not exist", report_dir) + return + subsystem_name_list = get_files_from_dir(report_dir, "_strip.info") + if len(subsystem_name_list) == 0: + print("Error: get subsytem trace files in \report directory failed.") + return + trace_file_list = [] + for subsystem in subsystem_name_list: + trace_file_name = os.path.join(report_dir, subsystem) + trace_file_list.append(trace_file_name) + cmd = "lcov -a {} -o {}".format(" -a ".join(trace_file_list), + os.path.join( + report_dir, "ohos_codeCoverage.info")) + execute_command(cmd) + + +def merge_all_subsystem_info(): + print("Merging all the sysbsystem trace files......") + merge_info(os.path.join(CODEPATH, REPORT_PATH)) + + +def gen_html(cov_path): + tracefile = os.path.join(CODEPATH, REPORT_PATH, "ohos_codeCoverage.info") + if not os.path.exists(tracefile): + print("Error: the trace file %s not exist", tracefile) + return + cmd = "genhtml --branch-coverage --demangle-cpp -o {} -p {} --ignore-errors source {}"\ + .format(os.path.join(CODEPATH, REPORT_PATH, "html"), CODEPATH, tracefile) + execute_command(cmd) + + +def gen_final_report(cov_path): + print("Generating the html report......") + gen_html(cov_path) + + +if __name__ == "__main__": + gen_all_test_info(subsystem_list=get_subsystem_name_list()) + merge_all_test_subsystem_info(subsystem_list=get_subsystem_name_list()) + merge_all_subsystem_info() + gen_final_report(os.path.join(CODEPATH, COVERAGE_GCDA_RESULTS)) diff --git a/localCoverage/codeCoverage/coverage_rc/lcovrc_cov_template b/localCoverage/codeCoverage/coverage_rc/lcovrc_cov_template new file mode 100644 index 0000000000000000000000000000000000000000..0f99e76a8a1b9acf728a58c019bbffa718fb4570 --- /dev/null +++ b/localCoverage/codeCoverage/coverage_rc/lcovrc_cov_template @@ -0,0 +1,175 @@ +# +# Copyright (c) 2023 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. +# +# +# /etc/lcovrc - system-wide defaults for LCOV +# +# To change settings for a single user, place a customized copy of this file +# at location ~/.lcovrc +# + +# Specify an external style sheet file (same as -css-file option of genhtml) +# genhtml_css_file = gcov.css + +# Specify coverage rate limits (in %) for classifying file entries +# HI: hi_limit <= rate <= 100 graph color: green +# MED: med_limit <= rate < hi_limit graph color: orange +# LO: 0 <= rate < med_limit graph color: red +genhtml_hi_limit = 90 +genhtml_med_limit = 75 + +# Width of line coverage field in source code view +genhtml_line_field_width = 12 + +# Width of branch coverage field in source code view +genhtml_branch_field_width = 16 + +# Width of overview image (used by --frames option of genhtml) +genhtml_overview_width = 80 + +# Resolution of overview navigation: this number specifies the maximum +# difference in lines between the position a user selected from the overview +# and the position the source code window is scrolled to (used by --frames +# option of genhtml) +genhtml_nav_resolution = 4 + +# Clicking a line in the overview image should show the source code view at +# a position a bit further up so that the requested line is not the first +# line in the window. This number specifies that offset in lines (used by +# --frames option of genhtml) +genhtml_nav_offset = 10 + +# Do not remove unused test descriptions if non-zero (same as +# --keep-descriptions option of genhtml) +genhtml_keep_descriptions = 0 + +# Do not remove prefix from directory names if non-zero (same as --no-prefix +# option of genhtml) +genhtml_no_prefix = 0 + +# Do not create source code view if non-zero (same as --no-source option of +# genhtml) +genhtml_no_source = 0 + +# Replace tabs with number of spaces in source view (same as --num-spaces +# option of genhtml) +genhtml_num_spaces = 8 + +# Highlight lines with converted-only data if non-zero (same as --highlight +# option of genhtml) +genhtml_highlight = 0 + +# Include color legend in HTML output if non-zero (same as --legend option of +# genhtml) +genhtml_legend = 0 + +# Use FILE as HTML prolog for generated pages (same as --html-prolog option of +# genhtml) +# genhtml_html_prolog = FILE + +# Use FILE as HTML epilog for generated pages (same as --html-epilog option of +# genhtml) +# genhtml_html_epilog = FILE + +# Use custom filename extension for pages (same as --html-extension option of +# genhtml) +# genhtml_html_extension = html + +# Compress all generated html files with gzip. +# genhtml_html_gzip = 1 + +# Include sorted overview pages (can be disabled by the --no-sort option of +# genhtml) +genhtml_sort = 1 + +# Include function coverage data display (can be disabled by the +# --no-func-coverage option of genhtml) +# genhtml_function_coverage = 1 + +# Include branch coverage data display (can be disabled by the +# --no-branch-coverage option of genhtml) +# genhtml_branch_coverage = 1 + +# Specify the character set of all generated HTML pages +genhtml_charset=UTF-8 + +# Allow HTML markup in test case description text if non-zero +genhtml_desc_html = 0 + +# Specify the precision for coverage rates +# genhtml_precision = 1 + +# Location of the gcov tool (same as --gcov-info option of geninfo) +# geninfo_gcov_tool = gcov + +# Adjust test names to include operating system information if non-zero +# geninfo_adjust_testname = 0 + +# Calculate checksum for each source code line if non-zero (same as --checksum +# option of geninfo if non-zero, same as --no-checksum if zero) +# geninfo_checksum = 1 + +# Specify whether to capture coverage data for external source files (can +# be overridden by the --external and --no-external options of geninfo/lcov) +# geninfo_external = 1 + +# Enable libtool compatibility mode if non-zero (same as --compat-libtool option +# of geninfo if non-zero, same as --no-compat-libtool if zero) +# geninfo_compat_libtool = 0 + +# Specify compatiblity modes (same as --compat option of geninfo). +# geninfo_compat = libtool = on, hammer=auto, split_crc=auto + +# Adjust path to source files by removing or changing path components that +# match the specified pattern (Perl regular expression format) +# geninfo_adjust_src_path = /tmp/build => /usr/src + +# Specify if geninfo should try to automatically determine the base-directory +# when collecting coverage data. +geninfo_auto_base = 1 + +# Directory containing gcov kernel files +# lcov_gcov_dir = /proc/gcov + +# Location of the insmod tool +lcov_insmod_tool = /sbin/insmod + +# Location of the modprobe tool +lcov_modprobe_tool = /sbin/modprobe + +# Location of the rmmod tool +lcov_rmmod_tool = /sbin/rmmod + +# Show full paths during list operation if non-zero (same as --list-full-path +# option of lcov) +lcov_list_full_path = 0 + +# Specify the maximum width for list output. This value is ignored when +# lcov_list_full_path is non-zero. +lcov_list_width = 80 + +# Specify the maximum percentage of file names which may be truncated when +# choosing a directory prefix in list output. This value is ignored when +# lcov_list_full_path is non-zero. +lcov_list_truncate_max = 20 + +# Specify if function coverage data should be collected and processed. +lcov_function_coverage = 1 + +# Specify if branch coverage data should be collected and processed. +lcov_branch_coverage = 1 + +# Specify the regular expression of lines to exclude from branch coveragel +# Default is 'LCOV_EXCL_BR_LINE'. +lcov_excl_br_line = LCOV_EXCL_BR_LINE \ No newline at end of file diff --git a/localCoverage/codeCoverage/llvm-gcov.sh b/localCoverage/codeCoverage/llvm-gcov.sh new file mode 100644 index 0000000000000000000000000000000000000000..4045480a93649cedd119ba4b5ff25f7b8f80730d --- /dev/null +++ b/localCoverage/codeCoverage/llvm-gcov.sh @@ -0,0 +1,20 @@ +# !/bin/bash +# +# Copyright (c) 2023 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. +# +# This file is autogenerated by c_coverage_mgr.py, do not edit manually . + +current_path=$(cd $(dirname $0);pwd) +root_path=${current_path%%/test/testfwk/developer_test/localCoverage/codeCoverage} +exec $root_path/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-cov gcov "$@" diff --git a/localCoverage/codeCoverage/mutilProcess_CodeCoverage.py b/localCoverage/codeCoverage/mutilProcess_CodeCoverage.py new file mode 100644 index 0000000000000000000000000000000000000000..69a4e3402a8d3e44a202c45cf79a2c85c27379b8 --- /dev/null +++ b/localCoverage/codeCoverage/mutilProcess_CodeCoverage.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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. +# + +import os +import json +import shutil +import shlex +import subprocess +import multiprocessing +from multiprocessing import Process + + +# 根代码目录 +root_path = os.getcwd() +CODEPATH = root_path.split("/test/testfwk/developer_test")[0] +# 子系统json目录 +SYSTEM_JSON = "test/testfwk/developer_test/localCoverage/codeCoverage/subsystem_config.json" +# 覆盖率gcda +COVERAGE_GCDA_RESULTS = "test/testfwk/developer_test/localCoverage/codeCoverage/results/coverage/data/cxx" +# 报告路径 +REPORT_PATH = "test/testfwk/developer_test/localCoverage/codeCoverage/results/coverage/reports/cxx" +# llvm-gcov.sh +LLVM_GCOV = "test/testfwk/developer_test/localCoverage/codeCoverage/llvm-gcov.sh" +# 编译生成的out路径 +OUTPUT = "out/baltimore" +# 屏蔽列表 +FILTEROUT_DIRS = ["unittest", "third_party", "test"] +# 测试套划分步长 +STEP_SIZE = 10 +# lcovrc配置文件集合 +LCOVRC_SET = CODEPATH + "/test/testfwk/developer_test/localCoverage/codeCoverage/coverage_rc" + + +def call(cmd_list, is_show_cmd=False, out=None, err=None): + return_flag = False + try: + if is_show_cmd: + print("execute command: {}".format(" ".join(cmd_list))) + if 0 == subprocess.call(cmd_list, shell=False, stdout=out, stderr=err): + return_flag = True + except: + print("Error : command {} execute faild!".format(cmd_list)) + return_flag = False + + return return_flag + + +def execute_command(command, printflag=False): + try: + cmd_list = shlex.split(command) + with open("coverage.log", 'a') as fd: + call(cmd_list, printflag, fd, fd) + except IOError as err: + print("Error: Exception occur in open: %s", err.message) + + +def get_subsystem_config_info(): + filter_subsystem_name_list = [ + "subsystem_examples", + ] + subsystem_info_dic = {} + subsystem_config_filepath = os.path.join(CODEPATH, SYSTEM_JSON) + if os.path.exists(subsystem_config_filepath): + data = None + with open(subsystem_config_filepath, "r", encoding="utf-8") as f: + data = json.load(f) + if not data: + print("subsystem config file error.") + for value in data.values(): + subsystem_name = value.get("name") + if subsystem_name in filter_subsystem_name_list: + continue + subsystem_dir = value.get('dir') + subsystem_path = value.get('path') + subsystem_project = value.get('project') + subsystem_rootpath = [] + for path in subsystem_path: + subsystem_rootpath.append(os.path.join(CODEPATH, path)) + subsystem_info_dic[subsystem_name] = [ + subsystem_project, subsystem_dir, + subsystem_path, subsystem_rootpath + ] + return subsystem_info_dic + + +def get_subsystem_name_list(): + subsystem_name_list = [] + subsystem_info_dic = get_subsystem_config_info() + for key in subsystem_info_dic.keys(): + subsystem_rootpath = subsystem_info_dic[key][3] + for subsystem_rootpath_item in subsystem_rootpath: + if os.path.exists(subsystem_rootpath_item): + subsystem_name_list.append(key) + + return subsystem_name_list + + +def get_subsystem_rootpath(subsystem_name): + subsystem_path = "" + subsystem_rootpath = "" + subsystem_info_dic = get_subsystem_config_info() + for key in subsystem_info_dic.keys(): + if key == subsystem_name: + subsystem_path = subsystem_info_dic[key][2] + subsystem_rootpath = subsystem_info_dic[key][3] + break + + return subsystem_path, subsystem_rootpath + + +def is_filterout_dir(ignore_prefix, check_path): + for dir in FILTEROUT_DIRS: + check_list = check_path[len(ignore_prefix):].split("/") + if dir in check_list: + return True + + return False + + +def rm_unnecessary_dir(cov_path): + topdir = os.path.join(cov_path, "obj") + for root, dirs, files in os.walk(topdir): + if is_filterout_dir(topdir, root): + shutil.rmtree(root) + + +def get_files_from_dir(find_path, postfix=None): + names = os.listdir(find_path) + file_list = [] + for fn in names: + if not os.path.isfile(os.path.join(find_path, fn)): + continue + if postfix is not None: + if fn.endswith(postfix): + file_list.append(fn) + else: + file_list.append(fn) + + return file_list + + +def get_gcno_files(cov_path, dir_name): + gcda_strip_path = dir_name[len(cov_path) + 1:] + gcda_list = get_files_from_dir(dir_name, ".gcda") + for file_name in gcda_list: + gcno_name = os.path.splitext(file_name)[0] + ".gcno" + gcno_path = os.path.join( + os.path.join(CODEPATH, OUTPUT), gcda_strip_path, gcno_name + ) + if os.path.exists(gcno_path): + shutil.copy(gcno_path, dir_name) + else: + print(f"{gcno_path} not exists!") + + +def get_module_gcno_files(cov_path, dir_name): + for root, dirs, files in os.walk(dir_name): + get_gcno_files(cov_path, root) + + +def gen_subsystem_trace_info(subsystem, data_dir, test_dir, lcovrc_path): + src_dir = os.path.join(CODEPATH, OUTPUT) + single_info_path = os.path.join( + CODEPATH, REPORT_PATH, "single_test", test_dir + ) + if not os.path.exists(single_info_path): + os.makedirs(single_info_path) + output_name = os.path.join( + CODEPATH, single_info_path, subsystem + "_output.info" + ) + if not os.path.exists(src_dir): + print(f"Sours path {src_dir} not exists!") + return + + cmd = "lcov -c -b {} -d {} --gcov-tool {} --config-file {} -o {} --ignore-errors" \ + "source,gcov".format(src_dir, data_dir, os.path.join( + CODEPATH, LLVM_GCOV), lcovrc_path, output_name) + print("single_test**##father_pid:%s##child_pid:%s cmd:%s config file:%s"%( + os.getpid(), os.getppid(), cmd, lcovrc_path + )) + execute_command(cmd) + + +def cut_info(subsystem, test_dir): + trace_file = os.path.join( + CODEPATH, REPORT_PATH, "single_test", + test_dir, subsystem + "_output.info" + ) + output_name = os.path.join( + CODEPATH, REPORT_PATH, "single_test", + test_dir, subsystem + "_strip.info" + ) + + remove = r"'*/third_party/*' 'sdk/android-arm64/*'" + if not os.path.exists(trace_file): + print(f"Error: trace file {trace_file} not exists!") + return + + cmd = "lcov --remove {} {} -o {}".format(trace_file, remove, output_name) + execute_command(cmd) + + +def gen_info(cov_path, test_dir, subsystem_list, lcovrc_path): + if len(subsystem_list) == 0: + print("Error: get subsystem list failed, can not generate trace info") + return + + loop = 0 + for subsystem in list(set(subsystem_list)): + subsystem_path, subsystem_rootpath = get_subsystem_rootpath(subsystem) + for subsys_path in subsystem_path: + subsystem_data_abspath = os.path.join(cov_path, "obj", subsys_path) + # check id subsystem data is exists + if not os.path.exists(subsystem_data_abspath): + continue + + # copy gcno to the gcda same directory + get_module_gcno_files(cov_path, subsystem_data_abspath) + + # generate coverage info for each subsystem + gen_subsystem_trace_info( + subsystem + "#" + subsys_path.replace("/", "_") + "#" + str(loop), + subsystem_data_abspath, test_dir, lcovrc_path + ) + + # remove some type which useless + cut_info(subsystem + "#" + subsys_path.replace("/", "_") + "#" + str(loop), test_dir) + + loop += 1 + + +def generate_coverage_info(single_test_dir_list, lcovrc_path, subsystem_list=[]): + cov_path = os.path.join(CODEPATH, COVERAGE_GCDA_RESULTS) + for index, cur_test_dir in enumerate(single_test_dir_list): + cur_test_abs_dir = os.path.join(cov_path, cur_test_dir) + gen_info(cur_test_abs_dir, cur_test_dir, subsystem_list, lcovrc_path) + + +def gen_all_test_info(subsystem_list=[]): + cov_path = os.path.join(CODEPATH, COVERAGE_GCDA_RESULTS) + print(os.getpid(), os.getppid()) + single_test_dir_list = [] + for root, dirs, files in os.walk(cov_path): + single_test_dir_list = dirs + break + + return single_test_dir_list + + +def merge_subsystem_info_from_all_test(subsystem): + single_test_info_path = os.path.join( + CODEPATH, REPORT_PATH, "single_test" + ) + subsystem_info_list = [] + subsystem_info_name = subsystem + "_strip.info" + for root, dirs, files in os.walk(single_test_info_path): + for file in files: + if file.startswith(subsystem) and file.endswith("_strip.info"): + subsystem_info_path_tmp = os.path.join( + single_test_info_path, root, file + ) + print("##" + subsystem_info_path_tmp) + subsystem_info_list.append(subsystem_info_path_tmp) + + if len(subsystem_info_list) == 0: + return + + info_output_name = os.path.join( + CODEPATH, REPORT_PATH, subsystem_info_name + ) + cmd = "lcov -a {} -o {}".format( + " -a ".join(subsystem_info_list), info_output_name + ) + execute_command(cmd) + + +def merge_all_test_subsystem_info(subsystem_list): + single_test_info_path = os.path.join( + CODEPATH, REPORT_PATH, "single_test" + ) + if not os.path.exists(single_test_info_path): + print(f"Error: the single test info path " + f"{single_test_info_path} not exist") + return + + for subsystem in subsystem_list: + print(f"Merging all {subsystem} info from test data") + merge_subsystem_info_from_all_test(subsystem) + + +def merge_info(report_dir): + if not os.path.exists(report_dir): + print(f"Error: report dir {report_dir} not exists!") + return + + subsystem_name_list = get_files_from_dir(report_dir, "_strip.info") + if len(subsystem_name_list) == 0: + print("Error: get subsystem trace files in report directory failed.") + return + + trace_file_list = [] + for subsystem in subsystem_name_list: + trace_file_name = os.path.join(report_dir, subsystem) + trace_file_list.append(trace_file_name) + + cmd = "lcov -a {} -o {}".format( + " -a ".join(trace_file_list), os.path.join(report_dir, "ohos_codeCoverage.info") + ) + execute_command(cmd) + + +def merge_all_subsystem_info(): + print("Merging all the subsystem trace files") + merge_info(os.path.join(CODEPATH, REPORT_PATH)) + + +def gen_html(cov_path): + tracefile = os.path.join(CODEPATH, REPORT_PATH, "ohos_codeCoverage.info") + if not os.path.exists(tracefile): + print(f"Error: the trace file {tracefile} not exists!") + return + + cmd = "genhtml --branch-coverage --demangle-cpp -o {} -p {} --ignore-errors " \ + "source {}".format(os.path.join(CODEPATH, REPORT_PATH, "html"), + CODEPATH, tracefile) + execute_command(cmd) + + +def gen_final_report(cov_path): + print("Generating the html report") + gen_html(cov_path) + + +if __name__ == '__main__': + caseLst = gen_all_test_info(subsystem_list=get_subsystem_name_list()) + multiprocessing.set_start_method("fork") # fork spawn forkserver + start = end = 0 + Tag = False + process_list = [] + for i in range(len(caseLst)): + lcovrc_path = LCOVRC_SET + "/" + "lcovrc_cov" + str(i) + print(lcovrc_path) + if os.path.exists(lcovrc_path): + print(lcovrc_path + "@" * 20 + "yes") + else: + raise Exception("mutilProcess have error -rc path not existed. " + "please fix add run") + + start = end + end += STEP_SIZE + if end >= len(caseLst): + end = len(caseLst) + Tag = True + + p = Process(target=generate_coverage_info, + args=(caseLst[start:end], lcovrc_path, + get_subsystem_name_list())) + p.daemon = True + p.start() + process_list.append(p) + if Tag: + break + + for i in process_list: + i.join() + + merge_all_test_subsystem_info(subsystem_list=get_subsystem_name_list()) + merge_all_subsystem_info() + gen_final_report(os.path.join(CODEPATH, COVERAGE_GCDA_RESULTS)) + + + + + + + + + + + + + + + + + + + + + diff --git a/localCoverage/coverage_tools.py b/localCoverage/coverage_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..f36f735308e61aee8cc68994449dd25eafbf290e --- /dev/null +++ b/localCoverage/coverage_tools.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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. +# + + +import os +import sys +import json +import shutil +import subprocess +from shutil import copyfile + + +def get_subsystem_config(test_part_list): + all_system_info_path = os.path.join( + developer_path, + "developer_test/localCoverage/all_subsystem_config.json" + ) + system_info_path = os.path.join( + developer_path, + "developer_test/localCoverage/codeCoverage/subsystem_config.json" + ) + if os.path.exists(all_system_info_path): + new_json_text = {} + for part in test_part_list: + with open(all_system_info_path, "r", encoding="utf-8") as system_text: + system_text_json = json.load(system_text) + if part in system_text_json: + new_json_text[part] = system_text_json[part] + else: + print("part not in all_subsystem_config.json") + + new_json = json.dumps(new_json_text, indent=4) + with open(system_info_path, "w") as out_file: + out_file.write(new_json) + else: + print("%s not exists.", all_system_info_path) + + +def copy_coverage(): + print("[*************** Start TO Get Coverage Report ***************]") + coverage_path = os.path.join( + developer_path, "developer_test/reports/coverage" + ) + code_path = os.path.join( + developer_path, + "developer_test/localCoverage/codeCoverage/results/coverage" + ) + if os.path.exists(code_path): + shutil.rmtree(code_path) + shutil.copytree(coverage_path, code_path) + + +def generate_coverage_rc(developer_path): + coverage_rc_path = os.path.join( + developer_path, + "developer_test/localCoverage/codeCoverage/coverage_rc" + ) + lcovrc_cov_template_path = os.path.join(coverage_rc_path, "lcovrc_cov_template") + for num in range(16): + tmp_cov_path = os.path.join(coverage_rc_path, f"tmp_cov_{num}") + lcovrc_cov_path = os.path.join(coverage_rc_path, f"lcovrc_cov_{num}") + if not os.path.exists(tmp_cov_path): + os.mkdir(tmp_cov_path) + if not os.path.exists(os.path.join(tmp_cov_path, "ex.txt")): + with open(os.path.join(tmp_cov_path, "ex.txt"), mode="w") as f: + f.write("") + + copyfile(lcovrc_cov_template_path, lcovrc_cov_path) + with open(lcovrc_cov_path, mode="a") as f: + f.write("\n\n") + f.write("# Location for temporary directories\n") + f.write(f"lcov_tmp_dir = {tmp_cov_path}") + + +def execute_code_cov_tools(): + llvm_gcov_path = os.path.join( + developer_path, + "developer_test/localCoverage/codeCoverage/llvm-gcov.sh" + ) + subprocess.Popen("dos2unix %s" % llvm_gcov_path, shell=True).communicate() + tools_path = os.path.join( + developer_path, + "developer_test/localCoverage/codeCoverage/mutilProcess_CodeCoverage.py" + ) + code_coverage_process = subprocess.Popen("python3 %s" % tools_path, shell=True) + code_coverage_process.communicate() + + +def get_subsystem_name(test_part_list): + testfwk_json_path = os.path.join( + root_path, "out/baltimore/build_configs/infos_for_testfwk.json" + ) + if os.path.exists(testfwk_json_path): + with open(testfwk_json_path, "r", encoding="utf-8") as json_text: + system_json = json.load(json_text) + subsystem_info = system_json.get("phone").get("subsystem_infos") + subsystem_list = [] + for part in test_part_list: + for key in subsystem_info.keys(): + if part in subsystem_info.keys() and key not in subsystem_list: + subsystem_list.append(key) + subsystem_str = ','.join(list(map(str, subsystem_list))) + return subsystem_str + else: + print("%s not exists.", testfwk_json_path) + + +def execute_interface_cov_tools(subsystem_str): + print("[*************** Start TO Get Interface Coverage Report ***************]") + innerkits_json_path = os.path.join( + developer_path, + "developer_test/localCoverage/interfaceCoverage/get_innerkits_json.py" + ) + interface_coverage_process = subprocess.Popen( + "python3 %s" % innerkits_json_path, shell=True + ) + interface_coverage_process.communicate() + + interface_path = os.path.join( + developer_path, + "developer_test/localCoverage/interfaceCoverage/interfaceCoverage_gcov_lcov.py" + ) + subprocess.run("python2 %s %s" % (interface_path, subsystem_str), shell=True) + + +if __name__ == '__main__': + testpart_args = sys.argv[1] + subsystem_args = sys.argv[2] + test_part_list = testpart_args.split("testpart=")[1].split(",") + subsystem_args_str = subsystem_args.split("subsystem=")[1] + + current_path = os.getcwd() + root_path = current_path.split("/test/testfwk/developer_test")[0] + developer_path = current_path.split("/developer_test/src")[0] + + # copy gcda数据到覆盖率工具指定位置 + copy_coverage() + generate_coverage_rc(developer_path) + + # 获取部件位置信息config + if len(test_part_list) > 0: + get_subsystem_config(test_part_list) + + # 执行代码覆盖率 + execute_code_cov_tools() + + # 执行接口覆盖率 + if subsystem_args_str: + subsystem_str = subsystem_args_str + else: + subsystem_str = get_subsystem_name(test_part_list) + + if subsystem_str: + execute_interface_cov_tools(subsystem_str) + else: + print("subsystem or part without!") + + + diff --git a/localCoverage/interfaceCoverage/__init__.py b/localCoverage/interfaceCoverage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/localCoverage/interfaceCoverage/get_innerkits_json.py b/localCoverage/interfaceCoverage/get_innerkits_json.py new file mode 100644 index 0000000000000000000000000000000000000000..94107b6695bb9ff30a7a4d33508c41654d432f8d --- /dev/null +++ b/localCoverage/interfaceCoverage/get_innerkits_json.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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. +# + + +import os +import json +import subprocess + + +def genPartsInfoJSON(folder_list, output_json_path): + """ + 根据部件信息,生成字典至json文件中 + """ + if len(folder_list) != 0: + data_dict = {} + for folder_str in folder_list: + data_dict[folder_str] = "innerkits/ohos-arm64/" + folder_str + output_json_path = os.path.join(output_json_path, "kits_modules_info.json") + json_str = json.dumps(data_dict, indent=2) + with open(output_json_path, "w") as json_file: + json_file.write(json_str) + else: + print("Failed to obtain component information") + + +def getPartsJson(path): + """ + #获取out/ohos-arm-release/innerkits/ohos-arm内部接口文件夹名称列表 + """ + if os.path.exists(path): + folder_list = os.listdir(path) + else: + print("The folder does not exist") + folder_list = [] + return folder_list + + +if __name__ == "__main__": + current_path = os.getcwd() + root_path = current_path.split("/test/testfwk/developer_test")[0] + part_info_path = os.path.join( + root_path, "out/baltimore/innerkits/ohos-arm64" + ) + output_json_path = os.path.join( + root_path, "out/baltimore/packages/phone/innerkits/ohos-arm64" + ) + subprocess.Popen("mkdir -p " + output_json_path, shell=True) + folder_list = getPartsJson(part_info_path) + genPartsInfoJSON(folder_list, output_json_path) + diff --git a/localCoverage/interfaceCoverage/interfaceCoverage_gcov_lcov.py b/localCoverage/interfaceCoverage/interfaceCoverage_gcov_lcov.py new file mode 100644 index 0000000000000000000000000000000000000000..66c77e85d482a9b677b70f0da1d9da7eb93cc446 --- /dev/null +++ b/localCoverage/interfaceCoverage/interfaceCoverage_gcov_lcov.py @@ -0,0 +1,461 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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. +# + + +import os +import sys +import json +import shutil +import subprocess +import CppHeaderParser +import get_innerkits_json +import makeReport + + +root_path = os.getcwd() +CODEPATH = root_path.split("/test/testfwk/developer_test")[0] +PATH_INFO_PATH = "out/baltimore/innerkits/ohos-arm64" +OUTPUT_JSON_PATH = "out/baltimore/packages/phone/innerkits/ohos-arm64" +KIT_MODULES_INFO = "out/baltimore/packages/phone/innerkits/ohos-arm64/kits_modules_info.json" +SUB_SYSTEM_INFO_PATH = os.path.join( + CODEPATH, "test/testfwk/developer_test/localCoverage/codeCoverage/results/coverage/reports/cxx") +OUTPUT_REPORT_PATH = os.path.join( + CODEPATH, "test/testfwk/developer_test/localCoverage/interfaceCoverage/results/coverage/interface_kits" +) + + +filter_file_name_list = [ + "appexecfwk/libjnikit/include/jni.h", +] +FILTER_CLASS_ATTRIBUTE_LIST = ["ACE_EXPORT", "OHOS_NWEB_EXPORT"] + + +def create_coverage_result_outpath(filepath): + if os.path.exists(filepath): + shutil.rmtree(filepath) + os.makedirs(filepath) + + +def get_subsystem_part_list(project_rootpath): + subsystme_part_dict = {} + subsystem_part_config_filepath = os.path.join( + project_rootpath, "out/baltimore/build_configs", "infos_for_testfwk.json") + print(subsystem_part_config_filepath) + if os.path.exists(subsystem_part_config_filepath): + try: + with open(subsystem_part_config_filepath, 'r') as f: + data = json.load(f) + except IOError as err_msg: + print("Error for open subsystem config file: ", err_msg) + if not data: + print("subsystem_part config file error.") + else: + subsystme_part_dict= data.get("phone", "").get("subsystem_infos", "") + return subsystme_part_dict + else: + print("subsystem_part_config_filepath not exists.") + + +def load_json_data(): + json_file_path = os.path.join(CODEPATH, KIT_MODULES_INFO) + json_data_dic = {} + if os.path.isfile(json_file_path): + try: + with open(json_file_path, 'r') as f: + json_data_dic = json.load(f) + if not json_data_dic: + print("Loadind file \"%s\" error" % json_file_path) + return {} + except(IOError, ValueError) as err_msg: + print("Error for load_json_data: \"%s\"" % json_file_path, err_msg) + else: + print("Info: \"%s\" not exist." % json_file_path) + return json_data_dic + + +def get_file_list(find_path, postfix): + file_names = os.listdir(find_path) + file_list = [] + if len(file_names) > 0: + for fn in file_names: + if fn.find(postfix) != -1 and fn[-len(postfix):] == postfix: + file_list.append(fn) + return file_list + + +def get_file_list_by_postfix(path, postfix, filter_jar=""): + file_list = [] + for dirs in os.walk(path): + files = get_file_list(find_path=dirs[0], postfix=postfix) + for file_path in files: + if "" != file_path and -1 == file_path.find(__file__): + pos = file_path.rfind(os.sep) + file_name = file_path[pos+1:] + file_path = os.path.join(dirs[0], file_path) + if filter_jar != "" and file_name == filter_jar: + print("Skipped %s" % file_path) + continue + file_list.append(file_path) + return file_list + + +def is_need_to_be_parsed(filepath): + for item in filter_file_name_list: + if -1 != filepath.find(item): + return False + return True + + +def get_pubilc_func_list_from_headfile(cxx_header_filepath): + pubilc_func_list = [] + try: + cpp_header = CppHeaderParser.CppHeader(cxx_header_filepath) + for classname in cpp_header.classes: + class_name = classname + curr_class = cpp_header.classes[classname] + for func in curr_class["methods"]["public"]: + func_returntype = func["rtnType"] + func_name = func["name"] + if class_name in FILTER_CLASS_ATTRIBUTE_LIST: + class_name = func_name + if func_returntype.find("KVSTORE_API") != -1: + func_returntype = func_returntype.replace("KVSTORE_API", "").strip() + if func_name.isupper(): + continue + if class_name == func_name: + destructor = func["destructor"] + if destructor == True: + func_name = "~" + func_name + func_returntype = "" + debug = func["debug"].replace("KVSTORE_API", "") + debug = debug.replace(" ", "") + debug = debug.strip("{") + if debug.endswith("=delete;"): + continue + if debug.endswith("=default;"): + continue + if debug.startswith("inline"): + continue + if debug.startswith("constexpr"): + continue + if debug.startswith("virtual"): + continue + template = func["template"] + if template != False: + continue + param_type_list = [t["type"] for t in func["parameters"]] + pubilc_func_list.append((cxx_header_filepath, class_name, + func_name, param_type_list, func_returntype)) + for func in cpp_header.functions: + func_returntype = func["rtnType"] + func_name = func["name"] + if func_returntype.find("KVSTORE_API") != -1: + func_returntype = func_returntype.replace("KVSTORE_API", "").strip() + if func_name.isupper(): + continue + template = func["template"] + if template != False: + continue + debug = func["debug"].replace("KVSTORE_API", "") + debug = debug.replace(" ", "") + debug = debug.strip("{") + if debug.startswith("inline"): + continue + if debug.startswith("constexpr"): + continue + param_type_list = [t["type"] for t in func["parameters"]] + pubilc_func_list.append( + (cxx_header_filepath, "", func_name, param_type_list, + func_returntype) + ) + except CppHeaderParser.CppParseError as e: + print(e) + return pubilc_func_list + + +def get_sdk_interface_func_list(part_name): + interface_func_list = [] + sub_path = load_json_data().get(part_name, "") + if sub_path == "": + return interface_func_list + + sdk_path = os.path.join(CODEPATH, "out", "baltimore", sub_path) + if os.path.exists(sdk_path): + file_list = get_file_list_by_postfix(sdk_path, ".h") + for file in file_list: + try: + if is_need_to_be_parsed(file): + interface_func_list += get_pubilc_func_list_from_headfile(file) + except: + print("get interface error ", sdk_path) + else: + print("Error: %s is not exist." % sdk_path) + + print("interface_func_list:", interface_func_list) + return interface_func_list + + +def get_function_info_string(func_string): + function_info = "" + cxxfilt_filepath = "/usr/bin/c++filt" + if os.path.exists(cxxfilt_filepath): + command = ["c++filt", func_string] + function_info = subprocess.check_output(command, shell=False) + else: + print("/usr/bin/c++filt is not exist.") + return function_info + + +def get_covered_function_list(subsystem_name): + covered_function_list = [] + file_name = subsystem_name + "_strip.info" + file_path = os.path.join(SUB_SYSTEM_INFO_PATH, file_name) + if os.path.exists(file_path): + with open(file_path, "r") as fd: + for line in fd: + if line.startswith("FNDA:"): + sub_line_string = line[len("FNDA:"):].replace("\n", "").strip() + temp_list = sub_line_string.split(",") + if len(temp_list) == 2 and int(temp_list[0]) != 0: + func_info = get_function_info_string(temp_list[1]) + if "" == func_info: + continue + func_info = func_info.replace("\n", "") + if func_info == temp_list[1] and func_info.startswith("_"): + continue + covered_function_list.append(func_info) + else: + pass + return covered_function_list + + +def get_para_sub_string(content): + start_index = -1 + ended_index = -1 + parentheses_list_left = [] + parentheses_list_right = [] + + for index in range(len(content)): + char = content[index] + if "<" == char: + if 0 == len(parentheses_list_left): + start_index = index + parentheses_list_left.append(char) + continue + if ">" == char: + parentheses_list_right.append(char) + if len(parentheses_list_left) == len(parentheses_list_right): + ended_index = index + break + continue + + if -1 == start_index: + substring = content + else: + if -1 != ended_index: + substring = content[start_index:ended_index+1] + else: + substring = content[start_index:] + + return substring + + +def filter_para_sub_string(source): + content = source + if content != "": + while True: + pos = content.find("<") + if -1 != pos: + substring = get_para_sub_string(content[pos:]) + content = content.replace(substring, "") + else: + break + return content + + +def get_function_para_count(func_info): + pos_start = func_info.find("(") + pos_end = func_info.rfind(")") + content = func_info[pos_start+1: pos_end] + if "" == content: + return 0 + content = filter_para_sub_string(content) + para_list = content.split(",") + return len(para_list) + + +def get_covered_result_data(public_interface_func_list, covered_func_list, subsystem_name): + coverage_result_list = [] + for item in public_interface_func_list: + data_list = list(item) + file_path = data_list[0] + class_name = data_list[1] + func_name = data_list[2] + para_list = data_list[3] + return_val = data_list[4] + para_string = "" + for index in range(len(para_list)): + if para_list[index].strip() == "": + continue + curr_para = para_list[index] + para_string += curr_para + if index < len(para_list)-1: + para_string += ", " + fun_string = return_val + " " + func_name + "(" + para_string.strip().strip(",") + ")" + fun_string = fun_string.strip() + fun_string = filter_para_sub_string(fun_string) + + find_string = "" + if class_name != "": + find_string = "::" + class_name + "::" + func_name + "(" + else: + find_string = func_name + func_info_list = [] + for line in covered_func_list: + if -1 != line.find(find_string): + func_info_list.append(line) + curr_list = [class_name, fun_string] + if len(func_info_list) == 0: + curr_list.append("N") + elif len(func_info_list) == 1: + curr_list.append("Y") + else: + interface_para_count = len(para_list) + find_flag = False + for funcinfo in func_info_list: + if find_string == funcinfo: + curr_list.append("Y") + break + para_count = get_function_para_count(funcinfo) + if interface_para_count == para_count: + curr_list.append("Y") + find_flag = True + break + if not find_flag: + curr_list.append("N") + coverage_result_list.append(curr_list) + return coverage_result_list + + +def get_interface_coverage_result_list(subsystem_name,subsystem_part_dict): + part_list = subsystem_part_dict.get(subsystem_name, []) + public_interface_func_list = [] + for part_str in part_list: + try: + interface_func_list = get_sdk_interface_func_list(part_str) + public_interface_func_list.extend(interface_func_list) + except: + print("####") + covered_func_list = get_covered_function_list(subsystem_name) + interface_coverage_result_list = get_covered_result_data( + public_interface_func_list, covered_func_list, subsystem_name) + return interface_coverage_result_list + + +def get_coverage_data(data_list): + covered_count = 0 + total_count = len(data_list) + if 0 != total_count: + for item in data_list: + if "Y" == item[2] or "Recorded" == item[2]: + covered_count += 1 + coverage = str(covered_count * 100 / total_count) + "%" + else: + coverage = "0%" + return covered_count, coverage + + +def get_summary_data(interface_data_list): + summary_list = [] + total_count = 0 + covered_count = 0 + + for item in interface_data_list: + subsystem_name = item[0] + data_list = item[1] + if 0 != len(data_list): + count, coverage = get_coverage_data(data_list) + summary_list.append([subsystem_name, len(data_list), count, coverage]) + total_count += len(data_list) + covered_count += count + if 0 != total_count: + total_coverage = str(covered_count * 100 / total_count) + "%" + summary_list.append(["Summary", total_count, covered_count, total_coverage]) + return summary_list + + +def make_summary_file(summary_list, output_path): + report_path = os.path.join(output_path, "coverage_summary_file.xml") + try: + with open(report_path, "w") as fd: + fd.write('\n') + fd.write('\n') + for item in summary_list: + fd.write(" \n" % ( + item[0], str(item[1]), item[3])) + fd.write('\n') + except(IOError, ValueError) as err_msg: + print("Error for make coverage result: ", err_msg) + + +def make_result_file(interface_data_list, summary_list, output_path, title_name): + report_path = os.path.join(output_path, "ohos_interfaceCoverage.html") + makeReport.create_html_start(report_path) + makeReport.create_title(report_path, title_name, summary_list) + makeReport.create_summary(report_path, summary_list) + for item in interface_data_list: + subsystem_name = item[0] + data_list = item[1] + if 0 == len(data_list): + continue + count, coverage = get_coverage_data(data_list) + makeReport.create_table_test( + report_path, subsystem_name, data_list, len(data_list), count) + makeReport.create_html_ended(report_path) + + +def make_coverage_result_file(interface_data_list, output_path, title_name): + summary_list = get_summary_data(interface_data_list) + make_summary_file(summary_list, output_path) + make_result_file(interface_data_list, summary_list, output_path, title_name) + + +def make_interface_coverage_result(): + subsystem_name_list = system_name_list + interface_data_list = [] + subsystem_part_dict = get_subsystem_part_list(CODEPATH) + for subsystem_name in subsystem_name_list: + coverage_result_list = get_interface_coverage_result_list( + subsystem_name,subsystem_part_dict) + interface_data_list.append([subsystem_name, coverage_result_list]) + make_coverage_result_file(interface_data_list, OUTPUT_REPORT_PATH, + "Inner Interface") + + +if __name__ == "__main__": + system_args = sys.argv[1] + system_name_list = system_args.split(",") + get_innerkits_json.genPartsInfoJSON( + get_innerkits_json.getPartsJson(os.path.join(CODEPATH,PATH_INFO_PATH)), + os.path.join(CODEPATH,OUTPUT_JSON_PATH) + ) + if len(system_name_list) > 0: + make_interface_coverage_result() + else: + print("subsystem_name not exists!") diff --git a/localCoverage/interfaceCoverage/makeReport.py b/localCoverage/interfaceCoverage/makeReport.py new file mode 100644 index 0000000000000000000000000000000000000000..4b46f1653b34482ed1f070e0a326a4b7748ad200 --- /dev/null +++ b/localCoverage/interfaceCoverage/makeReport.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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. +# + + +import sys +import datetime +reload(sys) +sys.setdefaultencoding("utf-8") + + +g_html_head = """ + + + + + 接口覆盖率邮件模板 + + +""" +g_html_body_start = """ +""" + +g_html_body_ended = """ +""" +g_html_ended = """ +""" + + +def sort_by_field_element(elem): + return int(elem[3][:-1]) #@######value是浮点数,如1.0,那么需要先转float再转int + + +def sort_by_field_element_data(elem): + return elem[2] + + +def create_html_start(reportpath): + try: + with open(reportpath, "w") as report: + report.write(g_html_head) + report.write(g_html_body_start) + except(IOError, ValueError) as err_msg: + print("Error for create html start: ", err_msg) + + +def create_title(reportpath, title_name, summary_list): + currdatetime = datetime.date.today().strftime("%Y-%m-%d") + report_title = """ +

%s coverage report (%s)

+ """ + content = report_title % (title_name, currdatetime) + report_title = content + """ +
+ + + + +
+

Summary Report

+

接口总数%s, 已覆盖%s, 未覆盖%s

+
+
+ """ + summary_list.sort(key=sort_by_field_element, reverse=False) + subsystems = "" + count = 0 + for item in summary_list: + subsystem = item[0] + if count < 3: + subsystems = subsystems + "、" + subsystem + count = count + 1 + if subsystem == "Summary": + nocoverd = item[1] - item[2] + report_title = report_title % (item[1], item[2], nocoverd) + try: + with open(reportpath, "a") as report: + report.write(report_title) + except(IOError, ValueError) as err_msg: + print("Error for create html title: ", err_msg) + + +def create_summary(reportpath, summary_list): + table_title = """ +

Summary

+ """ + + table_start = """
""" + + table_head = """ + + + + + + """ + + table_line = """ + + + + + + + """ + + table_ended = """
SubsystemNameTotalCountCoveredCountCoverage
%s%s%s%s
+ """ + try: + if len(summary_list) == 0: + return + with open(reportpath, "a") as report: + report.write(table_title) + report.write(table_start) + report.write(table_head) + for item in summary_list: + content = table_line % (item[0], str(item[1]), str(item[2]), item[3]) + report.write(content) + report.write(table_ended) + except(IOError, ValueError) as err_msg: + print("Error for create html summary: ", err_msg) + + +def create_table_test(reportpath, subsystem_name, datalist, total_count, covered_count): + table_title = """ + %s details: + """ + table_start = """
""" + table_head = """ + + + + + + """ + table_line = """ + + + + + + + """ + table_summary = """ + + + + """ + table_ended = """
SubsystemNameClassNameInterfaceNameIsCovered
%s%s%s%s
TotalCount: %s, CoveredCount:%s, Coverage: %s
+ """ + try: + with open(reportpath, "a") as report: + print("subsystem_name==" + subsystem_name) + tabletitle = table_title % (subsystem_name) + print("tabletitle==" + tabletitle) + tabletitle = "

" + tabletitle + "

" + report.write(tabletitle) + report.write(table_start) + report.write(table_head) + datalist.sort(key=sort_by_field_element_data, reverse=False) + + for line in datalist: + if str(line[2]) == "N": + content = table_line % ( + "" + subsystem_name + "", "" + line[0] + "", + "" + line[1] + "", + "" + str(line[2]) + "") + report.write(content) + else: + content = table_line % ( + "" + subsystem_name + "", "" + line[0] + "", + "" + line[1] + "", + "" + str(line[2]) + "") + report.write(content) + if 0 != total_count: + coverage = str(covered_count * 100 / total_count) + "%" + else: + coverage = "0%" + coverage = table_summary % (total_count, covered_count, coverage) + report.write(coverage) + report.write(table_ended) + except(IOError, ValueError) as err_msg: + print("Error for create html table test: ", err_msg) + + +def create_html_ended(reportpath): + try: + with open(reportpath, "a") as report: + report.write(g_html_body_ended) + report.write(g_html_ended) + except(IOError, ValueError) as err_msg: + print("Error for create html end: ", err_msg) diff --git a/localCoverage/interfaceCoverage/results/coverage/interface_kits/coverage_summary_file.xml b/localCoverage/interfaceCoverage/results/coverage/interface_kits/coverage_summary_file.xml new file mode 100644 index 0000000000000000000000000000000000000000..fb67817031aa6dee4ca08551f6eba93a9649ed24 --- /dev/null +++ b/localCoverage/interfaceCoverage/results/coverage/interface_kits/coverage_summary_file.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/localCoverage/interfaceCoverage/results/coverage/interface_kits/ohos_interfaceCoverage.html b/localCoverage/interfaceCoverage/results/coverage/interface_kits/ohos_interfaceCoverage.html new file mode 100644 index 0000000000000000000000000000000000000000..e506f9b41058743fd5414c45b414c886218e7bd4 --- /dev/null +++ b/localCoverage/interfaceCoverage/results/coverage/interface_kits/ohos_interfaceCoverage.html @@ -0,0 +1,1127 @@ + + + + + + 接口覆盖率邮件模板 + + + + +

Inner Interface coverage report (2022-08-23)

+ +
+ + + + +
+

Summary Report

+

接口总数147,已覆盖0,未覆盖147

+
+
+ +

Summary

+
+ + + + + + + + + + + + + + + + + + + +
SubsystemNameTotalCountCoveredCountCoverage
account14700.0%
Summary14700.0%
+

+ account details:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SubsystemNameClassNameInterfaceNameIsCovered
accountOsAccountSubscribeInfoOsAccountSubscribeInfo()N
accountOsAccountSubscribeInfoOsAccountSubscribeInfo(OS_ACCOUNT_SUBSCRIBE_TYPE &, std::string &)N
accountOsAccountSubscribeInfo~OsAccountSubscribeInfo()N
accountOsAccountSubscribeInfoErrCode GetOsAccountSubscribeType(OS_ACCOUNT_SUBSCRIBE_TYPE &)N
accountOsAccountSubscribeInfoErrCode SetOsAccountSubscribeType(const OS_ACCOUNT_SUBSCRIBE_TYPE &)N
accountOsAccountSubscribeInfoErrCode GetName(std::string &)N
accountOsAccountSubscribeInfoErrCode SetName(const std::string &)N
accountOsAccountSubscribeInfobool Marshalling(Parcel &)N
accountOsAccountSubscribeInfoOsAccountSubscribeInfo * Unmarshalling(Parcel &)N
accountOsAccountSubscriberOsAccountSubscriber()N
accountOsAccountSubscriberOsAccountSubscriber(const OsAccountSubscribeInfo &)N
accountOsAccountSubscriber~OsAccountSubscriber()N
accountOsAccountSubscriberErrCode GetSubscribeInfo(OsAccountSubscribeInfo &)N
accountOsAccountManagerErrCode CreateOsAccount(const std::string &, const OsAccountType &, OsAccountInfo &)N
accountOsAccountManagerErrCode CreateOsAccountForDomain(const OsAccountType &, const DomainAccountInfo &, OsAccountInfo &)N
accountOsAccountManagerErrCode RemoveOsAccount(const int)N
accountOsAccountManagerErrCode IsOsAccountExists(const int, bool &)N
accountOsAccountManagerErrCode IsOsAccountActived(const int, bool &)N
accountOsAccountManagerErrCode IsOsAccountConstraintEnable(const int, const std::string &, bool &)N
accountOsAccountManagerErrCode IsOsAccountVerified(const int, bool &)N
accountOsAccountManagerErrCode GetCreatedOsAccountsCount(unsigned int &)N
accountOsAccountManagerErrCode GetOsAccountLocalIdFromProcess(int &)N
accountOsAccountManagerErrCode IsMainOsAccount(bool &)N
accountOsAccountManagerErrCode GetOsAccountLocalIdFromUid(const int, int &)N
accountOsAccountManagerErrCode GetBundleIdFromUid(const int, int &)N
accountOsAccountManagerErrCode GetOsAccountLocalIdFromDomain(const DomainAccountInfo &, int &)N
accountOsAccountManagerErrCode QueryMaxOsAccountNumber(int &)N
accountOsAccountManagerErrCode GetOsAccountAllConstraints(const int, std::vector &)N
accountOsAccountManagerErrCode QueryAllCreatedOsAccounts(std::vector &)N
accountOsAccountManagerErrCode QueryCurrentOsAccount(OsAccountInfo &)N
accountOsAccountManagerErrCode QueryOsAccountById(const int, OsAccountInfo &)N
accountOsAccountManagerErrCode GetOsAccountTypeFromProcess(OsAccountType &)N
accountOsAccountManagerErrCode GetOsAccountProfilePhoto(const int, std::string &)N
accountOsAccountManagerErrCode IsMultiOsAccountEnable(bool &)N
accountOsAccountManagerErrCode SetOsAccountName(const int, const std::string &)N
accountOsAccountManagerErrCode SetOsAccountConstraints(const int, const std::vector &, const bool)N
accountOsAccountManagerErrCode SetOsAccountProfilePhoto(const int, const std::string &)N
accountOsAccountManagerErrCode GetDistributedVirtualDeviceId(std::string &)N
accountOsAccountManagerErrCode ActivateOsAccount(const int)N
accountOsAccountManagerErrCode StartOsAccount(const int)N
accountOsAccountManagerErrCode StopOsAccount(const int)N
accountOsAccountManagerErrCode GetOsAccountLocalIdBySerialNumber(const int64_t, int &)N
accountOsAccountManagerErrCode GetSerialNumberByOsAccountLocalId(const int &, int64_t &)N
accountOsAccountManagerErrCode SubscribeOsAccount(const std::shared_ptr &)N
accountOsAccountManagerErrCode UnsubscribeOsAccount(const std::shared_ptr &)N
accountOsAccountManagerOS_ACCOUNT_SWITCH_MOD GetOsAccountSwitchMod()N
accountOsAccountManagerErrCode IsCurrentOsAccountVerified(bool &)N
accountOsAccountManagerErrCode IsOsAccountCompleted(const int, bool &)N
accountOsAccountManagerErrCode SetCurrentOsAccountIsVerified(const bool)N
accountOsAccountManagerErrCode SetOsAccountIsVerified(const int, const bool)N
accountOsAccountManagerErrCode GetCreatedOsAccountNumFromDatabase(const std::string &, int &)N
accountOsAccountManagerErrCode GetSerialNumberFromDatabase(const std::string &, int64_t &)N
accountOsAccountManagerErrCode GetMaxAllowCreateIdFromDatabase(const std::string &, int &)N
accountOsAccountManagerErrCode GetOsAccountFromDatabase(const std::string &, const int, OsAccountInfo &)N
accountOsAccountManagerErrCode GetOsAccountListFromDatabase(const std::string &, std::vector &)N
accountOsAccountManagerErrCode QueryActiveOsAccountIds(std::vector &)N
accountOsAccountManagerErrCode QueryOsAccountConstraintSourceTypes(const int32_t, const std::string, std::vector &)N
accountOsAccountManagerErrCode SetGlobalOsAccountConstraints(const std::vector &, const bool, const int32_t, const bool)N
accountOsAccountManagerErrCode SetSpecificOsAccountConstraints(const std::vector &, const bool, const int32_t, const int32_t, const bool)N
accountDomainAccountInfoDomainAccountInfo()N
accountDomainAccountInfoDomainAccountInfo(const std::string &, const std::string &)N
accountDomainAccountInfovoid Clear()N
accountOsAccountInfoOsAccountInfo()N
accountOsAccountInfoOsAccountInfo(int, const std::string, OsAccountType, int64_t)N
accountOsAccountInfoOsAccountInfo(int, std::string, OsAccountType, std::vector, bool, std::string, int64_t, int64_t, int64_t, bool)N
accountOsAccountInfoint GetLocalId()N
accountOsAccountInfovoid SetLocalId(int)N
accountOsAccountInfostd::string GetLocalName()N
accountOsAccountInfovoid SetLocalName(const std::string)N
accountOsAccountInfoOsAccountType GetType()N
accountOsAccountInfovoid SetType(OsAccountType)N
accountOsAccountInfostd::vector GetConstraints()N
accountOsAccountInfovoid SetConstraints(const std::vector)N
accountOsAccountInfobool GetIsVerified()N
accountOsAccountInfovoid SetIsVerified(bool)N
accountOsAccountInfostd::string GetPhoto()N
accountOsAccountInfovoid SetPhoto(const std::string)N
accountOsAccountInfoint64_t GetCreateTime()N
accountOsAccountInfovoid SetCreateTime(const int64_t)N
accountOsAccountInfoint64_t GetLastLoginTime()N
accountOsAccountInfovoid SetLastLoginTime(const int64_t)N
accountOsAccountInfoJson ToJson()N
accountOsAccountInfovoid FromJson(const Json &)N
accountOsAccountInfobool Marshalling(Parcel &)N
accountOsAccountInfobool ReadFromParcel(Parcel &)N
accountOsAccountInfostd::string ToString()N
accountOsAccountInfostd::string GetPrimeKey()N
accountOsAccountInfoOsAccountInfo * Unmarshalling(Parcel &)N
accountOsAccountInfoint64_t GetSerialNumber()N
accountOsAccountInfovoid SetSerialNumber(const int64_t)N
accountOsAccountInfobool GetIsActived()N
accountOsAccountInfovoid SetIsActived(const bool)N
accountOsAccountInfobool GetIsCreateCompleted()N
accountOsAccountInfovoid SetIsCreateCompleted(const bool)N
accountOsAccountInfobool SetDomainInfo(const DomainAccountInfo &)N
accountOsAccountInfovoid GetDomainInfo(DomainAccountInfo &)N
accountOsAccountInfobool GetToBeRemoved()N
accountOsAccountInfovoid SetToBeRemoved(bool)N
accountOhosAccountKitsOhosAccountKits & GetInstance()N
accountDeviceAccountInfoDeviceAccountInfo()N
accountDeviceAccountInfoDeviceAccountInfo(const std::int32_t, const DeviceAccountType, const std::string &)N
accountDeviceAccountInfoDeviceAccountInfo(const std::int32_t, const DeviceAccountType, const std::string &, const std::string &)N
accountDeviceAccountInfo~DeviceAccountInfo()N
accountDeviceAccountInfobool operator==(const DeviceAccountInfo &)N
accountDeviceAccountInfostd::int32_t WriteDataToParcel(MessageParcel &)N
accountDeviceAccountInfovoid ReadDataFromParcel(MessageParcel &)N
accountOhosAccountInfoOhosAccountInfo(const std::string &, const std::string &, std::int32_t)N
accountOhosAccountInfoOhosAccountInfo()N
accountOhosAccountInfo~OhosAccountInfo()N
accountAccountInfoAccountInfo()N
accountAccountInfoAccountInfo(const std::string &, const std::string &, const std::int32_t &)N
accountAccountInfobool operator==(const AccountInfo &)N
accountAccountInfovoid clear(std::int32_t)N
accountAccountInfo~AccountInfo()N
accountAppAccountManagerErrCode AddAccount(const std::string &, const std::string &)N
accountAppAccountManagerErrCode AddAccountImplicitly(const std::string &, const std::string &, const AAFwk::Want &, const sptr &)N
accountAppAccountManagerErrCode DeleteAccount(const std::string &)N
accountAppAccountManagerErrCode GetAccountExtraInfo(const std::string &, std::string &)N
accountAppAccountManagerErrCode SetAccountExtraInfo(const std::string &, const std::string &)N
accountAppAccountManagerErrCode EnableAppAccess(const std::string &, const std::string &)N
accountAppAccountManagerErrCode DisableAppAccess(const std::string &, const std::string &)N
accountAppAccountManagerErrCode CheckAppAccountSyncEnable(const std::string &, bool &)N
accountAppAccountManagerErrCode SetAppAccountSyncEnable(const std::string &, const bool &)N
accountAppAccountManagerErrCode GetAssociatedData(const std::string &, const std::string &, std::string &)N
accountAppAccountManagerErrCode SetAssociatedData(const std::string &, const std::string &, const std::string &)N
accountAppAccountManagerErrCode GetAccountCredential(const std::string &, const std::string &, std::string &)N
accountAppAccountManagerErrCode SetAccountCredential(const std::string &, const std::string &, const std::string &)N
accountAppAccountManagerErrCode Authenticate(const std::string &, const std::string &, const std::string &, const AAFwk::Want &, const sptr &)N
accountAppAccountManagerErrCode GetOAuthToken(const std::string &, const std::string &, const std::string &, std::string &)N
accountAppAccountManagerErrCode SetOAuthToken(const std::string &, const std::string &, const std::string &)N
accountAppAccountManagerErrCode DeleteOAuthToken(const std::string &, const std::string &, const std::string &, const std::string &)N
accountAppAccountManagerErrCode SetOAuthTokenVisibility(const std::string &, const std::string &, const std::string &, bool)N
accountAppAccountManagerErrCode CheckOAuthTokenVisibility(const std::string &, const std::string &, const std::string &, bool &)N
accountAppAccountManagerErrCode GetAuthenticatorInfo(const std::string &, AuthenticatorInfo &)N
accountAppAccountManagerErrCode GetAllOAuthTokens(const std::string &, const std::string &, std::vector &)N
accountAppAccountManagerErrCode GetOAuthList(const std::string &, const std::string &, std::set &)N
accountAppAccountManagerErrCode GetAuthenticatorCallback(const std::string &, sptr &)N
accountAppAccountManagerErrCode GetAllAccounts(const std::string &, std::vector &)N
accountAppAccountManagerErrCode GetAllAccessibleAccounts(std::vector &)N
accountAppAccountManagerErrCode CheckAppAccess(const std::string &, const std::string &, bool &)N
accountAppAccountManagerErrCode DeleteAccountCredential(const std::string &, const std::string &)N
accountAppAccountManagerErrCode SelectAccountsByOptions(const SelectAccountsOptions &, const sptr &)N
accountAppAccountManagerErrCode VerifyCredential(const std::string &, const std::string &, const VerifyCredentialOptions &, const sptr &)N
accountAppAccountManagerErrCode CheckAccountLabels(const std::string &, const std::string &, const std::vector &, const sptr &)N
accountAppAccountManagerErrCode SetAuthenticatorProperties(const std::string &, const SetPropertiesOptions &, const sptr &)N
accountAppAccountManagerErrCode SubscribeAppAccount(const std::shared_ptr &)N
accountAppAccountManagerErrCode UnsubscribeAppAccount(const std::shared_ptr &)N
TotalCount: 147, CoveredCount:0, Coverage: 0.0%
+ + + \ No newline at end of file diff --git a/localCoverage/interfaceCoverage/results/coverage/interface_kits/test.png b/localCoverage/interfaceCoverage/results/coverage/interface_kits/test.png new file mode 100644 index 0000000000000000000000000000000000000000..9926563cf3090c93597c170f83e1951d9fabb462 Binary files /dev/null and b/localCoverage/interfaceCoverage/results/coverage/interface_kits/test.png differ diff --git a/src/core/command/run.py b/src/core/command/run.py index d47b2b279a3d46cf283d0fa419e6459e8d058856..57baef8a5a689d83a4c87104932253784fe91f47 100644 --- a/src/core/command/run.py +++ b/src/core/command/run.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # coding=utf-8 - +import platform # # Copyright (c) 2020-2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +16,13 @@ # limitations under the License. # -import random -from pydoc import classname -import time import os import sys +import time +import random import datetime +import subprocess +from pydoc import classname import xml.etree.ElementTree as ElementTree from core.constants import SchedulerType @@ -179,6 +180,13 @@ class Run(object): LOG.error("The test file list is empty.") return + if options.coverage and platform.system() != "Windows": + print("sys.framework_root_dir", sys.framework_root_dir) + coverage_path = os.path.join(sys.framework_root_dir, "reports/coverage") + if os.path.exists(coverage_path): + coverage_process = subprocess.Popen("rm -rf %s" % coverage_path, shell=True) + coverage_process.communicate() + if ("distributedtest" in options.testtype and len(options.testtype) == 1): from core.command.distribute_utils import get_test_case @@ -259,6 +267,17 @@ class Run(object): del self.history_cmd_list[0] self.history_cmd_list.append(cmd_record) print("-------------run end: ", self.history_cmd_list) + if options.coverage and platform.system() != "Windows": + cov_main_file_path = os.path.join(sys.framework_root_dir, "localCoverage/coverage_tools.py") + print("cov_main_file_path", cov_main_file_path) + testpart = ",".join(list(map(str, options.partname_list))) + subsystem = ",".join(list(map(str, options.subsystem))) + if os.path.exists(cov_main_file_path): + subprocess.run("python3 %s testpart=%s subsystem=%s" % ( + cov_main_file_path, testpart, subsystem), shell=True) + else: + print(f"{cov_main_file_path} not exists!") + return ############################################################## diff --git a/src/core/driver/drivers.py b/src/core/driver/drivers.py index f7a4771c05eefd152a7fbfca22b1e2ab1f78ce99..88cf5b345b5e5f8cd0d9231f266231ab031c5c37 100644 --- a/src/core/driver/drivers.py +++ b/src/core/driver/drivers.py @@ -1,1014 +1,1014 @@ -#!/usr/bin/env python3 -# coding=utf-8 - -# -# Copyright (c) 2020-2022 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. -# - -import json -import os -import re -import shutil -import subprocess -import time -import platform -import zipfile -import stat -from dataclasses import dataclass -from json import JSONDecodeError - -from xdevice import DeviceTestType -from xdevice import DeviceLabelType -from xdevice import CommonParserType -from xdevice import ExecuteTerminate -from xdevice import DeviceError -from xdevice import ShellHandler - -from xdevice import IDriver -from xdevice import platform_logger -from xdevice import Plugin -from xdevice import get_plugin -from ohos.environment.dmlib import process_command_ret -from core.utils import get_decode -from core.utils import get_fuzzer_path -from core.config.resource_manager import ResourceManager -from core.config.config_manager import FuzzerConfigManager - -__all__ = [ - "CppTestDriver", - "JSUnitTestDriver", - "disable_keyguard", - "GTestConst"] - -LOG = platform_logger("Drivers") -DEFAULT_TEST_PATH = "/%s/%s/" % ("data", "test") - -TIME_OUT = 900 * 1000 -JS_TIMEOUT = 10 -CYCLE_TIMES = 30 - - -############################################################################## -############################################################################## - - -class DisplayOutputReceiver: - def __init__(self): - self.output = "" - self.unfinished_line = "" - - def _process_output(self, output, end_mark="\n"): - content = output - if self.unfinished_line: - content = "".join((self.unfinished_line, content)) - self.unfinished_line = "" - lines = content.split(end_mark) - if content.endswith(end_mark): - return lines[:-1] - else: - self.unfinished_line = lines[-1] - return lines[:-1] - - def __read__(self, output): - self.output = "%s%s" % (self.output, output) - lines = self._process_output(output) - for line in lines: - line = line.strip() - if line: - LOG.info(get_decode(line)) - - def __error__(self, message): - pass - - def __done__(self, result_code="", message=""): - pass - - -@dataclass -class GTestConst(object): - exec_para_filter = "--gtest_filter" - exec_para_level = "--gtest_testsize" - exec_acts_para_filter = "--jstest_filter" - exec_acts_para_level = "--jstest_testsize" - - -def get_device_log_file(report_path, serial=None, log_name="device_log"): - from xdevice import Variables - log_path = os.path.join(report_path, Variables.report_vars.log_dir) - os.makedirs(log_path, exist_ok=True) - - serial = serial or time.time_ns() - device_file_name = "{}_{}.log".format(log_name, serial) - device_log_file = os.path.join(log_path, device_file_name) - return device_log_file - - -def get_level_para_string(level_string): - level_list = list(set(level_string.split(","))) - level_para_string = "" - for item in level_list: - if not item.isdigit(): - continue - item = item.strip(" ") - level_para_string = f"{level_para_string}Level{item}," - level_para_string = level_para_string.strip(",") - return level_para_string - - -def get_result_savepath(testsuit_path, result_rootpath): - findkey = os.sep + "tests" + os.sep - filedir, _ = os.path.split(testsuit_path) - pos = filedir.find(findkey) - if -1 != pos: - subpath = filedir[pos + len(findkey):] - pos1 = subpath.find(os.sep) - if -1 != pos1: - subpath = subpath[pos1 + len(os.sep):] - result_path = os.path.join(result_rootpath, "result", subpath) - else: - result_path = os.path.join(result_rootpath, "result") - else: - result_path = os.path.join(result_rootpath, "result") - - if not os.path.exists(result_path): - os.makedirs(result_path) - - LOG.info("result_savepath = " + result_path) - return result_path - - -# all testsuit common Unavailable test result xml -def _create_empty_result_file(filepath, filename, error_message): - error_message = str(error_message) - error_message = error_message.replace("\"", "") - error_message = error_message.replace("<", "") - error_message = error_message.replace(">", "") - error_message = error_message.replace("&", "") - if filename.endswith(".hap"): - filename = filename.split(".")[0] - if not os.path.exists(filepath): - with open(filepath, "w", encoding='utf-8') as file_desc: - time_stamp = time.strftime("%Y-%m-%d %H:%M:%S", - time.localtime()) - file_desc.write('\n') - file_desc.write( - '\n' % time_stamp) - file_desc.write( - ' \n' % - (filename, error_message)) - file_desc.write(' \n') - file_desc.write('\n') - return - - -def _unlock_screen(device): - device.execute_shell_command("svc power stayon true") - time.sleep(1) - - -def _unlock_device(device): - device.execute_shell_command("input keyevent 82") - time.sleep(1) - device.execute_shell_command("wm dismiss-keyguard") - time.sleep(1) - - -def _lock_screen(device): - device.execute_shell_command("svc power stayon false") - time.sleep(1) - - -def disable_keyguard(device): - _unlock_screen(device) - _unlock_device(device) - - -def _sleep_according_to_result(result): - if result: - time.sleep(1) - - -def _create_fuzz_crash_file(filepath, filename): - if not os.path.exists(filepath): - with open(filepath, "w", encoding='utf-8') as file_desc: - time_stamp = time.strftime("%Y-%m-%d %H:%M:%S", - time.localtime()) - file_desc.write('\n') - file_desc.write( - '\n' % time_stamp) - file_desc.write( - ' \n' % filename) - file_desc.write( - ' \n' % (filename, filename)) - file_desc.write( - ' \n') - file_desc.write(' \n') - file_desc.write(' \n') - file_desc.write(' \n') - file_desc.write('\n') - return - - -def _create_fuzz_pass_file(filepath, filename): - if not os.path.exists(filepath): - with open(filepath, "w", encoding='utf-8') as file_desc: - time_stamp = time.strftime("%Y-%m-%d %H:%M:%S", - time.localtime()) - file_desc.write('\n') - file_desc.write( - '\n' % time_stamp) - file_desc.write( - ' \n' % filename) - file_desc.write( - ' \n' % (filename, filename)) - file_desc.write(' \n') - file_desc.write('\n') - return - - -def _create_fuzz_result_file(filepath, filename, error_message): - error_message = str(error_message) - error_message = error_message.replace("\"", "") - error_message = error_message.replace("<", "") - error_message = error_message.replace(">", "") - error_message = error_message.replace("&", "") - if "AddressSanitizer" in error_message: - LOG.error("FUZZ TEST CRASH") - _create_fuzz_crash_file(filepath, filename) - elif re.search(r'Done (\b\d+\b) runs in (\b\d+\b) second', - error_message, re.M) is not None: - LOG.info("FUZZ TEST PASS") - _create_fuzz_pass_file(filepath, filename) - else: - LOG.error("FUZZ TEST UNAVAILABLE") - _create_empty_result_file(filepath, filename, error_message) - return - - -############################################################################## -############################################################################## - -class ResultManager(object): - def __init__(self, testsuit_path, config): - self.testsuite_path = testsuit_path - self.config = config - self.result_rootpath = self.config.report_path - self.device = self.config.device - if testsuit_path.endswith(".hap"): - self.device_testpath = self.config.test_hap_out_path - else: - self.device_testpath = self.config.target_test_path - self.testsuite_name = os.path.basename(self.testsuite_path) - self.is_coverage = False - - def set_is_coverage(self, is_coverage): - self.is_coverage = is_coverage - - def get_test_results(self, error_message=""): - # Get test result files - filepath = self.obtain_test_result_file() - if "fuzztest" == self.config.testtype[0]: - LOG.info("create fuzz test report") - _create_fuzz_result_file(filepath, self.testsuite_name, - error_message) - if not self.is_coverage: - self._obtain_fuzz_corpus() - - if not os.path.exists(filepath): - _create_empty_result_file(filepath, self.testsuite_name, - error_message) - if "benchmark" == self.config.testtype[0]: - self._obtain_benchmark_result() - # Get coverage data files - if self.is_coverage: - self.obtain_coverage_data() - - return filepath - - def _obtain_fuzz_corpus(self): - command = f"cd {DEFAULT_TEST_PATH}; tar czf {self.testsuite_name}_corpus.tar.gz corpus;" - self.config.device.execute_shell_command(command) - result_save_path = get_result_savepath(self.testsuite_path, self.result_rootpath) - LOG.info(f"fuzz_dir = {result_save_path}") - self.device.pull_file(f"{DEFAULT_TEST_PATH}/{self.testsuite_name}_corpus.tar.gz", result_save_path) - - def _obtain_benchmark_result(self): - benchmark_root_dir = os.path.abspath( - os.path.join(self.result_rootpath, "benchmark")) - benchmark_dir = os.path.abspath( - os.path.join(benchmark_root_dir, - self.get_result_sub_save_path(), - self.testsuite_name)) - - if not os.path.exists(benchmark_dir): - os.makedirs(benchmark_dir) - - LOG.info("benchmark_dir = %s" % benchmark_dir) - self.device.pull_file(os.path.join(self.device_testpath, - "%s.json" % self.testsuite_name), benchmark_dir) - if not os.path.exists(os.path.join(benchmark_dir, - "%s.json" % self.testsuite_name)): - os.rmdir(benchmark_dir) - return benchmark_dir - - def get_result_sub_save_path(self): - find_key = os.sep + "benchmark" + os.sep - file_dir, _ = os.path.split(self.testsuite_path) - pos = file_dir.find(find_key) - subpath = "" - if -1 != pos: - subpath = file_dir[pos + len(find_key):] - LOG.info("subpath = " + subpath) - return subpath - - def obtain_test_result_file(self): - result_save_path = get_result_savepath(self.testsuite_path, - self.result_rootpath) - result_file_path = os.path.join(result_save_path, - "%s.xml" % self.testsuite_name) - - result_josn_file_path = os.path.join(result_save_path, - "%s.json" % self.testsuite_name) - - if self.testsuite_path.endswith('.hap'): - remote_result_file = os.path.join(self.device_testpath, - "testcase_result.xml") - remote_json_result_file = os.path.join(self.device_testpath, - "%s.json" % self.testsuite_name) - else: - remote_result_file = os.path.join(self.device_testpath, - "%s.xml" % self.testsuite_name) - remote_json_result_file = os.path.join(self.device_testpath, - "%s.json" % self.testsuite_name) - - if self.config.testtype[0] != "fuzztest": - if self.device.is_file_exist(remote_result_file): - self.device.pull_file(remote_result_file, result_file_path) - elif self.device.is_file_exist(remote_json_result_file): - self.device.pull_file(remote_json_result_file, - result_josn_file_path) - result_file_path = result_josn_file_path - else: - LOG.info("%s not exist", remote_result_file) - - return result_file_path - - def make_empty_result_file(self, error_message=""): - result_savepath = get_result_savepath(self.testsuite_path, - self.result_rootpath) - result_filepath = os.path.join(result_savepath, "%s.xml" % - self.testsuite_name) - if not os.path.exists(result_filepath): - _create_empty_result_file(result_filepath, - self.testsuite_name, error_message) - - def is_exist_target_in_device(self, path, target): - if platform.system() == "Windows": - command = '\"ls -l %s | grep %s\"' % (path, target) - else: - command = "ls -l %s | grep %s" % (path, target) - - check_result = False - stdout_info = self.device.execute_shell_command(command) - if stdout_info != "" and stdout_info.find(target) != -1: - check_result = True - return check_result - - def obtain_coverage_data(self): - cov_root_dir = os.path.abspath(os.path.join( - self.result_rootpath, - "..", - "coverage", - "data", - "exec")) - - target_name = "obj" - cxx_cov_path = os.path.abspath(os.path.join( - self.result_rootpath, - "..", - "coverage", - "data", - "cxx", - self.testsuite_name + '_' + self.config.testtype[0])) - - if self.is_exist_target_in_device(DEFAULT_TEST_PATH, target_name): - if not os.path.exists(cxx_cov_path): - os.makedirs(cxx_cov_path) - self.config.device.execute_shell_command( - "cd %s; tar -czf %s.tar.gz %s" % (DEFAULT_TEST_PATH, target_name, target_name)) - src_file_tar = os.path.join(DEFAULT_TEST_PATH, "%s.tar.gz" % target_name) - self.device.pull_file(src_file_tar, cxx_cov_path, is_create=True, timeout=TIME_OUT) - tar_path = os.path.join(cxx_cov_path, "%s.tar.gz" % target_name) - if platform.system() == "Windows": - process = subprocess.Popen("tar -zxf %s -C %s" % (tar_path, cxx_cov_path), shell=True) - process.communicate() - os.remove(tar_path) - else: - subprocess.Popen("tar -zxf %s -C %s > /dev/null 2>&1" % - (tar_path, cxx_cov_path), shell=True) - subprocess.Popen("rm -rf %s" % tar_path, shell=True) - - -############################################################################## -############################################################################## - -@Plugin(type=Plugin.DRIVER, id=DeviceTestType.cpp_test) -class CppTestDriver(IDriver): - """ - CppTest is a Test that runs a native test package on given device. - """ - # test driver config - config = None - result = "" - - def __check_environment__(self, device_options): - if len(device_options) == 1 and device_options[0].label is None: - return True - if len(device_options) != 1 or \ - device_options[0].label != DeviceLabelType.phone: - return False - return True - - def __check_config__(self, config): - pass - - def __result__(self): - return self.result if os.path.exists(self.result) else "" - - def __execute__(self, request): - try: - self.config = request.config - self.config.target_test_path = DEFAULT_TEST_PATH - self.config.device = request.config.environment.devices[0] - - suite_file = request.root.source.source_file - LOG.debug("Testsuite FilePath: %s" % suite_file) - - if not suite_file: - LOG.error("test source '%s' not exists" % - request.root.source.source_string) - return - - if not self.config.device: - result = ResultManager(suite_file, self.config) - result.set_is_coverage(False) - result.make_empty_result_file( - "No test device is found. ") - return - self.config.device.set_device_report_path(request.config.report_path) - self.config.device.device_log_collector.start_hilog_task() - self._init_gtest() - self._run_gtest(suite_file) - - finally: - serial = "{}_{}".format(str(request.config.device.__get_serial__()), time.time_ns()) - log_tar_file_name = "{}_{}".format(request.get_module_name(), str(serial).replace( - ":", "_")) - self.config.device.device_log_collector.stop_hilog_task(log_tar_file_name) - - def _init_gtest(self): - self.config.device.connector_command("target mount") - self.config.device.execute_shell_command( - "rm -rf %s" % self.config.target_test_path) - self.config.device.execute_shell_command( - "mkdir -p %s" % self.config.target_test_path) - self.config.device.execute_shell_command( - "mount -o rw,remount,rw /") - if "fuzztest" == self.config.testtype[0]: - self.config.device.execute_shell_command( - "mkdir -p %s" % os.path.join(self.config.target_test_path, - "corpus")) - - def _run_gtest(self, suite_file): - from xdevice import Variables - filename = os.path.basename(suite_file) - test_para = self._get_test_para(self.config.testcase, - self.config.testlevel, - self.config.testtype, - self.config.target_test_path, - suite_file, - filename) - is_coverage_test = True if self.config.coverage else False - - # push testsuite file - self.config.device.push_file(suite_file, self.config.target_test_path) - self._push_corpus_if_exist(suite_file) - - # push resource files - resource_manager = ResourceManager() - resource_data_dic, resource_dir = \ - resource_manager.get_resource_data_dic(suite_file) - resource_manager.process_preparer_data(resource_data_dic, resource_dir, - self.config.device) - # execute testcase - if not self.config.coverage: - command = "cd %s; rm -rf %s.xml; chmod +x *; ./%s %s" % ( - self.config.target_test_path, - filename, - filename, - test_para) - else: - coverage_outpath = self.config.coverage_outpath - strip_num = len(coverage_outpath.strip("/").split("/")) - if "fuzztest" == self.config.testtype[0]: - self._push_corpus_cov_if_exist(suite_file) - command = f"cd {self.config.target_test_path}; tar zxf {filename}_corpus.tar.gz; \ - rm -rf {filename}.xml; chmod +x *; GCOV_PREFIX=.; \ - GCOV_PREFIX_STRIP={strip_num} ./{filename} {test_para}" - else: - command = "cd %s; rm -rf %s.xml; chmod +x *; GCOV_PREFIX=. " \ - "GCOV_PREFIX_STRIP=%s ./%s %s" % \ - (self.config.target_test_path, - filename, - str(strip_num), - filename, - test_para) - - result = ResultManager(suite_file, self.config) - result.set_is_coverage(is_coverage_test) - - try: - # get result - display_receiver = DisplayOutputReceiver() - self.config.device.execute_shell_command( - command, - receiver=display_receiver, - timeout=TIME_OUT, - retry=0) - return_message = display_receiver.output - except (ExecuteTerminate, DeviceError) as exception: - return_message = str(exception.args) - - self.result = result.get_test_results(return_message) - resource_manager.process_cleaner_data(resource_data_dic, - resource_dir, - self.config.device) - - @staticmethod - def _alter_init(name): - lines = list() - with open(name, "r") as f: - for line in f: - line_strip = line.strip() - if not line_strip: - continue - if line_strip[0] != "#" and line_strip[0] != "/" and line_strip[0] != "*": - lines.append(line_strip) - with open(name, "w") as f: - f.writelines(lines) - - def _push_corpus_cov_if_exist(self, suite_file): - cov_file = suite_file + "_corpus.tar.gz" - LOG.info("corpus_cov file :%s" % str(cov_file)) - self.config.device.push_file(cov_file, os.path.join(self.config.target_test_path)) - - def _push_corpus_if_exist(self, suite_file): - if "fuzztest" == self.config.testtype[0]: - corpus_path = os.path.join(get_fuzzer_path(suite_file), "corpus") - if not os.path.isdir(corpus_path): - return - - corpus_dirs = [] - corpus_file_list = [] - - for root, _, files in os.walk(corpus_path): - if not files: - continue - - corpus_dir = root.split("corpus")[-1] - if corpus_dir != "": - corpus_dirs.append(corpus_dir) - - for file in files: - cp_file = os.path.normcase(os.path.join(root, file)) - corpus_file_list.append(cp_file) - if file == "init": - self._alter_init(cp_file) - - # mkdir corpus files dir - if corpus_dirs: - for corpus in corpus_dirs: - mkdir_corpus_command = f"shell; mkdir -p {corpus}" - self.config.device.connector_command(mkdir_corpus_command) - - # push corpus file - if corpus_file_list: - for corpus_file in corpus_file_list: - self.config.device.push_file(corpus_file, - os.path.join(self.config.target_test_path, "corpus")) - - def _get_test_para(self, - testcase, - testlevel, - testtype, - target_test_path, - suite_file, - filename): - if "benchmark" == testtype[0]: - test_para = (" --benchmark_out_format=json" - " --benchmark_out=%s%s.json") % ( - target_test_path, filename) - return test_para - - if "" != testcase and "" == testlevel: - test_para = "%s=%s" % (GTestConst.exec_para_filter, testcase) - elif "" == testcase and "" != testlevel: - level_para = get_level_para_string(testlevel) - test_para = "%s=%s" % (GTestConst.exec_para_level, level_para) - else: - test_para = "" - - if "fuzztest" == testtype[0]: - cfg_list = FuzzerConfigManager(os.path.join(get_fuzzer_path( - suite_file), "project.xml")).get_fuzzer_config("fuzztest") - LOG.info("config list :%s" % str(cfg_list)) - if self.config.coverage: - test_para += "corpus -runs=0" + \ - " -max_len=" + cfg_list[0] + \ - " -max_total_time=" + cfg_list[1] + \ - " -rss_limit_mb=" + cfg_list[2] - else: - test_para += "corpus -max_len=" + cfg_list[0] + \ - " -max_total_time=" + cfg_list[1] + \ - " -rss_limit_mb=" + cfg_list[2] - - return test_para - - -############################################################################## -############################################################################## - -@Plugin(type=Plugin.DRIVER, id=DeviceTestType.jsunit_test) -class JSUnitTestDriver(IDriver): - """ - JSUnitTestDriver is a Test that runs a native test package on given device. - """ - - def __init__(self): - self.config = None - self.result = "" - self.start_time = None - self.ability_name = "" - self.package_name = "" - # log - self.hilog = None - self.hilog_proc = None - - def __check_environment__(self, device_options): - pass - - def __check_config__(self, config): - pass - - def __result__(self): - return self.result if os.path.exists(self.result) else "" - - def __execute__(self, request): - try: - LOG.info("developertest driver") - self.result = os.path.join( - request.config.report_path, "result", - '.'.join((request.get_module_name(), "xml"))) - self.config = request.config - self.config.target_test_path = DEFAULT_TEST_PATH - self.config.device = request.config.environment.devices[0] - - suite_file = request.root.source.source_file - if not suite_file: - LOG.error("test source '%s' not exists" % - request.root.source.source_string) - return - - if not self.config.device: - result = ResultManager(suite_file, self.config) - result.set_is_coverage(False) - result.make_empty_result_file( - "No test device is found") - return - - package_name, ability_name = self._get_package_and_ability_name( - suite_file) - self.package_name = package_name - self.ability_name = ability_name - self.config.test_hap_out_path = \ - "/data/data/%s/files/" % self.package_name - self.config.device.connector_command("shell hilog -r") - - self.hilog = get_device_log_file( - request.config.report_path, - request.config.device.__get_serial__() + "_" + request. - get_module_name(), - "device_hilog") - - hilog_open = os.open(self.hilog, os.O_WRONLY | os.O_CREAT | os.O_APPEND, - 0o755) - - with os.fdopen(hilog_open, "a") as hilog_file_pipe: - self.config.device.device_log_collector.add_log_address(None, self.hilog) - _, self.hilog_proc = self.config.device.device_log_collector.\ - start_catch_device_log(hilog_file_pipe=hilog_file_pipe) - self._init_jsunit_test() - self._run_jsunit(suite_file, self.hilog) - hilog_file_pipe.flush() - self.generate_console_output(self.hilog, request) - finally: - self.config.device.device_log_collector.remove_log_address(None, self.hilog) - self.config.device.device_log_collector.stop_catch_device_log(self.hilog_proc) - - def _init_jsunit_test(self): - self.config.device.connector_command("target mount") - self.config.device.execute_shell_command( - "rm -rf %s" % self.config.target_test_path) - self.config.device.execute_shell_command( - "mkdir -p %s" % self.config.target_test_path) - self.config.device.execute_shell_command( - "mount -o rw,remount,rw /") - - def _run_jsunit(self, suite_file, device_log_file): - filename = os.path.basename(suite_file) - _, suffix_name = os.path.splitext(filename) - - resource_manager = ResourceManager() - resource_data_dic, resource_dir = resource_manager.get_resource_data_dic(suite_file) - if suffix_name == ".hap": - json_file_path = suite_file.replace(".hap", ".json") - if os.path.exists(json_file_path): - timeout = self._get_json_shell_timeout(json_file_path) - else: - timeout = ResourceManager.get_nodeattrib_data(resource_data_dic) - else: - timeout = ResourceManager.get_nodeattrib_data(resource_data_dic) - resource_manager.process_preparer_data(resource_data_dic, resource_dir, self.config.device) - main_result = self._install_hap(suite_file) - result = ResultManager(suite_file, self.config) - if main_result: - self._execute_hapfile_jsunittest() - try: - status = False - actiontime = JS_TIMEOUT - times = CYCLE_TIMES - if timeout: - actiontime = timeout - times = 1 - device_log_file_open = os.open(device_log_file, os.O_RDONLY, stat.S_IWUSR | stat.S_IRUSR) - with os.fdopen(device_log_file_open, "r", encoding='utf-8') \ - as file_read_pipe: - for i in range(0, times): - if status: - break - else: - time.sleep(float(actiontime)) - start_time = int(time.time()) - while True: - data = file_read_pipe.readline() - if data.find("JSApp:") != -1 and data.find("[end] run suites end") != -1: - LOG.info("execute testcase successfully.") - status = True - break - if int(time.time()) - start_time > 5: - break - finally: - _lock_screen(self.config.device) - self._uninstall_hap(self.package_name) - else: - self.result = result.get_test_results("Error: install hap failed") - LOG.error("Error: install hap failed") - - resource_manager.process_cleaner_data(resource_data_dic, resource_dir, self.config.device) - - def generate_console_output(self, device_log_file, request): - result_message = self.read_device_log(device_log_file) - - report_name = request.get_module_name() - parsers = get_plugin( - Plugin.PARSER, CommonParserType.jsunit) - if parsers: - parsers = parsers[:1] - for listener in request.listeners: - listener.device_sn = self.config.device.device_sn - parser_instances = [] - - for parser in parsers: - parser_instance = parser.__class__() - parser_instance.suites_name = report_name - parser_instance.suite_name = report_name - parser_instance.listeners = request.listeners - parser_instances.append(parser_instance) - handler = ShellHandler(parser_instances) - process_command_ret(result_message, handler) - - def read_device_log(self, device_log_file): - device_log_file_open = os.open(device_log_file, os.O_RDONLY, - stat.S_IWUSR | stat.S_IRUSR) - - result_message = "" - with os.fdopen(device_log_file_open, "r", encoding='utf-8') \ - as file_read_pipe: - while True: - data = file_read_pipe.readline() - if not data: - break - # only filter JSApp log - if data.find("JSApp:") != -1: - result_message += data - if data.find("[end] run suites end") != -1: - break - return result_message - - def _execute_hapfile_jsunittest(self): - _unlock_screen(self.config.device) - _unlock_device(self.config.device) - - try: - return_message = self.start_hap_execute() - except (ExecuteTerminate, DeviceError) as exception: - return_message = str(exception.args) - - return return_message - - def _install_hap(self, suite_file): - message = self.config.device.connector_command("install %s" % suite_file) - message = str(message).rstrip() - if message == "" or "success" in message: - return_code = True - if message != "": - LOG.info(message) - else: - return_code = False - if message != "": - LOG.warning(message) - - _sleep_according_to_result(return_code) - return return_code - - def start_hap_execute(self): - try: - command = "aa start -d 123 -a %s.MainAbility -b %s" \ - % (self.package_name, self.package_name) - self.start_time = time.time() - result_value = self.config.device.execute_shell_command( - command, timeout=TIME_OUT) - - if "success" in str(result_value).lower(): - LOG.info("execute %s's testcase success. result value=%s" - % (self.package_name, result_value)) - else: - LOG.info("execute %s's testcase failed. result value=%s" - % (self.package_name, result_value)) - - _sleep_according_to_result(result_value) - return_message = result_value - except (ExecuteTerminate, DeviceError) as exception: - return_message = exception.args - - return return_message - - def _uninstall_hap(self, package_name): - return_message = self.config.device.execute_shell_command( - "bm uninstall -n %s" % package_name) - _sleep_according_to_result(return_message) - return return_message - - @staticmethod - def _get_acts_test_para(testcase, - testlevel, - testtype, - target_test_path, - suite_file, - filename): - if "actstest" == testtype[0]: - test_para = (" --actstest_out_format=json" - " --actstest_out=%s%s.json") % ( - target_test_path, filename) - return test_para - - if "" != testcase and "" == testlevel: - test_para = "%s=%s" % (GTestConst.exec_acts_para_filter, testcase) - elif "" == testcase and "" != testlevel: - level_para = get_level_para_string(testlevel) - test_para = "%s=%s" % (GTestConst.exec_acts_para_level, level_para) - else: - test_para = "" - return test_para - - @staticmethod - def _get_hats_test_para(testcase, - testlevel, - testtype, - target_test_path, - suite_file, - filename): - if "hatstest" == testtype[0]: - test_hats_para = (" --hatstest_out_format=json" - " --hatstest_out=%s%s.json") % ( - target_test_path, filename) - return test_hats_para - - if "" != testcase and "" == testlevel: - test_hats_para = "%s=%s" % (GTestConst.exec_para_filter, testcase) - elif "" == testcase and "" != testlevel: - level_para = get_level_para_string(testlevel) - test_hats_para = "%s=%s" % (GTestConst.exec_para_level, level_para) - else: - test_hats_para = "" - return test_hats_para - - @classmethod - def _get_json_shell_timeout(cls, json_filepath): - test_timeout = 300 - try: - with open(json_filepath, 'r') as json_file: - data_dic = json.load(json_file) - if not data_dic: - return test_timeout - else: - if "driver" in data_dic.keys(): - driver_dict = data_dic.get("driver") - if driver_dict and "test-timeout" in driver_dict.keys(): - test_timeout = int(driver_dict["shell-timeout"]) / 1000 - else: - return - return test_timeout - except JSONDecodeError: - return test_timeout - finally: - print(" get json shell timeout finally") - - @staticmethod - def _get_package_and_ability_name(hap_filepath): - package_name = "" - ability_name = "" - if os.path.exists(hap_filepath): - filename = os.path.basename(hap_filepath) - - # unzip the hap file - hap_bak_path = os.path.abspath(os.path.join( - os.path.dirname(hap_filepath), - "%s.bak" % filename)) - zf_desc = zipfile.ZipFile(hap_filepath) - try: - zf_desc.extractall(path=hap_bak_path) - except RuntimeError as error: - print(error) - zf_desc.close() - - # verify config.json file - app_profile_path = os.path.join(hap_bak_path, "config.json") - if not os.path.exists(app_profile_path): - print("file %s not exist" % app_profile_path) - return package_name, ability_name - - if os.path.isdir(app_profile_path): - print("%s is a folder, and not a file" % app_profile_path) - return package_name, ability_name - - # get package_name and ability_name value - load_dict = {} - with open(app_profile_path, 'r') as load_f: - load_dict = json.load(load_f) - profile_list = load_dict.values() - for profile in profile_list: - package_name = profile.get("package") - if not package_name: - continue - abilities = profile.get("abilities") - for abilitie in abilities: - abilities_name = abilitie.get("name") - if abilities_name.startswith("."): - ability_name = package_name + abilities_name[ - abilities_name.find("."):] - else: - ability_name = abilities_name - break - break - - # delete hap_bak_path - if os.path.exists(hap_bak_path): - shutil.rmtree(hap_bak_path) - else: - print("file %s not exist" % hap_filepath) - return package_name, ability_name +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2020-2022 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. +# + +import json +import os +import re +import shutil +import subprocess +import time +import platform +import zipfile +import stat +from dataclasses import dataclass +from json import JSONDecodeError + +from xdevice import DeviceTestType +from xdevice import DeviceLabelType +from xdevice import CommonParserType +from xdevice import ExecuteTerminate +from xdevice import DeviceError +from xdevice import ShellHandler + +from xdevice import IDriver +from xdevice import platform_logger +from xdevice import Plugin +from xdevice import get_plugin +from ohos.environment.dmlib import process_command_ret +from core.utils import get_decode +from core.utils import get_fuzzer_path +from core.config.resource_manager import ResourceManager +from core.config.config_manager import FuzzerConfigManager + +__all__ = [ + "CppTestDriver", + "JSUnitTestDriver", + "disable_keyguard", + "GTestConst"] + +LOG = platform_logger("Drivers") +DEFAULT_TEST_PATH = "/%s/%s/" % ("data", "test") + +TIME_OUT = 900 * 1000 +JS_TIMEOUT = 10 +CYCLE_TIMES = 30 + + +############################################################################## +############################################################################## + + +class DisplayOutputReceiver: + def __init__(self): + self.output = "" + self.unfinished_line = "" + + def _process_output(self, output, end_mark="\n"): + content = output + if self.unfinished_line: + content = "".join((self.unfinished_line, content)) + self.unfinished_line = "" + lines = content.split(end_mark) + if content.endswith(end_mark): + return lines[:-1] + else: + self.unfinished_line = lines[-1] + return lines[:-1] + + def __read__(self, output): + self.output = "%s%s" % (self.output, output) + lines = self._process_output(output) + for line in lines: + line = line.strip() + if line: + LOG.info(get_decode(line)) + + def __error__(self, message): + pass + + def __done__(self, result_code="", message=""): + pass + + +@dataclass +class GTestConst(object): + exec_para_filter = "--gtest_filter" + exec_para_level = "--gtest_testsize" + exec_acts_para_filter = "--jstest_filter" + exec_acts_para_level = "--jstest_testsize" + + +def get_device_log_file(report_path, serial=None, log_name="device_log"): + from xdevice import Variables + log_path = os.path.join(report_path, Variables.report_vars.log_dir) + os.makedirs(log_path, exist_ok=True) + + serial = serial or time.time_ns() + device_file_name = "{}_{}.log".format(log_name, serial) + device_log_file = os.path.join(log_path, device_file_name) + return device_log_file + + +def get_level_para_string(level_string): + level_list = list(set(level_string.split(","))) + level_para_string = "" + for item in level_list: + if not item.isdigit(): + continue + item = item.strip(" ") + level_para_string = f"{level_para_string}Level{item}," + level_para_string = level_para_string.strip(",") + return level_para_string + + +def get_result_savepath(testsuit_path, result_rootpath): + findkey = os.sep + "tests" + os.sep + filedir, _ = os.path.split(testsuit_path) + pos = filedir.find(findkey) + if -1 != pos: + subpath = filedir[pos + len(findkey):] + pos1 = subpath.find(os.sep) + if -1 != pos1: + subpath = subpath[pos1 + len(os.sep):] + result_path = os.path.join(result_rootpath, "result", subpath) + else: + result_path = os.path.join(result_rootpath, "result") + else: + result_path = os.path.join(result_rootpath, "result") + + if not os.path.exists(result_path): + os.makedirs(result_path) + + LOG.info("result_savepath = " + result_path) + return result_path + + +# all testsuit common Unavailable test result xml +def _create_empty_result_file(filepath, filename, error_message): + error_message = str(error_message) + error_message = error_message.replace("\"", "") + error_message = error_message.replace("<", "") + error_message = error_message.replace(">", "") + error_message = error_message.replace("&", "") + if filename.endswith(".hap"): + filename = filename.split(".")[0] + if not os.path.exists(filepath): + with open(filepath, "w", encoding='utf-8') as file_desc: + time_stamp = time.strftime("%Y-%m-%d %H:%M:%S", + time.localtime()) + file_desc.write('\n') + file_desc.write( + '\n' % time_stamp) + file_desc.write( + ' \n' % + (filename, error_message)) + file_desc.write(' \n') + file_desc.write('\n') + return + + +def _unlock_screen(device): + device.execute_shell_command("svc power stayon true") + time.sleep(1) + + +def _unlock_device(device): + device.execute_shell_command("input keyevent 82") + time.sleep(1) + device.execute_shell_command("wm dismiss-keyguard") + time.sleep(1) + + +def _lock_screen(device): + device.execute_shell_command("svc power stayon false") + time.sleep(1) + + +def disable_keyguard(device): + _unlock_screen(device) + _unlock_device(device) + + +def _sleep_according_to_result(result): + if result: + time.sleep(1) + + +def _create_fuzz_crash_file(filepath, filename): + if not os.path.exists(filepath): + with open(filepath, "w", encoding='utf-8') as file_desc: + time_stamp = time.strftime("%Y-%m-%d %H:%M:%S", + time.localtime()) + file_desc.write('\n') + file_desc.write( + '\n' % time_stamp) + file_desc.write( + ' \n' % filename) + file_desc.write( + ' \n' % (filename, filename)) + file_desc.write( + ' \n') + file_desc.write(' \n') + file_desc.write(' \n') + file_desc.write(' \n') + file_desc.write('\n') + return + + +def _create_fuzz_pass_file(filepath, filename): + if not os.path.exists(filepath): + with open(filepath, "w", encoding='utf-8') as file_desc: + time_stamp = time.strftime("%Y-%m-%d %H:%M:%S", + time.localtime()) + file_desc.write('\n') + file_desc.write( + '\n' % time_stamp) + file_desc.write( + ' \n' % filename) + file_desc.write( + ' \n' % (filename, filename)) + file_desc.write(' \n') + file_desc.write('\n') + return + + +def _create_fuzz_result_file(filepath, filename, error_message): + error_message = str(error_message) + error_message = error_message.replace("\"", "") + error_message = error_message.replace("<", "") + error_message = error_message.replace(">", "") + error_message = error_message.replace("&", "") + if "AddressSanitizer" in error_message: + LOG.error("FUZZ TEST CRASH") + _create_fuzz_crash_file(filepath, filename) + elif re.search(r'Done (\b\d+\b) runs in (\b\d+\b) second', + error_message, re.M) is not None: + LOG.info("FUZZ TEST PASS") + _create_fuzz_pass_file(filepath, filename) + else: + LOG.error("FUZZ TEST UNAVAILABLE") + _create_empty_result_file(filepath, filename, error_message) + return + + +############################################################################## +############################################################################## + +class ResultManager(object): + def __init__(self, testsuit_path, config): + self.testsuite_path = testsuit_path + self.config = config + self.result_rootpath = self.config.report_path + self.device = self.config.device + if testsuit_path.endswith(".hap"): + self.device_testpath = self.config.test_hap_out_path + else: + self.device_testpath = self.config.target_test_path + self.testsuite_name = os.path.basename(self.testsuite_path) + self.is_coverage = False + + def set_is_coverage(self, is_coverage): + self.is_coverage = is_coverage + + def get_test_results(self, error_message=""): + # Get test result files + filepath = self.obtain_test_result_file() + if "fuzztest" == self.config.testtype[0]: + LOG.info("create fuzz test report") + _create_fuzz_result_file(filepath, self.testsuite_name, + error_message) + if not self.is_coverage: + self._obtain_fuzz_corpus() + + if not os.path.exists(filepath): + _create_empty_result_file(filepath, self.testsuite_name, + error_message) + if "benchmark" == self.config.testtype[0]: + self._obtain_benchmark_result() + # Get coverage data files + if self.is_coverage: + self.obtain_coverage_data() + + return filepath + + def _obtain_fuzz_corpus(self): + command = f"cd {DEFAULT_TEST_PATH}; tar czf {self.testsuite_name}_corpus.tar.gz corpus;" + self.config.device.execute_shell_command(command) + result_save_path = get_result_savepath(self.testsuite_path, self.result_rootpath) + LOG.info(f"fuzz_dir = {result_save_path}") + self.device.pull_file(f"{DEFAULT_TEST_PATH}/{self.testsuite_name}_corpus.tar.gz", result_save_path) + + def _obtain_benchmark_result(self): + benchmark_root_dir = os.path.abspath( + os.path.join(self.result_rootpath, "benchmark")) + benchmark_dir = os.path.abspath( + os.path.join(benchmark_root_dir, + self.get_result_sub_save_path(), + self.testsuite_name)) + + if not os.path.exists(benchmark_dir): + os.makedirs(benchmark_dir) + + LOG.info("benchmark_dir = %s" % benchmark_dir) + self.device.pull_file(os.path.join(self.device_testpath, + "%s.json" % self.testsuite_name), benchmark_dir) + if not os.path.exists(os.path.join(benchmark_dir, + "%s.json" % self.testsuite_name)): + os.rmdir(benchmark_dir) + return benchmark_dir + + def get_result_sub_save_path(self): + find_key = os.sep + "benchmark" + os.sep + file_dir, _ = os.path.split(self.testsuite_path) + pos = file_dir.find(find_key) + subpath = "" + if -1 != pos: + subpath = file_dir[pos + len(find_key):] + LOG.info("subpath = " + subpath) + return subpath + + def obtain_test_result_file(self): + result_save_path = get_result_savepath(self.testsuite_path, + self.result_rootpath) + result_file_path = os.path.join(result_save_path, + "%s.xml" % self.testsuite_name) + + result_josn_file_path = os.path.join(result_save_path, + "%s.json" % self.testsuite_name) + + if self.testsuite_path.endswith('.hap'): + remote_result_file = os.path.join(self.device_testpath, + "testcase_result.xml") + remote_json_result_file = os.path.join(self.device_testpath, + "%s.json" % self.testsuite_name) + else: + remote_result_file = os.path.join(self.device_testpath, + "%s.xml" % self.testsuite_name) + remote_json_result_file = os.path.join(self.device_testpath, + "%s.json" % self.testsuite_name) + + if self.config.testtype[0] != "fuzztest": + if self.device.is_file_exist(remote_result_file): + self.device.pull_file(remote_result_file, result_file_path) + elif self.device.is_file_exist(remote_json_result_file): + self.device.pull_file(remote_json_result_file, + result_josn_file_path) + result_file_path = result_josn_file_path + else: + LOG.info("%s not exist", remote_result_file) + + return result_file_path + + def make_empty_result_file(self, error_message=""): + result_savepath = get_result_savepath(self.testsuite_path, + self.result_rootpath) + result_filepath = os.path.join(result_savepath, "%s.xml" % + self.testsuite_name) + if not os.path.exists(result_filepath): + _create_empty_result_file(result_filepath, + self.testsuite_name, error_message) + + def is_exist_target_in_device(self, path, target): + if platform.system() == "Windows": + command = '\"ls -l %s | grep %s\"' % (path, target) + else: + command = "ls -l %s | grep %s" % (path, target) + + check_result = False + stdout_info = self.device.execute_shell_command(command) + if stdout_info != "" and stdout_info.find(target) != -1: + check_result = True + return check_result + + def obtain_coverage_data(self): + cov_root_dir = os.path.abspath(os.path.join( + self.result_rootpath, + "..", + "coverage", + "data", + "exec")) + + target_name = "obj" + cxx_cov_path = os.path.abspath(os.path.join( + self.result_rootpath, + "..", + "coverage", + "data", + "cxx", + self.testsuite_name + '_' + self.config.testtype[0])) + + if self.is_exist_target_in_device(DEFAULT_TEST_PATH, target_name): + if not os.path.exists(cxx_cov_path): + os.makedirs(cxx_cov_path) + self.config.device.execute_shell_command( + "cd %s; tar -czf %s.tar.gz %s" % (DEFAULT_TEST_PATH, target_name, target_name)) + src_file_tar = os.path.join(DEFAULT_TEST_PATH, "%s.tar.gz" % target_name) + self.device.pull_file(src_file_tar, cxx_cov_path, is_create=True, timeout=TIME_OUT) + tar_path = os.path.join(cxx_cov_path, "%s.tar.gz" % target_name) + if platform.system() == "Windows": + process = subprocess.Popen("tar -zxf %s -C %s" % (tar_path, cxx_cov_path), shell=True) + process.communicate() + os.remove(tar_path) + else: + subprocess.Popen("tar -zxf %s -C %s > /dev/null 2>&1" % + (tar_path, cxx_cov_path), shell=True).communicate() + subprocess.Popen("rm -rf %s" % tar_path, shell=True).communicate() + + +############################################################################## +############################################################################## + +@Plugin(type=Plugin.DRIVER, id=DeviceTestType.cpp_test) +class CppTestDriver(IDriver): + """ + CppTest is a Test that runs a native test package on given device. + """ + # test driver config + config = None + result = "" + + def __check_environment__(self, device_options): + if len(device_options) == 1 and device_options[0].label is None: + return True + if len(device_options) != 1 or \ + device_options[0].label != DeviceLabelType.phone: + return False + return True + + def __check_config__(self, config): + pass + + def __result__(self): + return self.result if os.path.exists(self.result) else "" + + def __execute__(self, request): + try: + self.config = request.config + self.config.target_test_path = DEFAULT_TEST_PATH + self.config.device = request.config.environment.devices[0] + + suite_file = request.root.source.source_file + LOG.debug("Testsuite FilePath: %s" % suite_file) + + if not suite_file: + LOG.error("test source '%s' not exists" % + request.root.source.source_string) + return + + if not self.config.device: + result = ResultManager(suite_file, self.config) + result.set_is_coverage(False) + result.make_empty_result_file( + "No test device is found. ") + return + self.config.device.set_device_report_path(request.config.report_path) + self.config.device.device_log_collector.start_hilog_task() + self._init_gtest() + self._run_gtest(suite_file) + + finally: + serial = "{}_{}".format(str(request.config.device.__get_serial__()), time.time_ns()) + log_tar_file_name = "{}_{}".format(request.get_module_name(), str(serial).replace( + ":", "_")) + self.config.device.device_log_collector.stop_hilog_task(log_tar_file_name) + + def _init_gtest(self): + self.config.device.connector_command("target mount") + self.config.device.execute_shell_command( + "rm -rf %s" % self.config.target_test_path) + self.config.device.execute_shell_command( + "mkdir -p %s" % self.config.target_test_path) + self.config.device.execute_shell_command( + "mount -o rw,remount,rw /") + if "fuzztest" == self.config.testtype[0]: + self.config.device.execute_shell_command( + "mkdir -p %s" % os.path.join(self.config.target_test_path, + "corpus")) + + def _run_gtest(self, suite_file): + from xdevice import Variables + filename = os.path.basename(suite_file) + test_para = self._get_test_para(self.config.testcase, + self.config.testlevel, + self.config.testtype, + self.config.target_test_path, + suite_file, + filename) + is_coverage_test = True if self.config.coverage else False + + # push testsuite file + self.config.device.push_file(suite_file, self.config.target_test_path) + self._push_corpus_if_exist(suite_file) + + # push resource files + resource_manager = ResourceManager() + resource_data_dic, resource_dir = \ + resource_manager.get_resource_data_dic(suite_file) + resource_manager.process_preparer_data(resource_data_dic, resource_dir, + self.config.device) + # execute testcase + if not self.config.coverage: + command = "cd %s; rm -rf %s.xml; chmod +x *; ./%s %s" % ( + self.config.target_test_path, + filename, + filename, + test_para) + else: + coverage_outpath = self.config.coverage_outpath + strip_num = len(coverage_outpath.strip("/").split("/")) + if "fuzztest" == self.config.testtype[0]: + self._push_corpus_cov_if_exist(suite_file) + command = f"cd {self.config.target_test_path}; tar zxf {filename}_corpus.tar.gz; \ + rm -rf {filename}.xml; chmod +x *; GCOV_PREFIX=.; \ + GCOV_PREFIX_STRIP={strip_num} ./{filename} {test_para}" + else: + command = "cd %s; rm -rf %s.xml; chmod +x *; GCOV_PREFIX=. " \ + "GCOV_PREFIX_STRIP=%s ./%s %s" % \ + (self.config.target_test_path, + filename, + str(strip_num), + filename, + test_para) + + result = ResultManager(suite_file, self.config) + result.set_is_coverage(is_coverage_test) + + try: + # get result + display_receiver = DisplayOutputReceiver() + self.config.device.execute_shell_command( + command, + receiver=display_receiver, + timeout=TIME_OUT, + retry=0) + return_message = display_receiver.output + except (ExecuteTerminate, DeviceError) as exception: + return_message = str(exception.args) + + self.result = result.get_test_results(return_message) + resource_manager.process_cleaner_data(resource_data_dic, + resource_dir, + self.config.device) + + @staticmethod + def _alter_init(name): + lines = list() + with open(name, "r") as f: + for line in f: + line_strip = line.strip() + if not line_strip: + continue + if line_strip[0] != "#" and line_strip[0] != "/" and line_strip[0] != "*": + lines.append(line_strip) + with open(name, "w") as f: + f.writelines(lines) + + def _push_corpus_cov_if_exist(self, suite_file): + cov_file = suite_file + "_corpus.tar.gz" + LOG.info("corpus_cov file :%s" % str(cov_file)) + self.config.device.push_file(cov_file, os.path.join(self.config.target_test_path)) + + def _push_corpus_if_exist(self, suite_file): + if "fuzztest" == self.config.testtype[0]: + corpus_path = os.path.join(get_fuzzer_path(suite_file), "corpus") + if not os.path.isdir(corpus_path): + return + + corpus_dirs = [] + corpus_file_list = [] + + for root, _, files in os.walk(corpus_path): + if not files: + continue + + corpus_dir = root.split("corpus")[-1] + if corpus_dir != "": + corpus_dirs.append(corpus_dir) + + for file in files: + cp_file = os.path.normcase(os.path.join(root, file)) + corpus_file_list.append(cp_file) + if file == "init": + self._alter_init(cp_file) + + # mkdir corpus files dir + if corpus_dirs: + for corpus in corpus_dirs: + mkdir_corpus_command = f"shell; mkdir -p {corpus}" + self.config.device.connector_command(mkdir_corpus_command) + + # push corpus file + if corpus_file_list: + for corpus_file in corpus_file_list: + self.config.device.push_file(corpus_file, + os.path.join(self.config.target_test_path, "corpus")) + + def _get_test_para(self, + testcase, + testlevel, + testtype, + target_test_path, + suite_file, + filename): + if "benchmark" == testtype[0]: + test_para = (" --benchmark_out_format=json" + " --benchmark_out=%s%s.json") % ( + target_test_path, filename) + return test_para + + if "" != testcase and "" == testlevel: + test_para = "%s=%s" % (GTestConst.exec_para_filter, testcase) + elif "" == testcase and "" != testlevel: + level_para = get_level_para_string(testlevel) + test_para = "%s=%s" % (GTestConst.exec_para_level, level_para) + else: + test_para = "" + + if "fuzztest" == testtype[0]: + cfg_list = FuzzerConfigManager(os.path.join(get_fuzzer_path( + suite_file), "project.xml")).get_fuzzer_config("fuzztest") + LOG.info("config list :%s" % str(cfg_list)) + if self.config.coverage: + test_para += "corpus -runs=0" + \ + " -max_len=" + cfg_list[0] + \ + " -max_total_time=" + cfg_list[1] + \ + " -rss_limit_mb=" + cfg_list[2] + else: + test_para += "corpus -max_len=" + cfg_list[0] + \ + " -max_total_time=" + cfg_list[1] + \ + " -rss_limit_mb=" + cfg_list[2] + + return test_para + + +############################################################################## +############################################################################## + +@Plugin(type=Plugin.DRIVER, id=DeviceTestType.jsunit_test) +class JSUnitTestDriver(IDriver): + """ + JSUnitTestDriver is a Test that runs a native test package on given device. + """ + + def __init__(self): + self.config = None + self.result = "" + self.start_time = None + self.ability_name = "" + self.package_name = "" + # log + self.hilog = None + self.hilog_proc = None + + def __check_environment__(self, device_options): + pass + + def __check_config__(self, config): + pass + + def __result__(self): + return self.result if os.path.exists(self.result) else "" + + def __execute__(self, request): + try: + LOG.info("developertest driver") + self.result = os.path.join( + request.config.report_path, "result", + '.'.join((request.get_module_name(), "xml"))) + self.config = request.config + self.config.target_test_path = DEFAULT_TEST_PATH + self.config.device = request.config.environment.devices[0] + + suite_file = request.root.source.source_file + if not suite_file: + LOG.error("test source '%s' not exists" % + request.root.source.source_string) + return + + if not self.config.device: + result = ResultManager(suite_file, self.config) + result.set_is_coverage(False) + result.make_empty_result_file( + "No test device is found") + return + + package_name, ability_name = self._get_package_and_ability_name( + suite_file) + self.package_name = package_name + self.ability_name = ability_name + self.config.test_hap_out_path = \ + "/data/data/%s/files/" % self.package_name + self.config.device.connector_command("shell hilog -r") + + self.hilog = get_device_log_file( + request.config.report_path, + request.config.device.__get_serial__() + "_" + request. + get_module_name(), + "device_hilog") + + hilog_open = os.open(self.hilog, os.O_WRONLY | os.O_CREAT | os.O_APPEND, + 0o755) + + with os.fdopen(hilog_open, "a") as hilog_file_pipe: + self.config.device.device_log_collector.add_log_address(None, self.hilog) + _, self.hilog_proc = self.config.device.device_log_collector.\ + start_catch_device_log(hilog_file_pipe=hilog_file_pipe) + self._init_jsunit_test() + self._run_jsunit(suite_file, self.hilog) + hilog_file_pipe.flush() + self.generate_console_output(self.hilog, request) + finally: + self.config.device.device_log_collector.remove_log_address(None, self.hilog) + self.config.device.device_log_collector.stop_catch_device_log(self.hilog_proc) + + def _init_jsunit_test(self): + self.config.device.connector_command("target mount") + self.config.device.execute_shell_command( + "rm -rf %s" % self.config.target_test_path) + self.config.device.execute_shell_command( + "mkdir -p %s" % self.config.target_test_path) + self.config.device.execute_shell_command( + "mount -o rw,remount,rw /") + + def _run_jsunit(self, suite_file, device_log_file): + filename = os.path.basename(suite_file) + _, suffix_name = os.path.splitext(filename) + + resource_manager = ResourceManager() + resource_data_dic, resource_dir = resource_manager.get_resource_data_dic(suite_file) + if suffix_name == ".hap": + json_file_path = suite_file.replace(".hap", ".json") + if os.path.exists(json_file_path): + timeout = self._get_json_shell_timeout(json_file_path) + else: + timeout = ResourceManager.get_nodeattrib_data(resource_data_dic) + else: + timeout = ResourceManager.get_nodeattrib_data(resource_data_dic) + resource_manager.process_preparer_data(resource_data_dic, resource_dir, self.config.device) + main_result = self._install_hap(suite_file) + result = ResultManager(suite_file, self.config) + if main_result: + self._execute_hapfile_jsunittest() + try: + status = False + actiontime = JS_TIMEOUT + times = CYCLE_TIMES + if timeout: + actiontime = timeout + times = 1 + device_log_file_open = os.open(device_log_file, os.O_RDONLY, stat.S_IWUSR | stat.S_IRUSR) + with os.fdopen(device_log_file_open, "r", encoding='utf-8') \ + as file_read_pipe: + for i in range(0, times): + if status: + break + else: + time.sleep(float(actiontime)) + start_time = int(time.time()) + while True: + data = file_read_pipe.readline() + if data.find("JSApp:") != -1 and data.find("[end] run suites end") != -1: + LOG.info("execute testcase successfully.") + status = True + break + if int(time.time()) - start_time > 5: + break + finally: + _lock_screen(self.config.device) + self._uninstall_hap(self.package_name) + else: + self.result = result.get_test_results("Error: install hap failed") + LOG.error("Error: install hap failed") + + resource_manager.process_cleaner_data(resource_data_dic, resource_dir, self.config.device) + + def generate_console_output(self, device_log_file, request): + result_message = self.read_device_log(device_log_file) + + report_name = request.get_module_name() + parsers = get_plugin( + Plugin.PARSER, CommonParserType.jsunit) + if parsers: + parsers = parsers[:1] + for listener in request.listeners: + listener.device_sn = self.config.device.device_sn + parser_instances = [] + + for parser in parsers: + parser_instance = parser.__class__() + parser_instance.suites_name = report_name + parser_instance.suite_name = report_name + parser_instance.listeners = request.listeners + parser_instances.append(parser_instance) + handler = ShellHandler(parser_instances) + process_command_ret(result_message, handler) + + def read_device_log(self, device_log_file): + device_log_file_open = os.open(device_log_file, os.O_RDONLY, + stat.S_IWUSR | stat.S_IRUSR) + + result_message = "" + with os.fdopen(device_log_file_open, "r", encoding='utf-8') \ + as file_read_pipe: + while True: + data = file_read_pipe.readline() + if not data: + break + # only filter JSApp log + if data.find("JSApp:") != -1: + result_message += data + if data.find("[end] run suites end") != -1: + break + return result_message + + def _execute_hapfile_jsunittest(self): + _unlock_screen(self.config.device) + _unlock_device(self.config.device) + + try: + return_message = self.start_hap_execute() + except (ExecuteTerminate, DeviceError) as exception: + return_message = str(exception.args) + + return return_message + + def _install_hap(self, suite_file): + message = self.config.device.connector_command("install %s" % suite_file) + message = str(message).rstrip() + if message == "" or "success" in message: + return_code = True + if message != "": + LOG.info(message) + else: + return_code = False + if message != "": + LOG.warning(message) + + _sleep_according_to_result(return_code) + return return_code + + def start_hap_execute(self): + try: + command = "aa start -d 123 -a %s.MainAbility -b %s" \ + % (self.package_name, self.package_name) + self.start_time = time.time() + result_value = self.config.device.execute_shell_command( + command, timeout=TIME_OUT) + + if "success" in str(result_value).lower(): + LOG.info("execute %s's testcase success. result value=%s" + % (self.package_name, result_value)) + else: + LOG.info("execute %s's testcase failed. result value=%s" + % (self.package_name, result_value)) + + _sleep_according_to_result(result_value) + return_message = result_value + except (ExecuteTerminate, DeviceError) as exception: + return_message = exception.args + + return return_message + + def _uninstall_hap(self, package_name): + return_message = self.config.device.execute_shell_command( + "bm uninstall -n %s" % package_name) + _sleep_according_to_result(return_message) + return return_message + + @staticmethod + def _get_acts_test_para(testcase, + testlevel, + testtype, + target_test_path, + suite_file, + filename): + if "actstest" == testtype[0]: + test_para = (" --actstest_out_format=json" + " --actstest_out=%s%s.json") % ( + target_test_path, filename) + return test_para + + if "" != testcase and "" == testlevel: + test_para = "%s=%s" % (GTestConst.exec_acts_para_filter, testcase) + elif "" == testcase and "" != testlevel: + level_para = get_level_para_string(testlevel) + test_para = "%s=%s" % (GTestConst.exec_acts_para_level, level_para) + else: + test_para = "" + return test_para + + @staticmethod + def _get_hats_test_para(testcase, + testlevel, + testtype, + target_test_path, + suite_file, + filename): + if "hatstest" == testtype[0]: + test_hats_para = (" --hatstest_out_format=json" + " --hatstest_out=%s%s.json") % ( + target_test_path, filename) + return test_hats_para + + if "" != testcase and "" == testlevel: + test_hats_para = "%s=%s" % (GTestConst.exec_para_filter, testcase) + elif "" == testcase and "" != testlevel: + level_para = get_level_para_string(testlevel) + test_hats_para = "%s=%s" % (GTestConst.exec_para_level, level_para) + else: + test_hats_para = "" + return test_hats_para + + @classmethod + def _get_json_shell_timeout(cls, json_filepath): + test_timeout = 300 + try: + with open(json_filepath, 'r') as json_file: + data_dic = json.load(json_file) + if not data_dic: + return test_timeout + else: + if "driver" in data_dic.keys(): + driver_dict = data_dic.get("driver") + if driver_dict and "test-timeout" in driver_dict.keys(): + test_timeout = int(driver_dict["shell-timeout"]) / 1000 + else: + return + return test_timeout + except JSONDecodeError: + return test_timeout + finally: + print(" get json shell timeout finally") + + @staticmethod + def _get_package_and_ability_name(hap_filepath): + package_name = "" + ability_name = "" + if os.path.exists(hap_filepath): + filename = os.path.basename(hap_filepath) + + # unzip the hap file + hap_bak_path = os.path.abspath(os.path.join( + os.path.dirname(hap_filepath), + "%s.bak" % filename)) + zf_desc = zipfile.ZipFile(hap_filepath) + try: + zf_desc.extractall(path=hap_bak_path) + except RuntimeError as error: + print(error) + zf_desc.close() + + # verify config.json file + app_profile_path = os.path.join(hap_bak_path, "config.json") + if not os.path.exists(app_profile_path): + print("file %s not exist" % app_profile_path) + return package_name, ability_name + + if os.path.isdir(app_profile_path): + print("%s is a folder, and not a file" % app_profile_path) + return package_name, ability_name + + # get package_name and ability_name value + load_dict = {} + with open(app_profile_path, 'r') as load_f: + load_dict = json.load(load_f) + profile_list = load_dict.values() + for profile in profile_list: + package_name = profile.get("package") + if not package_name: + continue + abilities = profile.get("abilities") + for abilitie in abilities: + abilities_name = abilitie.get("name") + if abilities_name.startswith("."): + ability_name = package_name + abilities_name[ + abilities_name.find("."):] + else: + ability_name = abilities_name + break + break + + # delete hap_bak_path + if os.path.exists(hap_bak_path): + shutil.rmtree(hap_bak_path) + else: + print("file %s not exist" % hap_filepath) + return package_name, ability_name