revmc/tests/
macros.rs

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
macro_rules! matrix_tests {
    ($run:ident) => {
        #[cfg(feature = "llvm")]
        mod llvm {
            use super::*;
            #[allow(unused_imports)]
            use similar_asserts::assert_eq;

            fn run_llvm(compiler: &mut EvmCompiler<crate::llvm::EvmLlvmBackend<'_>>) {
                crate::tests::set_test_dump(compiler, module_path!());
                $run(compiler);
            }

            #[test]
            fn unopt() {
                crate::tests::with_llvm_backend_jit(crate::OptimizationLevel::None, run_llvm);
            }

            #[test]
            fn opt() {
                crate::tests::with_llvm_backend_jit(crate::OptimizationLevel::Aggressive, run_llvm);
            }
        }
    };

    ($name:ident = | $compiler:ident | $e:expr) => {
        mod $name {
            use super::*;
            #[allow(unused_imports)]
            use similar_asserts::assert_eq;

            fn run_generic<B: Backend>($compiler: &mut EvmCompiler<B>) {
                $e;
            }

            matrix_tests!(run_generic);
        }
    };
    ($name:ident = $run:ident) => {
        mod $name {
            use super::*;
            #[allow(unused_imports)]
            use similar_asserts::assert_eq;

            matrix_tests!($run);
        }
    };
}

macro_rules! build_push32 {
    ($code:ident[$i:ident], $x:expr) => {{
        $code[$i] = op::PUSH32;
        $i += 1;
        $code[$i..$i + 32].copy_from_slice(&$x.to_be_bytes::<32>());
        $i += 32;
    }};
}

macro_rules! tests {
    ($($group:ident { $($t:tt)* })*) => { uint! {
        $(
            mod $group {
                use super::*;
                #[allow(unused_imports)]
                use similar_asserts::assert_eq;

                tests!(@cases $($t)*);
            }
        )*
    }};

    (@cases $( $name:ident($($t:tt)*) ),* $(,)?) => {
        $(
            matrix_tests!($name = |jit| run_test_case(tests!(@case $($t)*), jit));
        )*
    };

    (@case @raw { $($fields:tt)* }) => { &TestCase { $($fields)* ..Default::default() } };

    (@case $op:expr $(, $args:expr)* $(,)? => $($ret:expr),* $(,)? $(; op_gas($op_gas:expr))?) => {
        &TestCase {
            bytecode: &tests!(@bytecode $op, $($args),*),
            expected_stack: &[$($ret),*],
            expected_gas: tests!(@gas $op $(, $op_gas)?; $($args),*),
            ..Default::default()
        }
    };

    (@bytecode $op:expr, $a:expr) => { bytecode_unop($op, $a) };
    (@bytecode $op:expr, $a:expr, $b:expr) => { bytecode_binop($op, $a, $b) };
    (@bytecode $op:expr, $a:expr, $b:expr, $c:expr) => { bytecode_ternop($op, $a, $b, $c) };

    (@gas $op:expr; $($args:expr),+) => {
        tests!(@gas
            $op,
            DEF_OPINFOS[$op as usize].base_gas() as u64;
            $($args),+
        )
    };
    (@gas $op:expr, $op_gas:expr; $($args:expr),+) => {
        $op_gas + tests!(@gas_base $($args),+)
    };
    (@gas_base $a:expr) => { 3 };
    (@gas_base $a:expr, $b:expr) => { 6 };
    (@gas_base $a:expr, $b:expr, $c:expr) => { 9 };
}