deqp_runner/
skqp_command.rs1use crate::parse::ResultParser;
2use crate::parse_skqp::{skqp_parse_testlist_file, SkqpResultParser, SkqpTestFile};
3use crate::timeout::{TimeoutChildStdout, Timer};
4use crate::{
5 runner_results::*, Caselist, FailCounter, SubRunConfig, TestConfiguration, TestGroups,
6};
7use crate::{CaselistResult, SingleNamedTestCommand, SingleTestCommand, TestCase, TestCommand};
8use anyhow::{Context, Result};
9use log::*;
10use serde::Deserialize;
11use std::path::{Path, PathBuf};
12use std::process::{Command, Stdio};
13use std::{fs, str};
14use structopt::StructOpt;
15
16pub struct SkqpCommand {
17 pub skqp: PathBuf,
18 pub config: TestConfiguration,
19 pub skqp_assets: PathBuf,
20}
21
22#[derive(Debug, Deserialize, StructOpt)]
24pub struct SkqpRunConfig {
25 #[structopt(long, help = "path to skqp binary")]
26 pub skqp: PathBuf,
27
28 #[structopt(
29 long,
30 help = "path to skia/platform_tools/android/apps/skqp/src/main/assets"
31 )]
32 pub skqp_assets: PathBuf,
33}
34
35#[derive(Deserialize)]
36pub struct SkqpTomlConfig {
37 #[serde(flatten)]
38 pub sub_config: SubRunConfig,
39
40 #[serde(flatten)]
41 pub skqp_config: SkqpRunConfig,
42}
43
44fn skqp_get_test_list(skqp_assets: &Path) -> Result<Vec<TestCase>> {
45 let rendertests_path = skqp_assets
46 .join("skqp")
47 .join(SkqpTestFile::RenderTest.to_string());
48
49 let rendertests = std::fs::read_to_string(&rendertests_path)
50 .with_context(|| format!("reading {:?}", rendertests_path))?;
51 let rendertests = skqp_parse_testlist_file(&rendertests).context("parsing render tests")?;
52
53 let mut test_list = Vec::new();
54 for test in rendertests {
55 for backend in &["gl", "gles", "vk"] {
56 test_list.push(TestCase::Named(format!("{}_{}", backend, test)));
57 }
58 }
59
60 let unittests_path = skqp_assets
61 .join("skqp")
62 .join(SkqpTestFile::UnitTest.to_string());
63
64 let unittests = std::fs::read_to_string(&unittests_path)
65 .with_context(|| format!("reading {:?}", unittests_path))?;
66 let unittests = skqp_parse_testlist_file(&unittests)?;
67 for test in unittests {
68 test_list.push(TestCase::Named(test.to_owned()));
69 }
70
71 Ok(test_list)
72}
73
74impl SkqpTomlConfig {
75 pub fn test_groups<'d>(&self, skqp: &'d SkqpCommand) -> Result<TestGroups<'d>> {
76 let tests: Vec<TestCase> = skqp_get_test_list(&self.skqp_config.skqp_assets)
77 .with_context(|| "Collecting skqp tests")?;
78
79 skqp.test_groups(tests)
80 }
81}
82
83#[derive(Debug, Eq, PartialEq, Clone)]
84pub struct SkqpTest {
85 pub name: String,
86}
87
88impl SkqpCommand {
89 fn skqp_output_dir_path(&self, test_name: &str, caselist: &Caselist) -> Result<PathBuf> {
90 Ok(self
91 .config
92 .output_dir
93 .join(format!("{}.r{}", test_name, caselist.caselist_id)))
94 }
95}
96
97impl SingleTestCommand for SkqpCommand {}
98impl SingleNamedTestCommand for SkqpCommand {}
99
100impl TestCommand for SkqpCommand {
101 fn name(&self) -> &str {
102 "Skqp"
103 }
104
105 fn prepare(&self, caselist: &Caselist) -> Result<Command> {
106 let test = self.current_test(caselist);
107
108 let test_output_dir = self.skqp_output_dir_path(test, caselist)?;
109 fs::create_dir_all(test_output_dir.to_str().unwrap())?;
110
111 let mut command = Command::new(&self.skqp);
112 command
113 .current_dir(&self.skqp_assets)
114 .stdout(Stdio::piped())
115 .stderr(Stdio::piped())
116 .stdin(Stdio::null())
117 .args(vec![
118 self.skqp_assets.to_str().unwrap(),
119 test_output_dir.canonicalize()?.to_str().unwrap(),
120 test,
121 ])
122 .envs(self.config.env.iter());
123
124 Ok(command)
125 }
126
127 fn clean(&self, caselist: &Caselist, results: &[RunnerResult]) -> Result<()> {
128 let test = self.current_test(caselist);
129 let test_output_dir = self.skqp_output_dir_path(test, caselist)?;
130
131 if !results.is_empty()
132 && results
133 .iter()
134 .all(|x| !x.status.should_save_logs(self.config.save_xfail_logs))
135 {
136 if let Err(e) = std::fs::remove_dir_all(&test_output_dir)
137 .with_context(|| format!("removing caselist at {:?}", &test_output_dir))
138 {
139 error!("{:?}", e);
140 }
141 }
142
143 Ok(())
144 }
145
146 fn parse_results(
147 &self,
148 caselist: &Caselist,
149 stdout: TimeoutChildStdout,
150 timer: Option<Timer>,
151 fail_counter: Option<FailCounter>,
152 ) -> Result<CaselistResult> {
153 let test = self.current_test(caselist);
154 let parser = SkqpResultParser::new(test);
155 parser.parse_with_timer(stdout, timer, fail_counter)
156 }
157
158 fn see_more(&self, caselist: &Caselist) -> String {
159 let test_name = self.current_test(caselist);
160 let test_output_dir = self.skqp_output_dir_path(test_name, caselist).unwrap();
161
162 format!(
163 "See {:?} and {:?}",
164 self.log_path(caselist),
165 test_output_dir.to_str().unwrap()
166 )
167 }
168
169 fn config(&self) -> &TestConfiguration {
170 &self.config
171 }
172}