Skip to content

Commit 1254f14

Browse files
authored
tests: validate "patch" and "ed" commands once, print meaningful messages (#226)
macOS' /usr/bin/patch and GNU patch have very subtle incompatibilities that cause only some "more advanced" tests to fail in obscure and very time-consuming ways - while other tests pass. In some cases (depending on test threads racing), the lack of newlines in some test data even causes the whole test suite to stall. This fix runs `patch -version` (only once), makes sure the output starts with "GNU patch" and shows a meaningful assert message when not. It also looks for `gpatch` instead of `patch` on macOS and shows a meaningful assert message if either is missing. Fixes: #225 This also provides faster and better feedback when `ed` is missing (see #39) and implements a portable and basic check. Last but not least, this new code is generic enough to support the validation of any other test dependency in the future.
1 parent c1943c5 commit 1254f14

5 files changed

Lines changed: 137 additions & 32 deletions

File tree

src/context_diff.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ pub fn diff(expected: &[u8], actual: &[u8], params: &Params) -> Vec<u8> {
381381
mod tests {
382382
use super::*;
383383
use pretty_assertions::assert_eq;
384+
385+
use crate::utils::testcmds::PATCH_CMD;
386+
384387
#[test]
385388
fn test_permutations() {
386389
// test all possible six-line files.
@@ -394,7 +397,6 @@ mod tests {
394397
for &f in &[0, 1, 2] {
395398
use std::fs::{self, File};
396399
use std::io::Write;
397-
use std::process::Command;
398400
let mut alef = Vec::new();
399401
let mut bet = Vec::new();
400402
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
@@ -450,7 +452,8 @@ mod tests {
450452
fb.write_all(&bet[..]).unwrap();
451453
let _ = fa;
452454
let _ = fb;
453-
let output = Command::new("patch")
455+
let output = PATCH_CMD
456+
.new()
454457
.arg("-p0")
455458
.arg("--context")
456459
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
@@ -482,7 +485,6 @@ mod tests {
482485
for &f in &[0, 1, 2] {
483486
use std::fs::{self, File};
484487
use std::io::Write;
485-
use std::process::Command;
486488
let mut alef = Vec::new();
487489
let mut bet = Vec::new();
488490
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
@@ -532,7 +534,8 @@ mod tests {
532534
fb.write_all(&bet[..]).unwrap();
533535
let _ = fa;
534536
let _ = fb;
535-
let output = Command::new("patch")
537+
let output = PATCH_CMD
538+
.new()
536539
.arg("-p0")
537540
.arg("--context")
538541
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
@@ -564,7 +567,6 @@ mod tests {
564567
for &f in &[0, 1, 2] {
565568
use std::fs::{self, File};
566569
use std::io::Write;
567-
use std::process::Command;
568570
let mut alef = Vec::new();
569571
let mut bet = Vec::new();
570572
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
@@ -617,7 +619,8 @@ mod tests {
617619
fb.write_all(&bet[..]).unwrap();
618620
let _ = fa;
619621
let _ = fb;
620-
let output = Command::new("patch")
622+
let output = PATCH_CMD
623+
.new()
621624
.arg("-p0")
622625
.arg("--context")
623626
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
@@ -649,7 +652,6 @@ mod tests {
649652
for &f in &[0, 1, 2] {
650653
use std::fs::{self, File};
651654
use std::io::Write;
652-
use std::process::Command;
653655
let mut alef = Vec::new();
654656
let mut bet = Vec::new();
655657
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
@@ -705,7 +707,8 @@ mod tests {
705707
fb.write_all(&bet[..]).unwrap();
706708
let _ = fa;
707709
let _ = fb;
708-
let output = Command::new("patch")
710+
let output = PATCH_CMD
711+
.new()
709712
.arg("-p0")
710713
.arg("--context")
711714
.stdin(File::open(format!("{target}/abr.diff")).unwrap())

src/ed_diff.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ pub fn diff(expected: &[u8], actual: &[u8], params: &Params) -> Result<Vec<u8>,
162162
mod tests {
163163
use super::*;
164164
use pretty_assertions::assert_eq;
165+
166+
use crate::utils::testcmds::ED_CMD;
167+
165168
pub fn diff_w(expected: &[u8], actual: &[u8], filename: &str) -> Result<Vec<u8>, DiffError> {
166169
let mut output = diff(expected, actual, &Params::default())?;
167170
writeln!(&mut output, "w {filename}").unwrap();
@@ -237,8 +240,8 @@ mod tests {
237240
let _ = fb;
238241
#[cfg(not(windows))] // there's no ed on windows
239242
{
240-
use std::process::Command;
241-
let output = Command::new("ed")
243+
let output = ED_CMD
244+
.new()
242245
.arg(format!("{target}/alef"))
243246
.stdin(File::open(format!("{target}/ab.ed")).unwrap())
244247
.output()
@@ -311,8 +314,8 @@ mod tests {
311314
let _ = fb;
312315
#[cfg(not(windows))] // there's no ed on windows
313316
{
314-
use std::process::Command;
315-
let output = Command::new("ed")
317+
let output = ED_CMD
318+
.new()
316319
.arg(format!("{target}/alef_"))
317320
.stdin(File::open(format!("{target}/ab_.ed")).unwrap())
318321
.output()
@@ -391,8 +394,8 @@ mod tests {
391394
let _ = fb;
392395
#[cfg(not(windows))] // there's no ed on windows
393396
{
394-
use std::process::Command;
395-
let output = Command::new("ed")
397+
let output = ED_CMD
398+
.new()
396399
.arg(format!("{target}/alefr"))
397400
.stdin(File::open(format!("{target}/abr.ed")).unwrap())
398401
.output()

src/normal_diff.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ mod tests {
215215
use super::*;
216216
use pretty_assertions::assert_eq;
217217

218+
use crate::utils::testcmds::PATCH_CMD;
219+
218220
#[test]
219221
fn test_basic() {
220222
let mut a = Vec::new();
@@ -239,7 +241,6 @@ mod tests {
239241
for &f in &[0, 1, 2] {
240242
use std::fs::{self, File};
241243
use std::io::Write;
242-
use std::process::Command;
243244
let mut alef = Vec::new();
244245
let mut bet = Vec::new();
245246
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
@@ -285,7 +286,8 @@ mod tests {
285286
fb.write_all(&bet[..]).unwrap();
286287
let _ = fa;
287288
let _ = fb;
288-
let output = Command::new("patch")
289+
let output = PATCH_CMD
290+
.new()
289291
.arg("-p0")
290292
.arg(format!("{target}/alef"))
291293
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
@@ -318,7 +320,6 @@ mod tests {
318320
for &g in &[0, 1, 2] {
319321
use std::fs::{self, File};
320322
use std::io::Write;
321-
use std::process::Command;
322323
let mut alef = Vec::new();
323324
let mut bet = Vec::new();
324325
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
@@ -377,7 +378,8 @@ mod tests {
377378
fb.write_all(&bet[..]).unwrap();
378379
let _ = fa;
379380
let _ = fb;
380-
let output = Command::new("patch")
381+
let output = PATCH_CMD
382+
.new()
381383
.arg("-p0")
382384
.arg("--normal")
383385
.arg(format!("{target}/alefn"))
@@ -411,7 +413,6 @@ mod tests {
411413
for &f in &[0, 1, 2] {
412414
use std::fs::{self, File};
413415
use std::io::Write;
414-
use std::process::Command;
415416
let mut alef = Vec::new();
416417
let mut bet = Vec::new();
417418
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
@@ -451,7 +452,8 @@ mod tests {
451452
fb.write_all(&bet[..]).unwrap();
452453
let _ = fa;
453454
let _ = fb;
454-
let output = Command::new("patch")
455+
let output = PATCH_CMD
456+
.new()
455457
.arg("-p0")
456458
.arg(format!("{target}/alef_"))
457459
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
@@ -483,7 +485,6 @@ mod tests {
483485
for &f in &[0, 1, 2] {
484486
use std::fs::{self, File};
485487
use std::io::Write;
486-
use std::process::Command;
487488
let mut alef = Vec::new();
488489
let mut bet = Vec::new();
489490
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
@@ -529,7 +530,8 @@ mod tests {
529530
fb.write_all(&bet[..]).unwrap();
530531
let _ = fa;
531532
let _ = fb;
532-
let output = Command::new("patch")
533+
let output = PATCH_CMD
534+
.new()
533535
.arg("-p0")
534536
.arg(format!("{target}/alefr"))
535537
.stdin(File::open(format!("{target}/abr.diff")).unwrap())

src/unified_diff.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ mod tests {
408408
use super::*;
409409
use pretty_assertions::assert_eq;
410410

411+
use crate::utils::testcmds::PATCH_CMD;
412+
411413
#[test]
412414
fn test_permutations() {
413415
let target = "target/unified-diff/";
@@ -421,7 +423,6 @@ mod tests {
421423
for &f in &[0, 1, 2] {
422424
use std::fs::{self, File};
423425
use std::io::Write;
424-
use std::process::Command;
425426
let mut alef = Vec::new();
426427
let mut bet = Vec::new();
427428
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
@@ -493,7 +494,10 @@ mod tests {
493494
.unwrap_or_else(|_| String::from("[Invalid UTF-8]"))
494495
);
495496

496-
let output = Command::new("patch")
497+
use crate::utils::testcmds::PATCH_CMD;
498+
499+
let output = PATCH_CMD
500+
.new()
497501
.arg("-p0")
498502
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
499503
.output()
@@ -525,7 +529,6 @@ mod tests {
525529
for &g in &[0, 1, 2] {
526530
use std::fs::{self, File};
527531
use std::io::Write;
528-
use std::process::Command;
529532
let mut alef = Vec::new();
530533
let mut bet = Vec::new();
531534
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
@@ -594,7 +597,8 @@ mod tests {
594597
fb.write_all(&bet[..]).unwrap();
595598
let _ = fa;
596599
let _ = fb;
597-
let output = Command::new("patch")
600+
let output = PATCH_CMD
601+
.new()
598602
.arg("-p0")
599603
.stdin(File::open(format!("{target}/abn.diff")).unwrap())
600604
.output()
@@ -627,7 +631,6 @@ mod tests {
627631
for &g in &[0, 1, 2, 3] {
628632
use std::fs::{self, File};
629633
use std::io::Write;
630-
use std::process::Command;
631634
let mut alef = Vec::new();
632635
let mut bet = Vec::new();
633636
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
@@ -691,7 +694,8 @@ mod tests {
691694
fb.write_all(&bet[..]).unwrap();
692695
let _ = fa;
693696
let _ = fb;
694-
let output = Command::new("patch")
697+
let output = PATCH_CMD
698+
.new()
695699
.arg("-p0")
696700
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
697701
.output()
@@ -723,7 +727,6 @@ mod tests {
723727
for &f in &[0, 1, 2] {
724728
use std::fs::{self, File};
725729
use std::io::Write;
726-
use std::process::Command;
727730
let mut alef = Vec::new();
728731
let mut bet = Vec::new();
729732
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
@@ -773,7 +776,8 @@ mod tests {
773776
fb.write_all(&bet[..]).unwrap();
774777
let _ = fa;
775778
let _ = fb;
776-
let output = Command::new("patch")
779+
let output = PATCH_CMD
780+
.new()
777781
.arg("-p0")
778782
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
779783
.output()
@@ -804,7 +808,6 @@ mod tests {
804808
for &f in &[0, 1, 2] {
805809
use std::fs::{self, File};
806810
use std::io::Write;
807-
use std::process::Command;
808811
let mut alef = Vec::new();
809812
let mut bet = Vec::new();
810813
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
@@ -860,7 +863,8 @@ mod tests {
860863
fb.write_all(&bet[..]).unwrap();
861864
let _ = fa;
862865
let _ = fb;
863-
let output = Command::new("patch")
866+
let output = PATCH_CMD
867+
.new()
864868
.arg("-p0")
865869
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
866870
.output()

0 commit comments

Comments
 (0)