nextest_runner/config/elements/
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::{core::NextestConfig, utils::test_helpers::*};
28 use camino_tempfile::tempdir;
29 use indoc::indoc;
30 use nextest_filtering::ParseContext;
31 use test_case::test_case;
32
33 #[test_case(
34 "",
35 Ok(GlobalTimeout { period: Duration::from_secs(946728000) }),
36 None
37
38 ; "empty config is expected to use the hardcoded values"
39 )]
40 #[test_case(
41 indoc! {r#"
42 [profile.default]
43 global-timeout = "30s"
44 "#},
45 Ok(GlobalTimeout { period: Duration::from_secs(30) }),
46 None
47
48 ; "overrides the default profile"
49 )]
50 #[test_case(
51 indoc! {r#"
52 [profile.default]
53 global-timeout = "30s"
54
55 [profile.ci]
56 global-timeout = "60s"
57 "#},
58 Ok(GlobalTimeout { period: Duration::from_secs(30) }),
59 Some(GlobalTimeout { period: Duration::from_secs(60) })
60
61 ; "adds a custom profile 'ci'"
62 )]
63 fn globaltimeout_adheres_to_hierarchy(
64 config_contents: &str,
65 expected_default: Result<GlobalTimeout, &str>,
66 maybe_expected_ci: Option<GlobalTimeout>,
67 ) {
68 let workspace_dir = tempdir().unwrap();
69
70 let graph = temp_workspace(&workspace_dir, config_contents);
71
72 let pcx = ParseContext::new(&graph);
73
74 let nextest_config_result = NextestConfig::from_sources(
75 graph.workspace().root(),
76 &pcx,
77 None,
78 &[][..],
79 &Default::default(),
80 );
81
82 match expected_default {
83 Ok(expected_default) => {
84 let nextest_config = nextest_config_result.expect("config file should parse");
85
86 assert_eq!(
87 nextest_config
88 .profile("default")
89 .expect("default profile should exist")
90 .apply_build_platforms(&build_platforms())
91 .global_timeout(),
92 expected_default,
93 );
94
95 if let Some(expected_ci) = maybe_expected_ci {
96 assert_eq!(
97 nextest_config
98 .profile("ci")
99 .expect("ci profile should exist")
100 .apply_build_platforms(&build_platforms())
101 .global_timeout(),
102 expected_ci,
103 );
104 }
105 }
106
107 Err(expected_err_str) => {
108 let err_str = format!("{:?}", nextest_config_result.unwrap_err());
109
110 assert!(
111 err_str.contains(expected_err_str),
112 "expected error string not found: {err_str}",
113 )
114 }
115 }
116 }
117}