about summary refs log tree commit diff
path: root/library/stdarch/crates/intrinsic-test/src/common/compare.rs
blob: cb55922eb199b4b7357ebf9bb577c7b241caf06f (plain)
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
use super::cli::FailureReason;
use rayon::prelude::*;
use std::process::Command;

pub fn compare_outputs(intrinsic_name_list: &Vec<String>, runner: &str, target: &str) -> bool {
    fn runner_command(runner: &str) -> Command {
        let mut it = runner.split_whitespace();
        let mut cmd = Command::new(it.next().unwrap());
        cmd.args(it);

        cmd
    }

    let intrinsics = intrinsic_name_list
        .par_iter()
        .filter_map(|intrinsic_name| {
            let c = runner_command(runner)
                .arg("./c_programs/intrinsic-test-programs")
                .arg(intrinsic_name)
                .output();

            let rust = runner_command(runner)
                .arg(format!("target/{target}/release/{intrinsic_name}"))
                .output();

            let (c, rust) = match (c, rust) {
                (Ok(c), Ok(rust)) => (c, rust),
                a => panic!("{a:#?}"),
            };

            if !c.status.success() {
                error!(
                    "Failed to run C program for intrinsic {intrinsic_name}\nstdout: {stdout}\nstderr: {stderr}",
                    stdout = std::str::from_utf8(&c.stdout).unwrap_or(""),
                    stderr = std::str::from_utf8(&c.stderr).unwrap_or(""),
                );
                return Some(FailureReason::RunC(intrinsic_name.clone()));
            }

            if !rust.status.success() {
                error!(
                    "Failed to run Rust program for intrinsic {intrinsic_name}\nstdout: {stdout}\nstderr: {stderr}",
                    stdout = String::from_utf8_lossy(&rust.stdout),
                    stderr = String::from_utf8_lossy(&rust.stderr),
                );
                return Some(FailureReason::RunRust(intrinsic_name.clone()));
            }

            info!("Comparing intrinsic: {intrinsic_name}");

            let c = std::str::from_utf8(&c.stdout)
                .unwrap()
                .to_lowercase()
                .replace("-nan", "nan");
            let rust = std::str::from_utf8(&rust.stdout)
                .unwrap()
                .to_lowercase()
                .replace("-nan", "nan");

            if c == rust {
                None
            } else {
                Some(FailureReason::Difference(intrinsic_name.clone(), c, rust))
            }
        })
        .collect::<Vec<_>>();

    intrinsics.iter().for_each(|reason| match reason {
        FailureReason::Difference(intrinsic, c, rust) => {
            println!("Difference for intrinsic: {intrinsic}");
            let diff = diff::lines(c, rust);
            diff.iter().for_each(|diff| match diff {
                diff::Result::Left(c) => println!("C: {c}"),
                diff::Result::Right(rust) => println!("Rust: {rust}"),
                diff::Result::Both(_, _) => (),
            });
            println!("****************************************************************");
        }
        FailureReason::RunC(intrinsic) => {
            println!("Failed to run C program for intrinsic {intrinsic}")
        }
        FailureReason::RunRust(intrinsic) => {
            println!("Failed to run rust program for intrinsic {intrinsic}")
        }
    });
    println!("{} differences found", intrinsics.len());
    intrinsics.is_empty()
}