deqp_runner/
piglit_command.rs

1//! Module for invoking [piglit](https://piglit.freedesktop.org/) tests.
2
3use crate::parse::ResultParser;
4use crate::parse_piglit::{parse_piglit_xml_testlist, read_profile_file, PiglitResultParser};
5use crate::timeout::{TimeoutChildStdout, Timer};
6use crate::{runner_results::*, runner_thread_index, FailCounter, SubRunConfig, TestConfiguration};
7use crate::{CaselistResult, SingleBinaryTestCommand, SingleTestCommand, TestCase, TestCommand};
8use anyhow::{Context, Result};
9use log::*;
10use serde::Deserialize;
11use std::path::{Path, PathBuf};
12use std::process::{Command, Stdio};
13use structopt::StructOpt;
14
15pub struct PiglitCommand {
16    pub config: TestConfiguration,
17    pub piglit_folder: PathBuf,
18    pub prefix: String,
19}
20
21// Common structure for configuring a piglit run between Run (single run) and deqp-runner Suite (muliple Runs)
22#[derive(Debug, Deserialize, StructOpt)]
23pub struct PiglitRunConfig {
24    #[structopt(long, help = "path to piglit folder")]
25    pub piglit_folder: PathBuf,
26
27    #[structopt(long, help = "piglit profile to run (such as quick_gl)")]
28    pub profile: String,
29
30    #[structopt(long = "process-isolation")]
31    #[serde(default)]
32    pub process_isolation: bool,
33}
34
35#[derive(Deserialize)]
36pub struct PiglitTomlConfig {
37    #[serde(flatten)]
38    pub sub_config: SubRunConfig,
39
40    #[serde(flatten)]
41    pub piglit_config: PiglitRunConfig,
42
43    #[serde(default)]
44    pub prefix: String,
45}
46
47impl PiglitTomlConfig {
48    pub fn test_groups<'d>(
49        &self,
50        piglit: &'d PiglitCommand,
51        filters: &[String],
52    ) -> Result<Vec<(&'d dyn TestCommand, Vec<TestCase>)>> {
53        let test_folder = self.piglit_config.piglit_folder.join("tests");
54        let text = read_profile_file(
55            &test_folder,
56            &self.piglit_config.profile,
57            self.piglit_config.process_isolation,
58        )?;
59        let tests: Vec<TestCase> =
60            parse_piglit_xml_testlist(&test_folder, &text, self.piglit_config.process_isolation)
61                .with_context(|| {
62                    format!("reading piglit profile '{}'", &self.piglit_config.profile)
63                })?;
64
65        piglit.test_groups(&self.sub_config, filters, tests)
66    }
67}
68
69impl SingleTestCommand for PiglitCommand {}
70impl SingleBinaryTestCommand for PiglitCommand {}
71
72impl TestCommand for PiglitCommand {
73    fn name(&self) -> &str {
74        "Piglit"
75    }
76
77    fn prepare(&self, _caselist_state: &CaselistState, tests: &[&TestCase]) -> Result<Command> {
78        let test = self.current_test(tests);
79        let mut bin_path = self.piglit_folder.clone();
80        bin_path.push("bin");
81
82        let mut command = Command::new(bin_path.join(Path::new(&test.binary)));
83        command
84            .current_dir(&self.piglit_folder)
85            .stdout(Stdio::piped())
86            .stderr(Stdio::piped())
87            .stdin(Stdio::null())
88            .args(&test.args)
89            .env("MESA_DEBUG", "silent")
90            .env("DEQP_RUNNER_THREAD", runner_thread_index()?.to_string())
91            .env("PIGLIT_SOURCE_DIR", &self.piglit_folder)
92            .envs(self.config.env.iter());
93
94        debug!("Begin test {}", test.name);
95        Ok(command)
96    }
97
98    fn clean(
99        &self,
100        _caselist_state: &CaselistState,
101        tests: &[&TestCase],
102        _results: &[RunnerResult],
103    ) -> Result<()> {
104        let test = self.current_test(tests);
105        debug!("End test {}", test.name);
106        Ok(())
107    }
108
109    fn parse_results(
110        &self,
111        _caselist_state: &CaselistState,
112        tests: &[&TestCase],
113        stdout: TimeoutChildStdout,
114        timer: Option<Timer>,
115        fail_counter: Option<FailCounter>,
116    ) -> Result<CaselistResult> {
117        let test = self.current_test(tests);
118        let parser = PiglitResultParser::new(&test.name);
119        parser.parse_with_timer(stdout, timer, fail_counter)
120    }
121
122    fn should_save_log(&self, _caselist_state: &CaselistState, tests: &[&TestCase]) -> bool {
123        let test = self.current_test(tests);
124        test.name.contains("glinfo")
125    }
126
127    fn log_path(&self, _caselist_state: &CaselistState, tests: &[&TestCase]) -> Result<PathBuf> {
128        let test = self.current_test(tests);
129        Ok(self
130            .config
131            .output_dir
132            .join(format!("piglit.{}.log", test.name).as_str()))
133    }
134
135    fn see_more(&self, test_name: &str, _caselist_state: &CaselistState) -> String {
136        let log_path = self
137            .config
138            .output_dir
139            .join(format!("piglit.{}.log", test_name).as_str());
140        format!("See {:?}", log_path)
141    }
142
143    fn config(&self) -> &TestConfiguration {
144        &self.config
145    }
146
147    fn prefix(&self) -> &str {
148        &self.prefix
149    }
150}