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