1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! # assert_hex
//! display expression using `{:#x?}` format when false assertion causes `panic!()`.
//!
//! # why
//! Writing and testing protocol level libraries requires many tests to be written
//! with respect to byte level protocol sections in hex. This library simplifies the process
//! of viewing the differences between these types when tests fail by displaying by using the
//! `{:#x?}` representation.
//!
//! # usage
//! Replace `assert_eq` or `assert_ne` with `assert_eq_hex` or `assert_ne_hex`
//! respectively.

/// Asserts that two expressions are equal to each other
///
/// On panic, this macro will print values of the expressions in their
/// `{:#x?}` (hexadecimal) representation
#[macro_export]
macro_rules! assert_eq_hex {
    ($left:expr, $right:expr $(,)?) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    // The reborrows below are intentional. Without them, the stack slot for the
                    // borrow is initialized even before the values are compared, leading to a
                    // noticeable slow down.
                    panic!(r#"assertion `left == right` failed
  left: {:#x?}
 right: {:#x?}"#, &*left_val, &*right_val)
                }
            }
        }
    });
    ($left:expr, $right:expr, $($arg:tt)+) => ({
        match (&($left), &($right)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    // The reborrows below are intentional. Without them, the stack slot for the
                    // borrow is initialized even before the values are compared, leading to a
                    // noticeable slow down.
                    panic!(r#"assertion `left == right` failed: {}
  left: {:#x?}
 right: {:#x?}"#, format_args!($($arg)+), &*left_val, &*right_val)
                }
            }
        }
    });
}

/// Asserts that two expressions are not equal to each other
///
/// On panic, this macro will print values of the expressions in their
/// `{:#x?}` (hexadecimal) representation
#[macro_export]
macro_rules! assert_ne_hex {
    ($left:expr, $right:expr $(,)?) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    // The reborrows below are intentional. Without them, the stack slot for the
                    // borrow is initialized even before the values are compared, leading to a
                    // noticeable slow down.
                    panic!(r#"assertion `left != right` failed
  left: {:#x?}
 right: {:#x?}"#, &*left_val, &*right_val)
                }
            }
        }
    });
    ($left:expr, $right:expr, $($arg:tt)+) => ({
        match (&($left), &($right)) {
            (left_val, right_val) => {
                if *left_val == *right_val {
                    // The reborrows below are intentional. Without them, the stack slot for the
                    // borrow is initialized even before the values are compared, leading to a
                    // noticeable slow down.
                    panic!(r#"assertion `left != right` failed: {}
  left: {:#x?}
 right: {:#x?}"#, format_args!($($arg)+), &*left_val, &*right_val)
                }
            }
        }
    });
}

#[cfg(test)]
mod tests {
    use crate::{assert_eq_hex, assert_ne_hex};

    #[test]
    #[should_panic(expected = r#"assertion `left == right` failed
  left: 0x50
 right: 0x46"#)]
    fn test_eq_0() {
        assert_eq_hex!(0x50, 0x46);
    }

    #[test]
    #[should_panic(expected = r#"assertion `left == right` failed
  left: 0xff
 right: 0x46"#)]
    fn test_eq_1() {
        assert_eq_hex!(0xff, 0x46);
    }

    #[test]
    #[should_panic(expected = r#"assertion `left == right` failed
  left: 0xff
 right: 0x46"#)]
    fn test_eq_2() {
        assert_eq_hex!(0xff, 0x46);
    }

    #[test]
    #[should_panic(expected = r#"assertion `left == right` failed
  left: [
    0x0,
    0x1,
    0x2,
]
 right: [
    0x46,
    0x50,
    0x40,
]"#)]
    fn test_eq_3() {
        assert_eq_hex!(vec![0x00, 0x01, 0x02], vec![0x46, 0x50, 0x40]);
    }

    #[test]
    #[should_panic(expected = r#"assertion `left == right` failed: yikes
  left: 0xff
 right: 0x0"#)]
    fn test_eq_more() {
        assert_eq_hex!(0xff, 0x00, "yikes");
    }

    #[test]
    #[should_panic(expected = r#"assertion `left != right` failed
  left: 0x50
 right: 0x50"#)]
    fn test_ne_0() {
        assert_ne_hex!(0x50, 0x50);
    }

    #[test]
    #[should_panic(expected = r#"assertion `left != right` failed
  left: 0xff
 right: 0xff"#)]
    fn test_ne_1() {
        assert_ne_hex!(0xff, 0xff);
    }

    #[test]
    #[should_panic(expected = r#"assertion `left != right` failed: yikes
  left: 0xff
 right: 0xff"#)]
    fn test_ne_more() {
        assert_ne_hex!(0xff, 0xff, "yikes");
    }
}