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

Harness output individual files #3360

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2d1d29d
Starting changes for multi-thread attempt
Alexander-Aghili May 23, 2024
1387cb1
Buggy- revert
Alexander-Aghili May 23, 2024
81e6dfc
Threading implemented
Alexander-Aghili May 23, 2024
406a4ed
File output for each harness
Alexander-Aghili May 23, 2024
767b61b
Merge branch 'main' of github.com:model-checking/kani into main
Alexander-Aghili May 23, 2024
ba3090a
Update to add directory
Alexander-Aghili Jun 20, 2024
72522bc
Added individual output to files + args, still issues with directory …
Alexander-Aghili Jul 19, 2024
5b85c39
Harness refactor + directory fix
Alexander-Aghili Jul 19, 2024
0a40e1b
Quick format fix and refactor to fix the output correctness
Alexander-Aghili Jul 19, 2024
6a951b4
Refactor of harness runner update for Harness Output Individual Files
Jul 23, 2024
01bd260
Untested configuration options change (commit to get to server to test)
Alexander-Aghili Jul 31, 2024
2524fa1
Remove enable-unstable requirement
Alexander-Aghili Jul 31, 2024
1e125f4
Comments + formatting
Alexander-Aghili Aug 4, 2024
8b008c4
Merge branch 'main' into harness_output_individual_files
jaisnan Aug 5, 2024
38b6698
Merge branch 'main' into harness_output_individual_files
jaisnan Aug 12, 2024
cca9648
Update kani-driver/src/harness_runner.rs
celinval Aug 14, 2024
698d718
Merge branch 'main' into harness_output_individual_files
jaisnan Aug 14, 2024
56159a1
Merge branch 'main' into harness_output_individual_files
jaisnan Aug 20, 2024
1f0a0fd
merge
Alexander-Aghili Sep 18, 2024
78733a0
Merge branch 'main' into harness_output_individual_files
Alexander-Aghili Oct 7, 2024
c86ff09
Added test + fix small formatting with harness runner
Alexander-Aghili Oct 7, 2024
34f8c80
Remove target
Alexander-Aghili Oct 8, 2024
d35c664
Merge branch 'main' into harness_output_individual_files
jaisnan Oct 8, 2024
c3546c0
Fix clippy issues
Alexander-Aghili Oct 13, 2024
f9cddfa
Merge branch 'harness_output_individual_files' of github.com:Alexande…
Alexander-Aghili Oct 13, 2024
37ed122
Output directory name fix
Alexander-Aghili Oct 15, 2024
666a818
Remove old test unrelated to PR
Alexander-Aghili Oct 15, 2024
1593d23
Fix clippy issues (again)
Alexander-Aghili Oct 15, 2024
395ba91
Fixed test
Alexander-Aghili Oct 24, 2024
8dfde5d
Add mut back in builder creation
Alexander-Aghili Oct 24, 2024
f6b1527
Added comment, lets CI run
Alexander-Aghili Oct 24, 2024
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
1 change: 1 addition & 0 deletions kani-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ rand = "0.8"
which = "6"
time = {version = "0.3.36", features = ["formatting"]}


# A good set of suggested dependencies can be found in rustup:
# https://github.com/rust-lang/rustup/blob/master/Cargo.toml
# Here are a few notes I'm keeping after looking through these
Expand Down
18 changes: 18 additions & 0 deletions kani-driver/src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ pub struct VerificationArgs {
)]
pub synthesize_loop_contracts: bool,

//Harness Output into individual files
#[arg(long, hide_short_help = true)]
pub output_into_files: bool,

/// Randomize the layout of structures. This option can help catching code that relies on
/// a specific layout chosen by the compiler that is not guaranteed to be stable in the future.
/// If a value is given, it will be used as the seed for randomization
Expand Down Expand Up @@ -609,6 +613,20 @@ impl ValidateArgs for VerificationArgs {
));
}

if self.output_into_files
&& !self.common_args.unstable_features.contains(UnstableFeature::UnstableOptions)
{
if self.common_args.enable_unstable {
print_deprecated(&self.common_args, "`--enable-unstable`", "-Z unstable-options");
} else {
return Err(Error::raw(
ErrorKind::MissingRequiredArgument,
"The `--output-into-files` argument is unstable and requires `-Z unstable-options` to enable \
unstable options support.",
));
}
}

Ok(())
}
}
Expand Down
54 changes: 45 additions & 9 deletions kani-driver/src/harness_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
use anyhow::{Result, bail};
use kani_metadata::{ArtifactType, HarnessMetadata};
use rayon::prelude::*;
use std::fs::File;
use std::io::Write;
use std::path::Path;

use crate::args::OutputFormat;
use crate::call_cbmc::{VerificationResult, VerificationStatus};
use crate::project::Project;
use crate::session::KaniSession;

use std::env::current_dir;
use std::path::PathBuf;

/// A HarnessRunner is responsible for checking all proof harnesses. The data in this structure represents
/// "background information" that the controlling driver (e.g. cargo-kani or kani) computed.
///
Expand Down Expand Up @@ -39,7 +44,6 @@ impl<'sess, 'pr> HarnessRunner<'sess, 'pr> {
self.check_stubbing(harnesses)?;

let sorted_harnesses = crate::metadata::sort_harnesses_by_loc(harnesses);

let pool = {
let mut builder = rayon::ThreadPoolBuilder::new();
if let Some(x) = self.sess.args.jobs() {
Expand Down Expand Up @@ -101,6 +105,45 @@ impl<'sess, 'pr> HarnessRunner<'sess, 'pr> {
}

impl KaniSession {
fn process_output(&self, result: &VerificationResult, harness: &HarnessMetadata) {
if self.should_print_output() {
if self.args.output_into_files {
self.write_output_to_file(result, harness);
}

let output = result.render(&self.args.output_format, harness.attributes.should_panic);
println!("{}", output);
}
}

fn should_print_output(&self) -> bool {
!self.args.common_args.quiet && self.args.output_format != OutputFormat::Old
}

fn write_output_to_file(&self, result: &VerificationResult, harness: &HarnessMetadata) {
let target_dir = self.result_output_dir().unwrap();
let file_name = target_dir.join(harness.pretty_name.clone());
let path = Path::new(&file_name);
let prefix = path.parent().unwrap();

std::fs::create_dir_all(prefix).unwrap();
let mut file = File::create(&file_name).unwrap();
let file_output = result.render(&OutputFormat::Regular, harness.attributes.should_panic);

if let Err(e) = writeln!(file, "{}", file_output) {
eprintln!(
"Failed to write to file {}: {}",
file_name.into_os_string().into_string().unwrap(),
e
);
}
}

fn result_output_dir(&self) -> Result<PathBuf> {
let target_dir = self.args.target_dir.clone().map_or_else(current_dir, Ok)?;
Ok(target_dir.join("result_output_dir")) //Hardcode output to result_output_dir, may want to make it adjustable?
}

/// Run the verification process for a single harness
pub(crate) fn check_harness(
&self,
Expand All @@ -119,14 +162,7 @@ impl KaniSession {
} else {
let mut result = self.with_timer(|| self.run_cbmc(binary, harness), "run_cbmc")?;

// When quiet, we don't want to print anything at all.
// When output is old, we also don't have real results to print.
if !self.args.common_args.quiet && self.args.output_format != OutputFormat::Old {
println!(
"{}",
result.render(&self.args.output_format, harness.attributes.should_panic)
);
}
self.process_output(&result, harness);
self.gen_and_add_concrete_playback(harness, &mut result)?;
Ok(result)
}
Expand Down
3 changes: 3 additions & 0 deletions tests/script-based-pre/individual_file_output/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT
script: individual_file_output.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

set +e

OUT_DIR=tmp_sample_crate

# Ensure output folder is clean
rm -rf ${OUT_DIR}

# Move the original source to the output folder since it will be modified
cp -r sample_crate ${OUT_DIR}
pushd $OUT_DIR

echo "Run verification..."
cargo kani -Z unstable-options --output-into-files

OUTPUT_DIR="result_output_dir"

# Check if the output directory exists
if [ ! -d "$OUTPUT_DIR" ]; then
echo "Output directory $OUT_DIR/$OUTPUT_DIR does not exist. Verification failed."
exit 1
fi

# Check if there are any files in the output directory
output_files=("$OUTPUT_DIR"/*)

if [ ${#output_files[@]} -eq 0 ]; then
echo "No files found in the output directory. Verification failed."
exit 1
fi

# Check if each file contains text
for file in "${output_files[@]}"; do
if [ ! -s "$file" ]; then
echo "File $file is empty. Verification failed."
exit 1
else
echo "File $file is present and contains text."
fi
done

popd
rm -rf ${OUT_DIR}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT
[package]
name = "sample_crate"
version = "0.1.0"
edition = "2021"

[package.metadata.kani.flags]
concrete-playback = "inplace"

[package.metadata.kani.unstable]
concrete-playback = true

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] }
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

//! This test checks that we can correctly generate tests from a cover statement and run them.

#[cfg(kani)]
mod verify {
#[kani::proof]
fn any_is_ok() {
let result: Result<char, bool> = kani::any();
kani::cover!(result.is_ok());
}

#[kani::proof]
fn any_is_err() {
let result: Result<char, bool> = kani::any();
kani::cover!(result.is_err());
}
}