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