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
#[macro_export]
macro_rules! approve {
    ($actual: ident) => {
        {
            use std::fs;
            use std::fs::{File, PathExt};
            use std::io::{Read, Write};
            use std::path::Path;
            use std::process::Command;

            let mut backtrace = vec![];
            ::std::rt::backtrace::write(&mut backtrace);
            let s = String::from_utf8(backtrace).unwrap();

            let method_name = s
                .as_str()
                .lines()
                .skip(2)
                .next()
                .unwrap()
                .split("-")
                .last()
                .unwrap()
                .split(":")
                .next()
                .unwrap()
                .trim_left_matches(" "); // FIXME: Handle all results/options

            let approvals_dirname = "approvals";
            let approvals_dir = Path::new(approvals_dirname);
            if !approvals_dir.exists() {
                match fs::create_dir(approvals_dir) {
                    Err(err) => panic!("Failed to create directory for approvals data: {:?}", err),
                    _ => {}
                }
            } else if !approvals_dir.is_dir() {
                panic!("Path for approvals data is not a directory")
            }

            let expected_filename = format!("{}/{}_expected.txt", approvals_dirname, method_name);
            let expected_path = Path::new(&expected_filename);
            let expected = match File::open(expected_path) {
                Ok(mut f) => {
                    let mut data = String::with_capacity($actual.len());
                    match f.read_to_string(&mut data) {
                        Err(err) => panic!("Failed to read expected data: {:?}", err),
                        _ => {}
                    }

                    data
                },
                Err(open_err) => {
                    match File::create(expected_path) {
                        Ok(_) => String::new(),
                        Err(create_err) => panic!("Failed to open file '{:?}'.\nOpen error: {:?}.\nCreate error: {:?}", expected_path, open_err, create_err)
                    }
                }
            };

            if $actual.trim_right_matches("\n") != expected.trim_right_matches("\n") {
                let actual_filename = format!("{}/{}_actual.txt", approvals_dirname, method_name);
                let mut actual_file = match File::create(actual_filename.clone()) {
                    Ok(f) => f,
                    Err(err) => panic!("Failed to create temp file: {:?}", err)
                };

                match actual_file.write_all($actual.as_bytes()) {
                    Err(err) => panic!("Failed to write actual data for comparing: {:?}", err),
                    _ => {}
                }

                let diff_tool = "vimdiff"; // FIXME: Configure

                let output = match
                    Command::new(diff_tool).arg(::std::ffi::OsStr::new(actual_filename.as_str()))
                    .arg(expected_path.as_os_str())
                    .spawn() {
                    Ok(p) => p.wait_with_output(),
                    Err(err) => panic!("Failed to launch diff tool '{}': {:?}", diff_tool, err)
                };

                match output {
                    Err(err) => panic!("Failed to launch diff tool '{}': {:?}", diff_tool, err),
                    _ => {}
                }

                fs::remove_file(actual_filename);

                panic!("strings are not equal")
            }
        }
    }
}