Skip to content

Commit

Permalink
Add a CI check for reproducible builds
Browse files Browse the repository at this point in the history
Add a --cfg reprocheck setting.  When enabled, mock! and #[automock]
will evaluate every call twice and verify that the output is identical.
Also add a test case that is known to currently generate
non-reproducible output.
  • Loading branch information
asomers committed Sep 10, 2021
1 parent 54b47ba commit 503b0b2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ task:
lint_script:
- rustup component add clippy
- cargo clippy $CARGO_ARGS --all-targets --workspace -- -D warnings
reproducibility_script:
- env RUSTFLAGS="--cfg reprocheck" cargo check $CARGO_ARGS --all-targets
minver_script:
- cargo update -Zminimal-versions
- cargo test $CARGO_ARGS
Expand Down
14 changes: 14 additions & 0 deletions mockall/tests/automock_multiple_lifetime_parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// vim: tw=80
//! Methods with multiple generic lifetime parameters should produce their
//! generated code deterministically.
//!
//! This test is designed to work with "--cfg reprocheck"
#![deny(warnings)]

use mockall::*;

#[automock]
trait Foo {
fn foo<'a, 'b, 'c, 'd, 'e, 'f>(&self, x: &'a &'b &'c &'d &'e &'f i32);
}
27 changes: 25 additions & 2 deletions mockall_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ fn mock_it<M: Into<MockableItem>>(inputs: M) -> TokenStream
ts
}

fn do_mock(input: TokenStream) -> TokenStream
fn do_mock_once(input: TokenStream) -> TokenStream
{
let item: MockableStruct = match syn::parse2(input) {
Ok(mock) => mock,
Expand All @@ -1044,6 +1044,18 @@ fn do_mock(input: TokenStream) -> TokenStream
mock_it(item)
}

fn do_mock(input: TokenStream) -> TokenStream
{
cfg_if! {
if #[cfg(reprocheck)] {
let ts_a = do_mock_once(input.clone());
let ts_b = do_mock_once(input.clone());
assert_eq!(ts_a.to_string(), ts_b.to_string());
}
}
do_mock_once(input)
}

#[proc_macro]
pub fn mock(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
do_mock(input.into()).into()
Expand All @@ -1058,7 +1070,7 @@ pub fn automock(attrs: proc_macro::TokenStream, input: proc_macro::TokenStream)
do_automock(attrs, input).into()
}

fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
fn do_automock_once(attrs: TokenStream, input: TokenStream) -> TokenStream {
let mut output = input.clone();
let attrs: Attrs = match parse2(attrs) {
Ok(a) => a,
Expand All @@ -1076,6 +1088,17 @@ fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
output
}

fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
cfg_if! {
if #[cfg(reprocheck)] {
let ts_a = do_automock_once(attrs.clone(), input.clone());
let ts_b = do_automock_once(attrs.clone(), input.clone());
assert_eq!(ts_a.to_string(), ts_b.to_string());
}
}
do_automock_once(attrs, input)
}

#[cfg(test)]
mod t {
use super::*;
Expand Down

0 comments on commit 503b0b2

Please sign in to comment.