Skip to content

Commit 877869e

Browse files
committed
tests: validate "patch" and "ed" commands once, print meaningful messages
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: #TODO 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 c811142 commit 877869e

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" })
@@ -449,7 +451,8 @@ mod tests {
449451
fb.write_all(&bet[..]).unwrap();
450452
let _ = fa;
451453
let _ = fb;
452-
let output = Command::new("patch")
454+
let output = PATCH_CMD
455+
.new()
453456
.arg("-p0")
454457
.arg("--context")
455458
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
@@ -481,7 +484,6 @@ mod tests {
481484
for &f in &[0, 1, 2] {
482485
use std::fs::{self, File};
483486
use std::io::Write;
484-
use std::process::Command;
485487
let mut alef = Vec::new();
486488
let mut bet = Vec::new();
487489
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
@@ -530,7 +532,8 @@ mod tests {
530532
fb.write_all(&bet[..]).unwrap();
531533
let _ = fa;
532534
let _ = fb;
533-
let output = Command::new("patch")
535+
let output = PATCH_CMD
536+
.new()
534537
.arg("-p0")
535538
.arg("--context")
536539
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
@@ -562,7 +565,6 @@ mod tests {
562565
for &f in &[0, 1, 2] {
563566
use std::fs::{self, File};
564567
use std::io::Write;
565-
use std::process::Command;
566568
let mut alef = Vec::new();
567569
let mut bet = Vec::new();
568570
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
@@ -614,7 +616,8 @@ mod tests {
614616
fb.write_all(&bet[..]).unwrap();
615617
let _ = fa;
616618
let _ = fb;
617-
let output = Command::new("patch")
619+
let output = PATCH_CMD
620+
.new()
618621
.arg("-p0")
619622
.arg("--context")
620623
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
@@ -646,7 +649,6 @@ mod tests {
646649
for &f in &[0, 1, 2] {
647650
use std::fs::{self, File};
648651
use std::io::Write;
649-
use std::process::Command;
650652
let mut alef = Vec::new();
651653
let mut bet = Vec::new();
652654
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
@@ -701,7 +703,8 @@ mod tests {
701703
fb.write_all(&bet[..]).unwrap();
702704
let _ = fa;
703705
let _ = fb;
704-
let output = Command::new("patch")
706+
let output = PATCH_CMD
707+
.new()
705708
.arg("-p0")
706709
.arg("--context")
707710
.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" })
@@ -492,7 +493,10 @@ mod tests {
492493
.unwrap_or_else(|_| String::from("[Invalid UTF-8]"))
493494
);
494495

495-
let output = Command::new("patch")
496+
use crate::utils::testcmds::PATCH_CMD;
497+
498+
let output = PATCH_CMD
499+
.new()
496500
.arg("-p0")
497501
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
498502
.output()
@@ -524,7 +528,6 @@ mod tests {
524528
for &g in &[0, 1, 2] {
525529
use std::fs::{self, File};
526530
use std::io::Write;
527-
use std::process::Command;
528531
let mut alef = Vec::new();
529532
let mut bet = Vec::new();
530533
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
@@ -592,7 +595,8 @@ mod tests {
592595
fb.write_all(&bet[..]).unwrap();
593596
let _ = fa;
594597
let _ = fb;
595-
let output = Command::new("patch")
598+
let output = PATCH_CMD
599+
.new()
596600
.arg("-p0")
597601
.stdin(File::open(format!("{target}/abn.diff")).unwrap())
598602
.output()
@@ -625,7 +629,6 @@ mod tests {
625629
for &g in &[0, 1, 2, 3] {
626630
use std::fs::{self, File};
627631
use std::io::Write;
628-
use std::process::Command;
629632
let mut alef = Vec::new();
630633
let mut bet = Vec::new();
631634
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
@@ -688,7 +691,8 @@ mod tests {
688691
fb.write_all(&bet[..]).unwrap();
689692
let _ = fa;
690693
let _ = fb;
691-
let output = Command::new("patch")
694+
let output = PATCH_CMD
695+
.new()
692696
.arg("-p0")
693697
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
694698
.output()
@@ -720,7 +724,6 @@ mod tests {
720724
for &f in &[0, 1, 2] {
721725
use std::fs::{self, File};
722726
use std::io::Write;
723-
use std::process::Command;
724727
let mut alef = Vec::new();
725728
let mut bet = Vec::new();
726729
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
@@ -769,7 +772,8 @@ mod tests {
769772
fb.write_all(&bet[..]).unwrap();
770773
let _ = fa;
771774
let _ = fb;
772-
let output = Command::new("patch")
775+
let output = PATCH_CMD
776+
.new()
773777
.arg("-p0")
774778
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
775779
.output()
@@ -800,7 +804,6 @@ mod tests {
800804
for &f in &[0, 1, 2] {
801805
use std::fs::{self, File};
802806
use std::io::Write;
803-
use std::process::Command;
804807
let mut alef = Vec::new();
805808
let mut bet = Vec::new();
806809
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
@@ -855,7 +858,8 @@ mod tests {
855858
fb.write_all(&bet[..]).unwrap();
856859
let _ = fa;
857860
let _ = fb;
858-
let output = Command::new("patch")
861+
let output = PATCH_CMD
862+
.new()
859863
.arg("-p0")
860864
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
861865
.output()

0 commit comments

Comments
 (0)