chiark / gitweb /
5f9c0cb9c503a46f56660e4d1082d61e0daf9a4f
[elogind.git] / test / udev-test.pl
1 #!/usr/bin/perl
2
3 # udev-test
4 #
5 # Provides automated testing of the udev binary.
6 # The whole test is self contained in this file, except the matching sysfs tree.
7 # Simply extend the @tests array, to add a new test variant.
8 #
9 # Every test is driven by its own temporary config file.
10 # This program prepares the environment, creates the config and calls udev.
11 #
12 # udev reads the config, looks at the provided sysfs and
13 # first creates and then removes the device node.
14 # After creation and removal the result is checked against the
15 # expected value and the result is printed.
16 #
17 # Kay Sievers <kay.sievers@vrfy.org>, 2003
18 # Leann Ogasawara <ogasawara@osdl.org>, 2004
19
20 use warnings;
21 use strict;
22
23 my $PWD = $ENV{PWD};
24 my $sysfs     = "sys/";
25 my $udev_bin  = "../udev";
26 my $udev_root = "udev-root/"; # !!! directory will be removed !!!
27 my $udev_db   = ".udevdb";
28 my $main_conf = "udev-test.conf";
29 my $conf_tmp  = "udev-test.rules";
30
31 # uncomment following line to run udev with valgrind.
32 # Should make this a runtime option to the script someday...
33 #my $udev_bin  = "valgrind --tool=memcheck --leak-check=yes   ../udev";
34
35 my @tests = (
36         {
37                 desc            => "label test of scsi disc",
38                 subsys          => "block",
39                 devpath         => "/block/sda",
40                 exp_name        => "boot_disk" ,
41                 conf            => <<EOF
42 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME="boot_disk%n"
43 KERNEL="ttyUSB0", NAME="visor"
44 EOF
45         },
46         {
47                 desc            => "label test of scsi partition",
48                 subsys          => "block",
49                 devpath         => "/block/sda/sda1",
50                 exp_name        => "boot_disk1" ,
51                 conf            => <<EOF
52 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME="boot_disk%n"
53 EOF
54         },
55         {
56                 desc            => "label test of pattern match",
57                 subsys          => "block",
58                 devpath         => "/block/sda/sda1",
59                 exp_name        => "boot_disk1" ,
60                 conf            => <<EOF
61 BUS="scsi", SYSFS{vendor}="?IBM-ESXS", NAME="boot_disk%n-1"
62 BUS="scsi", SYSFS{vendor}="IBM-ESXS?", NAME="boot_disk%n-2"
63 BUS="scsi", SYSFS{vendor}="IBM-ES??", NAME="boot_disk%n"
64 BUS="scsi", SYSFS{vendor}="IBM-ESXSS", NAME="boot_disk%n-3"
65 EOF
66         },
67         {
68                 desc            => "label test of multiple sysfs files",
69                 subsys          => "block",
70                 devpath         => "/block/sda/sda1",
71                 exp_name        => "boot_disk1" ,
72                 conf            => <<EOF
73 BUS="scsi", SYSFS{vendor}="IBM-ESXS", SYSFS{model}="ST336605LW   !#", NAME="boot_diskX%n"
74 BUS="scsi", SYSFS{vendor}="IBM-ESXS", SYSFS{model}="ST336605LW    !#", NAME="boot_disk%n"
75 EOF
76         },
77         {
78                 desc            => "label test of max sysfs files",
79                 subsys          => "block",
80                 devpath         => "/block/sda/sda1",
81                 exp_name        => "boot_disk1" ,
82                 conf            => <<EOF
83 BUS="scsi", SYSFS{vendor}="IBM-ESXS", SYSFS{model}="ST336605LW    !#", SYSFS{scsi_level}="4", SYSFS{rev}="B245", SYSFS{type}="2", SYSFS{queue_depth}="32", NAME="boot_diskXX%n"
84 BUS="scsi", SYSFS{vendor}="IBM-ESXS", SYSFS{model}="ST336605LW    !#", SYSFS{scsi_level}="4", SYSFS{rev}="B245", SYSFS{type}="0", NAME="boot_disk%n"
85 EOF
86         },
87         {
88                 desc            => "catch device by *",
89                 subsys          => "tty",
90                 devpath         => "/class/tty/ttyUSB0",
91                 exp_name        => "visor/0" ,
92                 conf            => <<EOF
93 KERNEL="ttyUSB*", NAME="visor/%n"
94 EOF
95         },
96         {
97                 desc            => "catch device by * - take 2",
98                 subsys          => "tty",
99                 devpath         => "/class/tty/ttyUSB0",
100                 exp_name        => "visor/0" ,
101                 conf            => <<EOF
102 KERNEL="*USB1", NAME="bad"
103 KERNEL="*USB0", NAME="visor/%n"
104 EOF
105         },
106         {
107                 desc            => "catch device by ?",
108                 subsys          => "tty",
109                 devpath         => "/class/tty/ttyUSB0",
110                 exp_name        => "visor/0" ,
111                 conf            => <<EOF
112 KERNEL="ttyUSB??*", NAME="visor/%n-1"
113 KERNEL="ttyUSB??", NAME="visor/%n-2"
114 KERNEL="ttyUSB?", NAME="visor/%n"
115 EOF
116         },
117         {
118                 desc            => "catch device by character class",
119                 subsys          => "tty",
120                 devpath         => "/class/tty/ttyUSB0",
121                 exp_name        => "visor/0" ,
122                 conf            => <<EOF
123 KERNEL="ttyUSB[A-Z]*", NAME="visor/%n-1"
124 KERNEL="ttyUSB?[0-9]", NAME="visor/%n-2"
125 KERNEL="ttyUSB[0-9]*", NAME="visor/%n"
126 EOF
127         },
128         {
129                 desc            => "replace kernel name",
130                 subsys          => "tty",
131                 devpath         => "/class/tty/ttyUSB0",
132                 exp_name        => "visor" ,
133                 conf            => <<EOF
134 KERNEL="ttyUSB0", NAME="visor"
135 EOF
136         },
137         {
138                 desc            => "Handle comment lines in config file (and replace kernel name)",
139                 subsys          => "tty",
140                 devpath         => "/class/tty/ttyUSB0",
141                 exp_name        => "visor" ,
142                 conf            => <<EOF
143 # this is a comment
144 KERNEL="ttyUSB0", NAME="visor"
145
146 EOF
147         },
148         {
149                 desc            => "Handle comment lines in config file with whitespace (and replace kernel name)",
150                 subsys          => "tty",
151                 devpath         => "/class/tty/ttyUSB0",
152                 exp_name        => "visor" ,
153                 conf            => <<EOF
154  # this is a comment with whitespace before the comment 
155 KERNEL="ttyUSB0", NAME="visor"
156
157 EOF
158         },
159         {
160                 desc            => "Handle whitespace only lines (and replace kernel name)",
161                 subsys          => "tty",
162                 devpath         => "/class/tty/ttyUSB0",
163                 exp_name        => "whitespace" ,
164                 conf            => <<EOF
165
166  
167
168  # this is a comment with whitespace before the comment 
169 KERNEL="ttyUSB0", NAME="whitespace"
170
171  
172
173 EOF
174         },
175         {
176                 desc            => "Handle empty lines in config file (and replace kernel name)",
177                 subsys          => "tty",
178                 devpath         => "/class/tty/ttyUSB0",
179                 exp_name        => "visor" ,
180                 conf            => <<EOF
181
182 KERNEL="ttyUSB0", NAME="visor"
183
184 EOF
185         },
186         {
187                 desc            => "Handle backslashed multi lines in config file (and replace kernel name)",
188                 subsys          => "tty",
189                 devpath         => "/class/tty/ttyUSB0",
190                 exp_name        => "visor" ,
191                 conf            => <<EOF
192 KERNEL="ttyUSB0", \\
193 NAME="visor"
194
195 EOF
196         },
197         {
198                 desc            => "Handle stupid backslashed multi lines in config file (and replace kernel name)",
199                 subsys          => "tty",
200                 devpath         => "/class/tty/ttyUSB0",
201                 exp_name        => "visor" ,
202                 conf            => <<EOF
203
204 #
205 \\
206
207 \\\\
208
209 #\\
210
211 KERNEL="ttyUSB0", \\
212         NAME="visor"
213
214 EOF
215         },
216         {
217                 desc            => "subdirectory handling",
218                 subsys          => "tty",
219                 devpath         => "/class/tty/ttyUSB0",
220                 exp_name        => "sub/direct/ory/visor" ,
221                 conf            => <<EOF
222 KERNEL="ttyUSB0", NAME="sub/direct/ory/visor"
223 EOF
224         },
225         {
226                 desc            => "place on bus of scsi partition",
227                 subsys          => "block",
228                 devpath         => "/block/sda/sda3",
229                 exp_name        => "first_disk3" ,
230                 conf            => <<EOF
231 BUS="scsi", PLACE="0:0:0:0", NAME="first_disk%n"
232 EOF
233         },
234         {
235                 desc            => "test NAME substitution chars",
236                 subsys          => "block",
237                 devpath         => "/block/sda/sda3",
238                 exp_name        => "Major:8:minor:3:kernelnumber:3:bus:0:0:0:0" ,
239                 conf            => <<EOF
240 BUS="scsi", PLACE="0:0:0:0", NAME="Major:%M:minor:%m:kernelnumber:%n:bus:%b"
241 EOF
242         },
243         {
244                 desc            => "test NAME substitution chars (with length limit)",
245                 subsys          => "block",
246                 devpath         => "/block/sda/sda3",
247                 exp_name        => "M8-m3-n3-b0:0-sIBM" ,
248                 conf            => <<EOF
249 BUS="scsi", PLACE="0:0:0:0", NAME="M%M-m%m-n%n-b%3b-s%3s{vendor}"
250 EOF
251         },
252         {
253                 desc            => "old style SYSFS_ attribute",
254                 subsys          => "block",
255                 devpath         => "/block/sda",
256                 exp_name        => "good" ,
257                 conf            => <<EOF
258 BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="good"
259 EOF
260         },
261         {
262                 desc            => "sustitution of sysfs value (%s{file})",
263                 subsys          => "block",
264                 devpath         => "/block/sda",
265                 exp_name        => "disk-IBM-ESXS-sda" ,
266                 conf            => <<EOF
267 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME="disk-%s{vendor}-%k"
268 KERNEL="ttyUSB0", NAME="visor"
269 EOF
270         },
271         {
272                 desc            => "program result substitution",
273                 subsys          => "block",
274                 devpath         => "/block/sda/sda3",
275                 exp_name        => "special-device-3" ,
276                 conf            => <<EOF
277 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="-special-*", NAME="%c-1-%n"
278 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special--*", NAME="%c-2-%n"
279 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special-device-", NAME="%c-3-%n"
280 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special-devic", NAME="%c-4-%n"
281 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special-*", NAME="%c-%n"
282 EOF
283         },
284         {
285                 desc            => "program result substitution (no argument should be subsystem)",
286                 subsys          => "block",
287                 devpath         => "/block/sda/sda3",
288                 exp_name        => "subsys_block" ,
289                 conf            => <<EOF
290 BUS="scsi", PROGRAM="/bin/echo", RESULT="block", NAME="subsys_block"
291 EOF
292         },
293         {
294                 desc            => "program result substitution (newline removal)",
295                 subsys          => "block",
296                 devpath         => "/block/sda/sda3",
297                 exp_name        => "newline_removed" ,
298                 conf            => <<EOF
299 BUS="scsi", PROGRAM="/bin/echo test", RESULT="test", NAME="newline_removed"
300 EOF
301         },
302         {
303                 desc            => "program result substitution",
304                 subsys          => "block",
305                 devpath         => "/block/sda/sda3",
306                 exp_name        => "test-0:0:0:0" ,
307                 conf            => <<EOF
308 BUS="scsi", PROGRAM="/bin/echo -n test-%b", RESULT="test-0:0*", NAME="%c"
309 EOF
310         },
311         {
312                 desc            => "program with escaped format char (tricky: callout returns format char!)",
313                 subsys          => "block",
314                 devpath         => "/block/sda/sda3",
315                 exp_name        => "escape-3" ,
316                 conf            => <<EOF
317 BUS="scsi", PROGRAM="/bin/echo -n escape-%%n", KERNEL="sda3", NAME="%c"
318 EOF
319         },
320         {
321                 desc            => "program with lots of arguments",
322                 subsys          => "block",
323                 devpath         => "/block/sda/sda3",
324                 exp_name        => "foo9" ,
325                 conf            => <<EOF
326 BUS="scsi", PROGRAM="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL="sda3", NAME="%c{7}"
327 EOF
328         },
329         {
330                 desc            => "program with subshell",
331                 subsys          => "block",
332                 devpath         => "/block/sda/sda3",
333                 exp_name        => "bar9" ,
334                 conf            => <<EOF
335 BUS="scsi", PROGRAM="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed  s/foo9/bar9/'", KERNEL="sda3", NAME="%c{7}"
336 EOF
337         },
338         {
339                 desc            => "program arguments combined with apostrophes",
340                 subsys          => "block",
341                 devpath         => "/block/sda/sda3",
342                 exp_name        => "foo7" ,
343                 conf            => <<EOF
344 BUS="scsi", PROGRAM="/bin/echo -n 'foo3 foo4'   'foo5   foo6   foo7 foo8'", KERNEL="sda3", NAME="%c{5}"
345 EOF
346         },
347         {
348                 desc            => "characters before the %c{N} substitution",
349                 subsys          => "block",
350                 devpath         => "/block/sda/sda3",
351                 exp_name        => "my-foo9" ,
352                 conf            => <<EOF
353 BUS="scsi", PROGRAM="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL="sda3", NAME="my-%c{7}"
354 EOF
355         },
356         {
357                 desc            => "substitute the second to last argument",
358                 subsys          => "block",
359                 devpath         => "/block/sda/sda3",
360                 exp_name        => "my-foo8" ,
361                 conf            => <<EOF
362 BUS="scsi", PROGRAM="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL="sda3", NAME="my-%c{6}"
363 EOF
364         },
365         {
366                 desc            => "invalid program for device with no bus",
367                 subsys          => "tty",
368                 devpath         => "/class/tty/console",
369                 exp_name        => "TTY" ,
370                 conf            => <<EOF
371 BUS="scsi", PROGRAM="/bin/echo -n foo", RESULT="foo", NAME="foo"
372 KERNEL="console", NAME="TTY"
373 EOF
374         },
375         {
376                 desc            => "valid program for device with no bus",
377                 subsys          => "tty",
378                 devpath         => "/class/tty/console",
379                 exp_name        => "foo" ,
380                 conf            => <<EOF
381 PROGRAM="/bin/echo -n foo", RESULT="foo", NAME="foo"
382 KERNEL="console", NAME="TTY"
383 EOF
384         },
385         {
386                 desc            => "invalid label for device with no bus",
387                 subsys          => "tty",
388                 devpath         => "/class/tty/console",
389                 exp_name        => "TTY" ,
390                 conf            => <<EOF
391 BUS="foo", SYSFS{dev}="5:1", NAME="foo"
392 KERNEL="console", NAME="TTY"
393 EOF
394         },
395         {
396                 desc            => "valid label for device with no bus",
397                 subsys          => "tty",
398                 devpath         => "/class/tty/console",
399                 exp_name        => "foo" ,
400                 conf            => <<EOF
401 SYSFS{dev}="5:1", NAME="foo"
402 KERNEL="console", NAME="TTY"
403 EOF
404         },
405         {
406                 desc            => "program and bus type match",
407                 subsys          => "block",
408                 devpath         => "/block/sda",
409                 exp_name        => "scsi-0:0:0:0" ,
410                 conf            => <<EOF
411 BUS="usb", PROGRAM="/bin/echo -n usb-%b", NAME="%c"
412 BUS="scsi", PROGRAM="/bin/echo -n scsi-%b", NAME="%c"
413 BUS="foo", PROGRAM="/bin/echo -n foo-%b", NAME="%c"
414 EOF
415         },
416         {
417                 desc            => "create all possible partitions",
418                 subsys          => "block",
419                 devpath         => "/block/sda",
420                 exp_name        => "boot_disk15" ,
421                 conf            => <<EOF
422 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME{all_partitions}="boot_disk"
423 EOF
424         },
425         {
426                 desc            => "sysfs parent hierarchy",
427                 subsys          => "tty",
428                 devpath         => "/class/tty/ttyUSB0",
429                 exp_name        => "visor" ,
430                 conf            => <<EOF
431 SYSFS{idProduct}="2008", NAME="visor"
432 EOF
433         },
434         {
435                 desc            => "name test with ! in the name",
436                 subsys          => "block",
437                 devpath         => "/block/rd!c0d0",
438                 exp_name        => "rd/c0d0" ,
439                 conf            => <<EOF
440 BUS="scsi", NAME="%k"
441 KERNEL="ttyUSB0", NAME="visor"
442 EOF
443         },
444         {
445                 desc            => "name test with ! in the name, but no matching rule",
446                 subsys          => "block",
447                 devpath         => "/block/rd!c0d0",
448                 exp_name        => "rd/c0d0" ,
449                 conf            => <<EOF
450 KERNEL="ttyUSB0", NAME="visor"
451 EOF
452         },
453         {
454                 desc            => "name test with ! in the name for a partition",
455                 subsys          => "block",
456                 devpath         => "/block/cciss!c0d0/cciss!c0d0p1",
457                 exp_name        => "cciss/c0d0p1" ,
458                 conf            => <<EOF
459 BUS="scsi", NAME="%k"
460 KERNEL="ttyUSB0", NAME="visor"
461 EOF
462         },
463         {
464                 desc            => "ID rule",
465                 subsys          => "block",
466                 devpath         => "/block/sda",
467                 exp_name        => "scsi-0:0:0:0",
468                 conf            => <<EOF
469 BUS="usb", ID="0:0:0:0", NAME="not-scsi"
470 BUS="scsi", ID="0:0:0:1", NAME="no-match"
471 BUS="scsi", ID=":0", NAME="short-id"
472 BUS="scsi", ID="/0:0:0:0", NAME="no-match"
473 BUS="scsi", ID="0:0:0:0", NAME="scsi-0:0:0:0"
474 EOF
475         },
476         {
477                 desc            => "ID wildcard all",
478                 subsys          => "block",
479                 devpath         => "/block/sda",
480                 exp_name        => "scsi-0:0:0:0",
481                 conf            => <<EOF
482 BUS="scsi", ID="*:1", NAME="no-match"
483 BUS="scsi", ID="*:0:1", NAME="no-match"
484 BUS="scsi", ID="*:0:0:1", NAME="no-match"
485 BUS="scsi", ID="*", NAME="scsi-0:0:0:0"
486 BUS="scsi", ID="0:0:0:0", NAME="bad"
487 EOF
488         },
489         {
490                 desc            => "ID wildcard partial",
491                 subsys          => "block",
492                 devpath         => "/block/sda",
493                 exp_name        => "scsi-0:0:0:0",
494                 conf            => <<EOF
495 BUS="scsi", ID="*:0", NAME="scsi-0:0:0:0"
496 BUS="scsi", ID="0:0:0:0", NAME="bad"
497 EOF
498         },
499         {
500                 desc            => "ID wildcard partial 2",
501                 subsys          => "block",
502                 devpath         => "/block/sda",
503                 exp_name        => "scsi-0:0:0:0",
504                 conf            => <<EOF
505 BUS="scsi", ID="*:0:0:0", NAME="scsi-0:0:0:0"
506 BUS="scsi", ID="0:0:0:0", NAME="bad"
507 EOF
508         },
509         {
510                 desc            => "ignore SYSFS attribute whitespace",
511                 subsys          => "block",
512                 devpath         => "/block/sda",
513                 exp_name        => "ignored",
514                 conf            => <<EOF
515 BUS="scsi", SYSFS{whitespace_test}="WHITE  SPACE", NAME="ignored"
516 EOF
517         },
518         {
519                 desc            => "do not ignore SYSFS attribute whitespace",
520                 subsys          => "block",
521                 devpath         => "/block/sda",
522                 exp_name        => "matched-with-space",
523                 conf            => <<EOF
524 BUS="scsi", SYSFS{whitespace_test}="WHITE  SPACE ", NAME="wrong-to-ignore"
525 BUS="scsi", SYSFS{whitespace_test}="WHITE  SPACE   ", NAME="matched-with-space"
526 EOF
527         },
528         {
529                 desc            => "permissions USER=bad GROUP=name",
530                 subsys          => "tty",
531                 devpath         => "/class/tty/tty33",
532                 exp_name        => "tty33",
533                 exp_perms       => "0:0:0660",
534                 conf            => <<EOF
535 KERNEL="tty33", NAME="tty33", OWNER="bad", GROUP="name"
536 EOF
537         },
538         {
539                 desc            => "permissions OWNER=5000",
540                 subsys          => "block",
541                 devpath         => "/block/sda",
542                 exp_name        => "node",
543                 exp_perms       => "5000::0660",
544                 conf            => <<EOF
545 BUS="scsi", KERNEL="sda", NAME="node", OWNER="5000"
546 EOF
547         },
548         {
549                 desc            => "permissions GROUP=100",
550                 subsys          => "block",
551                 devpath         => "/block/sda",
552                 exp_name        => "node",
553                 exp_perms       => ":100:0660",
554                 conf            => <<EOF
555 BUS="scsi", KERNEL="sda", NAME="node", GROUP="100"
556 EOF
557         },
558         {
559                 desc            => "permissions MODE=0777",
560                 subsys          => "block",
561                 devpath         => "/block/sda",
562                 exp_name        => "node",
563                 exp_perms       => "::0777",
564                 conf            => <<EOF
565 BUS="scsi", KERNEL="sda", NAME="node", MODE="0777"
566 EOF
567         },
568         {
569                 desc            => "permissions OWNER=5000 GROUP=100 MODE=0777",
570                 subsys          => "block",
571                 devpath         => "/block/sda",
572                 exp_name        => "node",
573                 exp_perms       => "5000:100:0777",
574                 conf            => <<EOF
575 BUS="scsi", KERNEL="sda", NAME="node", OWNER="5000", GROUP="100", MODE="0777"
576 EOF
577         },
578         {
579                 desc            => "permissions OWNER to 5000",
580                 subsys          => "tty",
581                 devpath         => "/class/tty/ttyUSB0",
582                 exp_name        => "ttyUSB0",
583                 exp_perms       => "5000::",
584                 conf            => <<EOF
585 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", OWNER="5000"
586 EOF
587         },
588         {
589                 desc            => "permissions GROUP to 100",
590                 subsys          => "tty",
591                 devpath         => "/class/tty/ttyUSB0",
592                 exp_name        => "ttyUSB0",
593                 exp_perms       => ":100:0660",
594                 conf            => <<EOF
595 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", GROUP="100"
596 EOF
597         },
598         {
599                 desc            => "permissions MODE to 0060",
600                 subsys          => "tty",
601                 devpath         => "/class/tty/ttyUSB0",
602                 exp_name        => "ttyUSB0",
603                 exp_perms       => "::0060",
604                 conf            => <<EOF
605 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", MODE="0060"
606 EOF
607         },
608         {
609                 desc            => "permissions OWNER, GROUP, MODE",
610                 subsys          => "tty",
611                 devpath         => "/class/tty/ttyUSB0",
612                 exp_name        => "ttyUSB0",
613                 exp_perms       => "5000:100:0777",
614                 conf            => <<EOF
615 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", OWNER="5000", GROUP="100", MODE="0777"
616 EOF
617         },
618         {
619                 desc            => "permissions only rule",
620                 subsys          => "tty",
621                 devpath         => "/class/tty/ttyUSB0",
622                 exp_name        => "ttyUSB0",
623                 exp_perms       => "5000:100:0777",
624                 conf            => <<EOF
625 KERNEL="ttyUSB[0-9]*", OWNER="5000", GROUP="100", MODE="0777"
626 KERNEL="ttyUSX[0-9]*", OWNER="5001", GROUP="101", MODE="0444"
627 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n"
628 EOF
629         },
630         {
631                 desc            => "multiple permissions only rule",
632                 subsys          => "tty",
633                 devpath         => "/class/tty/ttyUSB0",
634                 exp_name        => "ttyUSB0",
635                 exp_perms       => "3000:4000:0777",
636                 conf            => <<EOF
637 SUBSYSTEM="tty", OWNER="3000"
638 SUBSYSTEM="tty", GROUP="4000"
639 SUBSYSTEM="tty", MODE="0777"
640 KERNEL="ttyUSX[0-9]*", OWNER="5001", GROUP="101", MODE="0444"
641 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n"
642 EOF
643         },
644         {
645                 desc            => "permissions only rule with override at NAME rule",
646                 subsys          => "tty",
647                 devpath         => "/class/tty/ttyUSB0",
648                 exp_name        => "ttyUSB0",
649                 exp_perms       => "3000:8000:0777",
650                 conf            => <<EOF
651 SUBSYSTEM="tty", OWNER="3000"
652 SUBSYSTEM="tty", GROUP="4000"
653 SUBSYSTEM="tty", MODE="0777"
654 KERNEL="ttyUSX[0-9]*", OWNER="5001", GROUP="101", MODE="0444"
655 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", GROUP="8000"
656 EOF
657         },
658         {
659                 desc            => "major/minor number test",
660                 subsys          => "block",
661                 devpath         => "/block/sda",
662                 exp_name        => "node",
663                 exp_majorminor  => "8:0",
664                 conf            => <<EOF
665 BUS="scsi", KERNEL="sda", NAME="node"
666 EOF
667         },
668         {
669                 desc            => "big minor number test",
670                 subsys          => "i2c-dev",
671                 devpath         => "/class/i2c-dev/i2c-300",
672                 exp_name        => "node",
673                 exp_majorminor  => "89:300",
674                 conf            => <<EOF
675 KERNEL="i2c-300", NAME="node"
676 EOF
677         },
678         {
679                 desc            => "big major number test",
680                 subsys          => "i2c-dev",
681                 devpath         => "/class/i2c-dev/i2c-fake1",
682                 exp_name        => "node",
683                 exp_majorminor  => "4095:1",
684                 conf            => <<EOF
685 KERNEL="i2c-fake1", NAME="node"
686 EOF
687         },
688         {
689                 desc            => "big major and big minor number test",
690                 subsys          => "i2c-dev",
691                 devpath         => "/class/i2c-dev/i2c-fake2",
692                 exp_name        => "node",
693                 exp_majorminor  => "4094:89999",
694                 conf            => <<EOF
695 KERNEL="i2c-fake2", NAME="node"
696 EOF
697         },
698         {
699                 desc            => "multiple symlinks with format char",
700                 subsys          => "tty",
701                 devpath         => "/class/tty/ttyUSB0",
702                 exp_name        => "symlink2-ttyUSB0",
703                 exp_target      => "ttyUSB0",
704                 conf            => <<EOF
705 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
706 EOF
707         },
708         {
709                 desc            => "symlink creation (same directory)",
710                 subsys          => "tty",
711                 devpath         => "/class/tty/ttyUSB0",
712                 exp_name        => "visor0",
713                 exp_target      => "ttyUSB0",
714                 conf            => <<EOF
715 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="visor%n"
716 EOF
717         },
718         {
719                 desc            => "symlink creation (relative link forward)",
720                 subsys          => "block",
721                 devpath         => "/block/sda/sda2",
722                 exp_name        => "1/2/symlink" ,
723                 exp_target      => "a/b/node",
724                 conf            => <<EOF
725 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/symlink"
726 EOF
727         },
728         {
729                 desc            => "symlink creation (relative link back and forward)",
730                 subsys          => "block",
731                 devpath         => "/block/sda/sda2",
732                 exp_name        => "1/2/c/d/symlink" ,
733                 exp_target      => "../../a/b/node",
734                 conf            => <<EOF
735 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/c/d/symlink"
736 EOF
737         },
738         {
739                 desc            => "multiple symlinks",
740                 subsys          => "tty",
741                 devpath         => "/class/tty/ttyUSB0",
742                 exp_name        => "second-0" ,
743                 exp_target      => "visor" ,
744                 conf            => <<EOF
745 KERNEL="ttyUSB0", NAME="visor", SYMLINK="first-%n second-%n third-%n"
746 EOF
747         },
748         {
749                 desc            => "symlink only rule",
750                 subsys          => "block",
751                 devpath         => "/block/sda",
752                 exp_name        => "symlink-only2",
753                 exp_target      => "link",
754                 conf            => <<EOF
755 BUS="scsi", KERNEL="sda", SYMLINK="symlink-only1"
756 BUS="scsi", KERNEL="sda", SYMLINK="symlink-only2"
757 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK="symlink0"
758 EOF
759         },
760         {
761                 desc            => "symlink name empty",
762                 subsys          => "block",
763                 devpath         => "/block/sda",
764                 exp_name        => "",
765                 exp_target      => "link",
766                 exp_error       => "yes",
767                 conf            => <<EOF
768 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK=""
769 EOF
770         },
771         {
772                 desc            => "symlink name '.'",
773                 subsys          => "block",
774                 devpath         => "/block/sda",
775                 exp_name        => ".",
776                 exp_target      => "link",
777                 exp_error       => "yes",
778                 conf            => <<EOF
779 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK="."
780 EOF
781         },
782         {
783                 desc            => "symlink to empty name",
784                 subsys          => "block",
785                 devpath         => "/block/sda",
786                 exp_name        => "symlink",
787                 exp_target      => "",
788                 exp_error       => "yes",
789                 conf            => <<EOF
790 BUS="scsi", KERNEL="sda", NAME="", SYMLINK="symlink"
791 EOF
792         },
793         {
794                 desc            => "symlink and name empty",
795                 subsys          => "block",
796                 devpath         => "/block/sda",
797                 exp_name        => "",
798                 exp_target      => "",
799                 exp_error       => "yes",
800                 conf            => <<EOF
801 BUS="scsi", KERNEL="sda", NAME="", SYMLINK=""
802 EOF
803         },
804         {
805                 desc            => "symlink node to itself",
806                 subsys          => "tty",
807                 devpath         => "/class/tty/tty0",
808                 exp_name        => "link",
809                 exp_target      => "link",
810                 conf            => <<EOF
811 KERNEL="tty0", NAME="link", SYMLINK="link"
812 EOF
813         },
814         {
815                 desc            => "symlink %n substitution",
816                 subsys          => "tty",
817                 devpath         => "/class/tty/ttyUSB0",
818                 exp_name        => "symlink0",
819                 exp_target      => "ttyUSB0",
820                 conf            => <<EOF
821 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink%n"
822 EOF
823         },
824         {
825                 desc            => "symlink %k substitution",
826                 subsys          => "tty",
827                 devpath         => "/class/tty/ttyUSB0",
828                 exp_name        => "symlink-ttyUSB0",
829                 exp_target      => "ttyUSB0",
830                 conf            => <<EOF
831 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink-%k"
832 EOF
833         },
834         {
835                 desc            => "symlink %M:%m substitution",
836                 subsys          => "tty",
837                 devpath         => "/class/tty/ttyUSB0",
838                 exp_name        => "major-188:0",
839                 exp_target      => "ttyUSB0",
840                 conf            => <<EOF
841 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="major-%M:%m"
842 EOF
843         },
844         {
845                 desc            => "symlink %b substitution",
846                 subsys          => "block",
847                 devpath         => "/block/sda",
848                 exp_name        => "symlink-0:0:0:0",
849                 exp_target      => "node",
850                 conf            => <<EOF
851 BUS="scsi", KERNEL="sda", NAME="node", SYMLINK="symlink-%b"
852 EOF
853         },
854         {
855                 desc            => "symlink %c substitution",
856                 subsys          => "tty",
857                 devpath         => "/class/tty/ttyUSB0",
858                 exp_name        => "test",
859                 exp_target      => "ttyUSB0",
860                 conf            => <<EOF
861 KERNEL="ttyUSB[0-9]*", PROGRAM="/bin/echo test" NAME="ttyUSB%n", SYMLINK="%c"
862 EOF
863         },
864         {
865                 desc            => "symlink %c{N} substitution",
866                 subsys          => "tty",
867                 devpath         => "/class/tty/ttyUSB0",
868                 exp_name        => "test",
869                 exp_target      => "ttyUSB0",
870                 conf            => <<EOF
871 KERNEL="ttyUSB[0-9]*", PROGRAM="/bin/echo symlink test this" NAME="ttyUSB%n", SYMLINK="%c{2}"
872 EOF
873         },
874         {
875                 desc            => "symlink %c{N+} substitution",
876                 subsys          => "tty",
877                 devpath         => "/class/tty/ttyUSB0",
878                 exp_name        => "this",
879                 exp_target      => "ttyUSB0",
880                 conf            => <<EOF
881 KERNEL="ttyUSB[0-9]*", PROGRAM="/bin/echo symlink test this" NAME="ttyUSB%n", SYMLINK="%c{2+}"
882 EOF
883         },
884         {
885                 desc            => "symlink only rule with %c{N+}",
886                 subsys          => "block",
887                 devpath         => "/block/sda",
888                 exp_name        => "test",
889                 exp_target      => "link",
890                 conf            => <<EOF
891 BUS="scsi", KERNEL="sda", PROGRAM="/bin/echo link test this" SYMLINK="%c{2+}"
892 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK="symlink0"
893 EOF
894         },
895         {
896                 desc            => "symlink %s{filename} substitution",
897                 subsys          => "tty",
898                 devpath         => "/class/tty/ttyUSB0",
899                 exp_name        => "188:0",
900                 exp_target      => "ttyUSB0",
901                 conf            => <<EOF
902 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="%s{dev}"
903 EOF
904         },
905         {
906                 desc            => "symlink %Ns{filename} substitution",
907                 subsys          => "tty",
908                 devpath         => "/class/tty/ttyUSB0",
909                 exp_name        => "188",
910                 exp_target      => "ttyUSB0",
911                 conf            => <<EOF
912 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="%3s{dev}"
913 EOF
914         },
915         {
916                 desc            => "symlink with '%' in name",
917                 subsys          => "tty",
918                 devpath         => "/class/tty/ttyUSB0",
919                 exp_name        => "percent%sign",
920                 exp_target      => "ttyUSB0",
921                 conf            => <<EOF
922 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="percent%%sign"
923 EOF
924         },
925         {
926                 desc            => "symlink with '%' in name",
927                 subsys          => "tty",
928                 devpath         => "/class/tty/ttyUSB0",
929                 exp_name        => "%ttyUSB0_name",
930                 exp_target      => "ttyUSB0",
931                 conf            => <<EOF
932 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="%%%k_name"
933 EOF
934         },
935         {
936                 desc            => "program result substitution (numbered part of)",
937                 subsys          => "block",
938                 devpath         => "/block/sda/sda3",
939                 exp_name        => "link1",
940                 exp_target      => "node",
941                 conf            => <<EOF
942 BUS="scsi", PROGRAM="/bin/echo -n node link1 link2", RESULT="node *", NAME="%c{1}", SYMLINK="%c{2} %c{3}"
943 EOF
944         },
945         {
946                 desc            => "program result substitution (numbered part of+)",
947                 subsys          => "block",
948                 devpath         => "/block/sda/sda3",
949                 exp_name        => "link4",
950                 exp_target      => "node",
951                 conf            => <<EOF
952 BUS="scsi", PROGRAM="/bin/echo -n node link1 link2 link3 link4", RESULT="node *", NAME="%c{1}", SYMLINK="%c{2+}"
953 EOF
954         },
955         {
956                 desc            => "enumeration char test (single test)",
957                 subsys          => "block",
958                 devpath         => "/block/sda",
959                 exp_name        => "cdrom",
960                 conf            => <<EOF
961 KERNEL="sda", NAME="cdrom%e"
962 EOF
963         },
964         {
965                 desc            => "enumeration char test sequence 1/5 (keep)",
966                 subsys          => "block",
967                 devpath         => "/block/sda",
968                 exp_name        => "cdrom",
969                 option          => "keep",
970                 conf            => <<EOF
971 KERNEL="sda", NAME="cdrom%e"
972 EOF
973         },
974         {
975                 desc            => "enumeration char test sequence 2/5 (keep)",
976                 subsys          => "block",
977                 devpath         => "/block/sda/sda1",
978                 exp_name        => "enum",
979                 option          => "keep",
980                 conf            => <<EOF
981 KERNEL="sda1", NAME="enum%e"
982 EOF
983         },
984         {
985                 desc            => "enumeration char test sequence 3/5 (keep)",
986                 subsys          => "block",
987                 devpath         => "/block/sda/sda2",
988                 exp_name        => "cdrom1",
989                 option          => "keep",
990                 conf            => <<EOF
991 KERNEL="sda2", NAME="cdrom%e"
992 EOF
993         },
994         {
995                 desc            => "enumeration char test sequence 4/5 (keep)",
996                 subsys          => "block",
997                 devpath         => "/block/sda/sda3",
998                 exp_name        => "enum1",
999                 option          => "keep",
1000                 conf            => <<EOF
1001 KERNEL="sda3", NAME="enum%e"
1002 EOF
1003         },
1004         {
1005                 desc            => "enumeration char test sequence 5/5 (clean)",
1006                 subsys          => "block",
1007                 devpath         => "/block/sda/sda4",
1008                 exp_name        => "cdrom2",
1009                 option          => "clear",
1010                 conf            => <<EOF
1011 KERNEL="sda4", NAME="cdrom%e"
1012 EOF
1013         },
1014         {
1015                 desc            => "enumeration char test after cleanup (single test)",
1016                 subsys          => "block",
1017                 devpath         => "/block/sda",
1018                 exp_name        => "cdrom",
1019                 conf            => <<EOF
1020 KERNEL="sda", NAME="cdrom%e"
1021 EOF
1022         },
1023         {
1024                 desc            => "ignore rule test",
1025                 subsys          => "block",
1026                 devpath         => "/block/sda",
1027                 exp_name        => "node",
1028                 exp_error       => "yes",
1029                 conf            => <<EOF
1030 BUS="scsi", KERNEL="sda", NAME="node", OPTIONS="ignore"
1031 EOF
1032         },
1033         {
1034                 desc            => "all_partitions, option-only rule",
1035                 subsys          => "block",
1036                 devpath         => "/block/sda",
1037                 exp_name        => "node6",
1038                 conf            => <<EOF
1039 SUBSYSTEM="block", OPTIONS="all_partitions"
1040 BUS="scsi", KERNEL="sda", NAME="node"
1041 EOF
1042         },
1043         {
1044                 desc            => "all_partitions, option-only rule (fail on partition)",
1045                 subsys          => "block",
1046                 devpath         => "/block/sda/sda1",
1047                 exp_name        => "node6",
1048                 exp_error       => "yes",
1049                 conf            => <<EOF
1050 SUBSYSTEM="block", OPTIONS="all_partitions"
1051 BUS="scsi", KERNEL="sda", NAME="node"
1052 EOF
1053         },
1054         {
1055                 desc            => "ignore remove event test",
1056                 subsys          => "block",
1057                 devpath         => "/block/sda",
1058                 exp_name        => "node",
1059                 exp_error       => "yes",
1060                 conf            => <<EOF
1061 BUS="scsi", KERNEL="sda", NAME="node", OPTIONS="ignore_remove"
1062 EOF
1063         },
1064         {
1065                 desc            => "ignore remove event test (with all partitions)",
1066                 subsys          => "block",
1067                 devpath         => "/block/sda",
1068                 exp_name        => "node14",
1069                 exp_error       => "yes",
1070                 option          => "clear",
1071                 conf            => <<EOF
1072 BUS="scsi", KERNEL="sda", NAME="node", OPTIONS="ignore_remove, all_partitions"
1073 EOF
1074         },
1075         {
1076                 desc            => "SUBSYSTEM match test",
1077                 subsys          => "block",
1078                 devpath         => "/block/sda",
1079                 exp_name        => "node",
1080                 conf            => <<EOF
1081 BUS="scsi", KERNEL="sda", NAME="should_not_match", SUBSYSTEM="vc"
1082 BUS="scsi", KERNEL="sda", NAME="node", SUBSYSTEM="block"
1083 BUS="scsi", KERNEL="sda", NAME="should_not_match2", SUBSYSTEM="vc"
1084 EOF
1085         },
1086         {
1087                 desc            => "DRIVER match test",
1088                 subsys          => "block",
1089                 devpath         => "/block/sda",
1090                 exp_name        => "node",
1091                 conf            => <<EOF
1092 BUS="scsi", KERNEL="sda", NAME="should_not_match", DRIVER="sd-wrong"
1093 BUS="scsi", KERNEL="sda", NAME="node", DRIVER="sd"
1094 EOF
1095         },
1096         {
1097                 desc            => "temporary node creation test",
1098                 subsys          => "block",
1099                 devpath         => "/block/sda",
1100                 exp_name        => "node",
1101                 conf            => <<EOF
1102 BUS="scsi", KERNEL="sda", PROGRAM="/usr/bin/test -b %N" NAME="node"
1103 EOF
1104         },
1105         {
1106                 desc            => "devpath substitution test",
1107                 subsys          => "block",
1108                 devpath         => "/block/sda",
1109                 exp_name        => "sda",
1110                 conf            => <<EOF
1111 BUS="scsi", KERNEL="sda", PROGRAM="/bin/echo %p", RESULT="/block/sda" NAME="%k"
1112 EOF
1113         },
1114         {
1115                 desc            => "parent node name substitution test sequence 1/2 (keep)",
1116                 subsys          => "block",
1117                 devpath         => "/block/sda",
1118                 exp_name        => "main_device",
1119                 option          => "keep",
1120                 conf            => <<EOF
1121 BUS="scsi", KERNEL="sda", NAME="main_device"
1122 EOF
1123         },
1124         {
1125                 desc            => "parent node name substitution test sequence 2/2 (clean)",
1126                 subsys          => "block",
1127                 devpath         => "/block/sda/sda1",
1128                 exp_name        => "main_device-part-1",
1129                 option          => "clean",
1130                 conf            => <<EOF
1131 BUS="scsi", KERNEL="sda1", NAME="%P-part-1"
1132 EOF
1133         },
1134         {
1135                 desc            => "udev_root substitution",
1136                 subsys          => "block",
1137                 devpath         => "/block/sda/sda1",
1138                 exp_name        => "start-udev-root-end",
1139                 option          => "clean",
1140                 conf            => <<EOF
1141 BUS="scsi", KERNEL="sda1", NAME="start-%r-end"
1142 EOF
1143         },
1144 );
1145
1146 # set env
1147 $ENV{UDEV_TEST} = "yes";
1148 $ENV{SYSFS_PATH} = $sysfs;
1149 $ENV{UDEV_CONFIG_FILE} = $main_conf;
1150 $ENV{UDEV_NO_DEVD} = "yes";
1151 $ENV{UDEV_NO_HOTPLUGD} = "yes";
1152
1153
1154 sub udev {
1155         my ($action, $subsys, $devpath, $config) = @_;
1156
1157         $ENV{DEVPATH} = $devpath;
1158
1159         # create temporary config
1160         open CONF, ">$conf_tmp" || die "unable to create config file: $conf_tmp";
1161         print CONF $$config;
1162         close CONF;
1163
1164         $ENV{ACTION} = $action;
1165         system("$udev_bin $subsys");
1166 }
1167
1168 my $error = 0;
1169
1170 sub permissions_test {
1171         my($config, $uid, $gid, $mode) = @_;
1172
1173         my $wrong = 0;
1174         $config->{exp_perms} =~ m/^(.*):(.*):(.*)$/;
1175         if ($1 ne "") {
1176                 if ($uid != $1) { $wrong = 1; };
1177         }
1178         if ($2 ne "") {
1179                 if ($gid != $2) { $wrong = 1; };
1180         }
1181         if ($3 ne "") {
1182                 if (($mode & 07777) != oct($3)) { $wrong = 1; };
1183         }
1184         if ($wrong == 0) {
1185                 print "permissions: ok    ";
1186         } else {
1187                 printf "expected permissions are: %i:%i:%#o\n", $1, $2, oct($3);
1188                 printf "created permissions are : %i:%i:%#o\n", $uid, $gid, $mode & 07777;
1189                 $error++;
1190         }
1191 }
1192
1193 sub major_minor_test {
1194         my($config, $rdev) = @_;
1195
1196         my $major = ($rdev >> 8) & 0xfff;
1197         my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00);
1198         my $wrong = 0;
1199
1200         $config->{exp_majorminor} =~ m/^(.*):(.*)$/;
1201         if ($1 ne "") {
1202                 if ($major != $1) { $wrong = 1; };
1203         }
1204         if ($2 ne "") {
1205                 if ($minor != $2) { $wrong = 1; };
1206         }
1207         if ($wrong == 0) {
1208                 print "major:minor: ok    ";
1209         } else {
1210                 printf "expected major:minor is: %i:%i\n", $1, $2;
1211                 printf "created major:minor is : %i:%i\n", $major, $minor;
1212                 print "major:minor: error    ";
1213                 $error++;
1214         }
1215 }
1216
1217 sub symlink_test {
1218         my ($config) = @_;
1219
1220         my $output = `ls -l $PWD/$udev_root$config->{exp_name}`;
1221
1222         if ($output =~ m/(.*)-> (.*)/) {
1223                 if ($2 eq $config->{exp_target}) {
1224                         print "symlink: ok    ";
1225                 } else {
1226                         print "expected symlink from: \'$config->{exp_name}\' to \'$config->{exp_target}\'\n";
1227                         print "created symlink from: \'$config->{exp_name}\' to \'$2\'\n";
1228                         if ($config->{exp_error}) {
1229                                 print "as expected    ";
1230                         } else {
1231                                 $error++;
1232                         }
1233                 }
1234         } else {
1235                 print "expected symlink from: \'$config->{exp_name}\' to \'$config->{exp_target}\'\n";
1236                 print "symlink: not created ";
1237                 if ($config->{exp_error}) {
1238                         print "as expected    ";
1239                 } else {
1240                         $error++;
1241                 }
1242         }
1243 }
1244
1245 sub run_test {
1246         my ($config, $number) = @_;
1247
1248         print "TEST $number: $config->{desc}\n";
1249
1250         if ($config->{exp_target}) {
1251                 print "device \'$config->{devpath}\' expecting symlink '$config->{exp_name}' to node \'$config->{exp_target}\'\n";
1252         } else {
1253                 print "device \'$config->{devpath}\' expecting node \'$config->{exp_name}\'\n";
1254         }
1255
1256
1257         udev("add", $config->{subsys}, $config->{devpath}, \$config->{conf});
1258         if ((-e "$PWD/$udev_root$config->{exp_name}") ||
1259             (-l "$PWD/$udev_root$config->{exp_name}")) {
1260
1261                 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
1262                     $atime, $mtime, $ctime, $blksize, $blocks) = stat("$PWD/$udev_root$config->{exp_name}");
1263
1264                 if (defined($config->{exp_perms})) {
1265                         permissions_test($config, $uid, $gid, $mode);
1266                 }
1267                 if (defined($config->{exp_majorminor})) {
1268                         major_minor_test($config, $rdev);
1269                 }
1270                 if (defined($config->{exp_target})) {
1271                         symlink_test($config);
1272                 }
1273                 print "add: ok    ";
1274         } else {
1275                 print "add: error ";
1276                 if ($config->{exp_error}) {
1277                         print "as expected    ";
1278                 } else {
1279                         print "\n\n";
1280                         system("tree $udev_root");
1281                         print "\n";
1282                         $error++;
1283                 }
1284         }
1285
1286         if (defined($config->{option}) && $config->{option} eq "keep") {
1287                 print "\n\n";
1288                 return;
1289         }
1290
1291         udev("remove", $config->{subsys}, $config->{devpath}, \$config->{conf});
1292         if ((-e "$PWD/$udev_root$config->{exp_name}") ||
1293             (-l "$PWD/$udev_root$config->{exp_name}")) {
1294                 print "remove: error ";
1295                 if ($config->{exp_error}) {
1296                         print "as expected\n\n";
1297                 } else {
1298                         print "\n\n";
1299                         system("tree $udev_root");
1300                         print "\n";
1301                         $error++;
1302                 }
1303         } else {
1304                 print "remove: ok\n\n";
1305         }
1306
1307         if (defined($config->{option}) && $config->{option} eq "clear") {
1308                 system("rm -rf $udev_db");
1309                 system("rm -rf $udev_root");
1310                 mkdir($udev_root) || die "unable to create udev_root: $udev_root\n";
1311         }
1312
1313 }
1314
1315 # only run if we have root permissions
1316 # due to mknod restrictions
1317 if (!($<==0)) {
1318         print "Must have root permissions to run properly.\n";
1319         exit;
1320 }
1321
1322 # prepare
1323 system("rm -rf $udev_root");
1324 mkdir($udev_root) || die "unable to create udev_root: $udev_root\n";
1325
1326 # create initial config file
1327 open CONF, ">$main_conf" || die "unable to create config file: $main_conf";
1328 print CONF "udev_root=\"$udev_root\"\n";
1329 print CONF "udev_db=\"$udev_db\"\n";
1330 print CONF "udev_rules=\"$conf_tmp\"\n";
1331 close CONF;
1332
1333 my $test_num = 1;
1334
1335 if ($ARGV[0]) {
1336         # only run one test
1337         $test_num = $ARGV[0];
1338
1339         if (defined($tests[$test_num-1]->{desc})) {
1340                 print "udev-test will run test number $test_num only:\n\n";
1341                 run_test($tests[$test_num-1], $test_num);
1342         } else {
1343                 print "test does not exist.\n";
1344         }
1345 } else {
1346         # test all
1347         print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
1348
1349         foreach my $config (@tests) {
1350                 run_test($config, $test_num);
1351                 $test_num++;
1352         }
1353 }
1354
1355 print "$error errors occured\n\n";
1356
1357 # cleanup
1358 system("rm -rf $udev_db");
1359 system("rm -rf $udev_root");
1360 unlink($conf_tmp);
1361 unlink($main_conf);
1362