chiark / gitweb /
add edd_id tool to match BIOS EDD disk information
[elogind.git] / test / udevd-test / udevd-test.pl
1 #!/usr/bin/perl -w
2 #
3 # udevd-test
4 #
5 # Copyright (C) Intel Corp, 2004
6 #
7 # Author: Yin Hu <hu.yin@intel.com> 
8 #
9 # Provides automated testing of the udevd binary.This test script is self-contained.
10 # Before you run this script please modify $sysfs to locate your sysfs filesystem, 
11 # modify $udevsend_bin to locate your udevsend binary,
12 # modify $udev_bin to locate dummy udev script,
13 # modify $udev_bin2 to locate another dummy udev script ( amplify the execution time for test),
14 # modify $log_file to locate where udev script have placed the log file,
15 # modify $time_out to decide the time out for events,
16 # modify $udev_exe_time to decide the execution time for dummy udev script.
17 #
18 # Detail information of each test case please refer to the header of corresponding
19 # test case function.
20 #
21 #
22 #       This program is free software; you can redistribute it and/or modify it
23 #       under the terms of the GNU General Public License as published by the
24 #       Free Software Foundation version 2 of the License.
25 #
26 #       This program is distributed in the hope that it will be useful, but
27 #       WITHOUT ANY WARRANTY; without even the implied warranty of
28 #       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29 #       General Public License for more details.
30 #
31 #       You should have received a copy of the GNU General Public License along
32 #       with this program; if not, write to the Free Software Foundation, Inc.,
33 #       675 Mass Ave, Cambridge, MA 02139, USA.
34 #
35
36 use warnings;
37 use strict;
38
39 # modifiable settings
40 my $sysfs     =         "../sys";
41 my $udevd_bin = "../../udevd";
42 my $udevsend_bin =      "../../udevsend";
43 my $udev_bin  =         "$ENV{'PWD'}/udev-log-script.pl";
44 my $udev_bin2 =         "$ENV{'PWD'}/udev-log-amplify.pl";
45 my $log_file  =         "/tmp/udev_log.txt";
46 my $time_out  =         10;
47 my $udev_exe_time =     5;
48
49 # global variables
50 my $test_case = 0;
51
52 # common functions
53
54 sub restart_daemon {
55         my ($udev_binary) = @_;
56
57         system("killall udevd");
58         system("rm -f $log_file");
59         sleep 1;
60
61         if (!defined($udev_binary)) {
62                 $udev_binary = $udev_bin;
63         }
64
65         $ENV{'UDEV_BIN'} = $udev_binary;
66         system("/bin/sh -c $udevd_bin&");
67         sleep(1);
68 }
69
70 sub udevsend {
71         # This function prepares corresponding environment variables
72         # and then call $udevsend_bin to send event.
73
74         my ($seqnum, $devpath, $action, $subsystem, $script) = @_;
75
76         %ENV = ();
77         $ENV{'DEVPATH'} = $devpath;
78         $ENV{'ACTION'} = $action;
79         $ENV{'SUBSYSTEM'} = $subsystem;
80
81         if ( $seqnum != -1) {
82                 $ENV{SEQNUM} = $seqnum;
83         }
84
85         return system("$udevsend_bin $subsystem");
86 }
87
88 sub check_count_and_time { 
89         my $event_recv_time;
90         my $udev_fork_time;
91         my $log_ln_count = 0;
92         my $line;
93         my @content;
94         my @line_items;
95         my $diff;
96
97         ($event_recv_time) = @_;
98
99         print "   event receiving time:  $event_recv_time\n\n";
100
101         open(LOGF, $log_file) || die "Opening file $log_file: $!";
102         @content = <LOGF>;
103         foreach $line ( @content ) {
104                 @line_items = split(/,/,$line);
105                 print "   device: $line_items[0], action: $line_items[1] \n";
106                 print "   forking udev time:     $line_items[-1]";
107                 $diff = $line_items[-1] - $event_recv_time;
108                 print "   the delay time is:     $diff s \n\n";
109                 if ( $diff > $time_out+10 ) {
110                         print "   the delay time is: $diff \n";
111                         print "   udevd doesn't act properly. \n";
112                         exit 1;
113                 }
114                 $log_ln_count++;
115         }
116         close(LOGF);
117
118         return $log_ln_count;
119 }
120
121 sub check_sysfs_device_exist {
122         # check if the designated devices exist
123         my @dev_list = @_;
124         my $dev;
125
126         foreach $dev (@dev_list) {
127                 if (! -e $dev) {
128                         print "the designated device $dev doesn't exist. please change a device!\n";
129                         exit 1;
130                 }
131         }
132 }
133
134 sub show_result {
135         my $event_recv_time;
136         my $udev_fork_time;
137         my $line;
138         my @content;
139         my @line_items;
140         my $diff;
141
142         ($event_recv_time) = @_;
143
144         print "   event receiving time:  $event_recv_time\n\n";
145
146         open(LOGF, $log_file) || die "Opening file $log_file: $!";
147         @content = <LOGF>;
148         foreach $line ( @content ) {
149                 @line_items = split(/,/,$line);
150                 print "   device: $line_items[0], action: $line_items[1] \n";
151                 print "   forking udev time:     $line_items[-1]";
152                 $diff = $line_items[-1] - $event_recv_time;
153                 print "   the delay time is:     $diff s \n\n";
154         }
155         close(LOGF);
156 }
157
158 sub show_result_tm_out {
159         my $event_recv_time;
160         my $udev_fork_time;
161         my $line;
162         my @content;
163         my @line_items;
164         my $diff;
165
166         ($event_recv_time) = @_;
167
168         print "   event receiving time:  $event_recv_time\n\n";
169
170         open(LOGF, $log_file) || die "Opening file $log_file: $!";
171         @content = <LOGF>;
172         foreach $line ( @content ) {
173                 @line_items = split(/,/,$line);
174                 print "   device: $line_items[0], action: $line_items[1] \n";
175                 print "   forking udev time:     $line_items[-1]";
176                 $diff = $line_items[-1] - $event_recv_time;
177                 print "   the delay time is:     $diff s \n\n";
178                 if ( $diff < $time_out ) {
179                         print "   the delay time is:     $diff \n";
180                         print "   udevd doesn't act properly. \n";
181                         exit 1;
182                 }
183         }
184         close(LOGF);
185 }
186
187 sub show_result_immediate {
188         my $event_recv_time;
189         my $udev_fork_time;
190         my $line;
191         my @content;
192         my @line_items;
193         my $diff;
194
195         ($event_recv_time) = @_;
196
197         print "   event receiving time:  $event_recv_time\n\n";
198
199         open(LOGF, $log_file) || die "Opening file $log_file: $!";
200         @content = <LOGF>;
201         foreach $line ( @content ) {
202                 @line_items = split(/,/,$line);
203                 print "   device: $line_items[0], action: $line_items[1] \n";
204                 print "   forking udev time:     $line_items[-1]";
205                 $diff = $line_items[-1] - $event_recv_time;
206                 print "   the delay time is:     $diff s \n\n";
207                 if ( $diff > $time_out ) {
208                         print "   the delay time is:     $diff \n";
209                         print "   udevd doesn't act properly. \n";
210                         exit 1;
211                 }
212         }
213         close(LOGF);
214 }
215
216 sub check_exe_time {
217         my @exe_time;
218         my $i = 0;
219         my $line;
220         my @content;
221         my @line_items;
222         my $diff;
223
224         open(LOGF, $log_file) || die "Opening file $log_file: $!";
225         @content = <LOGF>;
226         close(LOGF);
227         foreach $line ( @content ) {
228                 @line_items = split(/,/,$line);
229                 $exe_time[$i] = $line_items[-1];
230                 $i++;
231         }
232         $diff = $exe_time[1] - $exe_time[0];
233         if ( $diff < $udev_exe_time ) {
234                 print "   there are more than one udev instance for a single device at the same time. \n";
235                 exit 1;
236         } else {
237                 print "   there is just one udev instance for a single device at the same time. \n";
238         }
239 }
240
241 # test case functions
242 sub run_no_seq_test {
243         print "Test case name:     no sequence number test\n";
244         print "Test case purpose:  check whether udevd forks udev immediately when environment variable SEQNUM is null.\n";
245         print "Test expected visible results: \n";
246         print "   the delay time between event receiving and forking udev for udevd should be negligible, \n";
247         print "   that is, udev should be forked at once. please notice the following time...\n\n";
248
249         my $time;
250
251         #
252         # add devices event test
253         #
254         restart_daemon();
255
256         # check if devices /block/sda exist
257         check_sysfs_device_exist("$sysfs/block/sda");
258
259         # log current system date/time
260         $time = time();
261
262         udevsend(-1, "/block/sda", "add", "block");
263
264         # check if execution is successful in time
265         sleep 1;
266         show_result_immediate($time);
267         print "   fork udev (add device) at once successfully.\n\n";
268
269         #
270         # remove devices event test
271         #
272         system("rm -f $log_file");
273
274         # log current system date/time
275         $time = time();
276
277         udevsend(-1, "/block/sda", "remove", "block");
278
279         # check if execution is successful in time
280         sleep 1;
281         show_result_immediate($time);
282         print "   fork udev (remove device) at once successfully.\n\n";
283         print "this case is ok\n\n";
284 }
285
286 sub run_normal_seq_test {
287         print "Test case name:    normal sequence number stress test\n";
288         print "Test case purpose: check whether udevd can fork massive udev instances for \n";
289         print "                   massive sequential events successfully. \n";
290         print "Test expected visible results: \n";
291         print "   Populate all the devices in directory $sysfs/class/tty, fork udved to send add/remove \n";
292         print "   event to udev for each device. \n";
293         print "   We can see the delay time for each device should be negligible. \n\n";
294
295         my @file_list;
296         my $file;
297         my $seq = 0;
298         my $time;
299         my $ret_seq;
300
301         restart_daemon();
302         @file_list = glob "$sysfs/class/tty/*";
303
304         # log current system date/time for device add events
305         $time = time();
306
307         #
308         # add devices event test
309         #
310         print "add device events test: \n";
311         foreach $file (@file_list) {
312                 udevsend($seq, substr($file, length($sysfs), length($file)-length($sysfs)), "add", "tty");
313                 # check if execution is successful
314                 if ($? == 0) {
315                         $seq++;
316                 } else {
317                         print "add event: error\n\n";
318                         exit 1;
319                 }
320         }
321
322         # we'd better wait the udev to create all the device for a few seconds
323         print "   wait for udevd processing about $time_out s... \n\n";
324         sleep $time_out + 5;
325
326         $ret_seq = check_count_and_time($time);
327         if ( $ret_seq != $seq ) {
328                 print "   add event: failed. some device-adding events fail to execute.\n\n";
329                 exit 1;
330         } else {
331                 print "   $seq pieces of device-adding events have executed successfully.\n\n";
332         }
333
334         # log current system date/time for device remove events
335         $time = time();
336
337         #
338         # remove devices event test
339         #
340         print "remove device events test: \n";
341         restart_daemon();
342         @file_list = glob "$sysfs/class/tty/*"; 
343         $seq = 0;
344         foreach $file (@file_list) {
345                 udevsend($seq, substr($file, length($sysfs), length($file)-length($sysfs)), "remove", "tty");
346                 # check if execution is successful
347                 if ($? == 0) {
348                         $seq++;
349                 } else {
350                         print "remove event: error\n\n";
351                         exit 1;
352                 }
353         }
354
355         # we'd better wait the udev to create all the device for a few seconds
356         print "   waiting for udev removing devices (about $time_out s)...\n";
357         sleep $time_out + 5;
358
359         # show results
360         $ret_seq = check_count_and_time($time);
361         if ( $ret_seq != $seq ) {
362                 print "   remove event: failed. some device-removing events fail to execute.\n\n";
363                 exit 1;
364         } else {
365                 print "   $seq pieces of device-removing events have executed successfully.\n\n";
366                 print "this case is ok.\n\n";
367         }
368 }
369
370 sub run_random_seq_test {
371         print "Test case name:    random sequence number test case,\n";
372         print "Test case purpose: check whether udevd can order the events with random sequence number \n";
373         print "                   and fork udev correctly. \n";
374         print "Test expected visible results: \n";
375         print "   We have disordered the events sent to udevd, if udevd can order them correctly, the devices' \n";
376         print "   add/remove sequence should be tty0, tty1, tty2. \n\n";
377
378         my $time;
379
380         # check if devices /class/tty/tty0, tty1, tty2 exist
381         check_sysfs_device_exist("$sysfs/class/tty/tty0", "$sysfs/class/tty/tty1", "$sysfs/class/tty/tty2");
382
383         #
384         # add device events test
385         #
386         print "add device events test: \n";
387         restart_daemon();
388
389         # log current system date/time for device remove events
390         $time = time();
391
392         # parameters: 1 sequence number, 2 device, 3 action, 4 subsystem
393         udevsend(3, "/class/tty/tty2", "add", "tty");
394         udevsend(1, "/class/tty/tty0", "add", "tty");
395         udevsend(2, "/class/tty/tty1", "add", "tty");
396         print "   wait for udevd processing about $time_out s... \n\n";
397         sleep $time_out+1;
398         show_result_tm_out($time);
399
400         #
401         # remove device events test
402         #
403         print "\nremove device events test: \n";
404         restart_daemon();
405
406         # log current system date/time for device remove events
407         $time = time();
408
409         udevsend(3, "/class/tty/tty2", "remove", "tty");
410         udevsend(2, "/class/tty/tty1", "remove", "tty");
411         udevsend(1, "/class/tty/tty0", "remove", "tty");
412
413         # show results
414         print "   wait for udevd processing about $time_out s... \n\n";
415         sleep $time_out+1;
416         show_result_tm_out($time);
417         print "this case is ok.\n\n";
418 }
419
420 sub run_expected_seq_test { 
421         print "Test case name:    expected sequence number test \n";
422         print "Test case purpose: check whether udevd fork udev immediately when the incoming event\n";
423         print "                   is exactly the expected event sequence number.\n";
424         print "Test expected visible results:\n";
425         print "   first, udevd disposes disorder events(sequence number is 3,1,2,5,4,6),\n";
426         print "   thus after disposed the expected event number for udevd is 7, when incoming event is 7, udevd\n";
427         print "   should fork udev immediately, the delay time should be negligible. \n";
428         print "   where: event 7 is (add device /class/tty/tty2) \n\n";
429
430         my $time;
431
432         # check if devices /class/tty0, tty1, tty2 exist
433         check_sysfs_device_exist("$sysfs/class/tty/tty0", "$sysfs/class/tty/tty1", "$sysfs/class/tty/tty2");
434
435         restart_daemon();
436
437         # parameters: 1 sequence number, 2 device, 3 action, 4 subsystem
438         udevsend(3, "/class/tty/tty2", "add", "tty");
439         udevsend(1, "/class/tty/tty0", "add", "tty");
440         udevsend(2, "/class/tty/tty1", "add", "tty");
441         udevsend(5, "/class/tty/tty1", "remove", "tty");
442         udevsend(4, "/class/tty/tty0", "remove", "tty");
443         udevsend(6, "/class/tty/tty2", "remove", "tty");
444
445         print "   wait for udevd timing out for disorder events (about $time_out s) \n\n";
446         sleep $udev_exe_time + $time_out+1;
447         system("rm -f $log_file");
448
449         # log current system date/time for device remove events
450         $time = time();
451
452         # show results
453         udevsend(7, "/class/tty/tty2", "add", "tty");
454         sleep 1;
455         print "   event sequence number: 7 \n";
456         show_result_immediate($time);
457
458         print "this case is ok.\n\n";
459 }
460
461 sub run_single_instance_test { 
462         print "Test case name:    single instance running for a single device test \n";
463         print "Test case purpose: check whether udevd only fork one udev instance for a single\n";
464         print "                   device at the same time. For each event a udev instance is \n";
465         print "                   executed in the background. All further events for the same \n";
466         print "                   device are delayed until the execution is finished. This way \n";
467         print "                   there will never be more than one instance running for a single \n";
468         print "                   device at the same time.\n";
469         print "Test expected visible results:\n";
470         print "   In this test we amplify the execution time of udev (about 5 seconds), first, \n";
471         print "   we send a add event for device /block/sda, and then we send a remove event, so the \n";
472         print "   execution of remove event should be delayed until add is finished. \n\n";
473
474         my $time;
475
476         restart_daemon($udev_bin2);
477
478         # check if device exists
479         check_sysfs_device_exist("$sysfs/block/sda");
480
481         # log current system date/time
482         $time = time();
483
484         udevsend(-1, "/block/sda", "add", "block");
485         udevsend(-1, "/block/sda", "remove", "block");
486
487         # show results
488         print "   wait for udevd processing about $udev_exe_time s... \n\n";
489         sleep $udev_exe_time+1;
490         show_result_immediate($time);
491         check_exe_time();
492         print "this case is ok\n\n";
493 }
494
495 sub run_same_events_test { 
496         print "Test case name:    event sequence number overlap test \n";
497         print "Test case purpose: check whether udevd doesn't fork udev untill time out\n";
498         print "                   when encountering a event with sequence number same as the pevious event. \n";
499         print "Test expected visible results:\n";
500         print "   event ( remove device /block/sda ) should be no delay, \n";
501         print "   event ( add device /class/tty/tty1 ) should be delayed for $time_out s than its previous \n";
502         print "   event ( remove device /block/sda ) \n\n";
503
504         my $time;
505
506         restart_daemon();
507
508         # check if device exist
509         check_sysfs_device_exist("$sysfs/block/sda", "$sysfs/class/tty/tty1");
510
511         udevsend(0, "/block/sda", "add", "block");
512
513         # log current system date/time
514         sleep 1;
515         $time = time();
516         system("rm -f $log_file");
517
518         udevsend(1, "/block/sda", "remove", "block");
519         udevsend(1, "/class/tty/tty1", "add", "tty");
520
521         # show results
522         print "   wait for udevd processing about $time_out s... \n\n";
523         sleep $time_out+1;
524         show_result($time);
525         print "this case is ok\n\n";
526 }
527
528 sub run_missing_seq_test {
529         print "Test case name:    missing sequence number test \n";
530         print "Test case purpose: check whether udevd doesn't fork udev untill time out\n";
531         print "                   when certain event sequence number is missing.\n";
532         print "Test expected visible results:\n";
533         print "   the delay time for event(add device /block/sda) should be about $time_out s.\n\n";
534
535         my $time;
536
537         restart_daemon();
538
539         # check if device exist
540         check_sysfs_device_exist("$sysfs/block/sda", "$sysfs/class/tty/tty1");
541
542         udevsend(0, "/class/tty/tty1", "add", "tty");
543         udevsend(1, "/class/tty/tty1", "remove", "tty");
544         sleep 1;
545
546         # log current system date/time
547         $time = time();
548         system("rm -f $log_file");
549
550         udevsend(3, "/block/sda", "add", "block");
551
552         # show results
553         print "   wait for udevd processing about $time_out s... \n\n";
554         sleep $time_out+1;
555         show_result($time);
556         print "this case is ok\n\n";
557 }
558
559 sub run_all_cases_test { 
560         run_no_seq_test();
561         run_normal_seq_test();
562         run_random_seq_test();
563         run_missing_seq_test();
564         run_expected_seq_test();
565         run_same_events_test();
566         run_single_instance_test();
567 }
568
569 # main program
570 if ($ARGV[0]) {
571         $test_case = $ARGV[0];
572
573         if ($test_case == 1) {
574                 run_no_seq_test();
575         } elsif ($test_case == 2) {
576                 run_normal_seq_test();
577         } elsif ($test_case == 3) {
578                 run_random_seq_test();
579         } elsif ($test_case == 4) {
580                 run_missing_seq_test();
581         } elsif ($test_case == 5) {
582                 run_expected_seq_test();
583         } elsif ($test_case == 6) {
584                 run_single_instance_test();
585         } elsif ($test_case == 7) {
586                 run_same_events_test();
587         } else {
588                 run_all_cases_test();
589         }
590 } else {
591         # echo usage
592         print "command format: perl udevd-test.pl <case number>\n";
593         print "   test case:\n";
594         print "           1: no event sequence number\n";
595         print "           2: sequential event sequence number\n";
596         print "           3: random event sequence number\n";
597         print "           4: missing event sequence number\n";
598         print "           5: the incoming event sequence number is right the expected sequence number\n";
599         print "           6: single udev instance on a single device at the same time\n";
600         print "           7: test event sequence number overlap\n";
601         print "           9: all the cases\n\n";
602 }