### StateData::start Method Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/statemachine/trait.StateData.html Starts the tracing process. Returns None if waiting for the start signal, allowing the statemachine to handle timeouts. ```rust fn start(&mut self) -> Result, RunError> ``` -------------------------------- ### Setup Execution Environment Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/cargo/mod.rs.html Configures the command environment with necessary LLVM profile paths, RUSTFLAGS, and RUSTDOCFLAGS. ```rust fn setup_environment(cmd: &mut Command, config: &Config, cargo_config: &CargoConfigFields) { // https://github.com/rust-lang/rust/issues/107447 cmd.env("LLVM_PROFILE_FILE", config.root().join(BUILD_PROFRAW)); cmd.env("TARPAULIN", "1"); let rustflags = "RUSTFLAGS"; let value = rust_flags(config, cargo_config); cmd.env(rustflags, value); // doesn't matter if we don't use it let rustdoc = "RUSTDOCFLAGS"; let value = rustdoc_flags(config, cargo_config); trace!("Setting RUSTDOCFLAGS='{}'", value); cmd.env(rustdoc, value); if let Ok(bootstrap) = env::var("RUSTC_BOOTSTRAP") { cmd.env("RUSTC_BOOTSTRAP", bootstrap); } } ``` -------------------------------- ### Implement From for ConfigWrapper Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/config/struct.ConfigWrapper.html Enables conversion from ConfigArgs to ConfigWrapper. This allows creating a ConfigWrapper directly from configuration arguments, simplifying setup. ```rust fn from(args: ConfigArgs) -> Self ``` -------------------------------- ### Initialize LinuxData State Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/statemachine/linux.rs.html Creates a new `LinuxData` instance with provided tracing, analysis, configuration, and event log data. This is the initial setup for managing a process's state. ```rust pub struct LinuxData<'a> { /// Recent results from waitpid to be handled by statemachine wait_queue: Vec, /// Pending action queue, this is for actions where we need to wait one cycle before we can /// apply them :sobs: pending_actions: Vec>, /// Parent pid of the test parent: Pid, /// Current Pid to process current: Pid, /// Program config config: &'a Config, /// Optional event log to update as the test progresses event_log: &'a Option, /// Instrumentation points in code with associated coverage data traces: &'a mut TraceMap, /// Source analysis, needed in case we need to follow any executables analysis: &'a HashMap, /// Processes we're tracing processes: HashMap, /// Map from pids to their parent pid_map: HashMap, /// So if we have the exit code but we're also waiting for all the spawned processes to end exit_code: Option, } impl<'a> LinuxData<'a> { fn new(traces: &'a mut TraceMap, analysis: &'a HashMap, config: &'a Config, event_log: &'a Option) -> Self { Self { wait_queue: Vec::new(), pending_actions: Vec::new(), parent: Pid::from_raw(0), // Placeholder, will be set in create_state_machine current: Pid::from_raw(0), // Placeholder, will be set in create_state_machine config, event_log, traces, analysis, processes: HashMap::new(), pid_map: HashMap::new(), exit_code: None, } } } ``` -------------------------------- ### Get Configuration Name Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/lib.rs.html Returns the configuration name or a default anonymous string if empty. ```rust fn config_name(config: &Config) -> String { if config.name.is_empty() { "".to_string() } else { config.name.clone() } } ``` -------------------------------- ### Get Analysis - SourceAnalysis Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/source_analysis/struct.SourceAnalysis.html Creates a SourceAnalysis instance based on the provided configuration. This is the primary method for initiating source code analysis. ```rust pub fn get_analysis(config: &Config) -> Self ``` -------------------------------- ### Get TestBinary Path Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the path to the binary as a reference. ```rust pub fn path(&self) -> &Path> ``` -------------------------------- ### Create New TraceMap Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/traces/struct.TraceMap.html Creates a new, empty TraceMap instance. This is the starting point for managing trace data. ```rust pub fn new() -> TraceMap ``` -------------------------------- ### Default Implementation for TraceMapSettings Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/traces/struct.TraceMapSettings.html Provides a default configuration for TraceMapSettings. Use this when you need a basic setup without specifying all parameters. ```rust fn default() -> TraceMapSettings ``` -------------------------------- ### Get TestBinary Manifest Directory Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the manifest directory associated with the binary, if available. ```rust pub fn manifest_dir(&self) -> &Option> ``` -------------------------------- ### Create Temporary Directory in Rust Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/path_utils.rs.html Generates a unique temporary directory with a specified prefix. Useful for test setup. ```Rust use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; fn make_temp_dir(prefix: &str) -> PathBuf { let n = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_nanos(); let dir = std::env::temp_dir().join(format!("{}", prefix, n)); let _ = fs::create_dir_all(&dir); dir } ``` -------------------------------- ### Get Trace Map Settings Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/config/mod.rs.html Retrieves settings for generating trace maps, including package information, workspace status, and file inclusion/exclusion patterns. ```rust pub fn get_tracemap_settings(&self) -> TraceMapSettings { TraceMapSettings { packages: self.packages.clone().into_iter().collect(), workspace: self.all, excluded_files_raw: self.excluded_files_raw.clone().into_iter().collect(), included_files_raw: self.included_files_raw.clone().into_iter().collect(), exclude: self.exclude.clone().into_iter().collect(), run_types: self.run_types.clone().into_iter().collect(), varargs: self.varargs.clone().into_iter().collect(), } } ``` -------------------------------- ### Configuration Merging and Path Handling Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/config/mod.rs.html This section details how configuration options like exclusions, varargs, unstable features, test names, bin names, example names, bench names, and run types are merged and processed. It also covers the logic for handling included and excluded files, including the invalidation of compiled regex caches. ```APIDOC ## Configuration Merging and Path Handling ### Description This section details how configuration options like exclusions, varargs, unstable features, test names, bin names, example names, bench names, and run types are merged and processed. It also covers the logic for handling included and excluded files, including the invalidation of compiled regex caches. ### Methods #### `extend` (Implicit) Merges configuration from another source into the current configuration. #### `pick_optional_config` Selects a configuration value, prioritizing the override if present. #### `objects` Returns a slice of `PathBuf` representing the objects. #### `has_named_tests` Checks if there are any named tests, bins, examples, or benches. #### `is_coveralls` Checks if the coveralls option is set. #### `exclude_path` Determines if a given path should be excluded based on the compiled exclusion globs. #### `include_path` Determines if a given path should be included based on the compiled inclusion globs. If no includes are specified, all paths are included by default. #### `get_base_dir` Retrieves the base directory of the project, resolving it relative to the root or the current working directory. ### Path Handling Details - **Exclusions**: Packages and files can be excluded. When `excluded_files_raw` is updated, the compiled regex cache for `excluded_files` is cleared. - **Inclusions**: Files can be included. When `included_files_raw` is updated, the compiled regex cache for `included_files` is cleared. If `included_files` is empty, all paths are considered included. - **Base Directory**: The base directory is determined by the `root` configuration or the current working directory if `root` is not absolute. ### Internal Caching - `excluded_files`: A cache for compiled globs from `excluded_files_raw`. Cleared when `excluded_files_raw` changes. - `included_files`: A cache for compiled globs from `included_files_raw`. Cleared when `included_files_raw` changes. ### Example Usage (Conceptual) ```rust // Assuming `config` is a mutable instance of the configuration struct // Merging configurations // let other_config = ...; // config.extend(&other_config); // Checking for named tests // if config.has_named_tests() { ... } // Checking if a path is excluded // let path_to_check = Path::new("src/main.rs"); // if config.exclude_path(path_to_check) { ... } // Getting the base directory // let base_dir = config.get_base_dir(); ``` ``` -------------------------------- ### Setup Logging Function Signature Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/fn.setup_logging.html This function signature defines how to set up logging for cargo-tarpaulin. It accepts parameters for color output, debug mode, verbosity, and whether to use stderr. ```rust pub fn setup_logging(color: Color, debug: bool, verbose: bool, stderr: bool) ``` -------------------------------- ### Get Line Range from Tokens Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/source_analysis/macros.rs.html Calculates the starting and ending line numbers for a given set of tokens. This utility function is crucial for determining the scope of code elements like macros. ```rust pub(crate) fn get_line_range(tokens: T) -> Range where T: ToTokens, { let mut start = None; let mut end = None; for token in tokens.into_token_stream() { let temp_start = token.span().start().line; let temp_end = token.span().end().line + 1; start = match start { Some(x) => Some(min(temp_start, x)), None => Some(temp_start), }; end = match end { Some(x) => Some(max(temp_end, x)), None => Some(temp_end), }; } match (start, end) { (Some(s), Some(e)) => s..e, _ => 0..0, } } ``` -------------------------------- ### setup_logging Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/fn.setup_logging.html Configures the logging settings for the application based on provided parameters. ```APIDOC ## setup_logging ### Description Configures the logging output for cargo-tarpaulin based on color, debug, verbose, and stderr settings. ### Parameters - **color** (Color) - Required - Specifies the color output configuration. - **debug** (bool) - Required - Enables debug level logging if true. - **verbose** (bool) - Required - Enables verbose logging if true. - **stderr** (bool) - Required - Redirects logging output to stderr if true. ``` -------------------------------- ### EventLog Initialization Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/event_log.rs.html Initializes a new EventLog with a starting timestamp, manifest paths, and output folder configuration. This structure is used to collect and manage events during the tarpaulin run. ```rust 177 pub fn new(manifest_paths: HashSet, config: &Config) -> Self { 178 Self { 179 events: RefCell::new(vec![]), 180 start: Some(Instant::now()), 181 manifest_paths, 182 output_folder: config.output_dir(), 183 } 184 } ``` -------------------------------- ### TraceMap Initialization and Settings Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/traces.rs.html Provides methods for creating a new TraceMap and managing its settings, including inserting and appending settings, and retrieving the current settings. ```APIDOC ## TraceMap Initialization and Settings ### Description Methods for creating and managing TraceMap settings. ### Methods #### `new()` - **Description**: Creates a new, empty TraceMap. - **Returns**: `TraceMap` #### `insert_settings(tracemap_settings: TraceMapSettings)` - **Description**: Inserts a single `TraceMapSettings` object into the TraceMap's settings. - **Parameters**: - `tracemap_settings` (TraceMapSettings) - The settings object to insert. #### `append_settings(tracemap_settings: Vec)` - **Description**: Appends a vector of `TraceMapSettings` objects to the TraceMap's settings. - **Parameters**: - `tracemap_settings` (Vec) - A vector of settings objects to append. #### `get_settings() -> &BTreeSet` - **Description**: Returns a reference to the set of `TraceMapSettings` currently stored in the TraceMap. - **Returns**: `&BTreeSet` ``` -------------------------------- ### Get TypeId for Any Trait Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the `TypeId` of a type implementing the `Any` trait. ```rust fn type_id(&self) -> TypeId> ``` -------------------------------- ### Implement PolicyExt::or Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/report/json/struct.CoverageReport.html Creates a new Policy that returns Action::Follow if either self or other policies return Action::Follow. Requires T to implement Policy. ```rust fn or(self, other: P) -> Or where T: Policy, P: Policy, ``` -------------------------------- ### EventWrapper Struct Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/event_log.rs.html Wraps an Event with a timestamp indicating when it was created relative to a starting point. ```rust pub struct EventWrapper { #[serde(flatten)] event: Event, // The time this was created in seconds created: f64, } ``` -------------------------------- ### Get Data from TracerAction Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/statemachine/enum.TracerAction.html Retrieves the associated data of type T from a TracerAction variant if it exists. ```rust pub fn get_data(&self) -> Option<&T> ``` -------------------------------- ### Create New EventLog Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/event_log/struct.EventLog.html Initializes a new EventLog instance. Requires a set of manifest paths and a configuration object. ```rust pub fn new(manifest_paths: HashSet, config: &Config) -> Self ``` -------------------------------- ### Get TestBinary Package Authors Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the package authors associated with the binary, if available. ```rust pub fn pkg_authors(&self) -> &Option>> ``` -------------------------------- ### Configuration File Discovery and Loading Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/config/mod.rs.html Logic for locating 'tarpaulin.toml' or '.tarpaulin.toml' files and loading them into the configuration structure. ```rust pub fn check_for_configs(&self) -> Option { if let Some(config_file) = env::var_os("CARGO_TARPAULIN_CONFIG_FILE") { Some(config_file.into()) } else if let Some(root) = &self.root { Self::check_path_for_configs(root) } else if let Some(root) = self.manifest.clone().parent() { Self::check_path_for_configs(root) } else { None } } fn check_path_for_configs>(path: P) -> Option { let mut path_1 = PathBuf::from(path.as_ref()); let mut path_2 = path_1.clone(); path_1.push("tarpaulin.toml"); path_2.push(".tarpaulin.toml"); if path_1.exists() { Some(path_1) } else if path_2.exists() { Some(path_2) } else { None } } pub fn load_config_file>(file: P) -> std::io::Result> { let buffer = fs::read_to_string(file.as_ref())?; let mut res = Self::parse_config_toml(&buffer); let parent = match file.as_ref().parent() { Some(p) => p.to_path_buf(), None => PathBuf::new(), }; if let Ok(cfs) = res.as_mut() { for c in cfs.iter_mut() { c.config = Some(file.as_ref().to_path_buf()); c.manifest = make_absolute_with_parent(&c.manifest, &parent); if let Some(root) = c.root.as_mut() { *root = make_absolute_with_parent(&root, &parent); } if let Some(root) = c.output_directory.as_mut() { *root = make_absolute_with_parent(&root, &parent); } if let Some(root) = c.target_dir.as_mut() { *root = make_absolute_with_parent(&root, &parent); } } } res } ``` -------------------------------- ### Get TestBinary Package Version Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the package version associated with the binary, if available. ```rust pub fn pkg_version(&self) -> &Option> ``` -------------------------------- ### Implement TraceMap Methods Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/traces.rs.html Core methods for managing TraceMap instances, including initialization, settings management, and data merging. ```rust impl TraceMap { /// Create a new TraceMap pub fn new() -> TraceMap { Self::default() } pub fn insert_settings(&mut self, tracemap_settings: TraceMapSettings) { self.settings.insert(tracemap_settings); } pub fn append_settings(&mut self, tracemap_settings: Vec) { let mut settings_collection: BTreeSet = tracemap_settings.into_iter().collect(); self.settings.append(&mut settings_collection); } pub fn get_settings(&self) -> &BTreeSet { &self.settings } pub fn set_functions(&mut self, functions: HashMap>) { self.functions = functions; } /// Returns true if there are no traces pub fn is_empty(&self) -> bool { self.traces.is_empty() } /// Provides an iterator to the underlying map of PathBufs to Vec pub fn iter(&self) -> Iter<'_, PathBuf, Vec> { self.traces.iter() } /// Merges the results of one tracemap into the current one. /// This adds records which are missing and adds the statistics gathered to /// existing records pub fn merge(&mut self, other: &TraceMap) { self.functions .extend(other.functions.iter().map(|(k, v)| (k.clone(), v.clone()))); for (k, values) in other.iter() { if !self.traces.contains_key(k) { self.traces.insert(k.clone(), values.clone()); } else { let existing = self.traces.get_mut(k).unwrap(); for v in values.iter() { let mut added = false; if let Some(ref mut t) = existing .iter_mut() .find(|x| x.line == v.line && x.address == v.address) { t.stats = t.stats.clone() + v.stats.clone(); added = true; } if !added { existing.push((*v).clone()); existing.sort_unstable(); } } } } } /// This will collapse duplicate Traces into a single trace. Warning this /// will lose the addresses of the duplicate traces but increment the results /// should be called only if you don't need those addresses from then on /// TODO possibly not the cleanest solution pub fn dedup(&mut self) { for values in self.traces.values_mut() { // Map of lines and stats, merge duplicated stats here let mut lines: HashMap = HashMap::new(); // Duplicated traces need cleaning up. Maintain a list of them! let mut dirty: Vec = Vec::new(); for v in values.iter() { lines .entry(v.line) .and_modify(|e| { dirty.push(v.line); *e = e.clone() + v.stats.clone(); }) .or_insert_with(|| v.stats.clone()); } for d in &dirty { let mut first = true; values.retain(|x| { let res = x.line != *d; if !res { if first { first = false; true } else { false } } else { res } }); if let Some(new_stat) = lines.remove(d) { if let Some(ref mut t) = values.iter_mut().find(|x| x.line == *d) { ``` -------------------------------- ### Execute Test with LLVM Coverage Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/process_handling/mod.rs.html Launches a test executable, setting up environment variables and arguments for LLVM coverage collection. It configures the LLVM_PROFILE_FILE to manage coverage reports. ```rust match config.engine() { TraceEngine::Llvm => { info!("Setting LLVM_PROFILE_FILE"); // Used for llvm coverage to avoid report naming clashes TODO could have clashes // between runs let profile_dir = config .profraw_dir() .join(format!("{}_%m-%p.profraw", test.file_name())); envars.push(( "LLVM_PROFILE_FILE".to_string(), profile_dir.display().to_string(), )); debug!("Env vars: {:?}", envars); debug!("Args: {:?}", argv); let mut child = Command::new(test.path()); child.envs(envars).args(&argv); let others = other_binaries.to_vec(); let hnd = RunningProcessHandle::new(test, others, &mut child, config)?; Ok(hnd.into()) } } ``` -------------------------------- ### Get TestBinary Package Name Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the package name associated with the binary, if available. ```rust pub fn pkg_name(&self) -> &Option> ``` -------------------------------- ### Get TestBinary Run Type Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/cargo/struct.TestBinary.html Retrieves the optional run type associated with the binary. ```rust pub fn run_type(&self) -> Option> ``` -------------------------------- ### EventLog Push Methods Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/event_log.rs.html Provides methods to push different types of events (BinaryLaunch, Trace, ConfigLaunch, Marker) into the EventLog. These methods wrap the event with a timestamp and add it to the internal event list. ```rust 186 pub fn push_binary(&self, binary: TestBinary) { 187 self.events.borrow_mut().push(EventWrapper::new( 188 Event::BinaryLaunch(binary), 189 self.start.unwrap(), 190 )); 191 } ``` ```rust 193 pub fn push_trace(&self, event: TraceEvent) { 194 self.events 195 .borrow_mut() 196 .push(EventWrapper::new(Event::Trace(event), self.start.unwrap())); 197 } ``` ```rust 199 pub fn push_config(&self, name: String) { 200 self.events.borrow_mut().push(EventWrapper::new( 201 Event::ConfigLaunch(name), 202 self.start.unwrap(), 203 )); 204 } ``` ```rust 206 pub fn push_marker(&self) { 207 // Prevent back to back markers when we spend a lot of time waiting on events 208 if self 209 .events 210 .borrow() 211 .last() 212 .filter(|x| matches!(x.event, Event::Marker(_))) 213 .is_none() 214 { 215 self.events 216 .borrow_mut() 217 .push(EventWrapper::new(Event::Marker(None), self.start.unwrap())); 218 } 219 } ``` -------------------------------- ### Path and File Utility Functions Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/path_utils.rs.html A collection of functions for handling UNC paths, identifying file types, and checking directory properties. ```rust 1use crate::config::Config; 2use std::env::var; 3use std::ffi::OsStr; 4use std::path::{Component, Path, PathBuf}; 5use walkdir::{DirEntry, WalkDir}; 6 7/// On windows removes the `\?\` prefix to UNC paths. For other operation systems just turns the 8/// `Path` into a `PathBuf` 9pub fn fix_unc_path(res: &Path) -> PathBuf { 10 if cfg!(windows) { 11 let res_str = res.display().to_string(); 12 if res_str.starts_with(r#"\\?"#) { 13 PathBuf::from(res_str.replace(r#"\\?\"#, "")) 14 } else { 15 res.to_path_buf() 16 } 17 } else { 18 res.to_path_buf() 19 } 20} 21 22/// Returns true if the file is a rust source file 23pub fn is_profraw_file(entry: &DirEntry) -> bool { 24 let p = entry.path(); 25 p.is_file() && p.extension() == Some(OsStr::new("profraw")) 26} 27 28/// Returns true if the file is a rust source file 29pub fn is_source_file(entry: &DirEntry) -> bool { 30 let p = entry.path(); 31 p.is_file() && p.extension() == Some(OsStr::new("rs")) 32} 33 34/// Returns true if the folder is a target folder 35fn is_target_folder(entry: &Path, target: &Path) -> bool { 36 entry.starts_with(target) 37} 38 39/// Returns true if the file or folder is hidden 40fn is_hidden(entry: &Path, root: &Path) -> bool { 41 let check_hidden = |e: &Path| e.iter().any(|x| x.to_string_lossy().starts_with('.')); 42 match entry.strip_prefix(root) { 43 Ok(e) => check_hidden(e), 44 Err(_) => check_hidden(entry), 45 } 46} 47 48/// If `CARGO_HOME` is set filters out all folders within `CARGO_HOME` 49fn is_cargo_home(entry: &Path, root: &Path) -> bool { 50 match var("CARGO_HOME") { 51 Ok(s) => { 52 let path = Path::new(&s); 53 if path.is_absolute() && entry.starts_with(path) { 54 true 55 } else { 56 let home = root.join(path); 57 entry.starts_with(home) 58 } 59 } 60 _ => false, 61 } 62} 63 64fn is_part_of_project(e: &Path, root: &Path) -> bool { 65 if e.is_absolute() && root.is_absolute() { 66 e.starts_with(root) 67 } else if root.is_absolute() { 68 root.join(e).is_file() 69 } else { 70 // they're both relative and this isn't hit a lot - only really with FFI code 71 true 72 } 73} 74 75pub fn is_coverable_file_path( 76 path: impl AsRef, 77 root: impl AsRef, 78 target: impl AsRef, 79) -> bool { 80 let e = path.as_ref(); 81 let ignorable_paths = !(is_target_folder(e, target.as_ref()) 82 || is_hidden(e, root.as_ref()) 83 || is_cargo_home(e, root.as_ref())); 84 85 ignorable_paths && is_part_of_project(e, root.as_ref()) 86} 87 88pub fn get_source_walker(config: &Config) -> impl Iterator + '_ { 89 let root = config.root(); 90 let target = config.target_dir(); 91 92 let walker = WalkDir::new(&root).into_iter(); 93 walker 94 .filter_entry(move |e| { 95 if !config.include_tests() && is_tests_folder_package(&root, e.path()) { 96 return false; //Removes entire tests folder at once 97 } 98 is_coverable_file_path(e.path(), &root, &target) 99 }) 100 .filter_map(Result::ok) 101 .filter(move |e| !(config.exclude_path(e.path()))) 102 .filter(move |e| config.include_path(e.path())) 103 .filter(is_source_file) 104} 105 106fn is_tests_folder_package(root: &Path, path: &Path) -> bool { 107 let mut is_pkg_tests: bool = false; 108 let tests_folder_name = "tests"; 109 110 // Ensure `path` is under `root` 111 let relative = match path.strip_prefix(root) { 112 Ok(p) => p, 113 Err(_) => return false, 114 }; 115 116 // check if the path contains a `tests` folder (platform independent) 117 let has_tests_component = relative 118 .components() 119 .any(|c| matches!(c, Component::Normal(name) if name == tests_folder_name)); 120 121 if has_tests_component { 122 // Locate the actual `tests` directory in the ancestor chain. stopping at root 123 if let Some(tests_dir) = path.ancestors().take_while(|anc| *anc != root).find(|anc| { 124 anc.file_name() 125 .map(|n| n == tests_folder_name) 126 .unwrap_or(false) 127 }) { 128 if let Some(pkg_dir) = tests_dir.parent() { 129 is_pkg_tests = pkg_dir.join("Cargo.toml").is_file() && pkg_dir.join("src").is_dir(); 130 } 131 } 132 } 133 134 is_pkg_tests 135} 136 137pub fn get_profile_walker(config: &Config) -> impl Iterator { 138 let walker = WalkDir::new(config.profraw_dir()).into_iter(); 139 walker.filter_map(Result::ok).filter(is_profraw_file) 140} 141 142#[cfg(test)] 143mod tests { 144 use super::*; 145 use std::fs::{self, File}; 146 use std::io::Write; ``` -------------------------------- ### Create EventWrapper Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/event_log.rs.html Constructor for EventWrapper that calculates the creation time based on a provided start Instant. ```rust fn new(event: Event, since: Instant) -> Self { let created = Instant::now().duration_since(since).as_secs_f64(); Self { event, created } } ``` -------------------------------- ### Get TraceMap Settings Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/traces/struct.TraceMap.html Retrieves an immutable reference to the set of TraceMapSettings currently used by the TraceMap. ```rust pub fn get_settings(&self) -> &BTreeSet ``` -------------------------------- ### Launch Test Function Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/process_handling/mod.rs.html Launches a test binary based on the configured TraceEngine. Supports Ptrace on supported platforms and LLVM. Logs the binary being tested if a logger is provided. ```rust fn launch_test( test: &TestBinary, other_binaries: &[PathBuf], config: &Config, cargo_config: Rc, ignored: bool, logger: &Option, ) -> Result, RunError> { if let Some(log) = logger.as_ref() { log.push_binary(test.clone()); } match config.engine() { TraceEngine::Ptrace => { cfg_if::cfg_if! { if #[cfg(ptrace_supported)] { linux::get_test_coverage(test, config, cargo_config, ignored) } else { error!("Ptrace is not supported on this platform"); Err(RunError::TestCoverage("Unsupported OS".to_string())) } } } TraceEngine::Llvm => { // 1 test thread because https://github.com/rust-lang/rust/issues/91092 let res = execute_test(test, other_binaries, ignored, config, cargo_config, Some(1))?; Ok(Some(res)) } e => { error!( "Tarpaulin cannot execute tests with {:?} on this platform", e ); Err(RunError::TestCoverage("Unsupported OS".to_string())) } } } ``` -------------------------------- ### Create LLVM Instrumented State Machine Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/statemachine/instrumented.rs.html Initializes the state machine for LLVM coverage. Requires a running process handle. If a process handle is not provided, it returns an error state. ```rust #![allow(dead_code)] use crate::path_utils::{get_profile_walker, get_source_walker}; use crate::process_handling::RunningProcessHandle; use crate::statemachine::*; use llvm_profparser::*; use std::thread::sleep; use tracing::{info, warn}; pub fn create_state_machine<'a>( test: impl Into, traces: &'a mut TraceMap, analysis: &'a HashMap, config: &'a Config, event_log: &'a Option, ) -> (TestState, LlvmInstrumentedData<'a>) { let handle = test.into(); if let TestHandle::Process(process) = handle { let llvm = LlvmInstrumentedData { process: Some(process), event_log, config, traces, analysis, }; (TestState::start_state(), llvm) } else { error!("The llvm cov statemachine requires a process::Child"); let invalid = LlvmInstrumentedData { process: None, config, event_log, traces, analysis, }; (TestState::End(1), invalid) } } ``` -------------------------------- ### Get Include Tests Option Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/config/mod.rs.html Returns the current setting for whether tests are included in coverage calculations. ```rust pub fn include_tests(&self) -> bool { self.include_tests } ``` -------------------------------- ### Get Aligned Address Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/process_handling/breakpoint.rs.html Calculates the memory address aligned to an 8-byte boundary, which is required for `ptrace` operations. ```rust pub fn aligned_address(&self) -> u64 { align_address(self.pc) } ``` -------------------------------- ### DocTestBinaryMeta Initialization Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/cargo/mod.rs.html Constructor for DocTestBinaryMeta that parses path components to extract prefix and line information. ```rust impl DocTestBinaryMeta { fn new>(test: P) -> Option { if let Some(Component::Normal(folder)) = test.as_ref().components().nth_back(1) { let temp = folder.to_string_lossy(); let file_end = temp.rfind("rs").map(|i| i + 2)?; let end = temp.rfind('_')?; if end > file_end + 1 { let line = temp[(file_end + 1)..end].parse::().ok()?; Some(Self { prefix: temp[..file_end].to_string(), line, }) } else { None } } else { None } } } ``` -------------------------------- ### Manage Traces and Files Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/traces.rs.html Methods for adding traces to specific files and initializing new files in the tracemap. ```rust pub fn add_trace(&mut self, file: &Path, trace: Trace) { if self.traces.contains_key(file) { if let Some(trace_vec) = self.traces.get_mut(file) { trace_vec.push(trace); trace_vec.sort_unstable(); } } else { self.traces.insert(file.to_path_buf(), vec![trace]); } } ``` ```rust pub fn add_file(&mut self, file: &Path) { if !self.traces.contains_key(file) { self.traces.insert(file.to_path_buf(), vec![]); } } ``` -------------------------------- ### Ignore first line of file Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/source_analysis/mod.rs.html Filters out the first line of a file from coverage analysis if it does not start with 'pub' or 'fn'. ```rust fn maybe_ignore_first_line(file: &Path, result: &mut HashMap) { if let Ok(f) = File::open(file) { let read_file = BufReader::new(f); if let Some(Ok(first)) = read_file.lines().next() { if !(first.starts_with("pub") || first.starts_with("fn")) { let file = file.to_path_buf(); let line_analysis = result.entry(file).or_default(); line_analysis.add_to_ignore([1]); } } } } ``` -------------------------------- ### Execute Test Process Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/process_handling/linux.rs.html Executes a test binary with specified arguments and environment variables. It also handles ASLR disabling and ptrace request. ```APIDOC ## POST /api/execute/test ### Description Executes a test binary with the provided command-line arguments and environment variables. This function also ensures ASLR is disabled and requests ptrace capabilities for coverage collection. ### Method POST ### Endpoint `/api/execute/test` ### Parameters #### Path Parameters - **test** (Path) - Required - The path to the test executable. #### Request Body - **argv** (Vec) - Required - Command-line arguments for the test. - **envar** (Vec<(String, String)>) - Required - Environment variables for the test process. ### Response #### Success Response (200) - **TestHandle** - A handle to the executed test process. #### Response Example ```json { "TestHandle::Id(1234)" } ``` #### Error Response (500) - **RunError** - If ASLR disabling fails, ptrace request fails, or the execution itself fails. ``` -------------------------------- ### Implement PolicyExt::and Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/report/json/struct.CoverageReport.html Creates a new Policy that returns Action::Follow only if both self and other policies return Action::Follow. Requires T to implement Policy. ```rust fn and(self, other: P) -> And where T: Policy, P: Policy, ``` -------------------------------- ### Get Doctest Directory Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/config/mod.rs.html Constructs and returns the path to the directory where doctest outputs are stored, based on the target directory. ```rust pub fn doctest_dir(&self) -> PathBuf { // https://github.com/rust-lang/rust/issues/98690 let mut result = self.target_dir(); result.push("doctests"); result } ``` -------------------------------- ### Execute test binary Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/process_handling/linux.rs.html Prepares and executes a test binary using execve, ensuring ASLR is disabled and tracing is requested. ```rust pub fn execute( test: &Path, argv: &[String], envar: &[(String, String)], ) -> Result { let program = CString::new(test.display().to_string()).unwrap_or_default(); if is_aslr_enabled() { disable_aslr().map_err(|e| RunError::TestRuntime(format!("ASLR disable failed: {e}")))?; } request_trace().map_err(|e| RunError::Trace(e.to_string()))?; let envar = envar .iter() .map(|(k, v)| CString::new(format!("{k}={v}").as_str()).unwrap_or_default()) .collect::>(); let argv = argv .iter() .map(|x| CString::new(x.as_str()).unwrap_or_default()) .collect::>(); let arg_ref = argv.iter().map(AsRef::as_ref).collect::>(); let env_ref = envar.iter().map(AsRef::as_ref).collect::>(); execve(&program, &arg_ref, &env_ref).map_err(|_| RunError::Internal)?; unreachable!(); } ``` -------------------------------- ### Get Coverable Arguments Source: https://docs.rs/cargo-tarpaulin/latest/src/cargo_tarpaulin/source_analysis/expressions.rs.html Helper function to extract line numbers for non-literal arguments in a punctuated expression list. ```rust fn get_coverable_args(args: &Punctuated) -> HashSet { let mut lines: HashSet = HashSet::new(); for a in args.iter() { match *a { Expr::Lit(_) => {} _ => { for i in get_line_range(a) { lines.insert(i); } } } } lines } ``` -------------------------------- ### ProcessInfo Blanket Implementations Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/statemachine/linux/struct.ProcessInfo.html Information on blanket implementations provided for ProcessInfo, such as Any, Borrow, CloneToUninit, etc. ```APIDOC ## Blanket Implementations for ProcessInfo ### `impl Any for T` - `fn type_id(&self) -> TypeId` Gets the `TypeId` of `self`. ### `impl Borrow for T` - `fn borrow(&self) -> &T` Immutably borrows from an owned value. ### `impl BorrowMut for T` - `fn borrow_mut(&mut self) -> &mut T` Mutably borrows from an owned value. ### `impl CloneToUninit for T` - `unsafe fn clone_to_uninit(&self, dest: *mut u8)` Performs copy-assignment from `self` to `dest`. ### `impl Equivalent for Q` - `fn equivalent(&self, key: &K) -> bool` Compare self to `key` and return `true` if they are equal. ### `impl From for T` - `fn from(t: T) -> T` Returns the argument unchanged. ### `impl Instrument for T` - `fn instrument(self, span: Span) -> Instrumented` Instruments this type with the provided `Span`, returning an `Instrumented` wrapper. - `fn in_current_span(self) -> Instrumented` Instruments this type with the current `Span`, returning an `Instrumented` wrapper. ### `impl Into for T` - `fn into(self) -> U` Calls `U::from(self)`. ### `impl PolicyExt for T` - `fn and(self, other: P) -> And` Create a new `Policy` that returns `Action::Follow` only if `self` and `other` return `Action::Follow`. - `fn or(self, other: P) -> Or` Create a new `Policy` that returns `Action::Follow` if either `self` or `other` returns `Action::Follow`. ### `impl ToOwned for T` - `type Owned = T` The resulting type after obtaining ownership. - `fn to_owned(&self) -> T` Creates owned data from borrowed data, usually by cloning. - `fn clone_into(&self, target: &mut T)` Uses borrowed data to replace owned data, usually by cloning. ### `impl TryFrom for T` - `type Error = Infallible` The type returned in the event of a conversion error. - `fn try_from(value: U) -> Result>::Error>` Performs the conversion. ### `impl TryInto for T` - `type Error = >::Error` The type returned in the event of a conversion error. ``` -------------------------------- ### Define TestState Enum Source: https://docs.rs/cargo-tarpaulin/latest/cargo_tarpaulin/statemachine/enum.TestState.html Defines the possible states for a test execution, including start time tracking and exit codes. ```rust pub enum TestState { Start { start_time: Instant, }, Initialise, Waiting { start_time: Instant, }, Stopped, End(i32), } ```