diff --git a/localCoverage/coverage_tools.py b/localCoverage/coverage_tools.py index ad036c7fa528600970d0c0c5f18c2b7bf0944da6..0fb233564aa4cdee558a4d641e6c5b096cef688b 100644 --- a/localCoverage/coverage_tools.py +++ b/localCoverage/coverage_tools.py @@ -176,5 +176,9 @@ if __name__ == '__main__': developer_path, "localCoverage/restore_comment/restore_source_code.py") subprocess.run("python3 %s" % restore_source_code_path, shell=True) + keyword_path = os.path.join( + developer_path, "localCoverage/keyword_registration/keyword_filter.py") + subprocess.run("python3 %s" % keyword_path, shell=True) + print(r"See the code coverage report in: " r"/test/testfwk/developer_test/localCoverage/codeCoverage/results/coverage/reports/cxx/html") diff --git a/localCoverage/keyword_registration/keyword.json b/localCoverage/keyword_registration/keyword.json new file mode 100644 index 0000000000000000000000000000000000000000..3c742e9422fb54940cad54cefe988358aa52e357 --- /dev/null +++ b/localCoverage/keyword_registration/keyword.json @@ -0,0 +1,83 @@ +{ + "KEYWORD": [ + "unmap(", "ReadInterfaceToken(", "DeepCopyGroupEntry(", "readUint32(", + "ifstream fin(", "InitFunc", "AddInt64StringToJson(", "WriteFloatVector(", + "GetUint64Value(", "realpath(", "fchmod(", "SendEvent(", "WriteParcelable(", + "EVP_DecryptInit_ex(", "CreateJson(", "InitThread(", "ParcelWrite(", + "SetUint8Value(", "OnRemoveSystemAbility(", "EVP_CIPHER_CTX_ctrl(", "umount(", + "SetAttributesValue(", "GetBundleManager(", "fstat(", "ChangeModeFile(", + "HcFileClose", "FD_ISSET(", "CheckSystemAbility(", "SendTransactCmd(", + "SetUint8ArrayValue(", "GetUint8ArrayValue(", "SerializeToArray(", + "pthread_getname_np(", "LoadSymbol(", "fchown(", "InitClient(", + "ReadString16(", "TryConnect(", "EVP_PKEY_new_mac_key(", "WIFEXITED(", + "SendRequest(", "bind(", "GetInt32Value(", "read(", "ReadUint8(", "AsObject(", + "lseek(", "ChangePropertyContent(", "WriteToParcel(", "dlsym(", "pushBackT(", + "close(", "pwrite(", "SetCallRequestParamInfo(", "CheckGetSAPermission(", + "RSRenderServiceConnectHub::GetRenderService(", "readdir(", "memset_s(", + "is_object(", "curl_global_init(", "WriteTargetAndCallback", + "GetSystemAbility(", "pipe(", "fwrite(", "sendfile(", "Remote(", "HcMalloc(", + "CreateHdiScreen(", "GetDmsProxy(", "opendir(", "WriteInt32(", + "SetStringValue(", "WriteUint64(", "open(", "mkdir(", "CreateGroupEntry(", + "Peek(", "DirIterator(", "select(", "AddByteToJson(", "AddIntToJson(", + "SetDataCapacity", "RSTransactionProxy::GetInstance(", "ReadUint32(", "link(", + "Malloc(", "DeepCopyDeviceEntry(", "ParseFromString(", "CreateConnection(", + "readstring(", "AddDeathRecipient(", "WriteBuffer(", "EVP_DecryptFinal_ex(", + "GetStringValue(", "curl_multi_init(", "mount(", "InitDmsImplFunc", + "GetUint32Value(", "WriteUint16(", "umount2(", "AddObjToArray(", + "GetContextObject(", "rfind(", "SetUint16Value(", "GetDeviceProfileService(", + "statvfs(", "fork(", "sprintf_s(", "free(", "ReadInt16(", "remove(", "ioctl(", + "GetParcelableInfo(", "GetAttributesValue(", "WriteParcelableVector(", + "ReadUint64(", "HcFileRead(", "futimens(", "fputc(", + "HdiFramebufferSurface::CreateFramebufferSurface(", "popen(", "HcFileOpen(", + "ReadStringVector(", "ReadString(", "strdup(", "GetUint16ArrayValue(", + "is_discarded(", "ReadUnpadBuffer(", "WriteInt32Vector(", + "SetUint16ArrayValue(", "fgets(", "kill(", "ChangeModeDirectory(", "getline(", + "GetRealPath(", "fclose(", "GetUdid(", "newLine.empty(", "ReportSystemFault(", + "is_open(", "GetUint16Value(", "MakeShared(", "ReadParcelable&", + "AddObjToJson(", "SetUint32Value(", "EVP_EncryptInit_ex(", "make_shared&", + "CreateDeviceEntry(", "setmntent(", "OnAddSystemAbility(", "fdopen(", + "RSMainThread::Instance(", "access(", "NLMSG_SPACE(", "mmap(", + "CheckAddOrRemovePermission(", "dlopen(", "dlsy(", "malloc(", "chmod(", + "curl_multi_setopt(", "PackJsonToString(", "OnStart(", "ReadRemoteObject(", + "stat(","GetUint64ArrayValue(", "new","ifstream(", "poll(", "CmMalloc(", + "HcfMalloc(", "SetUint64ArrayValue(", "PathExists(", "StringSetPointer(", + "unlink(", "major(", "CreateSurfaceAsConsumer(", "ParcelWriteUint64(", + "EVP_DigestSignUpdate(", "ReadInt32(","ReadUInt8Vector(", "snprintf_s(", + "WriteInt16(", "readlink(", "LoadLibrary(", "WriteString16(", "memcpy_s(", + "rename(", "statfs(", "GetUint8Value(","closedir(", "mknod(","HcFileRemove(", + "getmntent_r(","fopen(", "SetBoolValue(","Seek(", "GetUint32ArrayValue(", + "strcmp(", "CheckListSAPermission(", "Mmap(","iface_cast(", + "EVP_DigestSignInit(", "UnpackInt32(", "GetSystemAbilityManager(", "Write(", + "ReadBool(","vsnprintf_s(", "IsProxyObject(","dlerror(", "WriteInt64(", + "EVP_EncryptFinal_ex(","lstat(", "IsObjectDead","Unmarshing(", "strcpy_s(", + "EVP_DecryptUpdate(","New(", "rmdir(","WriteInterfaceToken(", + "GetBoolValue(", "WriteUInt32Vector(", "ReadUInt32Vector(", "EVP_Digest(", + "ParcelWriteUint32(", "StringSet(","AddStringToJson(", "Marshalling(", + "ParcelReadUint64(", "ReadFloat(","Create(", "SaveStringToFd(","fprintf(", + "GetProxy(", "EVP_EncryptUpdate(", "ParcelRead(","Publish(","Free(", + "make_unique&","execvp(", "HdiBackend::GetInstance(", "ReadInt32Vector(", + "pushBack(", "CreateVSyncReceiver(", "WriteStringVector(", "HcGetUdid(", + "UnMarshalling(", "WriteUint32(", "ReadUInt64Vector(", "GetRemoteObject(", + "none_of(", "WriteUInt64Vector(", "CreateJsonArray(","sendmsg(", "socket(", + "SetUint32ArrayValue(", "SetInt32Value(","dprintf(", "syncfs(", + "SetUint64Value(", "RAND_bytes(","CheckGetRemoteSAPermission(", + "MarshalSAExtraProp(", "ReadFloatVector(","WriteFloat(", "Serialize(", + "syscall(", "HcFileWrite(", "ReadFromParcel(", "InitHcMutex(", "MALLOC(", + "new(", "CreateSurfaceAsProducer(", "ReadString16Vector(", "chown(", + "HcFileSize(", "HdiDevice::GetInstance(", + "RSProcessorFactory::CreateProcessor(", "ReadInt64(", "WriteRawData(", + "strncat_s(", "newLine.find(", "ReadParcelableVector(", "ChkRWError(", + "CreateOrGetScreenManager(", "fread(", "readUint64(", "HksMalloc(", + "RemoveDeathRecipient(", "sscanf_s(", "EVP_DigestSignFinal(", "ReadUint16(", + "fseek(", "promote(", "WriteUInt8Vector(", "WriteRemoteObject(", + "EVP_CIPHER_CTX_new(", "ParcelReadUint32(", "PostTask(", "ReadRawData(", + "ReadVectorFromparcel(", "WriteUint8(", "UnpackUint64(", "WriteBool(", + "ForceCreateDirectory(", "chdir(", "DelayedSingleton&", "dup2(", "write(", + "AddBoolToJson(", "EVP_MD_CTX_create(", "Alloc(", "recvmsg(", "WriteString(", + "SoftBusMutexLock(", "pthread_mutex_lock(", "RequireAuthLock(", "Lock(", + "LaneQosLock(", "SoftBusCalloc(", "SoftBusMalloc(", "cJSON_AddItemToObject(", + "RewindWrite(", "WritePointer(", "DBinderService::GetInstance(", + "IPCProcessSkeleton::GetCurrent(", "IPCThreadSkeleton::GetCurrent(", + "ISessionService::GetInstance(" + ] +} \ No newline at end of file diff --git a/localCoverage/keyword_registration/keyword_filter.py b/localCoverage/keyword_registration/keyword_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..c23d3c8de673285338f5bdeeb80c498d8cacf947 --- /dev/null +++ b/localCoverage/keyword_registration/keyword_filter.py @@ -0,0 +1,925 @@ +#!/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 re +import time +import json +import fcntl +import platform +import linecache +import traceback +from multiprocessing import Pool +from lxml import html +from selectolax.parser import HTMLParser + +etree = html.etree + + +class CoverageReportPath: + def __init__(self, report_path): + self.report_path = report_path + + def gcov_file_generator(self): + """ + gcov文件生成器 + """ + for root_path, dir, files in os.walk(self.report_path): + for file in files: + if not file.endswith(".gcov.html"): + continue + file_path = os.path.join(root_path, file) + yield file_path + + def modify_report_style(self): + """ + 修改覆盖率报告css样式 + """ + css_file_path = "" + for root_path, dir, files in os.walk(self.report_path): + for file in files: + if file == "gcov.css": + css_file_path = os.path.join(root_path, file) + text = """ +/* update */ +span.linenumupdate, span.branchexecupdate, span.branchnoexecupdate, +span.linecovupdate, span.linenocovupdate, span.branchcovupdate, +span.branchnocovupdate +{ + background-color:#BBBBBB; +}""" + with open(css_file_path, "a+", encoding="utf-8") as file: + file.write(text) + + def get_statistic_path(self, gcov_file_path: str): + """ + 根据gcov.html路径和统计等级获取统计报告路径 + """ + file_name_list = ["index.html", "index-sort-b.html", + "index-sort-f.html", "index-sort-l.html"] + index_path_list = [ + os.path.normcase(os.path.join(os.path.dirname(gcov_file_path), file_name)) + for file_name in file_name_list + ] + out_path_list = [ + os.path.normcase(os.path.join(self.report_path, file_name)) + for file_name in file_name_list + ] + index_path_list.extend(out_path_list) + return index_path_list + + +class KeywordRegistration: + def __init__(self, report_path): + self.report_path = report_path + self.keyword_file_path = os.path.normcase( + os.path.join(os.path.dirname(__file__), "keyword.json")) + + def get_keyword_info(self): + """ + 获取报备关键字信息 + """ + try: + with open(self.keyword_file_path, "r") as file: + keyword_dict = json.load(file) + keyword_list = keyword_dict.get("KEYWORD") + return keyword_list + except (FileNotFoundError, AttributeError, FileExistsError) as error: + print(f"获取报备过滤关键字报错,error:{error}") + + @staticmethod + def get_coverage_content(file_path): + """ + 获取覆盖率文件内容 + """ + if not os.path.exists(file_path): + return + with open(file_path, "r", encoding="utf-8") as file: + content = file.read() + return content + + @staticmethod + def get_tag(content, line): + start_index = content.find(f'")[0] + + if source_code: + source_code = "".join(source_code) + return source_code + + @staticmethod + def update_tag(tag: str): + replace_item_list = ["lineNum", "branchNoCov", "branchCov", "lineCov", + "branchNoExec", "lineNoCov", "branchExec"] + + for item in replace_item_list: + if item in tag: + replace_item = (item + "Update").lower() + tag = tag.replace(item, replace_item) + return tag + + def get_coverage_lines_by_branch(self, file_path, content=None): + """ + 获取覆盖率报告中的所有的if分支行号 + """ + if not content: + content = self.get_coverage_content(file_path) + if not content: + return + _, file_name = os.path.split(file_path) + branch_line_list = re.findall( + r''' 200: + return None, None + next_tag = get_tag(content, str(next_line)) + func_body_tag_list_append(next_tag) + if "{" in next_tag: + if branch_braces_sub: + branch_braces_sub += 1 + braces_sub += 1 + if "}" in next_tag: + if branch_braces_sub: + branch_braces_sub -= 1 + braces_sub -= 1 + if 'title="Branch' in next_tag: + branch_braces_sub += 1 + sub_brace_start_status = True + if not branch_braces_sub and \ + (sub_brace_start_status == sub_brace_end_status): + next_tag = update_tag(next_tag) + if not branch_braces_sub and sub_brace_start_status: + sub_brace_end_status = True + update_func_body_tag_list_append(next_tag) + next_line += 1 + return func_body_tag_list, update_func_body_tag_list + + def get_line_funcname(self, branch_line, content): + """ + 获取行号源码所在函数的函数名 + """ + function_name = "" + previous_line = int(branch_line) + loop_count = 0 + get_tag = self.get_tag + try: + while not function_name: + loop_count += 1 + if loop_count > 200: + return + previous_line -= 1 + tag = get_tag(content, previous_line) + tag_text = HTMLParser(tag).text() + if tag_text[39:].strip().startswith("{"): + left_parentheses_count = right_parentheses_count = 0 + child_count = 0 + while previous_line: + child_count += 1 + if child_count > 200: + return + previous_line -= 1 + html_text = get_tag(content, previous_line) + source_code = HTMLParser(html_text).text()[39:].strip() + + left_parentheses_count += source_code.count("(") + right_parentheses_count += source_code.count(")") + if not left_parentheses_count == right_parentheses_count: + continue + if " operator" in source_code: + class_name_list = re.findall(r'\((.*?)\)', source_code) + if class_name_list: + function_name_str = class_name_list[0] + if not function_name_str: + return + function_name = function_name_str.split()[-1] + return function_name + function_name_list = re.findall(r' (.*?)\(', source_code) + if function_name_list: + function_name_str = function_name_list[0] + if not function_name_str: + return + function_name = function_name_str.split()[-1] + return function_name + except (OSError, IndexError, TypeError) as error: + print(f"覆盖率报告{branch_line}行获取函数名报错, error:{error}", + traceback.format_exc()) + + @staticmethod + def get_branch_line_list(keyword_line: int, branch_line_list: list): + """ + 获取大于关键字行号的所有分支行号 + """ + if keyword_line in branch_line_list: + index = branch_line_list.index(keyword_line) + branch_line_list = branch_line_list[index:] + else: + for line in branch_line_list: + if line > keyword_line: + index = branch_line_list.index(line) + branch_line_list = branch_line_list[index:] + break + return branch_line_list + + @staticmethod + def get_keyword_judge_char(keyword, keyword_source_code): + """ + 获取关键字替代字符 + """ + if "&" in keyword: + keyword = keyword.replace("&", "<") + + keyword_index = keyword_source_code.find(keyword) + if keyword_index == -1: + return + + try: + keyword_code = keyword_source_code[:keyword_index + len(keyword)] + if " = " in keyword_code: + judge_key = keyword_code.split(" = ")[0].split()[-1] + else: + bracket_index = keyword_code.find("(") + bracket_code = keyword_code[:bracket_index] + judge_key = bracket_code.split()[-1] + return judge_key + except (IndexError, ValueError) as error: + print("获取关键字替代字符", error, traceback.format_exc()) + + @staticmethod + def get_branch_data_by_tag(tag_html: str, symbol_status=None): + """ + 根据前端标签获取分支数据 + """ + if symbol_status: + key = r"#+\-*" + else: + key = r"#+\-" + branch_line_list = re.findall(rf"> ([{key}]) ", tag_html) + + return branch_line_list + + @staticmethod + def get_judge_condition_index(judge_key: str, source_code: str): + """ + 获取判断条件索引 + """ + keyword_index_list = [] + keyword_index_list_append = keyword_index_list.append + + condition_str_list = re.split(rf"\|\||&&", source_code) + for index, code_str in enumerate(condition_str_list): + if judge_key in code_str: + keyword_index_list_append(index) + return keyword_index_list, condition_str_list + + @staticmethod + def update_source_code_tag(html_tag: str): + replace_item_list = ["lineNum", "lineCov", "lineNoCov"] + + for item in replace_item_list: + if item in html_tag: + replace_item = (item + "Update").lower() + html_tag = html_tag.replace(item, replace_item) + + return html_tag + + def get_break_line_tag(self, content, origin_branch_html, branch_line): + """ + 获取分支换行的判断条件源码tag + """ + get_tag = self.get_tag + left_brace_exist = False + line_break = loop_count = 0 + while not left_brace_exist: + if loop_count > 10: + break + line_break += 1 + origin_branch_html += "\n" + next_line_tag = get_tag(content, branch_line + line_break) + if "{" in next_line_tag: + left_brace_exist = True + origin_branch_html += next_line_tag + loop_count += 1 + return origin_branch_html + + @staticmethod + def modify_tag_style(tag, rate): + """ + 修改标签样式 + """ + if 75 <= rate < 90: + tag = tag.replace("headerCovTableEntryLo", "headerCovTableEntryMed") + tag = tag.replace("coverPerLo", "coverPerMed") + tag = tag.replace("coverNumLo", "coverNumMed") + elif rate >= 90: + tag = tag.replace("headerCovTableEntryLo", "headerCovTableEntryHi") + tag = tag.replace("headerCovTableEntryMed", "headerCovTableEntryHi") + tag = tag.replace("coverPerLo", "coverPerHi") + tag = tag.replace("coverNumLo", "coverNumHi") + tag = tag.replace("coverPerMed", "coverPerHi") + tag = tag.replace("coverNumMed", "coverNumHi") + return tag + + def update_coverage_ratio_tag(self, file_path): + """ + 修改覆盖率比率数据 + """ + with open(file_path, "r", encoding="utf-8") as coverage_file: + content = coverage_file.read() + + covered_nums = len(re.findall(r"> ([+]) ", content)) + branch_total = len(re.findall(r"> ([+\-#]) ", content)) + + line = 0 + start_line = 1 + content_list = content.splitlines() + for line_text in content_list: + if '