|
1 | 1 | //! Tests for ctrl-C handling.
|
2 | 2 |
|
| 3 | +use cargo_test_support::{project, slow_cpu_multiplier}; |
3 | 4 | use std::fs;
|
4 | 5 | use std::io::{self, Read};
|
5 | 6 | use std::net::TcpListener;
|
6 | 7 | use std::process::{Child, Stdio};
|
7 | 8 | use std::thread;
|
8 |
| - |
9 |
| -use cargo_test_support::{project, slow_cpu_multiplier}; |
| 9 | +use std::time; |
10 | 10 |
|
11 | 11 | #[cargo_test]
|
12 | 12 | fn ctrl_c_kills_everyone() {
|
@@ -87,6 +87,155 @@ fn ctrl_c_kills_everyone() {
|
87 | 87 | );
|
88 | 88 | }
|
89 | 89 |
|
| 90 | +#[cargo_test] |
| 91 | +fn kill_cargo_add_never_corrupts_cargo_toml() { |
| 92 | + cargo_test_support::registry::init(); |
| 93 | + cargo_test_support::registry::Package::new("my-package", "0.1.1+my-package").publish(); |
| 94 | + |
| 95 | + let with_dependency = r#" |
| 96 | +[package] |
| 97 | +name = "foo" |
| 98 | +version = "0.0.1" |
| 99 | +authors = [] |
| 100 | +
|
| 101 | +[dependencies] |
| 102 | +my-package = "0.1.1" |
| 103 | +"#; |
| 104 | + let without_dependency = r#" |
| 105 | +[package] |
| 106 | +name = "foo" |
| 107 | +version = "0.0.1" |
| 108 | +authors = [] |
| 109 | +"#; |
| 110 | + |
| 111 | + for sleep_time_ms in [30, 60, 90] { |
| 112 | + let p = project() |
| 113 | + .file("Cargo.toml", without_dependency) |
| 114 | + .file("src/lib.rs", "") |
| 115 | + .build(); |
| 116 | + |
| 117 | + let mut cargo = p.cargo("add").arg("my-package").build_command(); |
| 118 | + cargo |
| 119 | + .stdin(Stdio::piped()) |
| 120 | + .stdout(Stdio::piped()) |
| 121 | + .stderr(Stdio::piped()); |
| 122 | + |
| 123 | + let mut child = cargo.spawn().unwrap(); |
| 124 | + |
| 125 | + thread::sleep(time::Duration::from_millis(sleep_time_ms)); |
| 126 | + |
| 127 | + assert!(child.kill().is_ok()); |
| 128 | + assert!(child.wait().is_ok()); |
| 129 | + |
| 130 | + // check the Cargo.toml |
| 131 | + let contents = fs::read(p.root().join("Cargo.toml")).unwrap(); |
| 132 | + |
| 133 | + // not empty |
| 134 | + assert_ne!( |
| 135 | + contents, b"", |
| 136 | + "Cargo.toml is empty, and should not be at {} milliseconds", |
| 137 | + sleep_time_ms |
| 138 | + ); |
| 139 | + |
| 140 | + // We should have the original Cargo.toml or the new one, nothing else. |
| 141 | + if std::str::from_utf8(&contents) |
| 142 | + .unwrap() |
| 143 | + .contains("[dependencies]") |
| 144 | + { |
| 145 | + assert_eq!( |
| 146 | + std::str::from_utf8(&contents).unwrap(), |
| 147 | + with_dependency, |
| 148 | + "Cargo.toml is with_dependency after add at {} milliseconds", |
| 149 | + sleep_time_ms |
| 150 | + ); |
| 151 | + } else { |
| 152 | + assert_eq!( |
| 153 | + std::str::from_utf8(&contents).unwrap(), |
| 154 | + without_dependency, |
| 155 | + "Cargo.toml is without_dependency after add at {} milliseconds", |
| 156 | + sleep_time_ms |
| 157 | + ); |
| 158 | + } |
| 159 | + } |
| 160 | +} |
| 161 | + |
| 162 | +#[cargo_test] |
| 163 | +fn kill_cargo_remove_never_corrupts_cargo_toml() { |
| 164 | + let with_dependency = r#" |
| 165 | +[package] |
| 166 | +name = "foo" |
| 167 | +version = "0.0.1" |
| 168 | +authors = [] |
| 169 | +build = "build.rs" |
| 170 | +
|
| 171 | +[dependencies] |
| 172 | +bar = "0.0.1" |
| 173 | +"#; |
| 174 | + let without_dependency = r#" |
| 175 | +[package] |
| 176 | +name = "foo" |
| 177 | +version = "0.0.1" |
| 178 | +authors = [] |
| 179 | +build = "build.rs" |
| 180 | +"#; |
| 181 | + |
| 182 | + // This test depends on killing the cargo process at the right time to cause a failed write. |
| 183 | + // Note that we're iterating and using the index as time in ms to sleep before killing the cargo process. |
| 184 | + // If it is working correctly, we never fail, but can't hang out here all day... |
| 185 | + // So we'll just run it a few times and hope for the best. |
| 186 | + for sleep_time_ms in [30, 60, 90] { |
| 187 | + // new basic project with a single dependency |
| 188 | + let p = project() |
| 189 | + .file("Cargo.toml", with_dependency) |
| 190 | + .file("src/lib.rs", "") |
| 191 | + .build(); |
| 192 | + |
| 193 | + // run cargo remove the dependency |
| 194 | + let mut cargo = p.cargo("remove").arg("bar").build_command(); |
| 195 | + cargo |
| 196 | + .stdin(Stdio::piped()) |
| 197 | + .stdout(Stdio::piped()) |
| 198 | + .stderr(Stdio::piped()); |
| 199 | + |
| 200 | + let mut child = cargo.spawn().unwrap(); |
| 201 | + |
| 202 | + thread::sleep(time::Duration::from_millis(sleep_time_ms)); |
| 203 | + |
| 204 | + assert!(child.kill().is_ok()); |
| 205 | + assert!(child.wait().is_ok()); |
| 206 | + |
| 207 | + // check the Cargo.toml |
| 208 | + let contents = fs::read(p.root().join("Cargo.toml")).unwrap(); |
| 209 | + |
| 210 | + // not empty |
| 211 | + assert_ne!( |
| 212 | + contents, b"", |
| 213 | + "Cargo.toml is empty, and should not be at {} milliseconds", |
| 214 | + sleep_time_ms |
| 215 | + ); |
| 216 | + |
| 217 | + // We should have the original Cargo.toml or the new one, nothing else. |
| 218 | + if std::str::from_utf8(&contents) |
| 219 | + .unwrap() |
| 220 | + .contains("[dependencies]") |
| 221 | + { |
| 222 | + assert_eq!( |
| 223 | + std::str::from_utf8(&contents).unwrap(), |
| 224 | + with_dependency, |
| 225 | + "Cargo.toml is not the same as the original at {} milliseconds", |
| 226 | + sleep_time_ms |
| 227 | + ); |
| 228 | + } else { |
| 229 | + assert_eq!( |
| 230 | + std::str::from_utf8(&contents).unwrap(), |
| 231 | + without_dependency, |
| 232 | + "Cargo.toml is not the same as expected at {} milliseconds", |
| 233 | + sleep_time_ms |
| 234 | + ); |
| 235 | + } |
| 236 | + } |
| 237 | +} |
| 238 | + |
90 | 239 | #[cfg(unix)]
|
91 | 240 | pub fn ctrl_c(child: &mut Child) {
|
92 | 241 | let r = unsafe { libc::kill(-(child.id() as i32), libc::SIGINT) };
|
|
0 commit comments