Skip to content

Commit

Permalink
Merge branch 'main' into future-clippy-warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
tautschnig committed Oct 4, 2023
2 parents 24570ca + fb08f3e commit 9765d3e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 89 deletions.
20 changes: 20 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,12 @@ dependencies = [
"libc",
]

[[package]]
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"

[[package]]
name = "getopts"
version = "0.2.21"
Expand Down Expand Up @@ -504,6 +510,7 @@ dependencies = [
"serde_json",
"strum 0.25.0",
"strum_macros 0.25.2",
"tempfile",
"toml",
"tracing",
"tracing-subscriber",
Expand Down Expand Up @@ -1190,6 +1197,19 @@ dependencies = [
"unicode-ident",
]

[[package]]
name = "tempfile"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall",
"rustix",
"windows-sys 0.48.0",
]

[[package]]
name = "thiserror"
version = "1.0.49"
Expand Down
1 change: 1 addition & 0 deletions kani-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ rayon = "1.5.3"
comfy-table = "7.0.1"
strum = {version = "0.25.0"}
strum_macros = {version = "0.25.2"}
tempfile = "3"
tracing = {version = "0.1", features = ["max_level_trace", "release_max_level_debug"]}
tracing-subscriber = {version = "0.3.8", features = ["env-filter", "json", "fmt"]}
rand = "0.8"
Expand Down
25 changes: 14 additions & 11 deletions kani-driver/src/concrete_playback/test_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use crate::args::ConcretePlaybackMode;
use crate::call_cbmc::VerificationResult;
use crate::session::KaniSession;
use crate::util::tempfile::TempFile;
use anyhow::{Context, Result};
use concrete_vals_extractor::{extract_harness_values, ConcreteVal};
use kani_metadata::HarnessMetadata;
Expand All @@ -18,6 +17,7 @@ use std::hash::{Hash, Hasher};
use std::io::{BufRead, BufReader, Write};
use std::path::Path;
use std::process::Command;
use tempfile::NamedTempFile;

impl KaniSession {
/// The main driver for generating concrete playback unit tests and adding them to source code.
Expand Down Expand Up @@ -158,25 +158,28 @@ impl KaniSession {

// Create temp file
if !unit_tests.is_empty() {
let mut temp_file = TempFile::try_new("concrete_playback.tmp")?;
let source_basedir = Path::new(source_path).parent().unwrap_or(Path::new("."));
let mut temp_file = NamedTempFile::with_prefix_in("concrete_playback", source_basedir)?;
let mut curr_line_num = 0;

// Use a buffered reader/writer to generate the unit test line by line
for line in source_reader.lines().flatten() {
curr_line_num += 1;
if let Some(temp_writer) = temp_file.writer.as_mut() {
writeln!(temp_writer, "{line}")?;
if curr_line_num == proof_harness_end_line {
for unit_test in unit_tests.iter() {
for unit_test_line in unit_test.code.iter() {
curr_line_num += 1;
writeln!(temp_writer, "{unit_test_line}")?;
}
writeln!(temp_file, "{line}")?;
if curr_line_num == proof_harness_end_line {
for unit_test in unit_tests.iter() {
for unit_test_line in unit_test.code.iter() {
curr_line_num += 1;
writeln!(temp_file, "{unit_test_line}")?;
}
}
}
}
temp_file.rename(source_path).expect("Could not rename file");

// Renames are usually automic, so we won't corrupt the user's source file during a
// crash; but first flush all updates to disk, which persist wouldn't take care of.
temp_file.as_file().sync_all()?;
temp_file.persist(source_path).expect("Could not rename file");
}

Ok(!unit_tests.is_empty())
Expand Down
78 changes: 0 additions & 78 deletions kani-driver/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,84 +14,6 @@ use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::process::Command;

pub mod tempfile {
use std::{
env,
fs::{self, rename, File},
io::{BufWriter, Error, Write},
path::PathBuf,
};

use crate::util;
use ::rand;
use anyhow::Context;
use rand::Rng;

/// Handle a writable temporary file which will be deleted when the object is dropped.
/// To save the contents of the file, users can invoke `rename` which will move the file to
/// its new location and no further deletion will be performed.
pub struct TempFile {
pub file: File,
pub temp_path: PathBuf,
pub writer: Option<BufWriter<File>>,
renamed: bool,
}

impl TempFile {
/// Create a temp file
pub fn try_new(suffix_name: &str) -> Result<Self, Error> {
let mut temp_path = env::temp_dir();

// Generate a unique name for the temporary directory
let hash: u32 = rand::thread_rng().gen();
let file_name: &str = &format!("kani_tmp_{hash}_{suffix_name}");

temp_path.push(file_name);
let temp_file = File::create(&temp_path)?;
let writer = BufWriter::new(temp_file.try_clone()?);

Ok(Self { file: temp_file, temp_path, writer: Some(writer), renamed: false })
}

/// Rename the temporary file to the new path, replacing the original file if the path points to a file that already exists.
pub fn rename(mut self, source_path: &str) -> Result<(), String> {
// flush here
self.writer.as_mut().unwrap().flush().unwrap();
self.writer = None;
// Renames are usually automic, so we won't corrupt the user's source file during a crash.
rename(&self.temp_path, source_path)
.with_context(|| format!("Error renaming file {}", self.temp_path.display()))
.unwrap();
self.renamed = true;
Ok(())
}
}

/// Ensure that the bufwriter is flushed and temp variables are dropped
/// everytime the tempfile is out of scope
/// note: the fields for the struct are dropped automatically by destructor
impl Drop for TempFile {
fn drop(&mut self) {
// if writer is not flushed, flush it
if self.writer.as_ref().is_some() {
// couldn't use ? as drop does not handle returns
if let Err(e) = self.writer.as_mut().unwrap().flush() {
util::warning(
format!("failed to flush {}: {e}", self.temp_path.display()).as_str(),
);
}
self.writer = None;
}

if !self.renamed {
if let Err(_e) = fs::remove_file(self.temp_path.clone()) {
util::warning(&format!("Error removing file {}", self.temp_path.display()));
}
}
}
}
}

/// Replace an extension with another one, in a new PathBuf. (See tests for examples)
pub fn alter_extension(path: &Path, ext: &str) -> PathBuf {
path.with_extension(ext)
Expand Down

0 comments on commit 9765d3e

Please sign in to comment.