From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mx.groups.io with SMTP id smtpd.web11.4494.1663830549554291597 for ; Thu, 22 Sep 2022 00:09:12 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=IydQE42x; spf=pass (domain: intel.com, ip: 134.134.136.100, 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=1663830550; x=1695366550; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/bOWawVfaNDRD6bMopvpBXvV3XZ9PotvQRK85hZ/Ulo=; b=IydQE42x8rwrwfr2dbaWBSAz494rqbaUSBTWkAwA+L8NyO9UlgHQogjQ tmnSfoSPqNMhB60EhXjP8J/0ycb7XGKYA+J3oAbdldeHZ767lvOgnOin/ q6EufmRj55zLrLFVfTCg64HPhuQY51KNnd9/O5XEwfs4pcOzfYLTM9N4h hfSrBVI8mYs9nOUFiVZA/Fl3vwOfoW61vrhxKhj7m/5atSz/dIOmsB9Lp 2E7IQSx/FJd1tR01YFYjS7Zu1W9B9R/Dpx/KedIZOck5RbspCnEGMKodu bW793jQDnNuOMOxSmQIkDAYK7WtGjO6MYce3SKAh3DZQWt5p1bz44hptW Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10477"; a="364198680" X-IronPort-AV: E=Sophos;i="5.93,335,1654585200"; d="scan'208";a="364198680" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2022 00:09:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,335,1654585200"; d="scan'208";a="621986204" Received: from gguo-desk.gar.corp.intel.com ([10.5.215.23]) by fmsmga007.fm.intel.com with ESMTP; 22 Sep 2022 00:09:10 -0700 From: "Guo, Gua" To: devel@edk2.groups.io Cc: Gua Guo , Bob Feng , Liming Gao , Bret Barkelew , Michael D Kinney , Sean Brogan Subject: [PATCH v3 2/2] BaseTools/Plugin: Add coverage support for Unit Test Date: Thu, 22 Sep 2022 15:09:05 +0800 Message-Id: <9bd869e8a7384e1e60680d18a3e2713cd2891f2f.1663830230.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: Liming Gao Cc: Bret Barkelew Cc: Michael D Kinney Cc: Sean Brogan Signed-off-by: Gua Guo --- .../HostBasedUnitTestRunner.py | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunn= er.py b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py index c1eeaf2625..0b77576f3c 100644 --- a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py +++ b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py @@ -112,4 +112,128 @@ 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=3D "TRUE":=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") =3D=3D "VS2= 019":=0D + self.gen_code_coverage_msvc(thebuilder)=0D + else:=0D + logging.info("Skipping code coverage. Only supported o= n GCC.")=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 HTML file if requested.by each package=0D + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE":=0D + ret =3D RunCmd("pycobertura", f"show --format html --output {b= uildOutputBase}/coverage.html {buildOutputBase}/coverage.xml --source {work= space}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate HTML = in single package..")=0D +=0D + # Generate and HTML 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 + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE":=0D + if os.path.isfile(f"{workspace}/Build/coverage.html"):=0D + os.remove(f"{workspace}/Build/coverage.html")=0D + ret =3D RunCmd("pycobertura", f"show --format html --output {w= orkspace}/Build/coverage.html {workspace}/Build/coverage.xml --source {work= space}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate HTML.= ")=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 +=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 + # Generate and HTML file if requested.by each package=0D + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE":=0D + ret =3D RunCmd("OpenCppCoverage", f"--export_type cobertura:{b= uildOutputBase}/coverage.xml --working_dir=3D{workspace}/Build {coverageFil= e}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate cober= tura format xml in single package.")=0D + return 1=0D +=0D + ret =3D RunCmd("pycobertura", f"show --format html --output {b= uildOutputBase}/cverage.html {buildOutputBase}/coverage.xml --source {works= pace}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate HTML = in single package.")=0D + return 1=0D +=0D + # Generate total report HTML 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 + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE":=0D + ret =3D RunCmd("OpenCppCoverage", f"--export_type cobertura:{w= orkspace}/Build/coverage.xml --working_dir=3D{workspace}/Build {coverageFil= e}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate cober= tura format xml.")=0D + return 1=0D +=0D + ret =3D RunCmd("pycobertura", f"show --format html --output {w= orkspace}/Build/coverage.html {workspace}/Build/coverage.xml --source {work= space}")=0D + if(ret !=3D 0):=0D + logging.error("UnitTest Coverage: Failed to generate HTML.= ")=0D + return 1=0D +=0D + return 0=0D --=20 2.31.1.windows.1