diff --git a/.vsts-ci-templates/build_and_test.yml b/.vsts-ci-templates/build_and_test.yml index 5ccc0f9ff..ec0908b54 100644 --- a/.vsts-ci-templates/build_and_test.yml +++ b/.vsts-ci-templates/build_and_test.yml @@ -33,3 +33,15 @@ steps: ls *_test | xargs -n1 -I '{}' sh -c 'printf "\n*** Binary: {} ***\n "; llvm-cov-7 report -object {} -instr-profile {}.profdata -ignore-filename-regex="(boost|openenclave|3rdparty|/test/)"' displayName: Coverage workingDirectory: build + +- script: | + ../tests/coverage/generate_coverage.sh + displayName: CoverageGeneration + workingDirectory: build + +- task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: '$(System.DefaultWorkingDirectory)/build/coverage.xml' + reportDirectory: '$(System.DefaultWorkingDirectory)/build/coverage' + condition: succeededOrFailed() diff --git a/tests/coverage/cobertura_generator.py b/tests/coverage/cobertura_generator.py new file mode 100644 index 000000000..e54169733 --- /dev/null +++ b/tests/coverage/cobertura_generator.py @@ -0,0 +1,70 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the Apache 2.0 License. +import xml.etree.ElementTree as et +import json +import xml.dom.minidom as minidom +import time + + +def pretty_print(tree_root): + tree_string = et.tostring(tree_root, "utf-8") + final_string = tree_string + reparsed = minidom.parseString(final_string) + return reparsed.toprettyxml(indent="\t") + + +with open("coverage.json", "r") as file: + timestamp = str(time.time()) + data = json.load(file)["data"][0] + + line_rate = str(data["totals"]["lines"]["percent"] / 100.0) + lines_covered = str(data["totals"]["lines"]["covered"]) + lines_valid = str(data["totals"]["lines"]["count"]) + branch_rate = str(data["totals"]["functions"]["percent"] / 100.0) + branch_covered = str(data["totals"]["functions"]["covered"]) + branch_valid = str(data["totals"]["functions"]["count"]) + coverage = et.Element( + "coverage", + attrib={ + "line-rate": line_rate, + "lines-covered": lines_covered, + "lines-valid": lines_valid, + "branches-covered": branch_covered, + "branches-valid": branch_valid, + "branch-rate": branch_rate, + "version": "1.0", + "timestamp": timestamp, + }, + ) + packages = et.SubElement(coverage, "packages") + package = et.SubElement( + packages, + "package", + attrib={"name": "ccf", "line-rate": line_rate, "branch-rate": branch_rate}, + ) + classes = et.SubElement(package, "classes") + + files = data["files"] + for file in files: + filename = file["filename"] + line_rate = str(file["summary"]["lines"]["percent"] / 100.0) + branch_rate = str(file["summary"]["functions"]["percent"] / 100.0) + class_element = et.SubElement( + classes, + "class", + name=filename, + attrib={ + "filename": filename, + "line-rate": line_rate, + "branch-rate": branch_rate, + }, + ) + et.SubElement( + class_element, + "line", + attrib={"branch": "false", "hits": "1", "number": "1"}, + ) + + tree = pretty_print(coverage) + with open("coverage.xml", "w") as xml_file: + xml_file.write(tree) diff --git a/tests/coverage/generate_coverage.sh b/tests/coverage/generate_coverage.sh new file mode 100755 index 000000000..32a4f354a --- /dev/null +++ b/tests/coverage/generate_coverage.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the Apache 2.0 License. + +for f in *profraw; do + echo "$f" >> prof_files +done + +llvm-profdata-7 merge -sparse -f prof_files -o coverage.profdata + +objects=() +for f in *_test; do + objects+=( -object "$f") + llvm-cov-7 show -instr-profile "$f".profdata -output-dir=cov_"$f" -format=html "$f" -Xdemangler c++filt -Xdemangler -n -ignore-filename-regex="(boost|openenclave|3rdparty|/test/)" +done + +llvm-cov-7 show -instr-profile coverage.profdata -output-dir=coverage -format=html ds_test "${objects[@]}" -Xdemangler c++filt -Xdemangler -n -ignore-filename-regex="(boost|openenclave|3rdparty|/test/)" +llvm-cov-7 export -instr-profile coverage.profdata -format=text ds_test "${objects[@]}" -Xdemangler c++filt -Xdemangler -n -ignore-filename-regex="(boost|openenclave|3rdparty|/test/)" -summary-only > coverage.json + +mv cov_* coverage/ + +python3.7 ../tests/coverage/cobertura_generator.py +python3.7 ../tests/coverage/style_html.py \ No newline at end of file diff --git a/tests/coverage/style_html.py b/tests/coverage/style_html.py new file mode 100644 index 000000000..8e17ced6e --- /dev/null +++ b/tests/coverage/style_html.py @@ -0,0 +1,39 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the Apache 2.0 License. +import glob +import os + +""" +copies the css into the html files +""" + +style_file = "coverage/style.css" +index_html = "coverage/index.html" + +with open(index_html, "a") as index_file: + index_file.write("

") + index_file.write("

") + index_file.write( + "" + ) + + for cov_dir in glob.glob("coverage/cov_*", recursive=False): + directory = os.path.basename(cov_dir) + index_file.write( + "" + ) + index_file.write("
Coverage Per Unit Test
"
+            + directory
+            + "
") + index_file.write("
") + index_file.write("

") + +with open(style_file) as style: + css = style.read() + for filename in glob.iglob("coverage/**/*.html", recursive=True): + with open(filename, "a") as html: + html.write('")