Path: blob/main/tests/integration_tests/build/test_coverage.py
1958 views
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.1# SPDX-License-Identifier: Apache-2.02"""Tests pertaining to line/branch test coverage for the Firecracker code base.34# TODO56- Put the coverage in `s3://spec.firecracker` and update it automatically.7target should be put in `s3://spec.firecracker` and automatically updated.8"""91011import os12import platform13import re14import shutil15import pytest1617import framework.utils as utils18import host_tools.cargo_build as host # pylint: disable=import-error19import host_tools.proc as proc2021# AMD has a slightly different coverage due to22# the appearance of the brand string. On Intel,23# this contains the frequency while on AMD it does not.24# Checkout the cpuid crate. In the future other25# differences may appear.26COVERAGE_DICT = {"Intel": 84.84, "AMD": 84.22, "ARM": 83.05}2728PROC_MODEL = proc.proc_type()2930COVERAGE_MAX_DELTA = 0.053132CARGO_KCOV_REL_PATH = os.path.join(host.CARGO_BUILD_REL_PATH, 'kcov')3334KCOV_COVERAGE_FILE = 'index.js'35"""kcov will aggregate coverage data in this file."""3637KCOV_COVERED_LINES_REGEX = r'"covered_lines":"(\d+)"'38"""Regex for extracting number of total covered lines found by kcov."""3940KCOV_TOTAL_LINES_REGEX = r'"total_lines" : "(\d+)"'41"""Regex for extracting number of total executable lines found by kcov."""4243SECCOMPILER_BUILD_DIR = '../build/seccompiler'444546@pytest.mark.timeout(400)47def test_coverage(test_fc_session_root_path, test_session_tmp_path):48"""Test line coverage with kcov.4950The result is extracted from the $KCOV_COVERAGE_FILE file created by kcov51after a coverage run.52"""53proc_model = [item for item in COVERAGE_DICT if item in PROC_MODEL]54assert len(proc_model) == 1, "Could not get processor model!"55coverage_target_pct = COVERAGE_DICT[proc_model[0]]56exclude_pattern = (57'${CARGO_HOME:-$HOME/.cargo/},'58'build/,'59'tests/,'60'usr/lib/gcc,'61'lib/x86_64-linux-gnu/,'62'test_utils.rs,'63# The following files/directories are auto-generated64'bootparam.rs,'65'elf.rs,'66'mpspec.rs,'67'msr_index.rs,'68'_gen'69)70exclude_region = '\'mod tests {\''71target = "{}-unknown-linux-musl".format(platform.machine())7273cmd = (74'RUSTFLAGS="{}" CARGO_TARGET_DIR={} cargo kcov --all '75'--target {} --output {} -- '76'--exclude-pattern={} '77'--exclude-region={} --verify'78).format(79host.get_rustflags(),80os.path.join(test_fc_session_root_path, CARGO_KCOV_REL_PATH),81target,82test_session_tmp_path,83exclude_pattern,84exclude_region85)86# We remove the seccompiler custom build directory, created by the87# vmm-level `build.rs`.88# If we don't delete it before and after running the kcov command, we will89# run into linker errors.90shutil.rmtree(SECCOMPILER_BUILD_DIR, ignore_errors=True)91# By default, `cargo kcov` passes `--exclude-pattern=$CARGO_HOME --verify`92# to kcov. To pass others arguments, we need to include the defaults.93utils.run_cmd(cmd)9495shutil.rmtree(SECCOMPILER_BUILD_DIR)9697coverage_file = os.path.join(test_session_tmp_path, KCOV_COVERAGE_FILE)98with open(coverage_file) as cov_output:99contents = cov_output.read()100covered_lines = int(re.findall(KCOV_COVERED_LINES_REGEX, contents)[0])101total_lines = int(re.findall(KCOV_TOTAL_LINES_REGEX, contents)[0])102coverage = covered_lines / total_lines * 100103print("Number of executable lines: {}".format(total_lines))104print("Number of covered lines: {}".format(covered_lines))105print("Thus, coverage is: {:.2f}%".format(coverage))106107coverage_low_msg = (108'Current code coverage ({:.2f}%) is below the target ({}%).'109.format(coverage, coverage_target_pct)110)111112min_coverage = coverage_target_pct - COVERAGE_MAX_DELTA113assert coverage >= min_coverage, coverage_low_msg114115# Get the name of the variable that needs updating.116namespace = globals()117cov_target_name = [name for name in namespace if namespace[name]118is COVERAGE_DICT][0]119120coverage_high_msg = (121'Current code coverage ({:.2f}%) is above the target ({}%).\n'122'Please update the value of {}.'123.format(coverage, coverage_target_pct, cov_target_name)124)125126assert coverage - coverage_target_pct <= COVERAGE_MAX_DELTA,\127coverage_high_msg128129130