|
1 | 1 | use crate::binary_pins::{ |
2 | | - Arch, DistroVersion, PinnedBinary, VALGRIND_CODSPEED_VERSION, VALGRIND_CODSPEED_VERSION_STRING, |
3 | | - ValgrindTarget, |
| 2 | + Arch, DistroVersion, PinnedBinary, VALGRIND_CODSPEED_ITERATION, VALGRIND_CODSPEED_VERSION, |
| 3 | + VALGRIND_CODSPEED_VERSION_STRING, ValgrindTarget, |
4 | 4 | }; |
5 | 5 | use crate::cli::run::helpers::download_pinned_file; |
6 | 6 | use crate::executor::helpers::apt; |
@@ -126,45 +126,47 @@ pub fn get_valgrind_status() -> ToolStatus { |
126 | 126 | .trim() |
127 | 127 | .to_string(); |
128 | 128 |
|
| 129 | + ToolStatus { |
| 130 | + tool_name, |
| 131 | + status: classify_valgrind_version(version), |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +/// Classify a trimmed `valgrind --version` output against the pinned CodSpeed |
| 136 | +/// valgrind version. |
| 137 | +fn classify_valgrind_version(version: String) -> ToolInstallStatus { |
129 | 138 | // Check if it's a codspeed version |
130 | 139 | if !version.contains(".codspeed") { |
131 | | - return ToolStatus { |
132 | | - tool_name, |
133 | | - status: ToolInstallStatus::IncorrectVersion { |
134 | | - version, |
135 | | - message: "not a CodSpeed build".to_string(), |
136 | | - }, |
| 140 | + return ToolInstallStatus::IncorrectVersion { |
| 141 | + version, |
| 142 | + message: "not a CodSpeed build".to_string(), |
137 | 143 | }; |
138 | 144 | } |
139 | 145 |
|
140 | 146 | // Parse the installed version |
141 | 147 | let Some(installed_version) = parse_valgrind_codspeed_version(&version) else { |
142 | | - return ToolStatus { |
143 | | - tool_name, |
144 | | - status: ToolInstallStatus::IncorrectVersion { |
145 | | - version, |
146 | | - message: "could not parse version".to_string(), |
147 | | - }, |
| 148 | + return ToolInstallStatus::IncorrectVersion { |
| 149 | + version, |
| 150 | + message: "could not parse version".to_string(), |
148 | 151 | }; |
149 | 152 | }; |
150 | 153 |
|
151 | | - if installed_version.semver < VALGRIND_CODSPEED_VERSION { |
152 | | - return ToolStatus { |
153 | | - tool_name, |
154 | | - status: ToolInstallStatus::IncorrectVersion { |
155 | | - version, |
156 | | - message: format!( |
157 | | - "version too old, expecting {} or higher", |
158 | | - VALGRIND_CODSPEED_VERSION_STRING.as_str() |
159 | | - ), |
160 | | - }, |
| 154 | + // Legacy `.codspeed` builds (no iteration suffix) predate iteration |
| 155 | + // tracking, so they count as iteration 0. |
| 156 | + let installed_iteration = installed_version.codspeed_iteration.unwrap_or(0); |
| 157 | + let is_version_outdated = (installed_version.semver, installed_iteration) |
| 158 | + < (VALGRIND_CODSPEED_VERSION, VALGRIND_CODSPEED_ITERATION); |
| 159 | + if is_version_outdated { |
| 160 | + return ToolInstallStatus::IncorrectVersion { |
| 161 | + version, |
| 162 | + message: format!( |
| 163 | + "version too old, expecting {} or higher", |
| 164 | + VALGRIND_CODSPEED_VERSION_STRING.as_str() |
| 165 | + ), |
161 | 166 | }; |
162 | 167 | } |
163 | 168 |
|
164 | | - ToolStatus { |
165 | | - tool_name, |
166 | | - status: ToolInstallStatus::Installed { version }, |
167 | | - } |
| 169 | + ToolInstallStatus::Installed { version } |
168 | 170 | } |
169 | 171 |
|
170 | 172 | fn is_valgrind_installed() -> bool { |
@@ -330,6 +332,57 @@ mod tests { |
330 | 332 | assert_ne!(v1, v2); |
331 | 333 | } |
332 | 334 |
|
| 335 | + #[test] |
| 336 | + fn test_classify_same_version_older_iteration_is_rejected() { |
| 337 | + // Pinned is 3.26.0-0codspeed3: a cached 3.26.0.codspeed2 build is the |
| 338 | + // same upstream valgrind but an older repackaging, so it must be |
| 339 | + // rejected and reinstalled. |
| 340 | + let status = classify_valgrind_version("valgrind-3.26.0.codspeed2".to_string()); |
| 341 | + assert!( |
| 342 | + matches!(status, ToolInstallStatus::IncorrectVersion { .. }), |
| 343 | + "stale codspeed iteration must be rejected, got: Installed" |
| 344 | + ); |
| 345 | + } |
| 346 | + |
| 347 | + #[test] |
| 348 | + fn test_classify_legacy_suffix_with_pinned_semver_is_rejected() { |
| 349 | + // Old builds report just `.codspeed` (no iteration); for the pinned |
| 350 | + // upstream version they predate the pinned iteration. |
| 351 | + let version = format!("valgrind-{VALGRIND_CODSPEED_VERSION}.codspeed"); |
| 352 | + let status = classify_valgrind_version(version); |
| 353 | + assert!(matches!(status, ToolInstallStatus::IncorrectVersion { .. })); |
| 354 | + } |
| 355 | + |
| 356 | + #[test] |
| 357 | + fn test_classify_pinned_iteration_is_installed() { |
| 358 | + let version = |
| 359 | + format!("valgrind-{VALGRIND_CODSPEED_VERSION}.codspeed{VALGRIND_CODSPEED_ITERATION}"); |
| 360 | + let status = classify_valgrind_version(version); |
| 361 | + assert!(matches!(status, ToolInstallStatus::Installed { .. })); |
| 362 | + } |
| 363 | + |
| 364 | + #[test] |
| 365 | + fn test_classify_newer_iteration_is_installed() { |
| 366 | + let version = format!( |
| 367 | + "valgrind-{VALGRIND_CODSPEED_VERSION}.codspeed{}", |
| 368 | + VALGRIND_CODSPEED_ITERATION + 1 |
| 369 | + ); |
| 370 | + let status = classify_valgrind_version(version); |
| 371 | + assert!(matches!(status, ToolInstallStatus::Installed { .. })); |
| 372 | + } |
| 373 | + |
| 374 | + #[test] |
| 375 | + fn test_classify_newer_semver_with_legacy_suffix_is_installed() { |
| 376 | + let status = classify_valgrind_version("valgrind-3.99.0.codspeed".to_string()); |
| 377 | + assert!(matches!(status, ToolInstallStatus::Installed { .. })); |
| 378 | + } |
| 379 | + |
| 380 | + #[test] |
| 381 | + fn test_classify_non_codspeed_build_is_rejected() { |
| 382 | + let status = classify_valgrind_version("valgrind-3.26.0".to_string()); |
| 383 | + assert!(matches!(status, ToolInstallStatus::IncorrectVersion { .. })); |
| 384 | + } |
| 385 | + |
333 | 386 | #[test] |
334 | 387 | fn test_parse_valgrind_codspeed_version_invalid_format() { |
335 | 388 | assert_eq!( |
|
0 commit comments