PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/tools/cargotest/main.rs

https://gitlab.com/rust-lang/rust
Rust | 187 lines | 158 code | 18 blank | 11 comment | 14 complexity | 3e3965057f04a3bf2e0200caf5aac498 MD5 | raw file
  1. use std::env;
  2. use std::fs;
  3. use std::path::{Path, PathBuf};
  4. use std::process::Command;
  5. struct Test {
  6. repo: &'static str,
  7. name: &'static str,
  8. sha: &'static str,
  9. lock: Option<&'static str>,
  10. packages: &'static [&'static str],
  11. features: Option<&'static [&'static str]>,
  12. manifest_path: Option<&'static str>,
  13. }
  14. const TEST_REPOS: &[Test] = &[
  15. Test {
  16. name: "iron",
  17. repo: "https://github.com/iron/iron",
  18. sha: "cf056ea5e8052c1feea6141e40ab0306715a2c33",
  19. lock: None,
  20. packages: &[],
  21. features: None,
  22. manifest_path: None,
  23. },
  24. Test {
  25. name: "ripgrep",
  26. repo: "https://github.com/BurntSushi/ripgrep",
  27. sha: "ced5b92aa93eb47e892bd2fd26ab454008721730",
  28. lock: None,
  29. packages: &[],
  30. features: None,
  31. manifest_path: None,
  32. },
  33. Test {
  34. name: "tokei",
  35. repo: "https://github.com/XAMPPRocky/tokei",
  36. sha: "fdf3f8cb279a7aeac0696c87e5d8b0cd946e4f9e",
  37. lock: None,
  38. packages: &[],
  39. features: None,
  40. manifest_path: None,
  41. },
  42. Test {
  43. name: "xsv",
  44. repo: "https://github.com/BurntSushi/xsv",
  45. sha: "3de6c04269a7d315f7e9864b9013451cd9580a08",
  46. lock: None,
  47. packages: &[],
  48. features: None,
  49. manifest_path: None,
  50. },
  51. Test {
  52. name: "servo",
  53. repo: "https://github.com/servo/servo",
  54. sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
  55. lock: None,
  56. // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
  57. // This takes much less time to build than all of Servo and supports stable Rust.
  58. packages: &["selectors"],
  59. features: None,
  60. manifest_path: None,
  61. },
  62. Test {
  63. name: "diesel",
  64. repo: "https://github.com/diesel-rs/diesel",
  65. sha: "91493fe47175076f330ce5fc518f0196c0476f56",
  66. lock: None,
  67. packages: &[],
  68. // Test the embedded sqlite variant of diesel
  69. // This does not require any dependency to be present,
  70. // sqlite will be compiled as part of the build process
  71. features: Some(&["sqlite", "libsqlite3-sys/bundled"]),
  72. // We are only interested in testing diesel itself
  73. // not any other crate present in the diesel workspace
  74. // (This is required to set the feature flags above)
  75. manifest_path: Some("diesel/Cargo.toml"),
  76. },
  77. ];
  78. fn main() {
  79. let args = env::args().collect::<Vec<_>>();
  80. let cargo = &args[1];
  81. let out_dir = Path::new(&args[2]);
  82. let cargo = &Path::new(cargo);
  83. for test in TEST_REPOS.iter().rev() {
  84. if args[3..].is_empty() || args[3..].iter().any(|s| s.contains(test.name)) {
  85. test_repo(cargo, out_dir, test);
  86. }
  87. }
  88. }
  89. fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
  90. println!("testing {}", test.repo);
  91. let dir = clone_repo(test, out_dir);
  92. if let Some(lockfile) = test.lock {
  93. fs::write(&dir.join("Cargo.lock"), lockfile).unwrap();
  94. }
  95. if !run_cargo_test(cargo, &dir, test.packages, test.features, test.manifest_path) {
  96. panic!("tests failed for {}", test.repo);
  97. }
  98. }
  99. fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
  100. let out_dir = out_dir.join(test.name);
  101. if !out_dir.join(".git").is_dir() {
  102. let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap();
  103. assert!(status.success());
  104. }
  105. // Try progressively deeper fetch depths to find the commit
  106. let mut found = false;
  107. for depth in &[0, 1, 10, 100, 1000, 100000] {
  108. if *depth > 0 {
  109. let status = Command::new("git")
  110. .arg("fetch")
  111. .arg(test.repo)
  112. .arg("master")
  113. .arg(&format!("--depth={}", depth))
  114. .current_dir(&out_dir)
  115. .status()
  116. .unwrap();
  117. assert!(status.success());
  118. }
  119. let status = Command::new("git")
  120. .arg("reset")
  121. .arg(test.sha)
  122. .arg("--hard")
  123. .current_dir(&out_dir)
  124. .status()
  125. .unwrap();
  126. if status.success() {
  127. found = true;
  128. break;
  129. }
  130. }
  131. if !found {
  132. panic!("unable to find commit {}", test.sha)
  133. }
  134. let status =
  135. Command::new("git").arg("clean").arg("-fdx").current_dir(&out_dir).status().unwrap();
  136. assert!(status.success());
  137. out_dir
  138. }
  139. fn run_cargo_test(
  140. cargo_path: &Path,
  141. crate_path: &Path,
  142. packages: &[&str],
  143. features: Option<&[&str]>,
  144. manifest_path: Option<&str>,
  145. ) -> bool {
  146. let mut command = Command::new(cargo_path);
  147. command.arg("test");
  148. if let Some(path) = manifest_path {
  149. command.arg(format!("--manifest-path={}", path));
  150. }
  151. if let Some(features) = features {
  152. command.arg("--no-default-features");
  153. for feature in features {
  154. command.arg(format!("--features={}", feature));
  155. }
  156. }
  157. for name in packages {
  158. command.arg("-p").arg(name);
  159. }
  160. let status = command
  161. // Disable rust-lang/cargo's cross-compile tests
  162. .env("CFG_DISABLE_CROSS_TESTS", "1")
  163. // Relax #![deny(warnings)] in some crates
  164. .env("RUSTFLAGS", "--cap-lints warn")
  165. .current_dir(crate_path)
  166. .status()
  167. .unwrap();
  168. status.success()
  169. }