Skip to content

Commit c1b2cb4

Browse files
marcianxcopybara-github
authored andcommitted
Support printing the two sides of a binary operator and traversing inside a unary operator in verify_pred.
PiperOrigin-RevId: 691782094
1 parent 02aca72 commit c1b2cb4

File tree

2 files changed

+114
-3
lines changed

2 files changed

+114
-3
lines changed

googletest/tests/assertions_test.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,95 @@ mod verify_pred {
333333
})))
334334
)
335335
}
336+
337+
#[test]
338+
fn binary_operator() -> Result<()> {
339+
// Add chaining and function calls.
340+
fn f(x: u32) -> u32 {
341+
x + 1
342+
}
343+
#[derive(Debug)]
344+
struct Apple;
345+
impl Apple {
346+
fn b(&self, y: u32) -> u32 {
347+
y + 10
348+
}
349+
}
350+
let a = Apple;
351+
let x = 1;
352+
let y = 2;
353+
let res = verify_pred!(f(x) - 1 == a.b(y + 1) + f(y));
354+
verify_that!(
355+
res,
356+
err(displays_as(contains_substring(indoc! {"
357+
f(x) - 1 == a.b(y + 1) + f(y) was false with
358+
x = 1,
359+
f(x) = 2,
360+
f(x) - 1 = 1,
361+
a = Apple,
362+
y + 1 = 3,
363+
a.b(y + 1) = 13,
364+
y = 2,
365+
f(y) = 3,
366+
a.b(y + 1) + f(y) = 16,
367+
at"
368+
})))
369+
)
370+
}
371+
372+
#[rustversion::before(1.77)]
373+
#[test]
374+
fn unary_operator() -> Result<()> {
375+
#[derive(Debug)]
376+
struct Apple;
377+
impl Apple {
378+
fn b(&self, _b: u32, _c: i32) -> i32 {
379+
0
380+
}
381+
}
382+
383+
let a = Apple;
384+
let b = 1;
385+
let res = verify_pred!(!a.b(b, -1) == !-2);
386+
verify_that!(
387+
res,
388+
err(displays_as(contains_substring(indoc! {"
389+
! a.b(b, - 1) ==! - 2 was false with
390+
a = Apple,
391+
b = 1,
392+
a.b(b, - 1) = 0,
393+
! a.b(b, - 1) = -1,
394+
! - 2 = 1,
395+
at"
396+
})))
397+
)
398+
}
399+
400+
#[rustversion::since(1.77)]
401+
#[test]
402+
fn unary_operator() -> Result<()> {
403+
#[derive(Debug)]
404+
struct Apple;
405+
impl Apple {
406+
fn b(&self, _b: u32, _c: i32) -> i32 {
407+
0
408+
}
409+
}
410+
411+
let a = Apple;
412+
let b = 1;
413+
let res = verify_pred!(!a.b(b, -1) == !-2);
414+
verify_that!(
415+
res,
416+
err(displays_as(contains_substring(indoc! {"
417+
! a.b(b, - 1) == ! - 2 was false with
418+
a = Apple,
419+
b = 1,
420+
a.b(b, - 1) = 0,
421+
! a.b(b, - 1) = -1,
422+
! - 2 = 1,
423+
at"
424+
})))
425+
)
426+
}
336427
}

googletest_macro/src/verify_pred.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ impl AccumulatePartsState {
4545
/// of the input expression with parts of it potentially replaced by the
4646
/// intermediate variables.
4747
fn accumulate_parts(&mut self, expr: Expr) -> Expr {
48+
// Literals don't need to be printed or stored in intermediate variables.
49+
if is_literal(&expr) {
50+
return expr;
51+
}
4852
let expr_string = expr_to_string(&expr);
4953
let new_expr = match expr {
5054
Expr::Group(mut group) => {
@@ -53,8 +57,6 @@ impl AccumulatePartsState {
5357
*group.expr = self.accumulate_parts(*group.expr);
5458
return Expr::Group(group);
5559
}
56-
// Literals don't need to be printed or stored in intermediate variables.
57-
Expr::Lit(_) => return expr,
5860
Expr::Field(mut field) => {
5961
// Don't assign field access to an intermediate variable to avoid moving out of
6062
// non-`Copy` fields.
@@ -74,6 +76,15 @@ impl AccumulatePartsState {
7476
// Cache method value into an intermediate variable.
7577
self.define_variable(&Expr::MethodCall(method_call))
7678
}
79+
Expr::Binary(mut binary) => {
80+
*binary.left = self.accumulate_parts(*binary.left);
81+
*binary.right = self.accumulate_parts(*binary.right);
82+
Expr::Binary(binary)
83+
}
84+
Expr::Unary(mut unary) => {
85+
*unary.expr = self.accumulate_parts(*unary.expr);
86+
Expr::Unary(unary)
87+
}
7788
// A path expression doesn't need to be stored in an intermediate variable.
7889
// This avoids moving out of an existing variable.
7990
Expr::Path(_) => expr,
@@ -101,7 +112,7 @@ impl AccumulatePartsState {
101112
args.into_pairs()
102113
.map(|mut pair| {
103114
// Don't need to assign literals to intermediate variables.
104-
if let Expr::Lit(_) = pair.value() {
115+
if is_literal(pair.value()) {
105116
return pair;
106117
}
107118

@@ -137,6 +148,15 @@ impl AccumulatePartsState {
137148
}
138149
}
139150

151+
// Whether it's a literal or unary operator applied to a literal (1, -1).
152+
fn is_literal(expr: &Expr) -> bool {
153+
match expr {
154+
Expr::Lit(_) => true,
155+
Expr::Unary(unary) => matches!(&*unary.expr, Expr::Lit(_)),
156+
_ => false,
157+
}
158+
}
159+
140160
pub fn verify_pred_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
141161
let parsed = parse_macro_input!(input as Expr);
142162
let error_message = quote!(#parsed).to_string() + " was false with";

0 commit comments

Comments
 (0)