Skip to main content

deqp_runner/
mock_piglit.rs

1use anyhow::Result;
2use rand::Rng;
3use std::fmt::Display;
4use std::io::prelude::*;
5use structopt::StructOpt;
6
7/// Mock piglit that uses conventions in the test name to control behavior of the
8/// test.  We use this for integration testing of piglit-runner.
9
10#[derive(Debug, StructOpt)]
11pub struct MockPiglit {
12    test: String,
13
14    #[structopt(long)]
15    #[allow(dead_code)]
16    auto: bool,
17
18    // Dump everything after '--' into here.  The -auto and -fbo will end up
19    // here, since we can't represent them as clap args.
20    #[allow(dead_code)]
21    args: Vec<String>,
22}
23
24enum PiglitResult {
25    Pass,
26    Skip,
27    Fail,
28}
29
30impl Display for PiglitResult {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        write!(
33            f,
34            "{}",
35            match self {
36                PiglitResult::Pass => "pass",
37                PiglitResult::Skip => "skip",
38                PiglitResult::Fail => "fail",
39            }
40        )
41    }
42}
43
44fn piglit_result(result: PiglitResult) {
45    println!("PIGLIT: {{\"result\": \"{}\" }}", result);
46
47    std::process::exit(match result {
48        PiglitResult::Pass | PiglitResult::Skip => 0,
49        PiglitResult::Fail => 1,
50    });
51}
52
53fn piglit_subtest_result(name: &str, result: PiglitResult) {
54    println!(
55        "PIGLIT: {{\"subtest\": {{\"{name}\" : \"{result}\"}}}}",
56        name = name,
57        result = result
58    );
59}
60
61pub fn mock_piglit(mock: &MockPiglit) -> Result<()> {
62    if mock.test.contains("@pass") {
63        piglit_result(PiglitResult::Pass);
64    } else if mock.test.contains("@skip") {
65        piglit_result(PiglitResult::Skip);
66    } else if mock.test.contains("@fail") {
67        piglit_result(PiglitResult::Fail);
68    } else if mock.test.contains("@subtest_statuses") {
69        piglit_subtest_result("p", PiglitResult::Pass);
70        piglit_subtest_result("f", PiglitResult::Fail);
71        piglit_subtest_result("s", PiglitResult::Skip);
72        piglit_result(PiglitResult::Fail);
73    } else if mock.test.contains("@subtest_commas") {
74        piglit_subtest_result(
75            "GL_INTENSITY12, swizzled, border color only",
76            PiglitResult::Fail,
77        );
78        piglit_subtest_result(
79            "GL_INTENSITY16, swizzled, border color only",
80            PiglitResult::Fail,
81        );
82        piglit_result(PiglitResult::Fail);
83    } else if mock.test.contains("@subtest_dupe") {
84        piglit_subtest_result("subtest", PiglitResult::Pass);
85        piglit_subtest_result("subtest", PiglitResult::Pass);
86        piglit_result(PiglitResult::Pass);
87    } else if mock.test.contains("@flake") {
88        if rand::thread_rng().gen::<bool>() {
89            piglit_result(PiglitResult::Pass);
90        } else {
91            piglit_result(PiglitResult::Fail);
92        }
93    } else if mock.test.contains("@crash") {
94        panic!("crashing!")
95    } else if mock.test.contains("@late_crash") {
96        println!("PIGLIT: {{\"result\": \"pass\" }}");
97        std::io::stdout().flush().unwrap();
98        panic!("crashing!")
99    } else if mock.test.contains("@timeout") {
100        // Simulate a testcase that doesn't return in time by infinite
101        // looping.
102        #[allow(clippy::empty_loop)]
103        loop {}
104    }
105
106    panic!("Unknown test name");
107}