Skip to content

Commit 07693ec

Browse files
committed
Add a CI check for reproducible builds
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.
1 parent 54b47ba commit 07693ec

3 files changed

Lines changed: 42 additions & 2 deletions

File tree

.cirrus.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ task:
3535
lint_script:
3636
- rustup component add clippy
3737
- cargo clippy $CARGO_ARGS --all-targets --workspace -- -D warnings
38+
reproducibility_script:
39+
- env RUSTFLAGS="--cfg reprocheck" cargo check $CARGO_ARGS --all-targets
3840
minver_script:
3941
- cargo update -Zminimal-versions
4042
- cargo test $CARGO_ARGS
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// vim: tw=80
2+
//! Methods with multiple generic lifetime parameters should produce their
3+
//! generated code deterministically.
4+
//!
5+
//! This test is designed to work with "--cfg reprocheck"
6+
7+
#![deny(warnings)]
8+
#![allow(clippy::needless_lifetimes)]
9+
10+
use mockall::*;
11+
12+
#[automock]
13+
trait Foo {
14+
fn foo<'a, 'b, 'c, 'd, 'e, 'f>(&self, x: &'a &'b &'c &'d &'e &'f i32);
15+
}

mockall_derive/src/lib.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ fn mock_it<M: Into<MockableItem>>(inputs: M) -> TokenStream
10331033
ts
10341034
}
10351035

1036-
fn do_mock(input: TokenStream) -> TokenStream
1036+
fn do_mock_once(input: TokenStream) -> TokenStream
10371037
{
10381038
let item: MockableStruct = match syn::parse2(input) {
10391039
Ok(mock) => mock,
@@ -1044,6 +1044,18 @@ fn do_mock(input: TokenStream) -> TokenStream
10441044
mock_it(item)
10451045
}
10461046

1047+
fn do_mock(input: TokenStream) -> TokenStream
1048+
{
1049+
cfg_if! {
1050+
if #[cfg(reprocheck)] {
1051+
let ts_a = do_mock_once(input.clone());
1052+
let ts_b = do_mock_once(input.clone());
1053+
assert_eq!(ts_a.to_string(), ts_b.to_string());
1054+
}
1055+
}
1056+
do_mock_once(input)
1057+
}
1058+
10471059
#[proc_macro]
10481060
pub fn mock(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
10491061
do_mock(input.into()).into()
@@ -1058,7 +1070,7 @@ pub fn automock(attrs: proc_macro::TokenStream, input: proc_macro::TokenStream)
10581070
do_automock(attrs, input).into()
10591071
}
10601072

1061-
fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
1073+
fn do_automock_once(attrs: TokenStream, input: TokenStream) -> TokenStream {
10621074
let mut output = input.clone();
10631075
let attrs: Attrs = match parse2(attrs) {
10641076
Ok(a) => a,
@@ -1076,6 +1088,17 @@ fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
10761088
output
10771089
}
10781090

1091+
fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
1092+
cfg_if! {
1093+
if #[cfg(reprocheck)] {
1094+
let ts_a = do_automock_once(attrs.clone(), input.clone());
1095+
let ts_b = do_automock_once(attrs.clone(), input.clone());
1096+
assert_eq!(ts_a.to_string(), ts_b.to_string());
1097+
}
1098+
}
1099+
do_automock_once(attrs, input)
1100+
}
1101+
10791102
#[cfg(test)]
10801103
mod t {
10811104
use super::*;

0 commit comments

Comments
 (0)