Hone logo
Hone
Problems

Rust Code Coverage Tracking Tool

This challenge asks you to implement a basic code coverage tracking tool in Rust. Code coverage is a crucial metric in software development, indicating the percentage of code executed during testing. Building a simple coverage tracker will help you understand how thoroughly your tests exercise your codebase.

Problem Description

You are tasked with creating a module that tracks which lines of code are executed within a given Rust function. The module should intercept function calls, record line numbers of executed lines, and provide a report summarizing the coverage. The core functionality involves modifying the provided code to instrument it for coverage tracking.

What needs to be achieved:

  1. Instrumentation: Modify a given Rust function to record the line numbers of executed statements. This will involve wrapping the function's body with code that logs line numbers.
  2. Coverage Tracking: Maintain a data structure (e.g., a HashSet) to store the line numbers that have been executed.
  3. Reporting: Provide a function that takes the original function's source code (as a string) and the set of executed line numbers as input. This function should return a string representing a coverage report, indicating which lines were executed and which were not. The report should clearly identify executed and unexecuted lines.

Key Requirements:

  • The solution should be modular and well-structured.
  • The instrumentation should be minimal and avoid significant performance overhead.
  • The reporting function should produce a readable and informative coverage report.
  • The solution should handle basic Rust code structures (e.g., let, if, else, for, while, function calls). Complex features like macros or advanced control flow are not required for this challenge.
  • Assume the input source code is syntactically valid Rust.

Expected Behavior:

  • When the instrumented function is called, the line numbers of executed statements are recorded.
  • The reporting function accurately identifies executed and unexecuted lines based on the recorded line numbers.
  • The code should compile and run without errors.

Edge Cases to Consider:

  • Empty functions.
  • Functions with only comments.
  • Functions with no executable statements.
  • Functions containing only control flow statements (e.g., if, else) without any associated code blocks.

Examples

Example 1:

Input (Original Function):
```rust
fn add(x: i32, y: i32) -> i32 {
    let sum = x + y;
    sum
}
Input (Executed Line Numbers): [3, 4]
Output:
Coverage Report:
Executed Lines:
  - 3
Unexecuted Lines:
  - 2

Example 2:

Input (Original Function):
```rust
fn greet(name: &str) -> String {
    if name.is_empty() {
        "Hello, world!".to_string()
    } else {
        format!("Hello, {}!", name)
    }
}
Input (Executed Line Numbers): [3, 4, 5, 6]
Output:
Coverage Report:
Executed Lines:
  - 3
  - 4
  - 5
  - 6
Unexecuted Lines:
  - 2

Example 3: (Edge Case - Empty Function)

Input (Original Function):
```rust
fn empty() {}
Input (Executed Line Numbers): []
Output:
Coverage Report:
Executed Lines:
Unexecuted Lines:
  - 1
  - 2

Constraints

  • The solution should be implemented in Rust.
  • The instrumentation should add minimal overhead to the original function's execution time. While precise performance measurement isn't required, avoid excessively complex or inefficient instrumentation.
  • The input source code string will be reasonably sized (less than 1000 characters).
  • The reporting function should produce a report string that is also reasonably sized (less than 500 characters).
  • The solution should not rely on external crates beyond the Rust standard library.

Notes

  • You can use a HashSet to efficiently track executed line numbers.
  • Consider using string manipulation techniques to extract line numbers from the source code. Regular expressions are not required, but can be helpful.
  • Focus on the core functionality of tracking and reporting coverage. Error handling and advanced features (e.g., branch coverage) are beyond the scope of this challenge.
  • The challenge is designed to be completed within a reasonable timeframe (e.g., 2-4 hours). Start with a simple function and gradually add complexity.
  • Think about how to represent line numbers in your data structures. A simple integer is usually sufficient.
  • The provided examples are meant to guide you, but you may need to explore other scenarios to ensure your solution is robust.
Loading editor...
rust