170 lines
5.3 KiB
Diff
170 lines
5.3 KiB
Diff
From 618d56c7ac8bd8cd701344a0eaca8373a78dea95 Mon Sep 17 00:00:00 2001
|
|
From: Martin Wilck <mwilck@suse.com>
|
|
Date: Mon, 23 Apr 2018 21:59:05 +0200
|
|
Subject: [PATCH] test/udev-test.pl: allow concurrent additions and removals
|
|
|
|
Allow testing cases where multiple devices are added and removed
|
|
simultaneously. Tests are started as synchronously as possible using a
|
|
semaphore, in order to test possible race conditions. If this isn't desired,
|
|
the test parameter "sleep_us" can be set to the number of microseconds to wait
|
|
between udev invocations.
|
|
|
|
(cherry picked from commit 09a4062d70b3a10d022e40066e2adf09df05bbbc)
|
|
|
|
Related: #1642728
|
|
---
|
|
test/udev-test.pl | 90 +++++++++++++++++++++++++++++++++++++----------
|
|
1 file changed, 72 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
|
index 8b5a97ad61..db25ef13c1 100755
|
|
--- a/test/udev-test.pl
|
|
+++ b/test/udev-test.pl
|
|
@@ -18,6 +18,10 @@
|
|
|
|
use warnings;
|
|
use strict;
|
|
+use POSIX qw(WIFEXITED WEXITSTATUS);
|
|
+use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR IPC_CREAT);
|
|
+use IPC::Semaphore;
|
|
+use Time::HiRes qw(usleep);
|
|
|
|
my $udev_bin = "./test-udev";
|
|
my $valgrind = 0;
|
|
@@ -2210,6 +2214,8 @@ sub check_add {
|
|
sleep(1);
|
|
}
|
|
}
|
|
+
|
|
+ print "device \'$device->{devpath}\' expecting node/link \'$device->{exp_name}\'\n";
|
|
if ((-e "$udev_dev/$device->{exp_name}") ||
|
|
(-l "$udev_dev/$device->{exp_name}")) {
|
|
|
|
@@ -2257,21 +2263,72 @@ sub check_remove {
|
|
}
|
|
}
|
|
|
|
+sub run_udev {
|
|
+ my ($action, $dev, $sleep_us, $sema) = @_;
|
|
+
|
|
+ # Notify main process that this worker has started
|
|
+ $sema->op(0, 1, 0);
|
|
+
|
|
+ # Wait for start
|
|
+ $sema->op(0, 0, 0);
|
|
+ usleep($sleep_us) if defined ($sleep_us);
|
|
+ my $rc = udev($action, $dev->{devpath});
|
|
+ exit $rc;
|
|
+}
|
|
+
|
|
+sub fork_and_run_udev {
|
|
+ my ($action, $rules, $sema) = @_;
|
|
+ my @devices = @{$rules->{devices}};
|
|
+ my $dev;
|
|
+ my $k = 0;
|
|
+
|
|
+ $sema->setval(0, 1);
|
|
+ foreach $dev (@devices) {
|
|
+ my $pid = fork();
|
|
+
|
|
+ if (!$pid) {
|
|
+ run_udev($action, $dev,
|
|
+ defined($rules->{sleep_us}) ? $k * $rules->{sleep_us} : undef,
|
|
+ $sema);
|
|
+ } else {
|
|
+ $dev->{pid} = $pid;
|
|
+ }
|
|
+ $k++;
|
|
+ }
|
|
+
|
|
+ # This operation waits for all workers to become ready, and
|
|
+ # starts them off when that's the case.
|
|
+ $sema->op(0, -($#devices + 2), 0);
|
|
+
|
|
+ foreach $dev (@devices) {
|
|
+ my $rc;
|
|
+ my $pid;
|
|
+
|
|
+ $pid = waitpid($dev->{pid}, 0);
|
|
+ if ($pid == -1) {
|
|
+ print "error waiting for pid dev->{pid}\n";
|
|
+ $error += 1;
|
|
+ }
|
|
+ if (WIFEXITED($?)) {
|
|
+ $rc = WEXITSTATUS($?);
|
|
+
|
|
+ if ($rc) {
|
|
+ print "$udev_bin $action for $dev->{devpath} failed with code $rc\n";
|
|
+ $error += 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
sub run_test {
|
|
- my ($rules, $number) = @_;
|
|
+ my ($rules, $number, $sema) = @_;
|
|
my $rc;
|
|
my @devices = @{$rules->{devices}};
|
|
|
|
print "TEST $number: $rules->{desc}\n";
|
|
create_rules(\$rules->{rules});
|
|
- foreach my $dev (@devices) {
|
|
- print "device \'$dev->{devpath}\' expecting node/link \'$dev->{exp_name}\'\n";
|
|
- $rc = udev("add", $dev->{devpath});
|
|
- if ($rc != 0) {
|
|
- print "$udev_bin add failed with code $rc\n";
|
|
- $error++;
|
|
- }
|
|
- }
|
|
+
|
|
+ fork_and_run_udev("add", $rules, $sema);
|
|
|
|
foreach my $dev (@devices) {
|
|
check_add($dev);
|
|
@@ -2282,13 +2339,8 @@ sub run_test {
|
|
return;
|
|
}
|
|
|
|
- foreach my $dev (@devices) {
|
|
- $rc = udev("remove", $dev->{devpath});
|
|
- if ($rc != 0) {
|
|
- print "$udev_bin remove failed with code $rc\n";
|
|
- $error++;
|
|
- }
|
|
- }
|
|
+ fork_and_run_udev("remove", $rules, $sema);
|
|
+
|
|
foreach my $dev (@devices) {
|
|
check_remove($dev);
|
|
}
|
|
@@ -2350,12 +2402,13 @@ foreach my $arg (@ARGV) {
|
|
push(@list, $arg);
|
|
}
|
|
}
|
|
+my $sema = IPC::Semaphore->new(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR | IPC_CREAT);
|
|
|
|
if ($list[0]) {
|
|
foreach my $arg (@list) {
|
|
if (defined($tests[$arg-1]->{desc})) {
|
|
print "udev-test will run test number $arg:\n\n";
|
|
- run_test($tests[$arg-1], $arg);
|
|
+ run_test($tests[$arg-1], $arg, $sema);
|
|
} else {
|
|
print "test does not exist.\n";
|
|
}
|
|
@@ -2365,11 +2418,12 @@ if ($list[0]) {
|
|
print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
|
|
|
|
foreach my $rules (@tests) {
|
|
- run_test($rules, $test_num);
|
|
+ run_test($rules, $test_num, $sema);
|
|
$test_num++;
|
|
}
|
|
}
|
|
|
|
+$sema->remove;
|
|
print "$error errors occurred\n\n";
|
|
|
|
cleanup();
|