1#!/usr/bin/env python3 2# coding=utf-8 3 4# 5# Copyright (c) 2023 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import os 20import re 21import time 22import json 23import stat 24import fcntl 25import platform 26import linecache 27import traceback 28from multiprocessing import Pool 29from lxml import html 30from selectolax.parser import HTMLParser 31 32FLAGS_WRITE = os.O_WRONLY | os.O_CREAT | os.O_EXCL 33FLAGS_ADD = os.O_WRONLY | os.O_APPEND | os.O_CREAT 34MODES = stat.S_IWUSR | stat.S_IRUSR 35 36 37class CoverageReportPath: 38 def __init__(self, report_path): 39 self.report_path = report_path 40 41 def gcov_file_generator(self): 42 """ 43 gcov文件生成器 44 """ 45 for root_path, _, files in os.walk(self.report_path): 46 for file in files: 47 if not file.endswith(".gcov.html"): 48 continue 49 file_path = os.path.join(root_path, file) 50 yield file_path 51 52 def modify_report_style(self): 53 """ 54 修改覆盖率报告css样式 55 """ 56 css_file_path = "" 57 for root_path, _, files in os.walk(self.report_path): 58 for file in files: 59 if file == "gcov.css": 60 css_file_path = os.path.join(root_path, file) 61 text = """ 62/* update */ 63span.linenumupdate, span.branchexecupdate, span.branchnoexecupdate, 64span.linecovupdate, span.linenocovupdate, span.branchcovupdate, 65span.branchnocovupdate 66{ 67 background-color:#BBBBBB; 68}""" 69 if os.path.exists(css_file_path): 70 with os.fdopen(os.open(css_file_path, FLAGS_ADD, MODES), 'a+') as file: 71 file.write(text) 72 73 def get_statistic_path(self, gcov_file_path: str): 74 """ 75 根据gcov.html路径和统计等级获取统计报告路径 76 """ 77 file_name_list = ["index.html", "index-sort-b.html", 78 "index-sort-f.html", "index-sort-l.html"] 79 index_path_list = [ 80 os.path.normcase(os.path.join(os.path.dirname(gcov_file_path), file_name)) 81 for file_name in file_name_list 82 ] 83 out_path_list = [ 84 os.path.normcase(os.path.join(self.report_path, file_name)) 85 for file_name in file_name_list 86 ] 87 index_path_list.extend(out_path_list) 88 return index_path_list 89 90 91class KeywordRegistration: 92 def __init__(self, report_path): 93 self.report_path = report_path 94 self.keyword_file_path = os.path.normcase( 95 os.path.join(os.path.dirname(__file__), "keyword.json")) 96 97 def get_keyword_info(self): 98 """ 99 获取报备关键字信息 100 """ 101 try: 102 with open(self.keyword_file_path, "r") as file: 103 keyword_dict = json.load(file) 104 keyword_list = keyword_dict.get("KEYWORD") 105 return keyword_list 106 except (FileNotFoundError, AttributeError, FileExistsError): 107 print(f"获取报备过滤关键字报错") 108 return [] 109 110 @staticmethod 111 def get_coverage_content(file_path): 112 """ 113 获取覆盖率文件内容 114 """ 115 if not os.path.exists(file_path): 116 return "" 117 with open(file_path, "r", encoding="utf-8") as file: 118 content = file.read() 119 return content 120 121 @staticmethod 122 def get_tag(content, line): 123 start_index = content.find(f'<a name="{line}"') 124 end_index = content.find(f'<a name="{int(line) + 1}"') 125 tag = content[start_index:end_index - 1] 126 return tag 127 128 @staticmethod 129 def get_source_code(tag): 130 etree = html.etree 131 parser = etree.HTMLParser(encoding="utf-8") 132 parser_obj = etree.HTML(tag, parser=parser) 133 source_code = parser_obj.xpath("//span[@class='lineNoCov' or " 134 "@class='lineCov' or " 135 "@class='linecovupdate' or" 136 "@class='linenocovupdate']/text()") 137 if not source_code: 138 index = tag.find(":") 139 source_code = tag[index + 1:].split("</a>")[0] 140 141 if source_code: 142 source_code = "".join(source_code) 143 return source_code 144 145 @staticmethod 146 def update_tag(tag: str): 147 replace_item_list = ["lineNum", "branchNoCov", "branchCov", "lineCov", 148 "branchNoExec", "lineNoCov", "branchExec"] 149 150 for item in replace_item_list: 151 if item in tag: 152 replace_item = (item + "Update").lower() 153 tag = tag.replace(item, replace_item) 154 return tag 155 156 def get_coverage_lines_by_branch(self, file_path, content=None): 157 """ 158 获取覆盖率报告中的所有的if分支行号 159 """ 160 if not content: 161 content = self.get_coverage_content(file_path) 162 if not content: 163 return [] 164 _, file_name = os.path.split(file_path) 165 branch_line_list = re.findall( 166 r'''<a name="(\d+).*?Branch.*? if \(| 167 <a name="(\d+).*?Branch.*? if\(''', content) 168 169 if branch_line_list: 170 branch_line_list = [int(line_tuple[0]) if line_tuple[0] else 171 int(line_tuple[1]) for line_tuple in branch_line_list] 172 return branch_line_list 173 else: 174 return [] 175 176 def get_coverage_lines_by_keyword(self, keyword, content): 177 """ 178 获取关键字在覆盖率报告中的行号 179 """ 180 if "&" in keyword: 181 keyword = keyword.replace("&", "") 182 origin_keyword = keyword 183 if keyword.endswith("("): 184 keyword = keyword.replace("(", "") 185 keyword_line_list = re.findall( 186 rf'<a name="(\d+).*?[ .;!:()]{keyword}[ .;!:()&]', content) 187 else: 188 keyword_line_list = re.findall( 189 rf'<a name="(\d+).*?[ .;!:()]{keyword}[ .;!:)&]', content) 190 191 if keyword_line_list: 192 keyword_line_list = [int(line) for line in keyword_line_list] 193 keyword_branch_list = [] 194 get_tag = self.get_tag 195 keyword_branch_list_append = keyword_branch_list.append 196 keyword_line_list_remove = keyword_line_list.remove 197 for line in keyword_line_list: 198 tag_html = get_tag(content, line) 199 if origin_keyword not in tag_html: 200 keyword_branch_list_append(line) 201 if 'title="Branch' not in tag_html: 202 continue 203 if "switch (" in tag_html or "switch(" in tag_html: 204 keyword_branch_list_append(line) 205 elif "while (" in tag_html or "while(" in tag_html: 206 keyword_branch_list_append(line) 207 elif "for (" in tag_html or "for(" in tag_html: 208 keyword_branch_list_append(line) 209 elif "do {" in tag_html or "do{" in tag_html: 210 keyword_branch_list_append(line) 211 for key in keyword_branch_list: 212 keyword_line_list_remove(key) 213 return keyword_line_list 214 215 def code_body_judge(self, line, content): 216 """ 217 全量报备按行获取覆盖率报告源码 218 """ 219 func_body_tag_list = [] 220 update_func_body_tag_list = [] 221 func_body_tag_list_append = func_body_tag_list.append 222 update_func_body_tag_list_append = update_func_body_tag_list.append 223 get_tag = self.get_tag 224 update_tag = self.update_tag 225 tag = get_tag(content, line) 226 if "{" not in tag: 227 return func_body_tag_list, update_func_body_tag_list 228 229 braces_sub = 1 230 if "{" not in tag: 231 braces_sub = 0 232 next_line = int(line) + 1 233 branch_braces_sub = count = 0 234 sub_brace_start_status = sub_brace_end_status = False 235 while braces_sub: 236 count += 1 237 if count > 200: 238 return [], [] 239 next_tag = get_tag(content, str(next_line)) 240 func_body_tag_list_append(next_tag) 241 if "{" in next_tag: 242 if branch_braces_sub: 243 branch_braces_sub += 1 244 braces_sub += 1 245 if "}" in next_tag: 246 if branch_braces_sub: 247 branch_braces_sub -= 1 248 braces_sub -= 1 249 if 'title="Branch' in next_tag: 250 branch_braces_sub += 1 251 sub_brace_start_status = True 252 if not branch_braces_sub and \ 253 (sub_brace_start_status == sub_brace_end_status): 254 next_tag = update_tag(next_tag) 255 if not branch_braces_sub and sub_brace_start_status: 256 sub_brace_end_status = True 257 update_func_body_tag_list_append(next_tag) 258 next_line += 1 259 return func_body_tag_list, update_func_body_tag_list 260 261 def get_line_funcname(self, branch_line, content): 262 """ 263 获取行号源码所在函数的函数名 264 """ 265 function_name = "" 266 previous_line = int(branch_line) 267 loop_count = 0 268 get_tag = self.get_tag 269 try: 270 while not function_name: 271 loop_count += 1 272 if loop_count > 200: 273 return "" 274 previous_line -= 1 275 tag = get_tag(content, previous_line) 276 tag_text = HTMLParser(tag).text() 277 if tag_text[39:].strip().startswith("{"): 278 left_parentheses_count = right_parentheses_count = 0 279 child_count = 0 280 while previous_line: 281 child_count += 1 282 if child_count > 200: 283 return "" 284 previous_line -= 1 285 html_text = get_tag(content, previous_line) 286 source_code = HTMLParser(html_text).text()[39:].strip() 287 288 left_parentheses_count += source_code.count("(") 289 right_parentheses_count += source_code.count(")") 290 if not left_parentheses_count == right_parentheses_count: 291 continue 292 if " operator" in source_code: 293 class_name_list = re.findall(r'\((.*?)\)', source_code) 294 if class_name_list: 295 function_name_str = class_name_list[0] 296 if not function_name_str: 297 return "" 298 299 function_name = function_name_str.split()[-1] 300 return function_name 301 function_name_list = re.findall(r' (.*?)\(', source_code) 302 if function_name_list: 303 function_name_str = function_name_list[0] 304 if not function_name_str: 305 return "" 306 function_name = function_name_str.split()[-1] 307 return function_name 308 return "" 309 except (OSError, IndexError, TypeError) as error: 310 print(f"覆盖率报告{branch_line}行获取函数名报错, error:{error}", 311 traceback.format_exc()) 312 return "" 313 314 @staticmethod 315 def get_branch_line_list(keyword_line: int, branch_line_list: list): 316 """ 317 获取大于关键字行号的所有分支行号 318 """ 319 if keyword_line in branch_line_list: 320 index = branch_line_list.index(keyword_line) 321 branch_line_list = branch_line_list[index:] 322 else: 323 for line in branch_line_list: 324 if line > keyword_line: 325 index = branch_line_list.index(line) 326 branch_line_list = branch_line_list[index:] 327 break 328 return branch_line_list 329 330 @staticmethod 331 def get_keyword_judge_char(keyword, keyword_source_code): 332 """ 333 获取关键字替代字符 334 """ 335 if "&" in keyword: 336 keyword = keyword.replace("&", "<") 337 338 keyword_index = keyword_source_code.find(keyword) 339 if keyword_index == -1: 340 return "" 341 342 try: 343 keyword_code = keyword_source_code[:keyword_index + len(keyword)] 344 if " = " in keyword_code: 345 judge_key = keyword_code.split(" = ")[0].split()[-1] 346 else: 347 bracket_index = keyword_code.find("(") 348 bracket_code = keyword_code[:bracket_index] 349 judge_key = bracket_code.split()[-1] 350 return judge_key 351 except (IndexError, ValueError): 352 print("获取关键字替代字符失败") 353 return "" 354 355 @staticmethod 356 def get_branch_data_by_tag(tag_html: str, symbol_status=None): 357 """ 358 根据前端标签获取分支数据 359 """ 360 if symbol_status: 361 key = r"#+\-*" 362 else: 363 key = r"#+\-" 364 branch_line_list = re.findall(rf"> ([{key}]) </span>", tag_html) 365 366 return branch_line_list 367 368 @staticmethod 369 def get_judge_condition_index(judge_key: str, source_code: str): 370 """ 371 获取判断条件索引 372 """ 373 keyword_index_list = [] 374 keyword_index_list_append = keyword_index_list.append 375 376 condition_str_list = re.split(rf"\|\||&&", source_code) 377 for index, code_str in enumerate(condition_str_list): 378 if judge_key in code_str: 379 keyword_index_list_append(index) 380 return keyword_index_list, condition_str_list 381 382 @staticmethod 383 def update_source_code_tag(html_tag: str): 384 replace_item_list = ["lineNum", "lineCov", "lineNoCov"] 385 386 for item in replace_item_list: 387 if item in html_tag: 388 replace_item = (item + "Update").lower() 389 html_tag = html_tag.replace(item, replace_item) 390 391 return html_tag 392 393 def get_break_line_tag(self, content, origin_branch_html, branch_line): 394 """ 395 获取分支换行的判断条件源码tag 396 """ 397 get_tag = self.get_tag 398 left_brace_exist = False 399 line_break = loop_count = 0 400 while not left_brace_exist: 401 if loop_count > 10: 402 break 403 line_break += 1 404 origin_branch_html = os.path.join(origin_branch_html, "\n") 405 next_line_tag = get_tag(content, branch_line + line_break) 406 if "{" in next_line_tag: 407 left_brace_exist = True 408 origin_branch_html += next_line_tag 409 loop_count += 1 410 return origin_branch_html 411 412 @staticmethod 413 def modify_tag_style(tag, rate): 414 """ 415 修改标签样式 416 """ 417 if 75 <= rate < 90: 418 tag = tag.replace("headerCovTableEntryLo", "headerCovTableEntryMed") 419 tag = tag.replace("coverPerLo", "coverPerMed") 420 tag = tag.replace("coverNumLo", "coverNumMed") 421 elif rate >= 90: 422 tag = tag.replace("headerCovTableEntryLo", "headerCovTableEntryHi") 423 tag = tag.replace("headerCovTableEntryMed", "headerCovTableEntryHi") 424 tag = tag.replace("coverPerLo", "coverPerHi") 425 tag = tag.replace("coverNumLo", "coverNumHi") 426 tag = tag.replace("coverPerMed", "coverPerHi") 427 tag = tag.replace("coverNumMed", "coverNumHi") 428 return tag 429 430 def update_coverage_ratio_tag(self, file_path): 431 """ 432 修改覆盖率比率数据 433 """ 434 with open(file_path, "r", encoding="utf-8") as coverage_file: 435 content = coverage_file.read() 436 437 covered_nums = len(re.findall(r"> ([+]) </span>", content)) 438 branch_total = len(re.findall(r"> ([+\-#]) </span>", content)) 439 440 line = 0 441 start_line = 1 442 content_list = content.splitlines() 443 for line_text in content_list: 444 if '<td class="headerItem">Branches:</td>' in line_text: 445 line = start_line 446 break 447 start_line += 1 448 linecache.clearcache() 449 coverage_tag = linecache.getline(file_path, line) 450 covered_tag = linecache.getline(file_path, line + 1) 451 coverage_total_tag = linecache.getline(file_path, line + 2) 452 try: 453 origin_hit = int(re.findall(r"(\d+)", covered_tag)[0]) 454 origin_total = int(re.findall(r"(\d+)", coverage_total_tag)[0]) 455 coverage_rate_tag = linecache.getline(file_path, line + 3) 456 replace_tag = coverage_tag + covered_tag + coverage_total_tag + \ 457 coverage_rate_tag 458 if origin_total - branch_total == 0 and origin_hit - covered_nums == 0: 459 return 460 if int(branch_total) == 0: 461 coverage = 0.0 462 else: 463 coverage = round(int(covered_nums) / int(branch_total) * 100, 1) 464 465 origin_rate = re.findall(r"(\d+.\d+)", coverage_rate_tag)[0] 466 update_tag = coverage_tag + covered_tag.replace( 467 str(origin_hit), str(covered_nums)) + \ 468 coverage_total_tag.replace(str(origin_total), 469 str(branch_total)) + \ 470 coverage_rate_tag.replace(origin_rate, str(coverage)) 471 472 update_tag = self.modify_tag_style(update_tag, coverage) 473 if replace_tag in content: 474 content = content.replace(replace_tag, update_tag) 475 476 os.remove(file_path) 477 with os.fdopen(os.open(file_path, FLAGS_WRITE, MODES), 'w') as file: 478 file.write(content) 479 480 # 修改数据统计页面 481 hit_shield_num = origin_hit - covered_nums 482 total_shield_num = origin_total - branch_total 483 self.update_statistic(file_path, hit_shield_num, total_shield_num) 484 except (IndexError, TypeError, FileNotFoundError): 485 print("修改分支数据失败") 486 487 def update_statistic(self, file_path, hit_shield_num, total_shield_num): 488 """ 489 修改覆盖率分支数据 490 """ 491 index_path_list = CoverageReportPath(self.report_path).get_statistic_path(file_path) 492 for index_path in index_path_list: 493 if not os.path.exists(index_path): 494 continue 495 496 with open(index_path, "r", encoding="utf-8") as coverage_file: 497 fcntl.flock(coverage_file.fileno(), fcntl.LOCK_EX) 498 content = coverage_file.read() 499 500 file_dir, file_name = os.path.split(file_path) 501 if os.path.normcase(file_dir) not in os.path.normcase(index_path): 502 if platform.system() == "Windows": 503 judge_item = file_dir.replace(self.report_path + "\\", "") 504 judge_item = ">" + judge_item.replace("\\", "/") + "</a>" 505 else: 506 judge_item = file_dir.replace(self.report_path + "/", "") 507 judge_item = ">" + judge_item + "</a>" 508 else: 509 judge_item = ">" + file_name.replace(".gcov.html", "") 510 511 start_line = 1 512 line = tag_line = 0 513 content_list = content.splitlines() 514 tmp = '<td class="headerItem">Branches:</td>' 515 for line_text in content_list: 516 if not line and tmp in line_text: 517 line = start_line 518 if judge_item in line_text: 519 tag_line = start_line 520 break 521 start_line += 1 522 try: 523 # total statistic modify 524 linecache.clearcache() 525 coverage_head_tag = linecache.getline(index_path, line) 526 origin_hit_tag = linecache.getline(index_path, line + 1) 527 origin_hit_num = int(re.findall(r"(\d+)", origin_hit_tag)[0]) 528 origin_total_tag = linecache.getline(index_path, line + 2) 529 origin_total_num = int(re.findall(r"(\d+)", origin_total_tag)[0]) 530 origin_rate_tag = linecache.getline(index_path, line + 3) 531 origin_rate = re.findall(r"(\d+.\d+)", origin_rate_tag)[0] 532 replace_tag = coverage_head_tag + origin_hit_tag + \ 533 origin_total_tag + origin_rate_tag 534 535 # file branch modify 536 no_change_file_tag = "" 537 for i in range(8): 538 no_change_file_tag += linecache.getline(index_path, tag_line + i) 539 file_rate_tag = linecache.getline(index_path, tag_line + 8) 540 file_covered_tag = linecache.getline(index_path, tag_line + 9) 541 file_tag = no_change_file_tag + file_rate_tag + file_covered_tag 542 origin_file_covered_num, origin_file_total_num = map( 543 int, re.findall(r"(\d+)", file_covered_tag)) 544 if origin_file_total_num: 545 origin_file_rate = re.findall(r"(\d+.\d+)", file_rate_tag)[0] 546 else: 547 # 不存在覆盖率 548 origin_file_rate = "-" 549 head_hit_num = origin_hit_num - hit_shield_num 550 head_total_num = origin_total_num - total_shield_num 551 if head_total_num == 0: 552 rate = 0.0 553 else: 554 rate = round(head_hit_num / head_total_num * 100, 1) 555 file_hit_num = origin_file_covered_num - hit_shield_num 556 file_total_num = origin_file_total_num - total_shield_num 557 if file_total_num == 0: 558 file_rate = 0.0 559 else: 560 file_rate = round(file_hit_num / file_total_num * 100, 1) 561 update_tag = coverage_head_tag + origin_hit_tag.replace( 562 str(origin_hit_num), str(head_hit_num)) + \ 563 origin_total_tag.replace(str(origin_total_num), 564 str(head_total_num)) + \ 565 origin_rate_tag.replace(origin_rate, str(rate)) 566 567 update_tag = self.modify_tag_style(update_tag, rate) 568 569 update_branch_tag = file_rate_tag.replace( 570 origin_file_rate, str(file_rate)) + \ 571 file_covered_tag.replace( 572 str(origin_file_covered_num) + " / " + 573 str(origin_file_total_num), str(file_hit_num) + " / " + 574 str(file_total_num)) 575 576 update_branch_tag = self.modify_tag_style(update_branch_tag, file_rate) 577 update_branch_tag = no_change_file_tag + update_branch_tag 578 if replace_tag in content: 579 content = content.replace(replace_tag, update_tag) 580 if file_tag in content: 581 content = content.replace(file_tag, update_branch_tag) 582 os.remove(index_path) 583 with os.fdopen(os.open(index_path, FLAGS_WRITE, MODES), 'w') as file: 584 file.write(content) 585 fcntl.flock(file.fileno(), fcntl.LOCK_UN) 586 time.sleep(1) 587 except (IndexError, TypeError, FileNotFoundError): 588 print("修改分支统计数据出错") 589 590 def _check_if_branch_line(self, judge_key, sub_branch_line_list, 591 key_line, content, function_name): 592 """ 593 确定if分支行号 594 """ 595 if_branch_line = None 596 for branch_line in sub_branch_line_list: 597 if branch_line == key_line: 598 if_branch_line = key_line 599 break 600 # 获取分支行所在函数名 601 branch_function_name = self.get_line_funcname( 602 branch_line, content) 603 # 关键字范围只在关键字所在函数之内 604 branch_line_tag = self.get_tag(content, branch_line) 605 try: 606 if "{" not in branch_line_tag: 607 branch_line_tag = self.get_break_line_tag( 608 content, branch_line_tag, branch_line) 609 branch_line_source_code = self.get_source_code( 610 branch_line_tag) 611 if function_name == branch_function_name: 612 if judge_key in branch_line_source_code: 613 if_branch_line = branch_line 614 break 615 else: 616 break 617 except (ValueError, KeyError): 618 print("获取关键字if分支行报错", traceback.format_exc()) 619 620 return if_branch_line 621 622 @staticmethod 623 def _branch_replace(branch): 624 """ 625 分支符号替换 626 """ 627 if branch == "#": 628 branch = "> # <" 629 elif branch == "+": 630 branch = "> + <" 631 elif branch == "*": 632 branch = "> * <" 633 else: 634 branch = "> - <" 635 return branch 636 637 @staticmethod 638 def _single_condition_modify_html(branch_html, branch_list): 639 """ 640 单条件修改代码块html 641 """ 642 line_item = '<span class="lineNum"> </span>' 643 line_feed_index = branch_html.find(line_item) 644 if line_feed_index == -1: 645 if "+" in branch_list: 646 update_branch_tag = branch_html.replace("> - <", "> <") 647 update_branch_tag = update_branch_tag.replace("> # <", "> <") 648 else: 649 try: 650 first_branch = branch_list[0] 651 first_branch = "> " + first_branch + " <" 652 first_branch_index = branch_html.find(first_branch) 653 branch_tag = branch_html[:first_branch_index + 5] 654 update_branch_tag = branch_html[first_branch_index + 5:] 655 update_branch_tag = update_branch_tag.replace("> - <", "> <") 656 update_branch_tag = update_branch_tag.replace("> # <", "> <") 657 update_branch_tag = branch_tag + update_branch_tag 658 except ValueError: 659 return "" 660 else: 661 line_feed_index = branch_html.find(line_item) 662 update_branch_tag = branch_html[:line_feed_index + len(line_item) + 1] 663 if "-" not in branch_list and "+" not in branch_list: 664 del_count = update_branch_tag.count("> # <") 665 update_branch_tag = update_branch_tag.replace("> # <", "> <", del_count - 1) 666 else: 667 update_branch_tag = update_branch_tag.replace("> - <", "> <") 668 update_branch_tag = update_branch_tag.replace("> # <", "> <") 669 branch_tag = branch_html[line_feed_index + len(line_item) + 1:] 670 line_feed_index = branch_tag.find(line_item) 671 if line_feed_index == -1: 672 branch_tag = branch_tag.replace("> - <", "> <") 673 branch_tag = branch_tag.replace("> # <", "> <") 674 update_branch_tag += branch_tag 675 else: 676 loop_count = 0 677 while line_feed_index + 1: 678 loop_count += 1 679 if loop_count > 200: 680 continue 681 try: 682 update_branch_tag += branch_tag[:line_feed_index + len(line_item) + 1] 683 update_branch_tag = update_branch_tag.replace("> - <", "> <") 684 update_branch_tag = update_branch_tag.replace("> # <", "> <") 685 branch_tag = branch_tag[line_feed_index + len(line_item) + 1:] 686 line_feed_index = branch_tag.find(line_item) 687 except ValueError: 688 return "" 689 690 branch_tag = branch_tag.replace("> - <", "> <") 691 update_branch_tag = update_branch_tag.replace("> # <", "> <") 692 update_branch_tag += branch_tag 693 return update_branch_tag 694 695 def _multi_condition_modify_html(self, branch_html, branch_length, 696 condition_str_list, judge_index_list): 697 """ 698 多条件修改代码块html 699 """ 700 line_item = '<span class="lineNum"> </span>' 701 if branch_length % len(condition_str_list): 702 line_feed_index = branch_html.find(line_item) 703 update_branch_tag = branch_html[:line_feed_index] 704 update_branch_tag = update_branch_tag.replace("> - <", "> <") 705 branch_html = branch_html[line_feed_index:] 706 loop_count = 0 707 while line_feed_index + 1: 708 loop_count += 1 709 if loop_count > 200: 710 continue 711 line_feed_index = branch_html.count(line_item) 712 if line_feed_index > 1: 713 try: 714 line_feed_length = len(line_item) 715 branch_tag_before = branch_html[:line_feed_length] 716 branch_html = branch_html[line_feed_length:] 717 line_feed_index = branch_html.find(line_item) 718 branch_tag_after = branch_html[:line_feed_index] 719 branch_tag_after = branch_tag_after.replace("> - <", "> <") 720 branch_tag = branch_tag_before + branch_tag_after 721 except ValueError: 722 return "" 723 else: 724 branch_tag = branch_html 725 branch_tag = branch_tag.replace("> - <", "> <") 726 # 不再换行,索引为-1 727 line_feed_index = -1 728 729 update_branch_tag += branch_tag 730 if line_feed_index == -1: 731 branch_html = "" 732 else: 733 branch_html = branch_html[line_feed_index:] 734 if branch_html != "": 735 branch_html = branch_html.replace("> - <", "> <") 736 update_branch_tag += branch_html 737 else: 738 branch_list = self.get_branch_data_by_tag(branch_html, True) 739 update_branch_tag = "" 740 end_count = -1 741 try: 742 for index in judge_index_list: 743 branch_data = branch_list[:(index + 1) * 2] 744 # 要修改的分支数据列表长度 745 branch_data_length = len(branch_data) 746 change_status = False 747 for count, branch in enumerate(branch_data, 1): 748 if count <= end_count: 749 continue 750 751 end_count = count 752 branch = self._branch_replace(branch) 753 end_index = branch_html.find(branch) 754 branch_tag = branch_html[:end_index + 5] 755 if branch_data_length - count in [0, 1]: 756 if change_status: 757 continue 758 if branch == "> # <": 759 change_status = True 760 branch_tag = branch_tag.replace("> # <", "> * <") 761 elif branch == "> - <": 762 change_status = True 763 branch_tag = branch_tag.replace("> - <", "> * <") 764 update_branch_tag += branch_tag 765 branch_html = branch_html[end_index + 5:] 766 except (ValueError, TypeError): 767 return "" 768 update_branch_tag += branch_html 769 return update_branch_tag 770 771 def judge_branch_exists(self, file_path): 772 """ 773 判断报告是否存在分支 774 """ 775 content = self.get_coverage_content(file_path) 776 branch_total = len(re.findall(r"> ([+\-#]) </span>", content)) 777 if branch_total: 778 return True 779 else: 780 return False 781 782 def modify_branch(self, file_path, keyword_list): 783 """ 784 html报告分支屏蔽修改 785 """ 786 branch_line_list = self.get_coverage_lines_by_branch(file_path) 787 if not branch_line_list: 788 return 789 790 branch_line_list.sort() 791 no_change_content = self.get_coverage_content(file_path) 792 for keyword in keyword_list: 793 content = self.get_coverage_content(file_path) 794 keyword_line_list = self.get_coverage_lines_by_keyword(keyword, content) 795 if not keyword_line_list: 796 continue 797 for key_line in keyword_line_list: 798 key_html = self.get_tag(content, key_line) 799 if not key_html or "LOG" in key_html: 800 continue 801 802 function_name = self.get_line_funcname(key_line, content) 803 sub_branch_line_list = self.get_branch_line_list( 804 key_line, branch_line_list) 805 keyword_source_code = self.get_source_code(key_html) 806 if not all([function_name, keyword_source_code, 807 sub_branch_line_list]): 808 continue 809 810 judge_key = keyword 811 if 'title="Branch' not in key_html: 812 judge_key = self.get_keyword_judge_char( 813 keyword, keyword_source_code) 814 if "*" in judge_key: 815 judge_key = judge_key.replace("*", "") 816 if "&" in judge_key: 817 judge_key = judge_key.replace("&", "") 818 if_branch_line = self._check_if_branch_line( 819 judge_key, sub_branch_line_list, key_line, 820 content, function_name) 821 822 if not if_branch_line: 823 continue 824 825 origin_branch_html = self.get_tag(content, if_branch_line) 826 branch_html = origin_branch_html 827 if "{" not in origin_branch_html: 828 origin_branch_html = self.get_break_line_tag( 829 content, origin_branch_html, if_branch_line) 830 branch_html = origin_branch_html 831 top_source_code = self.get_source_code(branch_html) 832 no_change_branch_html = self.get_tag( 833 no_change_content, if_branch_line) 834 branch_list = self.get_branch_data_by_tag(no_change_branch_html) 835 if not branch_list: 836 continue 837 if "#" not in branch_list and "-" not in branch_list: 838 continue 839 branch_tag_data = self.get_branch_data_by_tag(branch_html, True) 840 if len(branch_tag_data) <= 1: 841 continue 842 if len(branch_list) == 2: 843 if "-" in branch_list: 844 update_branch_tag = branch_html.replace("> - <", "> <") 845 else: 846 update_branch_tag = branch_html.replace("> # <", "> <", 1) 847 else: 848 branch_length = len(branch_list) 849 judge_index_list, condition_str_list = self.\ 850 get_judge_condition_index(judge_key, top_source_code) 851 if not len(judge_index_list): 852 continue 853 if len(condition_str_list) == 1: 854 update_branch_tag = self._single_condition_modify_html( 855 branch_html, branch_list) 856 else: 857 update_branch_tag = self._multi_condition_modify_html( 858 branch_html, branch_length, condition_str_list, 859 judge_index_list) 860 if not update_branch_tag: 861 return 862 863 update_branch_tag = self.update_source_code_tag( 864 update_branch_tag) 865 content = content.replace(origin_branch_html, update_branch_tag) 866 source_code_tag_list, update_source_code_tag_list = self.\ 867 code_body_judge(int(if_branch_line), content) 868 if source_code_tag_list: 869 source_code_tag_html = "\n".join(source_code_tag_list) 870 update_source_code_tag_html = "\n".join( 871 update_source_code_tag_list) 872 content = content.replace( 873 source_code_tag_html, update_source_code_tag_html) 874 os.remove(file_path) 875 with os.fdopen(os.open(file_path, FLAGS_WRITE, MODES), 'w') as new_html: 876 new_html.write(content) 877 878 content = self.get_coverage_content(file_path) 879 content = content.replace('> * </span>', '> </span>') 880 os.remove(file_path) 881 882 with os.fdopen(os.open(file_path, FLAGS_WRITE, MODES), 'w') as new_html: 883 new_html.write(content) 884 885 def keyword_registration(self, file_path, keyword_list): 886 """ 887 报备 888 """ 889 self.modify_branch(file_path, keyword_list) 890 891 # 修改覆盖率数据 892 self.update_coverage_ratio_tag(file_path) 893 return True 894 895 def multiprocessing_registration(self): 896 """ 897 多进程关键字报备 898 """ 899 keyword_list = self.get_keyword_info() 900 if not keyword_list: 901 return 902 903 # 创建报告路径生成器 904 report_instance = CoverageReportPath(self.report_path) 905 # 修改css文件 906 report_instance.modify_report_style() 907 # 创建报告路径生成器 908 report_generator = report_instance.gcov_file_generator() 909 # 获取关键字 910 keyword_registration = self.keyword_registration 911 912 pool = Pool(10) 913 apply_async = pool.apply_async 914 while True: 915 file_path = next(report_generator, None) 916 if not file_path: 917 break 918 919 # 关键字报备 920 apply_async(keyword_registration, args=(file_path, keyword_list)) 921 922 pool.close() 923 pool.join() 924 925 926def main(report_path): 927 print("*" * 50, "报备开始", "*" * 50) 928 manager = KeywordRegistration(report_path) 929 start_time = time.time() 930 manager.multiprocessing_registration() 931 end_time = time.time() 932 times = round(end_time - start_time, 3) 933 print("*" * 50, "报备结束", "*" * 50, "耗时:", times) 934 935 936if __name__ == '__main__': 937 current_path = os.getcwd() 938 home_path = current_path.split("/test/testfwk/developer_test")[0] 939 developer_path = os.path.join(home_path, "test/testfwk/developer_test") 940 html_path = os.path.join(developer_path, "localCoverage/codeCoverage/results/coverage/reports/cxx/html") 941 main(html_path) 942