chiark / gitweb /
[PATCH] udevd test script
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Sat, 17 Apr 2004 06:58:05 +0000 (23:58 -0700)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:35:15 +0000 (21:35 -0700)
Thanks to Yin, Hu <hu.yin@intel.com>, who made a nice perl script to test the
expected behavior of the udevd sequence number handling. The test sends
different SEQNUM sequences to udevd, while analyzing the reordering and timeout
handling of udevd.

test/udevd-test/udev-log-amplify.pl [new file with mode: 0644]
test/udevd-test/udev-log-script.pl [new file with mode: 0644]
test/udevd-test/udevd-test.pl [new file with mode: 0644]
udevd.c

diff --git a/test/udevd-test/udev-log-amplify.pl b/test/udevd-test/udev-log-amplify.pl
new file mode 100644 (file)
index 0000000..c2d4723
--- /dev/null
@@ -0,0 +1,87 @@
+#!/usr/bin/perl -w
+#
+# udev-log-amplify
+#
+# Copyright (C) Intel Corp, 2004
+#
+# Author: Yin Hu <hu.yin@intel.com> 
+#
+# This is a script for replacing udev binary during udevsend/udevd testing.
+# It first amplifies the execution time ( sleep 5 ) and then logs the event 
+# information sent by udved in order that test script udevd-test.pl can
+# analyze whether udved execute as we expected.
+# You should not execute this script directly because it will be invoked by 
+# udevd automatically.
+#
+# Before you run your test please modify $log_file to designate where the udev
+# log file should be placed, in fact, the default value is ok. 
+#
+#
+#      This program is free software; you can redistribute it and/or modify it
+#      under the terms of the GNU General Public License as published by the
+#      Free Software Foundation version 2 of the License.
+#
+#      This program is distributed in the hope that it will be useful, but
+#      WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#      General Public License for more details.
+#
+#      You should have received a copy of the GNU General Public License along
+#      with this program; if not, write to the Free Software Foundation, Inc.,
+#      675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+use warnings;
+use strict;
+
+# modifiable settings
+my $udev_exe_time = 5;
+my $log_file  = "/tmp/udev_log.txt";
+
+# global variables
+my $devpath;
+my $action;
+my $subsystem;
+
+# common functions
+sub getDate {
+       # Get current date/time
+       # If we want GTM time, simply pass GMT as first argument to this function.
+
+       my $format = @_;
+       my $date;
+
+       if( $format =~ /GMT/i ) {
+               $date = gmtime() . " GMT";
+       } else {
+               $date = localtime();
+       }
+       return $date;
+}
+
+# main program
+if ($ARGV[0]) {
+       $subsystem = $ARGV[0];
+       $devpath = $ENV{DEVPATH};
+       $action = $ENV{ACTION};
+
+       # Get current system date
+       my $time = getDate();
+
+       # Logging
+       if (open(LOGF, ">>$log_file")) {
+               print LOGF "$devpath,$action,$subsystem,$time\n";
+       } else {
+               print "File open failed. \n";
+               exit 1;
+       }
+       close(LOGF);
+
+       # Amplify the execution time of udev
+       sleep 5;
+
+       exit 0;
+} else {
+       print "Too less argument count.\n";
+       exit 1;
+}
diff --git a/test/udevd-test/udev-log-script.pl b/test/udevd-test/udev-log-script.pl
new file mode 100644 (file)
index 0000000..5f4f8a4
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/perl -w
+#
+# udev-log-script
+#
+# Copyright (C) Intel Corp, 2004
+#
+# Author: Yin Hu <hu.yin@intel.com> 
+#
+# This is a script for replacing udev binary during udevsend/udevd testing.
+# It just simply logs the event information sent by udved in order to
+# test script udevd-test.pl can analyze whether udved execute as we expected.
+# You should not execute this script directly because it will be invoked by
+# udevd automatically.
+#
+# Before you run your test please modify $log_file to designate where the udev
+# log file should be placed, in fact, the default value is ok.
+#
+# 
+#      This program is free software; you can redistribute it and/or modify it
+#      under the terms of the GNU General Public License as published by the
+#      Free Software Foundation version 2 of the License.
+#  
+#      This program is distributed in the hope that it will be useful, but
+#      WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#      General Public License for more details.
+#
+#      You should have received a copy of the GNU General Public License along
+#      with this program; if not, write to the Free Software Foundation, Inc.,
+#      675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+use warnings;
+use strict;
+
+# modifiable settings
+my $log_file  = "/tmp/udev_log.txt";
+
+# global variables
+my $devpath;
+my $action;
+my $subsystem;
+
+# common functions
+sub getDate {
+        # Get current date/time
+        # If we want GTM time, simply pass GMT as first argument to this function.
+        my $format = @_;
+        my $date;
+
+        if( $format =~ /GMT/i ) {
+                $date = gmtime() . " GMT";
+        } else {
+                $date = localtime();
+        }
+        return $date;
+}
+
+# main program
+if ($ARGV[0]) {
+       # prepare
+       $subsystem = $ARGV[0];
+       $devpath = $ENV{DEVPATH};
+       $action = $ENV{ACTION};
+
+       # Get current system date
+       my $time = getDate();
+
+       # Logging
+        if (open(LOGF, ">>$log_file")) {
+               print LOGF "$devpath,$action,$subsystem,$time\n";
+       } else {
+               print "File open failed. \n";
+               exit 1;
+       }
+        close(LOGF);
+
+       exit 0;
+} else {
+       print "Too less argument count.\n";
+       exit 1;
+}
diff --git a/test/udevd-test/udevd-test.pl b/test/udevd-test/udevd-test.pl
new file mode 100644 (file)
index 0000000..060c3ec
--- /dev/null
@@ -0,0 +1,669 @@
+#!/usr/bin/perl -w
+#
+# udevd-test
+#
+# Copyright (C) Intel Corp, 2004
+#
+# Author: Yin Hu <hu.yin@intel.com> 
+#        Kay Sievers <kay.sievers@vrfy.org>
+#
+# Provides automated testing of the udevd binary.This test script is self-contained.
+# Before you run this script please modify $sysfs to locate your sysfs filesystem, 
+# modify $udevd_bin to locate your udevsend binary,
+# modify $udev_bin to locate dummy udev script,
+# modify $udev_bin2 to locate another dummy udev script ( amplify the execution time for test),
+# modify $log_file to locate where udev script have placed the log file,
+# modify $time_out to decide the time out for events,
+# modify $udev_exe_time to decide the execution time for dummy udev script.
+#
+# Detail information of each test case please refer to the header of corresponding
+# test case function.
+#
+#
+#      This program is free software; you can redistribute it and/or modify it
+#      under the terms of the GNU General Public License as published by the
+#      Free Software Foundation version 2 of the License.
+#
+#      This program is distributed in the hope that it will be useful, but
+#      WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#      General Public License for more details.
+#
+#      You should have received a copy of the GNU General Public License along
+#      with this program; if not, write to the Free Software Foundation, Inc.,
+#      675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+use warnings;
+use strict;
+
+# modifiable settings
+my $sysfs     = "../sys";
+my $udevd_bin = "../../udevsend";
+my $udev_bin  = "$ENV{PWD}/udev-log-script.pl";
+my $udev_bin2 = "$ENV{PWD}/udev-log-amplify.pl";
+my $log_file  = "/tmp/udev_log.txt";
+my $time_out  = 10;
+my $udev_exe_time = 5;
+
+# global variables
+my $test_case = 0;
+
+# common functions
+
+sub kill_daemon {
+       system("killall udevd");
+       system("rm -f $log_file");
+       sleep 1;
+}
+
+sub udevsend {
+       # This function prepares corresponding environment variables
+       # and then call $udevd_bin to send event.
+
+       my ($seqnum, $devpath, $action, $subsystem, $udev_bin_tmp) = @_;
+
+       $ENV{DEVPATH} = $devpath;
+       $ENV{ACTION} = $action;
+       $udev_bin_tmp = $udev_bin if ( not $udev_bin_tmp );
+       $ENV{UDEV_BIN} = $udev_bin_tmp;
+       if ( $seqnum != -1) {
+               $ENV{SEQNUM} = $seqnum;
+       } else {
+               delete $ENV{SEQNUM};
+       }
+
+       return system("$udevd_bin $subsystem");
+}
+
+sub getDate {
+       # Get current date function
+       # If we want GTM time, simply pass GMT as first argument to this function.
+
+       my $format = @_;
+       my $date;
+
+       if( $format =~ /GMT/i ) {
+               $date = gmtime() . " GMT";
+       } else {
+               $date = localtime();
+       }
+
+       return $date;
+}
+
+sub cmpDate {
+       # This function should return a difference betweent date1 and date2
+
+       my ($date1, $date2) = @_;
+       my @monList = ( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+                         "Aug", "Sep", "Oct", "Nov", "Dec" );
+       my ( $m1, $m2, $tmp );
+
+       $date1 =~ s/([\D]*)$//g;
+       $date2 =~ s/([\D]*)$//g;
+
+       return if( (not $date1) or (not $date2) );
+
+       my $mon = 0;
+
+       my ( @T1 ) =
+        ( $date1 =~ /([\d]+)[\s]+([\d]+):([\d]+):([\d]+)[\s]+([\d]+)/g );
+       my ( @T2 ) = 
+        ( $date2 =~ /([\d]+)[\s]+([\d]+):([\d]+):([\d]+)[\s]+([\d]+)/g );
+
+       foreach $tmp (@monList) {
+               $m1 = sprintf("%2.2d",$mon) if( $date1 =~ /$tmp/i );
+               $m2 = sprintf("%2.2d",$mon) if( $date2 =~ /$tmp/i );
+               $mon++;
+       }
+
+       my $dt1 = sprintf("%4.4d%s%2.2d%2.2d%2.2d%2.2d", $T1[4], $m1, $T1[0],
+                                       $T1[1], $T1[2], $T1[3]);
+       my $dt2 = sprintf("%4.4d%s%2.2d%2.2d%2.2d%2.2d", $T2[4], $m2, $T2[0],
+                                       $T2[1], $T2[2], $T2[3]);
+
+       my $ret = $dt1 - $dt2;
+
+       if ( $ret > 40 ) {
+               $ret = abs($ret-40);
+       }
+
+       return $ret;
+}
+
+sub check_count_and_time { 
+       my $event_recv_time;
+       my $udev_fork_time;
+       my $log_ln_count = 0;
+       my $line;
+       my @content;
+       my @line_items;
+       my $diff;
+
+       ($event_recv_time) = @_;
+
+       print "   event receiving time:  $event_recv_time\n\n";
+
+       open(LOGF, $log_file) || die "Opening file $log_file: $!";
+       @content = <LOGF>;
+       foreach $line ( @content ) {
+               @line_items = split(/,/,$line);
+               print "   device: $line_items[0], action: $line_items[1] \n";
+               print "   forking udev time:     $line_items[-1]";
+               $diff = cmpDate($line_items[-1], $event_recv_time);
+               print "   the delay time is:     $diff s \n\n";
+               if ( $diff > $time_out ) {
+                       print "   the delay time is: $diff \n";
+                       print "   udevd doesn't act properly. \n";
+                       exit 1;
+               }
+               $log_ln_count++;
+       }
+       close(LOGF);
+
+       return $log_ln_count;
+}
+
+sub check_sysfs_device_exist {
+       # check if the designated devices exist
+       my @dev_list = @_;
+       my $dev;
+
+       foreach $dev (@dev_list) {
+               if (! -e $dev) {
+                       print "the designated device $dev doesn't exist. please change a device!\n";
+                       exit 1;
+               }
+       }
+}
+
+sub show_result {
+       my $event_recv_time;
+       my $udev_fork_time;
+       my $line;
+       my @content;
+       my @line_items;
+       my $diff;
+
+       ($event_recv_time) = @_;
+
+       print "   event receiving time:  $event_recv_time\n\n";
+
+       open(LOGF, $log_file) || die "Opening file $log_file: $!";
+       @content = <LOGF>;
+       foreach $line ( @content ) {
+               @line_items = split(/,/,$line);
+               print "   device: $line_items[0], action: $line_items[1] \n";
+               print "   forking udev time:     $line_items[-1]";
+               $diff = cmpDate($line_items[-1], $event_recv_time);
+               print "   the delay time is:     $diff s \n\n";
+       }
+       close(LOGF);
+}
+
+sub show_result_tm_out {
+       my $event_recv_time;
+       my $udev_fork_time;
+       my $line;
+       my @content;
+       my @line_items;
+       my $diff;
+
+       ($event_recv_time) = @_;
+
+       print "   event receiving time:  $event_recv_time\n\n";
+
+       open(LOGF, $log_file) || die "Opening file $log_file: $!";
+       @content = <LOGF>;
+       foreach $line ( @content ) {
+               @line_items = split(/,/,$line);
+               print "   device: $line_items[0], action: $line_items[1] \n";
+               print "   forking udev time:     $line_items[-1]";
+               $diff = cmpDate($line_items[-1], $event_recv_time);
+               print "   the delay time is:     $diff s \n\n";
+               if ( $diff < $time_out ) {
+                       print "   the delay time is:     $diff \n";
+                       print "   udevd doesn't act properly. \n";
+                       exit 1;
+               }
+       }
+       close(LOGF);
+}
+
+sub show_result_immediate {
+       my $event_recv_time;
+       my $udev_fork_time;
+       my $line;
+       my @content;
+       my @line_items;
+       my $diff;
+
+       ($event_recv_time) = @_;
+
+       print "   event receiving time:  $event_recv_time\n\n";
+
+       open(LOGF, $log_file) || die "Opening file $log_file: $!";
+       @content = <LOGF>;
+       foreach $line ( @content ) {
+               @line_items = split(/,/,$line);
+               print "   device: $line_items[0], action: $line_items[1] \n";
+               print "   forking udev time:     $line_items[-1]";
+               $diff = cmpDate($line_items[-1], $event_recv_time);
+               print "   the delay time is:     $diff s \n\n";
+               if ( $diff > $time_out ) {
+                       print "   the delay time is:     $diff \n";
+                       print "   udevd doesn't act properly. \n";
+                       exit 1;
+               }
+       }
+       close(LOGF);
+}
+
+sub check_exe_time {
+       my @exe_time;
+       my $i = 0;
+       my $line;
+       my @content;
+       my @line_items;
+       my $diff;
+
+       open(LOGF, $log_file) || die "Opening file $log_file: $!";
+       @content = <LOGF>;
+       close(LOGF);
+       foreach $line ( @content ) {
+               @line_items = split(/,/,$line);
+               $exe_time[$i] = $line_items[-1];
+               $i++;
+       }
+       $diff = cmpDate($exe_time[1], $exe_time[0]);
+       if ( $diff < $udev_exe_time ) {
+               print "   there are more than one udev instance for a single device at the same time. \n";
+               exit 1;
+       } else {
+               print "   there is just one udev instance for a single device at the same time. \n";
+       }
+}
+
+# test case functions
+sub run_no_seq_test {
+       print "Test case name:     no sequence number test\n";
+       print "Test case purpose:  check whether udevd forks udev immediately when environment variable SEQNUM is null.\n";
+       print "Test expected visible results: \n";
+       print "   the delay time between event receiving and forking udev for udevd should be negligible, \n";
+       print "   that is, udev should be forked at once. please notice the following time...\n\n";
+
+       # local variables
+       my $time;
+
+       #
+       # add devices event test
+       #
+       kill_daemon();
+
+       # check if devices /block/sda exist
+       check_sysfs_device_exist("$sysfs/block/sda");
+
+       # log current system date/time
+       $time = getDate();
+
+       # fork udevd
+       udevsend(-1, "/block/sda", "add", "block");
+
+       # check if execution is successful in time
+       sleep 1;
+       show_result_immediate($time);
+       print "   fork udev (add device) at once successfully.\n\n";
+
+       #
+       # remove devices event test
+       #
+       system("rm -f $log_file");
+
+       # log current system date/time
+       $time = getDate();
+
+       # fork udevd
+       udevsend(-1, "/block/sda", "remove", "block");
+
+       # check if execution is successful in time
+       sleep 1;
+       show_result_immediate($time);
+       print "   fork udev (remove device) at once successfully.\n\n";
+       print "this case is ok\n\n";
+}
+
+sub run_normal_seq_test {
+       print "Test case name:    normal sequence number stress test\n";
+       print "Test case purpose: check whether udevd can fork massive udev instances for \n";
+       print "                   massive sequential events successfully. \n";
+       print "Test expected visible results: \n";
+       print "   Populate all the devices in directory $sysfs/class/tty, fork udved to send add/remove \n";
+       print "   event to udev for each device. \n";
+       print "   We can see the delay time for each device should be negligible. \n\n";
+
+       # local variables
+       my @file_list;
+       my $file;
+       my $seq = 0;
+       my $time;
+       my $ret_seq;
+
+       # prepare
+       kill_daemon();
+       @file_list = glob "$sysfs/class/tty/*";
+
+       # log current system date/time for device add events
+       $time = getDate();
+
+       #
+       # add devices event test
+       #
+       print "add device events test: \n";
+       foreach $file (@file_list) {
+               udevsend($seq, substr($file, length($sysfs), length($file)-length($sysfs)), "add", "tty");
+               # check if execution is successful
+               if ($? == 0) {
+                       $seq++;
+               } else {
+                       print "add event: error\n\n";
+                       exit 1;
+               }
+       }
+
+       # we'd better wait the udev to create all the device for a few seconds
+       print "   wait for udevd processing about $time_out s... \n\n";
+       sleep $time_out;
+
+       $ret_seq = check_count_and_time($time);
+       if ( $ret_seq != $seq ) {
+               print "   add event: failed. some device-adding events fail to execute.\n\n";
+               exit 1;
+       } else {
+               print "   $seq pieces of device-adding events have executed successfully.\n\n";
+       }
+
+       # log current system date/time for device remove events
+       $time = getDate();
+
+       #
+       # remove devices event test
+       #
+       print "remove device events test: \n";
+       kill_daemon();
+       @file_list = glob "$sysfs/class/tty/*"; 
+       $seq = 0;
+       foreach $file (@file_list) {
+               udevsend($seq, substr($file, length($sysfs), length($file)-length($sysfs)), "remove", "tty");
+               # check if execution is successful
+               if ($? == 0) {
+                       $seq++;
+               } else {
+                       print "remove event: error\n\n";
+                       exit 1;
+               }
+       }
+
+       # we'd better wait the udev to create all the device for a few seconds
+       print "   waiting for udev removing devices (about $time_out s)...\n";
+       sleep $time_out;
+
+       # show results
+       $ret_seq = check_count_and_time($time);
+       if ( $ret_seq != $seq ) {
+               print "   remove event: failed. some device-removing events fail to execute.\n\n";
+               exit 1;
+       } else {
+               print "   $seq pieces of device-removing events have executed successfully.\n\n";
+               print "this case is ok.\n\n";
+       }
+}
+
+sub run_random_seq_test {
+       print "Test case name:    random sequence number test case,\n";
+       print "Test case purpose: check whether udevd can order the events with random sequence number \n";
+       print "                   and fork udev correctly. \n";
+       print "Test expected visible results: \n";
+       print "   We have disordered the events sent to udevd, if udevd can order them correctly, the devices' \n";
+       print "   add/remove sequence should be tty0, tty1, tty2. \n\n";
+
+       # local variables
+       my $time;
+
+       # check if devices /class/tty/tty0, tty1, tty2 exist
+       check_sysfs_device_exist("$sysfs/class/tty/tty0", "$sysfs/class/tty/tty1", "$sysfs/class/tty/tty2");
+
+       #
+       # add device events test
+       #
+       print "add device events test: \n";
+       kill_daemon();
+
+       # log current system date/time for device remove events
+       $time = getDate();
+
+       # parameters: 1 sequence number, 2 device, 3 action, 4 subsystem
+       udevsend(3, "/class/tty/tty2", "add", "tty");
+       udevsend(1, "/class/tty/tty0", "add", "tty");
+       udevsend(2, "/class/tty/tty1", "add", "tty");
+       print "   wait for udevd processing about $time_out s... \n\n";
+       sleep $time_out+1;
+       show_result_tm_out($time);
+
+       #
+       # remove device events test
+       #
+       print "\nremove device events test: \n";
+       kill_daemon();
+
+       # log current system date/time for device remove events
+       $time = getDate();
+
+       # fork udevd
+       udevsend(3, "/class/tty/tty2", "remove", "tty");
+       udevsend(2, "/class/tty/tty1", "remove", "tty");
+       udevsend(1, "/class/tty/tty0", "remove", "tty");
+
+       # show results
+       print "   wait for udevd processing about $time_out s... \n\n";
+       sleep $time_out+1;
+       show_result_tm_out($time);
+       print "this case is ok.\n\n";
+}
+
+sub run_expected_seq_test { 
+       print "Test case name:    expected sequence number test \n";
+       print "Test case purpose: check whether udevd fork udev immediately when the incoming event\n";
+       print "                   is exactly the expected event sequence number.\n";
+       print "Test expected visible results:\n";
+       print "   first, udevd disposes disorder events(sequence number is 3,1,2,5,4,6),\n";
+       print "   thus after disposed the expected event number for udevd is 7, when incoming event is 7, udevd\n";
+       print "   should fork udev immediately, the delay time should be negligible. \n";
+       print "   where: event 7 is (add device /class/tty/tty2) \n\n";
+
+       # local variables
+       my $time;
+
+       # check if devices /class/tty0, tty1, tty2 exist
+       check_sysfs_device_exist("$sysfs/class/tty/tty0", "$sysfs/class/tty/tty1", "$sysfs/class/tty/tty2");
+
+       # prepare
+       kill_daemon();
+
+       # parameters: 1 sequence number, 2 device, 3 action, 4 subsystem
+       udevsend(3, "/class/tty/tty2", "add", "tty");
+       udevsend(1, "/class/tty/tty0", "add", "tty");
+       udevsend(2, "/class/tty/tty1", "add", "tty");
+       udevsend(5, "/class/tty/tty1", "remove", "tty");
+       udevsend(4, "/class/tty/tty0", "remove", "tty");
+       udevsend(6, "/class/tty/tty2", "remove", "tty");
+
+       print "   wait for udevd timing out for disorder events (about $time_out s) \n\n";
+       sleep $time_out+1;
+       system("rm -f $log_file");
+
+       # log current system date/time for device remove events
+       $time = getDate();
+
+       # show results
+       udevsend(7, "/class/tty/tty2", "add", "tty");
+       sleep 1;
+       print "   event sequence number: 7 \n";
+       show_result_immediate($time);
+
+       print "this case is ok.\n\n";
+}
+
+sub run_single_instance_test { 
+       print "Test case name:    single instance running for a single device test \n";
+       print "Test case purpose: check whether udevd only fork one udev instance for a single\n";
+       print "                   device at the same time. For each event a udev instance is \n";
+       print "                   executed in the background. All further events for the same \n";
+       print "                   device are delayed until the execution is finished. This way \n";
+       print "                   there will never be more than one instance running for a single \n";
+       print "                   device at the same time.\n";
+       print "Test expected visible results:\n";
+       print "   In this test we amplify the execution time of udev (about 5 seconds), first, \n";
+       print "   we send a add event for device /block/sda, and then we send a remove event, so the \n";
+       print "   execution of remove event should be delayed until add is finished. \n\n";
+
+       # local variables
+       my $time;
+
+       # prepare
+       kill_daemon();
+
+       # check if device exists
+       check_sysfs_device_exist("$sysfs/block/sda");
+
+       # log current system date/time
+       $time = getDate();
+
+       # fork udved
+       udevsend(-1, "/block/sda", "add", "block", $udev_bin2);
+       udevsend(-1, "/block/sda", "remove", "block", $udev_bin2);
+
+       # show results
+       print "   wait for udevd processing about $udev_exe_time s... \n\n";
+       sleep $udev_exe_time+1;
+       show_result_immediate($time);
+       check_exe_time();
+       print "this case is ok\n\n";
+}
+
+sub run_same_events_test { 
+       print "Test case name:    event sequence number overlap test \n";
+       print "Test case purpose: check whether udevd doesn't fork udev untill time out\n";
+       print "                   when encountering a event with sequence number same as the pevious event. \n";
+       print "Test expected visible results:\n";
+       print "   event ( remove device /block/sda ) should be no delay, \n";
+       print "   event ( add device /class/tty/tty1 ) should be delayed for $time_out s than its previous \n";
+       print "   event ( remove device /block/sda ) \n\n";
+
+       # local variables
+       my $time;
+
+       # prepare
+       kill_daemon();
+
+       # check if device exist
+       check_sysfs_device_exist("$sysfs/block/sda", "$sysfs/class/tty/tty1");
+
+       # fork udevd
+       udevsend(0, "/block/sda", "add", "block");
+
+       # log current system date/time
+       sleep 1;
+       $time = getDate();
+       system("rm -f $log_file");
+
+       # fork udevd
+       udevsend(1, "/block/sda", "remove", "block");
+       udevsend(1, "/class/tty/tty1", "add", "tty");
+
+       # show results
+       print "   wait for udevd processing about $time_out s... \n\n";
+       sleep $time_out+1;
+       show_result($time);
+       print "this case is ok\n\n";
+}
+
+sub run_missing_seq_test {
+       print "Test case name:    missing sequence number test \n";
+       print "Test case purpose: check whether udevd doesn't fork udev untill time out\n";
+       print "                   when certain event sequence number is missing.\n";
+       print "Test expected visible results:\n";
+       print "   the delay time for event(add device /block/sda) should be about $time_out s.\n\n";
+
+       # local variables
+       my $time;
+
+       # prepare
+       kill_daemon();
+
+       # check if device exist
+       check_sysfs_device_exist("$sysfs/block/sda", "$sysfs/class/tty/tty1");
+
+       # fork udevd
+       udevsend(0, "/class/tty/tty1", "add", "tty");
+       udevsend(1, "/class/tty/tty1", "remove", "tty");
+       sleep 1;
+
+       # log current system date/time
+       $time = getDate();
+       system("rm -f $log_file");
+
+       # fork udevd
+       udevsend(3, "/block/sda", "add", "block");
+
+       # show results
+       print "   wait for udevd processing about $time_out s... \n\n";
+       sleep $time_out+1;
+       show_result($time);
+       print "this case is ok\n\n";
+}
+
+sub run_all_cases_test { 
+       run_no_seq_test();
+       run_normal_seq_test();
+       run_random_seq_test();
+       run_missing_seq_test();
+       run_expected_seq_test();
+       run_same_events_test();
+       run_single_instance_test();
+}
+
+# main program
+if ($ARGV[0]) {
+       $test_case = $ARGV[0];
+
+       if ($test_case == 1) {
+               run_no_seq_test();
+       } elsif ($test_case == 2) {
+               run_normal_seq_test();
+       } elsif ($test_case == 3) {
+               run_random_seq_test();
+       } elsif ($test_case == 4) {
+               run_missing_seq_test();
+       } elsif ($test_case == 5) {
+               run_expected_seq_test();
+       } elsif ($test_case == 6) {
+               run_single_instance_test();
+       } elsif ($test_case == 7) {
+               run_same_events_test();
+       } else {
+               run_all_cases_test();
+       }
+} else {
+       # echo usage
+       print "command format: perl udevd-test.pl <case number>\n";
+       print "   test case:\n";
+       print "           1: no event sequence number\n";
+       print "           2: sequential event sequence number\n";
+       print "           3: random event sequence number\n";
+       print "           4: missing event sequence number\n";
+       print "           5: the incoming event sequence number is right the expected sequence number\n";
+       print "           6: single udev instance on a single device at the same time\n";
+       print "           7: test event sequence number overlap\n";
+       print "           9: all the cases\n\n";
+}
diff --git a/udevd.c b/udevd.c
index b2cb62f..d807e41 100644 (file)
--- a/udevd.c
+++ b/udevd.c
@@ -60,6 +60,7 @@ static void exec_queue_manager(void);
 static void msg_queue_manager(void);
 static void user_sighandler(void);
 static void reap_kids(void);
+char *udev_bin;
 
 #ifdef LOG
 unsigned char logname[LOGNAME_SIZE];
@@ -146,7 +147,7 @@ static void udev_run(struct hotplug_msg *msg)
        switch (pid) {
        case 0:
                /* child */
-               execle(UDEV_BIN, "udev", msg->subsystem, NULL, env);
+               execle(udev_bin, "udev", msg->subsystem, NULL, env);
                dbg("exec of child failed");
                exit(1);
                break;
@@ -458,6 +459,13 @@ int main(int argc, char *argv[])
        /* enable receiving of the sender credentials */
        setsockopt(ssock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
 
+       /* possible override of udev binary, used for testing */
+       udev_bin = getenv("UDEV_BIN");
+       if (udev_bin != NULL)
+               dbg("udev binary is set to '%s'", udev_bin);
+       else
+               udev_bin = UDEV_BIN;
+
        FD_ZERO(&readfds);
        FD_SET(ssock, &readfds);
        FD_SET(pipefds[0], &readfds);