Skip to content

Commit 1c3d0f3

Browse files
authored
Add CI test for --use-local-toolchain (rust-lang#3074)
Adds a CI test for --use-local-toolchain. This test will run after every push to main. Additional cleanup to the setup as mentioned in rust-lang#3060 in next PR's. (In interest of keeping changes small & focused). By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent 506bfc4 commit 1c3d0f3

File tree

3 files changed

+155
-6
lines changed

3 files changed

+155
-6
lines changed

.github/workflows/release.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,106 @@ jobs:
101101
os: linux
102102
arch: x86_64-unknown-linux-gnu
103103

104+
test-use-local-toolchain:
105+
name: TestLocalToolchain
106+
needs: [build_bundle_macos, build_bundle_linux]
107+
strategy:
108+
matrix:
109+
os: [macos-13, ubuntu-20.04, ubuntu-22.04]
110+
include:
111+
- os: macos-13
112+
rust_target: x86_64-apple-darwin
113+
prev_job: ${{ needs.build_bundle_macos.outputs }}
114+
- os: ubuntu-20.04
115+
rust_target: x86_64-unknown-linux-gnu
116+
prev_job: ${{ needs.build_bundle_linux.outputs }}
117+
- os: ubuntu-22.04
118+
rust_target: x86_64-unknown-linux-gnu
119+
prev_job: ${{ needs.build_bundle_linux.outputs }}
120+
runs-on: ${{ matrix.os }}
121+
steps:
122+
- name: Download bundle
123+
uses: actions/download-artifact@v3
124+
with:
125+
name: ${{ matrix.prev_job.bundle }}
126+
127+
- name: Download kani-verifier crate
128+
uses: actions/download-artifact@v3
129+
with:
130+
name: ${{ matrix.prev_job.package }}
131+
132+
- name: Check download
133+
run: |
134+
ls -lh .
135+
136+
- name: Get toolchain version used to setup kani
137+
run: |
138+
tar zxvf ${{ matrix.prev_job.bundle }}
139+
DATE=$(cat ./kani-latest/rust-toolchain-version | cut -d'-' -f2,3,4)
140+
echo "Nightly date: $DATE"
141+
echo "DATE=$DATE" >> $GITHUB_ENV
142+
143+
- name: Install Kani from path
144+
run: |
145+
tar zxvf ${{ matrix.prev_job.package }}
146+
cargo install --locked --path kani-verifier-${{ matrix.prev_job.crate_version }}
147+
148+
- name: Create a custom toolchain directory
149+
run: mkdir -p ${{ github.workspace }}/../custom_toolchain
150+
151+
- name: Fetch the nightly tarball
152+
run: |
153+
echo "Downloading Rust toolchain from rust server."
154+
curl --proto '=https' --tlsv1.2 -O https://static.rust-lang.org/dist/$DATE/rust-nightly-${{ matrix.rust_target }}.tar.gz
155+
tar -xzf rust-nightly-${{ matrix.rust_target }}.tar.gz
156+
./rust-nightly-${{ matrix.rust_target }}/install.sh --prefix=${{ github.workspace }}/../custom_toolchain
157+
158+
- name: Ensure installation is correct
159+
run: |
160+
cargo kani setup --use-local-bundle ./${{ matrix.prev_job.bundle }} --use-local-toolchain ${{ github.workspace }}/../custom_toolchain/
161+
162+
- name: Ensure that the rustup toolchain is not present
163+
run: |
164+
if [ ! -e "~/.rustup/toolchains/" ]; then
165+
echo "Default toolchain file does not exist. Proceeding with running tests."
166+
else
167+
echo "::error::Default toolchain exists despite not installing."
168+
exit 1
169+
fi
170+
171+
- name: Checkout tests
172+
uses: actions/checkout@v4
173+
174+
- name: Move rust-toolchain file to outside kani
175+
run: |
176+
mkdir -p ${{ github.workspace }}/../post-setup-tests
177+
cp -r tests/cargo-ui ${{ github.workspace }}/../post-setup-tests
178+
cp -r tests/kani/Assert ${{ github.workspace }}/../post-setup-tests
179+
ls ${{ github.workspace }}/../post-setup-tests
180+
181+
- name: Run cargo-kani tests after moving
182+
run: |
183+
for dir in function multiple-harnesses verbose; do
184+
>&2 echo "Running test $dir"
185+
pushd ${{ github.workspace }}/../post-setup-tests/cargo-ui/$dir
186+
cargo kani
187+
popd
188+
done
189+
190+
- name: Check --help and --version
191+
run: |
192+
>&2 echo "Running cargo kani --help and --version"
193+
pushd ${{ github.workspace }}/../post-setup-tests/Assert
194+
cargo kani --help && cargo kani --version
195+
popd
196+
197+
- name: Run standalone kani test
198+
run: |
199+
>&2 echo "Running test on file bool_ref"
200+
pushd ${{ github.workspace }}/../post-setup-tests/Assert
201+
kani bool_ref.rs
202+
popd
203+
104204
test_bundle:
105205
name: TestBundle
106206
needs: [build_bundle_macos, build_bundle_linux]

src/setup.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,22 +141,42 @@ pub(crate) fn get_rust_toolchain_version(kani_dir: &Path) -> Result<String> {
141141
.context("Reading release bundle rust-toolchain-version")
142142
}
143143

144+
pub(crate) fn get_rustc_version_from_build(kani_dir: &Path) -> Result<String> {
145+
std::fs::read_to_string(kani_dir.join("rustc-version"))
146+
.context("Reading release bundle rustc-version")
147+
}
148+
144149
/// Install the Rust toolchain version we require
145150
fn setup_rust_toolchain(kani_dir: &Path, use_local_toolchain: Option<OsString>) -> Result<String> {
146151
// Currently this means we require the bundle to have been unpacked first!
147152
let toolchain_version = get_rust_toolchain_version(kani_dir)?;
148-
println!("[3/5] Installing rust toolchain version: {}", &toolchain_version);
153+
let rustc_version = get_rustc_version_from_build(kani_dir)?.trim().to_string();
149154

150155
// Symlink to a local toolchain if the user explicitly requests
151156
if let Some(local_toolchain_path) = use_local_toolchain {
152157
let toolchain_path = Path::new(&local_toolchain_path);
153-
// TODO: match the version against which kani was built
154-
// Issue: https://github.com/model-checking/kani/issues/3060
155-
symlink_rust_toolchain(toolchain_path, kani_dir)?;
156-
return Ok(toolchain_version);
158+
159+
let custom_toolchain_rustc_version =
160+
get_rustc_version_from_local_toolchain(local_toolchain_path.clone())?;
161+
162+
if rustc_version == custom_toolchain_rustc_version {
163+
symlink_rust_toolchain(toolchain_path, kani_dir)?;
164+
println!(
165+
"[3/5] Installing rust toolchain from path provided: {}",
166+
&toolchain_path.to_string_lossy()
167+
);
168+
return Ok(toolchain_version);
169+
} else {
170+
bail!(
171+
"The toolchain with rustc {:?} being used to setup is not the same as the one Kani used in its release bundle {:?}. Try to setup with the same version as the bundle.",
172+
custom_toolchain_rustc_version,
173+
rustc_version,
174+
);
175+
}
157176
}
158177

159178
// This is the default behaviour when no explicit path to a toolchain is mentioned
179+
println!("[3/5] Installing rust toolchain version: {}", &toolchain_version);
160180
Command::new("rustup").args(["toolchain", "install", &toolchain_version]).run()?;
161181
let toolchain = home::rustup_home()?.join("toolchains").join(&toolchain_version);
162182
symlink_rust_toolchain(&toolchain, kani_dir)?;
@@ -189,6 +209,27 @@ fn download_filename() -> String {
189209
format!("kani-{VERSION}-{TARGET}.tar.gz")
190210
}
191211

212+
/// Get the version of rustc that is being used to setup kani by the user
213+
fn get_rustc_version_from_local_toolchain(path: OsString) -> Result<String> {
214+
let path = Path::new(&path);
215+
let rustc_path = path.join("bin").join("rustc");
216+
217+
let output = Command::new(rustc_path).arg("--version").output();
218+
219+
match output {
220+
Ok(output) => {
221+
if output.status.success() {
222+
Ok(String::from_utf8(output.stdout).map(|s| s.trim().to_string())?)
223+
} else {
224+
bail!(
225+
"Could not parse rustc version string. Toolchain installation likely invalid. "
226+
);
227+
}
228+
}
229+
Err(_) => bail!("Could not get rustc version. Toolchain installation likely invalid"),
230+
}
231+
}
232+
192233
/// The download URL for this version of Kani
193234
fn download_url() -> String {
194235
let tag: &str = &format!("kani-{VERSION}");

tools/build-kani/src/main.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ fn bundle_kani(dir: &Path) -> Result<()> {
9797
cp_dir(&kani_sysroot_lib(), dir)?;
9898
cp_dir(&kani_playback_lib().parent().unwrap(), dir)?;
9999

100-
// 5. Record the exact toolchain we use
100+
// 5. Record the exact toolchain and rustc version we use
101101
std::fs::write(dir.join("rust-toolchain-version"), env!("RUSTUP_TOOLCHAIN"))?;
102+
std::fs::write(dir.join("rustc-version"), get_rustc_version()?)?;
102103

103104
// 6. Include a licensing note
104105
cp(Path::new("tools/build-kani/license-notes.txt"), dir)?;
@@ -181,6 +182,13 @@ fn cp(src: &Path, dst: &Path) -> Result<()> {
181182
Ok(())
182183
}
183184

185+
/// Record version of rustc being used to build Kani
186+
fn get_rustc_version() -> Result<String> {
187+
let output = Command::new("rustc").arg("--version").output();
188+
let rustc_version = String::from_utf8(output.unwrap().stdout)?;
189+
Ok(rustc_version)
190+
}
191+
184192
/// Copy files from `src` to `dst` that respect the given pattern.
185193
pub fn cp_files<P>(src: &Path, dst: &Path, predicate: P) -> Result<()>
186194
where

0 commit comments

Comments
 (0)