diff --git a/kani-driver/src/main.rs b/kani-driver/src/main.rs index ff0a97cce053..15b66db8084d 100644 --- a/kani-driver/src/main.rs +++ b/kani-driver/src/main.rs @@ -14,6 +14,7 @@ use crate::args::StandaloneSubcommand; use crate::concrete_playback::playback::{playback_cargo, playback_standalone}; use crate::project::Project; use crate::session::KaniSession; +use crate::version::print_kani_version; use clap::Parser; use tracing::debug; @@ -35,12 +36,15 @@ mod metadata; mod project; mod session; mod util; +mod version; /// The main function for the `kani-driver`. /// The driver can be invoked via `cargo kani` and `kani` commands, which determines what kind of /// project should be verified. fn main() -> ExitCode { - let result = match determine_invocation_type(Vec::from_iter(std::env::args_os())) { + let invocation_type = determine_invocation_type(Vec::from_iter(std::env::args_os())); + + let result = match invocation_type { InvocationType::CargoKani(args) => cargokani_main(args), InvocationType::Standalone => standalone_main(), }; @@ -59,10 +63,15 @@ fn main() -> ExitCode { /// The main function for the `cargo kani` command. fn cargokani_main(input_args: Vec) -> Result<()> { let input_args = join_args(input_args)?; - let args = args::CargoKaniArgs::parse_from(input_args); + let args = args::CargoKaniArgs::parse_from(&input_args); check_is_valid(&args); + let session = session::KaniSession::new(args.verify_opts)?; + if !session.args.common_args.quiet { + print_kani_version(InvocationType::CargoKani(input_args)); + } + match args.command { Some(CargoKaniSubcommand::Assess(args)) => { return assess::run_assess(session, *args); @@ -91,6 +100,11 @@ fn standalone_main() -> Result<()> { } let session = session::KaniSession::new(args.verify_opts)?; + + if !session.args.common_args.quiet { + print_kani_version(InvocationType::Standalone); + } + let project = project::standalone_project(&args.input.unwrap(), &session)?; if session.args.only_codegen { Ok(()) } else { verify_project(project, session) } } diff --git a/kani-driver/src/version.rs b/kani-driver/src/version.rs new file mode 100644 index 000000000000..95d98b0d6d3e --- /dev/null +++ b/kani-driver/src/version.rs @@ -0,0 +1,31 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +use crate::InvocationType; + +const KANI_RUST_VERIFIER: &str = "Kani Rust Verifier"; +/// We assume this is the same as the `kani-verifier` version, but we should +/// make sure it's enforced through CI: +/// +const KANI_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// Print Kani version. At present, this is only release version information. +pub(crate) fn print_kani_version(invocation_type: InvocationType) { + let kani_version = kani_version_release(invocation_type); + // TODO: Print development version information. + // + println!("{kani_version}"); +} + +/// Print Kani release version as `Kani Rust Verifier ()` +/// where: +/// - `` is the `kani-verifier` version +/// - `` is `cargo plugin` if Kani was invoked with `cargo kani` or +/// `standalone` if it was invoked with `kani`. +fn kani_version_release(invocation_type: InvocationType) -> String { + let invocation_str = match invocation_type { + InvocationType::CargoKani(_) => "cargo plugin", + InvocationType::Standalone => "standalone", + }; + format!("{KANI_RUST_VERIFIER} {KANI_VERSION} ({invocation_str})") +} diff --git a/tests/script-based-pre/cargo-kani-version-flag-version/cargo-kani-version-flag-version.expected b/tests/script-based-pre/cargo-kani-version-flag-version/cargo-kani-version-flag-version.expected new file mode 100644 index 000000000000..90033f7a5621 --- /dev/null +++ b/tests/script-based-pre/cargo-kani-version-flag-version/cargo-kani-version-flag-version.expected @@ -0,0 +1,2 @@ +success: version printed agrees +success: `(cargo plugin)` appears in version line \ No newline at end of file diff --git a/tests/script-based-pre/cargo-kani-version-flag-version/cargo-kani-version-flag-version.sh b/tests/script-based-pre/cargo-kani-version-flag-version/cargo-kani-version-flag-version.sh new file mode 100755 index 000000000000..c2cbb8a924db --- /dev/null +++ b/tests/script-based-pre/cargo-kani-version-flag-version/cargo-kani-version-flag-version.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright Kani Contributors +# SPDX-License-Identifier: Apache-2.0 OR MIT + +set -eu + +KANI_VERSION_CMD=`cargo kani --version` +KANI_VERSION_CMD_VERSION=`echo ${KANI_VERSION_CMD} | awk '{print $2}'` + +# Check that the version printed is the same. Note: We use `sed -n '1p'` instead +# of `head -n 1` to avoid https://github.com/model-checking/kani/issues/2618 +KANI_CARGO_OUTPUT_HEAD=`cd dummy-project; cargo kani | sed -n '1p'` +KANI_CARGO_OUTPUT_HEAD_VERSION=`echo ${KANI_CARGO_OUTPUT_HEAD} | awk '{print $4}'` + +if [[ $KANI_VERSION_CMD_VERSION == $KANI_CARGO_OUTPUT_HEAD_VERSION ]]; then + echo "success: version printed agrees" +else + echo "failed: version printed differs ($KANI_VERSION_CMD_VERSION - $KANI_CARGO_OUTPUT_HEAD_VERSION)" + exit 1 +fi + +KANI_CARGO_OUTPUT_HEAD_MODE=`echo ${KANI_CARGO_OUTPUT_HEAD} | awk '{print $5,$6}'` + +# Check that `(cargo plugin)` appears in the version line +if [[ $KANI_CARGO_OUTPUT_HEAD_MODE == "(cargo plugin)" ]]; then + echo "success: \`(cargo plugin)\` appears in version line" +else + echo "failed: expected \`(cargo plugin)\` in version line" + exit 1 +fi diff --git a/tests/script-based-pre/cargo-kani-version-flag-version/config.yml b/tests/script-based-pre/cargo-kani-version-flag-version/config.yml new file mode 100644 index 000000000000..c909770561f9 --- /dev/null +++ b/tests/script-based-pre/cargo-kani-version-flag-version/config.yml @@ -0,0 +1,4 @@ +# Copyright Kani Contributors +# SPDX-License-Identifier: Apache-2.0 OR MIT +script: cargo-kani-version-flag-version.sh +expected: cargo-kani-version-flag-version.expected diff --git a/tests/script-based-pre/cargo-kani-version-flag-version/dummy-project/Cargo.toml b/tests/script-based-pre/cargo-kani-version-flag-version/dummy-project/Cargo.toml new file mode 100644 index 000000000000..7afd9dd45bac --- /dev/null +++ b/tests/script-based-pre/cargo-kani-version-flag-version/dummy-project/Cargo.toml @@ -0,0 +1,11 @@ +# Copyright Kani Contributors +# SPDX-License-Identifier: Apache-2.0 OR MIT + +[package] +name = "dummy-project" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/script-based-pre/cargo-kani-version-flag-version/dummy-project/src/main.rs b/tests/script-based-pre/cargo-kani-version-flag-version/dummy-project/src/main.rs new file mode 100644 index 000000000000..ed4e2a18242b --- /dev/null +++ b/tests/script-based-pre/cargo-kani-version-flag-version/dummy-project/src/main.rs @@ -0,0 +1,14 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! This test is used to check that an invocation of `cargo kani` prints the version +//! and invocation type as expected. + +fn main() { + println!("Hello, world!"); +} + +#[kani::proof] +fn dummy() { + assert!(1 + 1 == 2); +} diff --git a/tests/script-based-pre/kani-version-flag-version/config.yml b/tests/script-based-pre/kani-version-flag-version/config.yml new file mode 100644 index 000000000000..8d70c7103c33 --- /dev/null +++ b/tests/script-based-pre/kani-version-flag-version/config.yml @@ -0,0 +1,4 @@ +# Copyright Kani Contributors +# SPDX-License-Identifier: Apache-2.0 OR MIT +script: kani-version-flag-version.sh +expected: kani-version-flag-version.expected diff --git a/tests/script-based-pre/kani-version-flag-version/dummy-file.rs b/tests/script-based-pre/kani-version-flag-version/dummy-file.rs new file mode 100644 index 000000000000..fb042d45cafa --- /dev/null +++ b/tests/script-based-pre/kani-version-flag-version/dummy-file.rs @@ -0,0 +1,10 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! This test is used to check that an invocation of `kani` or `cargo kani` +//! prints the version and invocation type as expected. + +#[kani::proof] +fn dummy() { + assert!(1 + 1 == 2); +} diff --git a/tests/script-based-pre/kani-version-flag-version/kani-version-flag-version.expected b/tests/script-based-pre/kani-version-flag-version/kani-version-flag-version.expected new file mode 100644 index 000000000000..d2b7de0d4e0e --- /dev/null +++ b/tests/script-based-pre/kani-version-flag-version/kani-version-flag-version.expected @@ -0,0 +1,2 @@ +success: version printed agrees +success: `(standalone)` appears in version line \ No newline at end of file diff --git a/tests/script-based-pre/kani-version-flag-version/kani-version-flag-version.sh b/tests/script-based-pre/kani-version-flag-version/kani-version-flag-version.sh new file mode 100755 index 000000000000..5c22918535e8 --- /dev/null +++ b/tests/script-based-pre/kani-version-flag-version/kani-version-flag-version.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Copyright Kani Contributors +# SPDX-License-Identifier: Apache-2.0 OR MIT + +set -eu + +KANI_VERSION_CMD=`kani --version` +KANI_VERSION_CMD_VERSION=`echo ${KANI_VERSION_CMD} | awk '{print $2}'` + +# Check that the version printed is the same. Note: We use `sed -n '1p'` instead +# of `head -n 1` to avoid https://github.com/model-checking/kani/issues/2618 +KANI_STANDALONE_OUTPUT_HEAD=`kani dummy-file.rs | sed -n '1p'` +KANI_STANDALONE_OUTPUT_HEAD_VERSION=`echo ${KANI_STANDALONE_OUTPUT_HEAD} | awk '{print $4}'` + +if [[ $KANI_VERSION_CMD_VERSION == $KANI_STANDALONE_OUTPUT_HEAD_VERSION ]]; then + echo "success: version printed agrees" +else + echo "failed: version printed differs ($KANI_VERSION_CMD_VERSION - $KANI_STANDALONE_OUTPUT_HEAD_VERSION)" + exit 1 +fi + +KANI_STANDALONE_OUTPUT_HEAD_MODE=`echo ${KANI_STANDALONE_OUTPUT_HEAD} | awk '{print $5}'` + +# Check that `(standalone)` appears in the version line +if [[ $KANI_STANDALONE_OUTPUT_HEAD_MODE == "(standalone)" ]]; then + echo "success: \`(standalone)\` appears in version line" +else + echo "failed: expected \`(standalone)\` in version line" + exit 1 +fi