Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.pytool/Plugin: Improve Rust support #578

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions .pytool/Plugin/RustHostUnitTestPlugin/RustHostUnitTestPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,39 @@ def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM,

# Build list of packages that are in the EDK2 package we are running CI on
pp = Path(Edk2pathObj.GetAbsolutePathOnThisSystemFromEdk2RelativePath(packagename))
package_name_list = [pkg.name for pkg in filter(lambda pkg: Path(pkg.path).is_relative_to(pp), rust_ws.members)]
package_path_list = [pkg.path for pkg in filter(lambda pkg: Path(pkg.path).is_relative_to(pp), rust_ws.members)]
logging.debug(f"Rust Packages to test: {' '.join(package_name_list)}")
crate_name_list = [pkg.name for pkg in filter(lambda pkg: Path(pkg.path).is_relative_to(pp), rust_ws.members)]
crate_path_list = [pkg.path for pkg in filter(lambda pkg: Path(pkg.path).is_relative_to(pp), rust_ws.members)]
logging.debug(f"Rust Crates to test: {' '.join(crate_name_list)}")

# Build a list of paths to ignore when computing results. This includes:
# 1. Any tests folder in a rust package
# 2. Everything in a submodule
# 3. Everything in an EDK2 package not being tested.
ignore_list = [Path("**", "tests", "*")]
ignore_list.extend([Path(s, "**", "*") for s in repo_details(ws)["Submodules"]])
ignore_list.extend(list(set([pkg.path for pkg in rust_ws.members]) - set(package_path_list)))
ignored_local_crates = list(set(crate.path for crate in rust_ws.members) - set(crate_path_list))
ignore_list.extend([Path(crate, "**", "*").relative_to(ws) for crate in ignored_local_crates])
ignore_list = [str(i) for i in ignore_list]
logging.debug(f"Paths to ignore when computing coverage: {' '.join(ignore_list)}")

# Run tests and evaluate results
results = rust_ws.coverage(package_name_list, ignore_list = ignore_list, report_type = "xml")
try:
results = rust_ws.coverage(crate_name_list, ignore_list = ignore_list, report_type = "xml")
except RuntimeError as e:
logging.warning(str(e))
tc.LogStdError(str(e))
tc.SetFailed(str(e), "CHECK_FAILED")
return 1

# Evaluate unit test results
failed = 0
for test in results["pass"]:
tc.LogStdOut(f'{test} ... PASS')

for test in results["fail"]:
tc.LogStdError(f'{test} ... FAIL')
e = f'{test} ... FAIL'
logging.warning(e)
tc.LogStdError(e)
failed += 1

# If we failed a unit test, we have no coverage data to evaluate
Expand All @@ -61,7 +70,11 @@ def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM,
coverage = {}
for file, cov in results["coverage"].items():
try:
package = next(pkg.name for pkg in rust_ws.members if Path(ws,file).is_relative_to(pkg.path))
package = next(
crate.name
for crate in rust_ws.members
if Path(ws, file).is_relative_to(crate.path)
)
except StopIteration:
continue
covered, total = cov.split("/")
Expand All @@ -80,7 +93,9 @@ def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM,
if calc_cov >= required_cov:
tc.LogStdOut(f'coverage::{pkg}: {calc_cov} greater than {required_cov} ... PASS')
else:
tc.LogStdError(f'coverage::{pkg}: {calc_cov} less than {required_cov} ... FAIL')
e = f'coverage::{pkg}: {calc_cov}% less than {required_cov}% ... FAIL'
logging.warning(e)
tc.LogStdError(e)
failed += 1

# Move coverage.xml to Build Directory
Expand Down
12 changes: 8 additions & 4 deletions .pytool/Plugin/RustPackageHelper/RustPackageHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ def coverage(self, pkg_list = None, ignore_list = None, report_type: str = "html
command = "cargo"
params = "make"
if ignore_list:
params += f' -e COV_FLAGS="--out {report_type} --exclude-files {",".join(ignore_list)}"'
params += f' -e COV_FLAGS="--out {report_type} --exclude-files {" --exclude-files ".join(ignore_list)}"'
else:
params += f' -e COV_FLAGS="--out {report_type}"'
params += f" coverage {','.join(pkg_list)}"

# Run the command
output = io.StringIO()
RunCmd(command, params, workingdir=self.path, outstream=output)
return_value = RunCmd(command, params, workingdir=self.path, outstream=output)
output.seek(0)
lines = output.readlines()

Expand All @@ -88,7 +88,7 @@ def coverage(self, pkg_list = None, ignore_list = None, report_type: str = "html
# Determine passed and failed tests
for line in lines:
line = line.strip().strip("\n")

if line.startswith("test result:"):
continue

Expand All @@ -99,7 +99,11 @@ def coverage(self, pkg_list = None, ignore_list = None, report_type: str = "html
else:
result["fail"].append(line.replace(" ... FAILED", ""))
continue


# Command failed, but we didn't parse any failed tests
if return_value != 0 and len(result["fail"]) == 0:
raise RuntimeError("Failed to compile tests or run command.")

if len(result["fail"]) > 0:
return result

Expand Down