nextest_runner/config/
global_timeout.rs1use serde::{Deserialize, Deserializer};
5use std::time::Duration;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub struct GlobalTimeout {
10 pub(crate) period: Duration,
11}
12
13impl<'de> Deserialize<'de> for GlobalTimeout {
14 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
15 where
16 D: Deserializer<'de>,
17 {
18 Ok(GlobalTimeout {
19 period: humantime_serde::deserialize(deserializer)?,
20 })
21 }
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use crate::config::{
28 NextestConfig,
29 test_helpers::{build_platforms, temp_workspace},
30 };
31 use camino_tempfile::tempdir;
32 use indoc::indoc;
33 use nextest_filtering::ParseContext;
34 use test_case::test_case;
35
36 #[test_case(
37 "",
38 Ok(GlobalTimeout { period: Duration::from_secs(946728000) }),
39 None
40
41 ; "empty config is expected to use the hardcoded values"
42 )]
43 #[test_case(
44 indoc! {r#"
45 [profile.default]
46 global-timeout = "30s"
47 "#},
48 Ok(GlobalTimeout { period: Duration::from_secs(30) }),
49 None
50
51 ; "overrides the default profile"
52 )]
53 #[test_case(
54 indoc! {r#"
55 [profile.default]
56 global-timeout = "30s"
57
58 [profile.ci]
59 global-timeout = "60s"
60 "#},
61 Ok(GlobalTimeout { period: Duration::from_secs(30) }),
62 Some(GlobalTimeout { period: Duration::from_secs(60) })
63
64 ; "adds a custom profile 'ci'"
65 )]
66 fn globaltimeout_adheres_to_hierarchy(
67 config_contents: &str,
68 expected_default: Result<GlobalTimeout, &str>,
69 maybe_expected_ci: Option<GlobalTimeout>,
70 ) {
71 let workspace_dir = tempdir().unwrap();
72
73 let graph = temp_workspace(&workspace_dir, config_contents);
74
75 let pcx = ParseContext::new(&graph);
76
77 let nextest_config_result = NextestConfig::from_sources(
78 graph.workspace().root(),
79 &pcx,
80 None,
81 &[][..],
82 &Default::default(),
83 );
84
85 match expected_default {
86 Ok(expected_default) => {
87 let nextest_config = nextest_config_result.expect("config file should parse");
88
89 assert_eq!(
90 nextest_config
91 .profile("default")
92 .expect("default profile should exist")
93 .apply_build_platforms(&build_platforms())
94 .global_timeout(),
95 expected_default,
96 );
97
98 if let Some(expected_ci) = maybe_expected_ci {
99 assert_eq!(
100 nextest_config
101 .profile("ci")
102 .expect("ci profile should exist")
103 .apply_build_platforms(&build_platforms())
104 .global_timeout(),
105 expected_ci,
106 );
107 }
108 }
109
110 Err(expected_err_str) => {
111 let err_str = format!("{:?}", nextest_config_result.unwrap_err());
112
113 assert!(
114 err_str.contains(expected_err_str),
115 "expected error string not found: {err_str}",
116 )
117 }
118 }
119 }
120}