1use crate::cargo::{self, Metadata, PackageMetadata};
2use crate::dependencies::{self, Dependency, EditionOrInherit};
3use crate::directory::Directory;
4use crate::env::Update;
5use crate::error::{Error, Result};
6use crate::expand::{expand_globs, ExpandedTest};
7use crate::flock::Lock;
8use crate::manifest::{Bin, Manifest, Name, Package, Workspace};
9use crate::message::{self, Fail, Warn};
10use crate::normalize::{self, Context, Variations};
11use crate::path::CanonicalPath;
12use crate::{features, Expected, Runner, Test};
13use serde_derive::Deserialize;
14use std::collections::{BTreeMap as Map, BTreeSet as Set};
15use std::env;
16use std::ffi::{OsStr, OsString};
17use std::fs::{self, File};
18use std::mem;
19use std::path::{Path, PathBuf};
20use std::str;
21
22#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Project {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["dir", "source_dir", "target_dir", "name", "update", "has_pass",
"has_compile_fail", "features", "workspace",
"path_dependencies", "manifest", "keep_going"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.dir, &self.source_dir, &self.target_dir, &self.name,
&self.update, &self.has_pass, &self.has_compile_fail,
&self.features, &self.workspace, &self.path_dependencies,
&self.manifest, &&self.keep_going];
::core::fmt::Formatter::debug_struct_fields_finish(f, "Project",
names, values)
}
}Debug)]
23pub struct Project {
24 pub dir: Directory,
25 pub source_dir: Directory,
26 pub target_dir: Directory,
27 pub name: String,
28 pub update: Update,
29 pub has_pass: bool,
30 pub has_compile_fail: bool,
31 pub features: Option<Vec<String>>,
32 pub workspace: Directory,
33 pub path_dependencies: Vec<PathDependency>,
34 pub manifest: Manifest,
35 pub keep_going: bool,
36}
37
38#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PathDependency {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"PathDependency", "name", &self.name, "normalized_path",
&&self.normalized_path)
}
}Debug)]
39pub struct PathDependency {
40 pub name: String,
41 pub normalized_path: Directory,
42}
43
44struct Report {
45 failures: usize,
46 created_wip: usize,
47}
48
49impl Runner {
50 pub fn run(&mut self) {
51 let mut tests = expand_globs(&self.tests);
52 filter(&mut tests);
53
54 let (project, _lock) = (|| {
55 let mut project = self.prepare(&tests)?;
56 let lock = Lock::acquire({
let mut path = std::path::PathBuf::new();
path.push(&(project.dir));
path.push(&(".lock"));
path
}path!(project.dir / ".lock"))?;
57 self.write(&mut project)?;
58 Ok((project, lock))
59 })()
60 .unwrap_or_else(|err| {
61 message::prepare_fail(err);
62 { ::core::panicking::panic_fmt(format_args!("tests failed")); };panic!("tests failed");
63 });
64
65 {
use std::io::Write;
let _ = crate::term::lock().write_fmt(format_args!("\n\n"));
};print!("\n\n");
66
67 let len = tests.len();
68 let mut report = Report {
69 failures: 0,
70 created_wip: 0,
71 };
72
73 if tests.is_empty() {
74 message::no_tests_enabled();
75 } else if project.keep_going && !project.has_pass {
76 report = match self.run_all(&project, tests) {
77 Ok(failures) => failures,
78 Err(err) => {
79 message::test_fail(err);
80 Report {
81 failures: len,
82 created_wip: 0,
83 }
84 }
85 }
86 } else {
87 for test in tests {
88 match test.run(&project) {
89 Ok(Outcome::Passed) => {}
90 Ok(Outcome::CreatedWip) => report.created_wip += 1,
91 Err(err) => {
92 report.failures += 1;
93 message::test_fail(err);
94 }
95 }
96 }
97 }
98
99 {
use std::io::Write;
let _ = crate::term::lock().write_fmt(format_args!("\n\n"));
};print!("\n\n");
100
101 if report.failures > 0 && project.name != "trybuild-tests" {
102 {
::core::panicking::panic_fmt(format_args!("{0} of {1} tests failed",
report.failures, len));
};panic!("{} of {} tests failed", report.failures, len);
103 }
104 if report.created_wip > 0 && project.name != "trybuild-tests" {
105 {
::core::panicking::panic_fmt(format_args!("successfully created new stderr files for {0} test cases",
report.created_wip));
};panic!(
106 "successfully created new stderr files for {} test cases",
107 report.created_wip,
108 );
109 }
110 }
111
112 fn prepare(&self, tests: &[ExpandedTest]) -> Result<Project> {
113 let Metadata {
114 target_directory: target_dir,
115 workspace_root: workspace,
116 packages,
117 } = cargo::metadata()?;
118
119 let mut has_pass = false;
120 let mut has_compile_fail = false;
121 for e in tests {
122 match e.test.expected {
123 Expected::Pass => has_pass = true,
124 Expected::CompileFail => has_compile_fail = true,
125 }
126 }
127
128 let source_dir = cargo::manifest_dir()?;
129 let source_manifest = dependencies::get_manifest(&source_dir)?;
130
131 let mut features = features::find();
132
133 let path_dependencies = source_manifest
134 .dependencies
135 .iter()
136 .filter_map(|(name, dep)| {
137 let path = dep.path.as_ref()?;
138 if packages.iter().any(|p| &p.name == name) {
139 None
141 } else {
142 Some(PathDependency {
143 name: name.clone(),
144 normalized_path: path.canonicalize().ok()?,
145 })
146 }
147 })
148 .collect();
149
150 let crate_name = &source_manifest.package.name;
151 let project_dir = crate::directory::Directory::new({
let mut path = std::path::PathBuf::new();
path.push(&(target_dir));
path.push(&("tests"));
path.push(&("trybuild"));
path.push(&(crate_name));
path
})path!(target_dir / "tests" / "trybuild" / crate_name /);
152 fs::create_dir_all(&project_dir)?;
153
154 let project_name = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}-tests", crate_name))
})format!("{}-tests", crate_name);
155 let manifest = Self::make_manifest(
156 &workspace,
157 &project_name,
158 &source_dir,
159 &packages,
160 tests,
161 source_manifest,
162 )?;
163
164 if let Some(enabled_features) = &mut features {
165 enabled_features.retain(|feature| manifest.features.contains_key(feature));
166 }
167
168 Ok(Project {
169 dir: project_dir,
170 source_dir,
171 target_dir,
172 name: project_name,
173 update: Update::env()?,
174 has_pass,
175 has_compile_fail,
176 features,
177 workspace,
178 path_dependencies,
179 manifest,
180 keep_going: false,
181 })
182 }
183
184 fn write(&self, project: &mut Project) -> Result<()> {
185 let manifest_toml = toml::to_string(&project.manifest)?;
186 fs::write({
let mut path = std::path::PathBuf::new();
path.push(&(project.dir));
path.push(&("Cargo.toml"));
path
}path!(project.dir / "Cargo.toml"), manifest_toml)?;
187
188 let main_rs = b"\
189 #![allow(unused_crate_dependencies, missing_docs)]\n\
190 fn main() {}\n\
191 ";
192 fs::write({
let mut path = std::path::PathBuf::new();
path.push(&(project.dir));
path.push(&("main.rs"));
path
}path!(project.dir / "main.rs"), &main_rs[..])?;
193
194 cargo::build_dependencies(project)?;
195
196 Ok(())
197 }
198
199 pub fn make_manifest(
200 workspace: &Directory,
201 project_name: &str,
202 source_dir: &Directory,
203 packages: &[PackageMetadata],
204 tests: &[ExpandedTest],
205 source_manifest: dependencies::Manifest,
206 ) -> Result<Manifest> {
207 let crate_name = source_manifest.package.name;
208 let workspace_manifest = dependencies::get_workspace_manifest(workspace);
209
210 let edition = match source_manifest.package.edition {
211 EditionOrInherit::Edition(edition) => edition,
212 EditionOrInherit::Inherit => workspace_manifest
213 .workspace
214 .package
215 .edition
216 .ok_or(Error::NoWorkspaceManifest)?,
217 };
218
219 let mut dependencies = Map::new();
220 dependencies.extend(source_manifest.dependencies);
221 dependencies.extend(source_manifest.dev_dependencies);
222
223 let cargo_toml_path = source_dir.join("Cargo.toml");
224 let mut has_lib_target = true;
225 for package_metadata in packages {
226 if package_metadata.manifest_path == cargo_toml_path {
227 has_lib_target = package_metadata
228 .targets
229 .iter()
230 .any(|target| target.crate_types != ["bin"]);
231 }
232 }
233 if has_lib_target {
234 dependencies.insert(
235 crate_name.clone(),
236 Dependency {
237 version: None,
238 path: Some(source_dir.clone()),
239 optional: false,
240 default_features: Some(false),
241 features: Vec::new(),
242 git: None,
243 branch: None,
244 tag: None,
245 rev: None,
246 workspace: false,
247 rest: Map::new(),
248 },
249 );
250 }
251
252 let mut targets = source_manifest.target;
253 for target in targets.values_mut() {
254 let dev_dependencies = mem::take(&mut target.dev_dependencies);
255 target.dependencies.extend(dev_dependencies);
256 }
257
258 let mut features = source_manifest.features;
259 for (feature, enables) in &mut features {
260 enables.retain(|en| {
261 let Some(dep_name) = en.strip_prefix("dep:") else {
262 return false;
263 };
264 if let Some(Dependency { optional: true, .. }) = dependencies.get(dep_name) {
265 return true;
266 }
267 for target in targets.values() {
268 if let Some(Dependency { optional: true, .. }) =
269 target.dependencies.get(dep_name)
270 {
271 return true;
272 }
273 }
274 false
275 });
276 if has_lib_target {
277 enables.insert(0, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}/{1}", crate_name, feature))
})format!("{}/{}", crate_name, feature));
278 }
279 }
280
281 let mut manifest = Manifest {
282 cargo_features: source_manifest.cargo_features,
283 package: Package {
284 name: project_name.to_owned(),
285 version: "0.0.0".to_owned(),
286 edition,
287 resolver: source_manifest.package.resolver,
288 publish: false,
289 },
290 features,
291 dependencies,
292 target: targets,
293 bins: Vec::new(),
294 workspace: Some(Workspace {
295 dependencies: workspace_manifest.workspace.dependencies,
296 }),
297 patch: workspace_manifest.patch,
300 replace: workspace_manifest.replace,
301 profile: workspace_manifest.profile,
302 };
303
304 manifest.bins.push(Bin {
305 name: Name(project_name.to_owned()),
306 path: Path::new("main.rs").to_owned(),
307 });
308
309 for expanded in tests {
310 if expanded.error.is_none() {
311 manifest.bins.push(Bin {
312 name: expanded.name.clone(),
313 path: source_dir.join(&expanded.test.path),
314 });
315 }
316 }
317
318 Ok(manifest)
319 }
320
321 fn run_all(&self, project: &Project, tests: Vec<ExpandedTest>) -> Result<Report> {
322 let mut report = Report {
323 failures: 0,
324 created_wip: 0,
325 };
326
327 let mut path_map = Map::new();
328 for t in &tests {
329 let src_path = CanonicalPath::new(&project.source_dir.join(&t.test.path));
330 path_map.insert(src_path, (&t.name, &t.test));
331 }
332
333 let output = cargo::build_all_tests(project)?;
334 let parsed = parse_cargo_json(project, &output.stdout, &path_map);
335 let fallback = Stderr::default();
336
337 for mut t in tests {
338 let show_expected = false;
339 message::begin_test(&t.test, show_expected);
340
341 if t.error.is_none() {
342 t.error = check_exists(&t.test.path).err();
343 }
344
345 if t.error.is_none() {
346 let src_path = CanonicalPath::new(&project.source_dir.join(&t.test.path));
347 let this_test = parsed.stderrs.get(&src_path).unwrap_or(&fallback);
348 match t.test.check(project, &t.name, this_test, "") {
349 Ok(Outcome::Passed) => {}
350 Ok(Outcome::CreatedWip) => report.created_wip += 1,
351 Err(error) => t.error = Some(error),
352 }
353 }
354
355 if let Some(err) = t.error {
356 report.failures += 1;
357 message::test_fail(err);
358 }
359 }
360
361 Ok(report)
362 }
363}
364
365enum Outcome {
366 Passed,
367 CreatedWip,
368}
369
370impl Test {
371 fn run(&self, project: &Project, name: &Name) -> Result<Outcome> {
372 let show_expected = project.has_pass && project.has_compile_fail;
373 message::begin_test(self, show_expected);
374 check_exists(&self.path)?;
375
376 let mut path_map = Map::new();
377 let src_path = CanonicalPath::new(&project.source_dir.join(&self.path));
378 path_map.insert(src_path.clone(), (name, self));
379
380 let output = cargo::build_test(project, name)?;
381 let parsed = parse_cargo_json(project, &output.stdout, &path_map);
382 let fallback = Stderr::default();
383 let this_test = parsed.stderrs.get(&src_path).unwrap_or(&fallback);
384 self.check(project, name, this_test, &parsed.stdout)
385 }
386
387 fn check(
388 &self,
389 project: &Project,
390 name: &Name,
391 result: &Stderr,
392 build_stdout: &str,
393 ) -> Result<Outcome> {
394 let check = match self.expected {
395 Expected::Pass => Test::check_pass,
396 Expected::CompileFail => Test::check_compile_fail,
397 };
398
399 check(
400 self,
401 project,
402 name,
403 result.success,
404 build_stdout,
405 &result.stderr,
406 )
407 }
408
409 fn check_pass(
410 &self,
411 project: &Project,
412 name: &Name,
413 success: bool,
414 build_stdout: &str,
415 variations: &Variations,
416 ) -> Result<Outcome> {
417 let preferred = variations.preferred();
418 if !success {
419 message::failed_to_build(preferred);
420 return Err(Error::CargoFail);
421 }
422
423 let mut output = cargo::run_test(project, name)?;
424 output.stdout.splice(..0, build_stdout.bytes());
425 message::output(preferred, &output);
426 if output.status.success() {
427 Ok(Outcome::Passed)
428 } else {
429 Err(Error::RunFailed)
430 }
431 }
432
433 fn check_compile_fail(
434 &self,
435 project: &Project,
436 _name: &Name,
437 success: bool,
438 build_stdout: &str,
439 variations: &Variations,
440 ) -> Result<Outcome> {
441 let preferred = variations.preferred();
442
443 if success {
444 message::should_not_have_compiled();
445 message::fail_output(Fail, build_stdout);
446 message::warnings(preferred);
447 return Err(Error::ShouldNotHaveCompiled);
448 }
449
450 let stderr_path = self.path.with_extension("stderr");
451
452 if !stderr_path.exists() {
453 let outcome = match project.update {
454 Update::Wip => {
455 let wip_dir = Path::new("wip");
456 fs::create_dir_all(wip_dir)?;
457 let gitignore_path = wip_dir.join(".gitignore");
458 fs::write(gitignore_path, "*\n")?;
459 let stderr_name = stderr_path
460 .file_name()
461 .unwrap_or_else(|| OsStr::new("test.stderr"));
462 let wip_path = wip_dir.join(stderr_name);
463 message::write_stderr_wip(&wip_path, &stderr_path, preferred);
464 fs::write(wip_path, preferred).map_err(Error::WriteStderr)?;
465 Outcome::CreatedWip
466 }
467 Update::Overwrite => {
468 message::overwrite_stderr(&stderr_path, preferred);
469 fs::write(stderr_path, preferred).map_err(Error::WriteStderr)?;
470 Outcome::Passed
471 }
472 };
473 message::fail_output(Warn, build_stdout);
474 return Ok(outcome);
475 }
476
477 let expected = fs::read_to_string(&stderr_path)
478 .map_err(Error::ReadStderr)?
479 .replace("\r\n", "\n");
480
481 if variations.any(|stderr| expected == stderr) {
482 message::ok();
483 return Ok(Outcome::Passed);
484 }
485
486 match project.update {
487 Update::Wip => {
488 message::mismatch(&expected, preferred);
489 Err(Error::Mismatch)
490 }
491 Update::Overwrite => {
492 message::overwrite_stderr(&stderr_path, preferred);
493 fs::write(stderr_path, preferred).map_err(Error::WriteStderr)?;
494 Ok(Outcome::Passed)
495 }
496 }
497 }
498}
499
500fn check_exists(path: &Path) -> Result<()> {
501 if path.exists() {
502 return Ok(());
503 }
504 match File::open(path) {
505 Ok(_) => Ok(()),
506 Err(err) => Err(Error::Open(path.to_owned(), err)),
507 }
508}
509
510impl ExpandedTest {
511 fn run(self, project: &Project) -> Result<Outcome> {
512 match self.error {
513 None => self.test.run(project, &self.name),
514 Some(error) => {
515 let show_expected = false;
516 message::begin_test(&self.test, show_expected);
517 Err(error)
518 }
519 }
520 }
521}
522
523#[allow(clippy::needless_collect)] fn filter(tests: &mut Vec<ExpandedTest>) {
534 let filters = env::args_os()
535 .flat_map(OsString::into_string)
536 .filter_map(|mut arg| {
537 const PREFIX: &str = "trybuild=";
538 if arg.starts_with(PREFIX) && arg != PREFIX {
539 Some(arg.split_off(PREFIX.len()))
540 } else {
541 None
542 }
543 })
544 .collect::<Vec<String>>();
545
546 if filters.is_empty() {
547 return;
548 }
549
550 tests.retain(|t| {
551 filters
552 .iter()
553 .any(|f| t.test.path.to_string_lossy().contains(f))
554 });
555}
556
557#[derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for CargoMessage {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __field2, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"reason" => _serde::__private228::Ok(__Field::__field0),
"target" => _serde::__private228::Ok(__Field::__field1),
"message" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"reason" => _serde::__private228::Ok(__Field::__field0),
b"target" => _serde::__private228::Ok(__Field::__field1),
b"message" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<CargoMessage>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = CargoMessage;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct CargoMessage")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<Reason>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct CargoMessage with 3 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<RustcTarget>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct CargoMessage with 3 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<RustcMessage>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct CargoMessage with 3 elements")),
};
_serde::__private228::Ok(CargoMessage {
reason: __field0,
target: __field1,
message: __field2,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<Reason> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<RustcTarget> =
_serde::__private228::None;
let mut __field2:
_serde::__private228::Option<RustcMessage> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("reason"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<Reason>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("target"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<RustcTarget>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("message"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<RustcMessage>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("reason")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("target")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("message")?,
};
_serde::__private228::Ok(CargoMessage {
reason: __field0,
target: __field1,
message: __field2,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["reason", "target", "message"];
_serde::Deserializer::deserialize_struct(__deserializer,
"CargoMessage", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<CargoMessage>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
558struct CargoMessage {
559 #[allow(dead_code)]
560 reason: Reason,
561 target: RustcTarget,
562 message: RustcMessage,
563}
564
565#[derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for Reason {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"variant identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
_ =>
_serde::__private228::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 1")),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"compiler-message" =>
_serde::__private228::Ok(__Field::__field0),
_ => {
_serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
VARIANTS))
}
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"compiler-message" =>
_serde::__private228::Ok(__Field::__field0),
_ => {
let __value =
&_serde::__private228::from_utf8_lossy(__value);
_serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
VARIANTS))
}
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<Reason>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = Reason;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"enum Reason")
}
fn visit_enum<__A>(self, __data: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::EnumAccess<'de> {
match _serde::de::EnumAccess::variant(__data)? {
(__Field::__field0, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(Reason::CompilerMessage)
}
}
}
}
#[doc(hidden)]
const VARIANTS: &'static [&'static str] =
&["compiler-message"];
_serde::Deserializer::deserialize_enum(__deserializer,
"Reason", VARIANTS,
__Visitor {
marker: _serde::__private228::PhantomData::<Reason>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
566enum Reason {
567 #[serde(rename = "compiler-message")]
568 CompilerMessage,
569}
570
571#[derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for RustcTarget {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"src_path" => _serde::__private228::Ok(__Field::__field0),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"src_path" => _serde::__private228::Ok(__Field::__field0),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<RustcTarget>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = RustcTarget;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct RustcTarget")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<PathBuf>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct RustcTarget with 1 element")),
};
_serde::__private228::Ok(RustcTarget { src_path: __field0 })
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<PathBuf> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("src_path"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<PathBuf>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("src_path")?,
};
_serde::__private228::Ok(RustcTarget { src_path: __field0 })
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &["src_path"];
_serde::Deserializer::deserialize_struct(__deserializer,
"RustcTarget", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<RustcTarget>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
572struct RustcTarget {
573 src_path: PathBuf,
574}
575
576#[derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for RustcMessage {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"rendered" => _serde::__private228::Ok(__Field::__field0),
"level" => _serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"rendered" => _serde::__private228::Ok(__Field::__field0),
b"level" => _serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<RustcMessage>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = RustcMessage;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct RustcMessage")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct RustcMessage with 2 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct RustcMessage with 2 elements")),
};
_serde::__private228::Ok(RustcMessage {
rendered: __field0,
level: __field1,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field1: _serde::__private228::Option<String> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("rendered"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("level"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("rendered")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("level")?,
};
_serde::__private228::Ok(RustcMessage {
rendered: __field0,
level: __field1,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["rendered", "level"];
_serde::Deserializer::deserialize_struct(__deserializer,
"RustcMessage", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<RustcMessage>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
577struct RustcMessage {
578 rendered: String,
579 level: String,
580}
581
582struct ParsedOutputs {
583 stdout: String,
584 stderrs: Map<CanonicalPath, Stderr>,
585}
586
587struct Stderr {
588 success: bool,
589 stderr: Variations,
590}
591
592impl Default for Stderr {
593 fn default() -> Self {
594 Stderr {
595 success: true,
596 stderr: Variations::default(),
597 }
598 }
599}
600
601fn parse_cargo_json(
602 project: &Project,
603 stdout: &[u8],
604 path_map: &Map<CanonicalPath, (&Name, &Test)>,
605) -> ParsedOutputs {
606 let mut map = Map::new();
607 let mut nonmessage_stdout = String::new();
608 let mut remaining = &*String::from_utf8_lossy(stdout);
609 let mut seen = Set::new();
610 while !remaining.is_empty() {
611 let Some(begin) = remaining.find("{\"reason\":") else {
612 break;
613 };
614 let (nonmessage, rest) = remaining.split_at(begin);
615 nonmessage_stdout.push_str(nonmessage);
616 let len = match rest.find('\n') {
617 Some(end) => end + 1,
618 None => rest.len(),
619 };
620 let (message, rest) = rest.split_at(len);
621 remaining = rest;
622 if !seen.insert(message) {
623 continue;
628 }
629 if let Ok(de) = serde_json::from_str::<CargoMessage>(message) {
630 if de.message.level != "failure-note" {
631 let src_path = CanonicalPath::new(&de.target.src_path);
632 let Some((name, test)) = path_map.get(&src_path) else {
633 continue;
634 };
635 let entry = map.entry(src_path).or_insert_with(Stderr::default);
636 if de.message.level == "error" {
637 entry.success = false;
638 }
639 let normalized = normalize::diagnostics(
640 &de.message.rendered,
641 Context {
642 krate: &name.0,
643 source_dir: &project.source_dir,
644 workspace: &project.workspace,
645 input_file: &test.path,
646 target_dir: &project.target_dir,
647 path_dependencies: &project.path_dependencies,
648 },
649 );
650 entry.stderr.concat(&normalized);
651 }
652 }
653 }
654 nonmessage_stdout.push_str(remaining);
655 ParsedOutputs {
656 stdout: nonmessage_stdout,
657 stderrs: map,
658 }
659}