trybuild_internals_api/
run.rs

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                    // Skip path dependencies coming from the workspace itself
140                    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            // Within a workspace, only the [patch] / [replace] / [profile] sections in
298            // the workspace root's Cargo.toml are applied by Cargo.
299            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// Filter which test cases are run by trybuild.
524//
525//     $ cargo test -- ui trybuild=tuple_structs.rs
526//
527// The first argument after `--` must be the trybuild test name i.e. the name of
528// the function that has the #[test] attribute and calls trybuild. That's to get
529// Cargo to run the test at all. The next argument starting with `trybuild=`
530// provides a filename filter. Only test cases whose filename contains the
531// filter string will be run.
532#[allow(clippy::needless_collect)] // false positive https://github.com/rust-lang/rust-clippy/issues/5991
533fn 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            // Discard duplicate messages. This might no longer be necessary
624            // after https://github.com/rust-lang/rust/issues/106571 is fixed.
625            // Normally rustc would filter duplicates itself and I think this is
626            // a short-lived bug.
627            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}