From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web10.94050.1670987992757650940 for ; Tue, 13 Dec 2022 19:19:54 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=nkPMXMzF; spf=pass (domain: intel.com, ip: 192.55.52.115, mailfrom: gua.guo@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1670987994; x=1702523994; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YqDAYoz5b4+rSU/Rri7b++6DWE9yQHlahbKmQhE8YXs=; b=nkPMXMzFSlxUrv1xynliijIncHBsAKSih5lIe3hruaJk9MoP0ncPb0oG PK7oQh7QLk1gZlx9EGk4dR+Uq8ClFoT5d+u81TkCpR61oYWsR+BLpE9TW veBdrKaRYNp+CbNcUAUPCcEgxrPNI0XpJH4hyNn8umu7b2sr1YU2wflhd FFwUF8bt0t7C5yeAr1rWifDvFWJ/u1VlwB6WnWHukqdzxx5Cb8CdWv1t8 lmr9lVEh7QrfP62SkIrmvj/5slHQS8JLJr+fXpy7hhjj++P/yJUHM+EXi wxnBCF9Db1fWDUZCN8Z/H1PgwCkXrcDAk5TTXtvufe4FFADp5lKqrp52t w==; X-IronPort-AV: E=McAfee;i="6500,9779,10560"; a="318342291" X-IronPort-AV: E=Sophos;i="5.96,243,1665471600"; d="scan'208";a="318342291" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Dec 2022 19:19:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10560"; a="823110070" X-IronPort-AV: E=Sophos;i="5.96,243,1665471600"; d="scan'208";a="823110070" Received: from gguo-desk.gar.corp.intel.com ([10.5.215.23]) by orsmga005.jf.intel.com with ESMTP; 13 Dec 2022 19:19:52 -0800 From: "Guo, Gua" To: devel@edk2.groups.io Cc: Gua Guo , Bob Feng , Bret Barkelew , Liming Gao , Michael D Kinney , Sean Brogan Subject: [PATCH v6 2/3] BaseTools/Plugin: Add coverage support for Unit Test Date: Wed, 14 Dec 2022 11:19:44 +0800 Message-Id: <514b97e62df10b11c2fbb6b8421efc14c6885870.1670987653.git.gua.guo@intel.com> X-Mailer: git-send-email 2.31.1.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Gua Guo For GCC, use lcov to generate Unit Test code coverage report For VS2019, use OpenCppCoverage to generate code coverage report Cc: Bob Feng Cc: Bret Barkelew Cc: Liming Gao Cc: Michael D Kinney Cc: Sean Brogan Signed-off-by: Gua Guo --- .../HostBasedUnitTestRunner.py | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunn= er.py b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py index a8220aacd3..ad63923b69 100644 --- a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py +++ b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py @@ -115,4 +115,104 @@ class HostBasedUnitTestRunner(IUefiBuildPlugin): " %s - %s" % (case.attrib['na= me'], result.text))=0D failure_count +=3D 1=0D =0D + if thebuilder.env.GetValue("CODE_COVERAGE") !=3D "FALSE":=0D + if thebuilder.env.GetValue("TOOL_CHAIN_TAG") =3D=3D "GCC5"= :=0D + self.gen_code_coverage_gcc(thebuilder)=0D + elif thebuilder.env.GetValue("TOOL_CHAIN_TAG").startswith = ("VS"):=0D + self.gen_code_coverage_msvc(thebuilder)=0D + else:=0D + logging.info("Skipping code coverage. Currently, suppo= rt GCC and MSVC compiler.")=0D +=0D return failure_count=0D +=0D + def gen_code_coverage_gcc(self, thebuilder):=0D + logging.info("Generating UnitTest code coverage")=0D +=0D + buildOutputBase =3D thebuilder.env.GetValue("BUILD_OUTPUT_BASE")=0D + workspace =3D thebuilder.env.GetValue("WORKSPACE")=0D +=0D + # Generate base code coverage for all source files=0D + ret =3D RunCmd("lcov", f"--no-external --capture --initial --direc= tory {buildOutputBase} --output-file {buildOutputBase}/cov-base.info --rc l= cov_branch_coverage=3D1")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to build initial cove= rage data.")=0D + return 1=0D +=0D + # Coverage data for tested files only=0D + ret =3D RunCmd("lcov", f"--capture --directory {buildOutputBase}/ = --output-file {buildOutputBase}/coverage-test.info --rc lcov_branch_coverag= e=3D1")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to build coverage dat= a for tested files.")=0D + return 1=0D +=0D + # Aggregate all coverage data=0D + ret =3D RunCmd("lcov", f"--add-tracefile {buildOutputBase}/cov-bas= e.info --add-tracefile {buildOutputBase}/coverage-test.info --output-file {= buildOutputBase}/total-coverage.info --rc lcov_branch_coverage=3D1")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to aggregate coverage= data.")=0D + return 1=0D +=0D + # Generate coverage XML=0D + ret =3D RunCmd("lcov_cobertura",f"{buildOutputBase}/total-coverage= .info -o {buildOutputBase}/compare.xml")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate coverage = XML.")=0D + return 1=0D +=0D + # Filter out auto-generated and test code=0D + ret =3D RunCmd("lcov_cobertura",f"{buildOutputBase}/total-coverage= .info --excludes ^.*UnitTest\|^.*MU\|^.*Mock\|^.*DEBUG -o {buildOutputBase}= /coverage.xml")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed generate filtered cov= erage XML.")=0D + return 1=0D +=0D + # Generate all coverage file=0D + testCoverageList =3D glob.glob (f"{workspace}/Build/**/total-cover= age.info", recursive=3DTrue)=0D +=0D + coverageFile =3D ""=0D + for testCoverage in testCoverageList:=0D + coverageFile +=3D " --add-tracefile " + testCoverage=0D + ret =3D RunCmd("lcov", f"{coverageFile} --output-file {workspace}/= Build/all-coverage.info --rc lcov_branch_coverage=3D1")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed generate all coverage= file.")=0D + return 1=0D +=0D + # Generate and XML file if requested.for all package=0D + if os.path.isfile(f"{workspace}/Build/coverage.xml"):=0D + os.remove(f"{workspace}/Build/coverage.xml")=0D + ret =3D RunCmd("lcov_cobertura",f"{workspace}/Build/all-coverage.i= nfo --excludes ^.*UnitTest\|^.*MU\|^.*Mock\|^.*DEBUG -o {workspace}/Build/c= overage.xml")=0D +=0D + return 0=0D +=0D +=0D + def gen_code_coverage_msvc(self, thebuilder):=0D + logging.info("Generating UnitTest code coverage")=0D +=0D +=0D + buildOutputBase =3D thebuilder.env.GetValue("BUILD_OUTPUT_BASE")=0D + testList =3D glob.glob(os.path.join(buildOutputBase, "**","*Test*.= exe"), recursive=3DTrue)=0D + workspace =3D thebuilder.env.GetValue("WORKSPACE")=0D + workspace =3D (workspace + os.sep) if workspace[-1] !=3D os.sep el= se workspace=0D + # Generate coverage file=0D + coverageFile =3D ""=0D + for testFile in testList:=0D + ret =3D RunCmd("OpenCppCoverage", f"--source {workspace} --exp= ort_type binary:{testFile}.cov -- {testFile}")=0D + coverageFile +=3D " --input_coverage=3D" + testFile + ".cov"=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to collect covera= ge data.")=0D + return 1=0D +=0D + DiskName =3D workspace[:workspace.find (":\\") + 2]=0D + # Generate and XML file if requested.by each package=0D + ret =3D RunCmd("OpenCppCoverage", f"--export_type cobertura:{os.pa= th.join(buildOutputBase, 'coverage.xml')} --working_dir=3D{workspace}Build = {coverageFile}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate cobertura= format xml in single package.")=0D + return 1=0D +=0D + # Generate total report XML file for all package=0D + testCoverageList =3D glob.glob(os.path.join(workspace, "Build", "*= *","*Test*.exe.cov"), recursive=3DTrue)=0D + coverageFile =3D ""=0D + for testCoverage in testCoverageList:=0D + coverageFile +=3D " --input_coverage=3D" + testCoverage=0D +=0D + ret =3D RunCmd("OpenCppCoverage", f"--export_type cobertura:{works= pace}Build/coverage.xml --working_dir=3D{workspace}Build {coverageFile}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate cobertura= format xml.")=0D + return 1=0D +=0D + return 0=0D --=20 2.31.1.windows.1