chiark / gitweb /
[PATCH] add test for ! in partition name
[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            => "name test with ! in the name for a partition",
404                 subsys          => "block",
405                 devpath         => "/block/cciss!c0d0/cciss!c0d0p1",
406                 exp_name        => "cciss/c0d0p1" ,
407                 conf            => <<EOF
408 BUS="scsi", NAME="%k"
409 KERNEL="ttyUSB0", NAME="visor"
410 EOF
411         },
412         {
413                 desc            => "ID rule",
414                 subsys          => "block",
415                 devpath         => "/block/sda",
416                 exp_name        => "scsi-0:0:0:0",
417                 conf            => <<EOF
418 BUS="usb", ID="0:0:0:0", NAME="not-scsi"
419 BUS="scsi", ID="0:0:0:1", NAME="no-match"
420 BUS="scsi", ID=":0", NAME="short-id"
421 BUS="scsi", ID="/0:0:0:0", NAME="no-match"
422 BUS="scsi", ID="0:0:0:0", NAME="scsi-0:0:0:0"
423 EOF
424         },
425         {
426                 desc            => "ID wildcard all",
427                 subsys          => "block",
428                 devpath         => "/block/sda",
429                 exp_name        => "scsi-0:0:0:0",
430                 conf            => <<EOF
431 BUS="scsi", ID="*:1", NAME="no-match"
432 BUS="scsi", ID="*:0:1", NAME="no-match"
433 BUS="scsi", ID="*:0:0:1", NAME="no-match"
434 BUS="scsi", ID="*", 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",
440                 subsys          => "block",
441                 devpath         => "/block/sda",
442                 exp_name        => "scsi-0:0:0:0",
443                 conf            => <<EOF
444 BUS="scsi", ID="*:0", NAME="scsi-0:0:0:0"
445 BUS="scsi", ID="0:0:0:0", NAME="bad"
446 EOF
447         },
448         {
449                 desc            => "ID wildcard partial 2",
450                 subsys          => "block",
451                 devpath         => "/block/sda",
452                 exp_name        => "scsi-0:0:0:0",
453                 conf            => <<EOF
454 BUS="scsi", ID="*:0:0:0", NAME="scsi-0:0:0:0"
455 BUS="scsi", ID="0:0:0:0", NAME="bad"
456 EOF
457         },
458         {
459                 desc            => "ignore SYSFS attribute whitespace",
460                 subsys          => "block",
461                 devpath         => "/block/sda",
462                 exp_name        => "ignored",
463                 conf            => <<EOF
464 BUS="scsi", SYSFS{whitespace_test}="WHITE  SPACE", NAME="ignored"
465 EOF
466         },
467         {
468                 desc            => "do not ignore SYSFS attribute whitespace",
469                 subsys          => "block",
470                 devpath         => "/block/sda",
471                 exp_name        => "matched-with-space",
472                 conf            => <<EOF
473 BUS="scsi", SYSFS{whitespace_test}="WHITE  SPACE ", NAME="wrong-to-ignore"
474 BUS="scsi", SYSFS{whitespace_test}="WHITE  SPACE   ", NAME="matched-with-space"
475 EOF
476         },
477         {
478                 desc            => "permissions test",
479                 subsys          => "block",
480                 devpath         => "/block/sda",
481                 exp_name        => "node",
482                 exp_perms       => "5000::0444",
483                 conf            => <<EOF
484 BUS="scsi", KERNEL="sda", NAME="node", OWNER="5000", MODE="0444"
485 EOF
486         },
487         {
488                 desc            => "permissions ttyUSB0:root:uucp:0660",
489                 subsys          => "tty",
490                 devpath         => "/class/tty/ttyUSB0",
491                 exp_name        => "ttyUSB0",
492                 exp_perms       => "0:14:0660",
493                 conf            => <<EOF
494 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n"
495 EOF
496         },
497         {
498                 desc            => "permissions tty0::root:0444",
499                 subsys          => "tty",
500                 devpath         => "/class/tty/tty0",
501                 exp_name        => "tty0",
502                 exp_perms       => "0:0:0444",
503                 conf            => <<EOF
504 KERNEL="tty0", NAME="tty0"
505 EOF
506         },
507         {
508                 desc            => "permissions tty1:root::0555",
509                 subsys          => "tty",
510                 devpath         => "/class/tty/tty1",
511                 exp_name        => "tty1",
512                 exp_perms       => "0:0:0555",
513                 conf            => <<EOF
514 KERNEL="tty1", NAME="tty1"
515 EOF
516         },
517         {
518                 desc            => "permissions tty2:::0777",
519                 subsys          => "tty",
520                 devpath         => "/class/tty/tty2",
521                 exp_name        => "tty2",
522                 exp_perms       => "0:0:0777",
523                 conf            => <<EOF
524 KERNEL="tty2", NAME="tty2"
525 EOF
526         },
527         {
528                 desc            => "permissions tty3:::",
529                 subsys          => "tty",
530                 devpath         => "/class/tty/tty3",
531                 exp_name        => "tty3",
532                 exp_perms       => "0:0:0",
533                 conf            => <<EOF
534 KERNEL="tty3", NAME="tty3"
535 EOF
536         },
537         {
538                 desc            => "permissions i2c-300:root:sys:0744",
539                 subsys          => "i2c-dev",
540                 devpath         => "/class/i2c-dev/i2c-300",
541                 exp_name        => "i2c-300",
542                 exp_perms       => "0:3:0744",
543                 conf            => <<EOF
544 KERNEL="i2c-300", NAME="i2c-300"
545 EOF
546         },
547         {
548                 desc            => "permissions i2c-fake1:root:7:0007",
549                 subsys          => "i2c-dev",
550                 devpath         => "/class/i2c-dev/i2c-fake1",
551                 exp_name        => "i2c-fake1",
552                 exp_perms       => "0:7:0007",
553                 conf            => <<EOF
554 KERNEL="i2c-fake1", NAME="i2c-fake1"
555 EOF
556         },
557         {
558                 desc            => "permissions ttyS[01]:0:5:0700",
559                 subsys          => "tty",
560                 devpath         => "/class/tty/ttyS1",
561                 exp_name        => "ttyS1",
562                 exp_perms       => "0:5:0700",
563                 conf            => <<EOF
564 KERNEL="ttyS1", NAME="ttyS1"
565 EOF
566         },
567         {
568                 desc            => "permissions ttyS[4-9]:tty:5:0060",
569                 subsys          => "tty",
570                 devpath         => "/class/tty/ttyS7",
571                 exp_name        => "ttyS7",
572                 exp_perms       => "0:5:0060",
573                 conf            => <<EOF
574 KERNEL="ttyS7", NAME="ttyS7"
575 EOF
576         },
577         {
578                 desc            => "permissions tty4:0:5:0707",
579                 subsys          => "ttyS4",
580                 devpath         => "/class/tty/tty4",
581                 exp_name        => "tty4",
582                 exp_perms       => "0:5:0707",
583                 conf            => <<EOF
584 KERNEL="tty4", NAME="tty4"
585 EOF
586         },
587         {
588                 desc            => "permissions tty4?:0:5:0007",
589                 subsys          => "tty",
590                 devpath         => "/class/tty/tty44",
591                 exp_name        => "tty44",
592                 exp_perms       => "0:5:0007",
593                 conf            => <<EOF
594 KERNEL="tty44", NAME="tty44"
595 EOF
596         },
597         {
598                 desc            => "permissions tty3[!3]:::0467",
599                 subsys          => "tty",
600                 devpath         => "/class/tty/tty35",
601                 exp_name        => "tty35",
602                 exp_perms       => "0:0:0467",
603                 conf            => <<EOF
604 KERNEL="tty35", NAME="tty35"
605 EOF
606         },
607         {
608                 desc            => "permissions tty33:bad:name:0500",
609                 subsys          => "tty",
610                 devpath         => "/class/tty/tty33",
611                 exp_name        => "tty33",
612                 exp_perms       => "0:0:0500",
613                 conf            => <<EOF
614 KERNEL="tty33", NAME="tty33"
615 EOF
616         },
617         {
618                 desc            => "permissions rtc:0:users:0600",
619                 subsys          => "misc",
620                 devpath         => "/class/misc/rtc",
621                 exp_name        => "misc/rtc",
622                 exp_perms       => "0:100:0600",
623                 conf            => <<EOF
624 KERNEL="rtc", NAME="misc/rtc"
625 EOF
626         },
627         {
628                 desc            => "permissions misc:0:users:0600",
629                 subsys          => "misc",
630                 devpath         => "/class/misc/psaux",
631                 exp_name        => "misc/psaux",
632                 exp_perms       => "0:100:0600",
633                 conf            => <<EOF
634 KERNEL="psaux", NAME="misc/psaux"
635 EOF
636         },
637         {
638                 desc            => "permissions set OWNER=5000",
639                 subsys          => "block",
640                 devpath         => "/block/sda",
641                 exp_name        => "node",
642                 exp_perms       => "5000::0600",
643                 conf            => <<EOF
644 BUS="scsi", KERNEL="sda", NAME="node", OWNER="5000"
645 EOF
646         },
647         {
648                 desc            => "permissions set GROUP=100",
649                 subsys          => "block",
650                 devpath         => "/block/sda",
651                 exp_name        => "node",
652                 exp_perms       => ":100:0600",
653                 conf            => <<EOF
654 BUS="scsi", KERNEL="sda", NAME="node", GROUP="100"
655 EOF
656         },
657         {
658                 desc            => "permissions set mode=0777",
659                 subsys          => "block",
660                 devpath         => "/block/sda",
661                 exp_name        => "node",
662                 exp_perms       => "::0777",
663                 conf            => <<EOF
664 BUS="scsi", KERNEL="sda", NAME="node", MODE="0777"
665 EOF
666         },
667         {
668                 desc            => "permissions set OWNER=5000 GROUP=100 MODE=0777",
669                 subsys          => "block",
670                 devpath         => "/block/sda",
671                 exp_name        => "node",
672                 exp_perms       => "5000:100:0777",
673                 conf            => <<EOF
674 BUS="scsi", KERNEL="sda", NAME="node", OWNER="5000", GROUP="100", MODE="0777"
675 EOF
676         },
677         {
678                 desc            => "permissions override OWNER to 5000",
679                 subsys          => "tty",
680                 devpath         => "/class/tty/ttyUSB0",
681                 exp_name        => "ttyUSB0",
682                 exp_perms       => "5000:14:0660",
683                 conf            => <<EOF
684 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", OWNER="5000"
685 EOF
686         },
687         {
688                 desc            => "permissions override GROUP to 100",
689                 subsys          => "tty",
690                 devpath         => "/class/tty/ttyUSB0",
691                 exp_name        => "ttyUSB0",
692                 exp_perms       => ":100:0660",
693                 conf            => <<EOF
694 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", GROUP="100"
695 EOF
696         },
697         {
698                 desc            => "permissions override MODE to 0060",
699                 subsys          => "tty",
700                 devpath         => "/class/tty/ttyUSB0",
701                 exp_name        => "ttyUSB0",
702                 exp_perms       => ":14:0060",
703                 conf            => <<EOF
704 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", MODE="0060"
705 EOF
706         },
707         {
708                 desc            => "permissions override OWNER, GROUP, MODE",
709                 subsys          => "tty",
710                 devpath         => "/class/tty/ttyUSB0",
711                 exp_name        => "ttyUSB0",
712                 exp_perms       => "5000:100:0777",
713                 conf            => <<EOF
714 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", OWNER="5000", GROUP="100", MODE="0777"
715 EOF
716         },
717         {
718                 desc            => "major/minor number test",
719                 subsys          => "block",
720                 devpath         => "/block/sda",
721                 exp_name        => "node",
722                 exp_majorminor  => "8:0",
723                 conf            => <<EOF
724 BUS="scsi", KERNEL="sda", NAME="node"
725 EOF
726         },
727         {
728                 desc            => "big minor number test",
729                 subsys          => "i2c-dev",
730                 devpath         => "/class/i2c-dev/i2c-300",
731                 exp_name        => "node",
732                 exp_majorminor  => "89:300",
733                 conf            => <<EOF
734 KERNEL="i2c-300", NAME="node"
735 EOF
736         },
737         {
738                 desc            => "big major number test",
739                 subsys          => "i2c-dev",
740                 devpath         => "/class/i2c-dev/i2c-fake1",
741                 exp_name        => "node",
742                 exp_majorminor  => "4095:1",
743                 conf            => <<EOF
744 KERNEL="i2c-fake1", NAME="node"
745 EOF
746         },
747         {
748                 desc            => "big major and big minor number test",
749                 subsys          => "i2c-dev",
750                 devpath         => "/class/i2c-dev/i2c-fake2",
751                 exp_name        => "node",
752                 exp_majorminor  => "4094:89999",
753                 conf            => <<EOF
754 KERNEL="i2c-fake2", NAME="node"
755 EOF
756         },
757         {
758                 desc            => "symlink creation (same directory)",
759                 subsys          => "tty",
760                 devpath         => "/class/tty/ttyUSB0",
761                 exp_name        => "visor0",
762                 exp_target      => "ttyUSB0",
763                 conf            => <<EOF
764 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="visor%n"
765 EOF
766         },
767         {
768                 desc            => "symlink creation (relative link forward)",
769                 subsys          => "block",
770                 devpath         => "/block/sda/sda2",
771                 exp_name        => "1/2/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/symlink"
775 EOF
776         },
777         {
778                 desc            => "symlink creation (relative link back and forward)",
779                 subsys          => "block",
780                 devpath         => "/block/sda/sda2",
781                 exp_name        => "1/2/c/d/symlink" ,
782                 exp_target      => "../../a/b/node",
783                 conf            => <<EOF
784 BUS="scsi", SYSFS{vendor}="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/c/d/symlink"
785 EOF
786         },
787         {
788                 desc            => "multiple symlinks",
789                 subsys          => "tty",
790                 devpath         => "/class/tty/ttyUSB0",
791                 exp_name        => "second-0" ,
792                 exp_target      => "visor" ,
793                 conf            => <<EOF
794 KERNEL="ttyUSB0", NAME="visor", SYMLINK="first-%n second-%n third-%n"
795 EOF
796         },
797         {
798                 desc            => "symlink only rule",
799                 subsys          => "block",
800                 devpath         => "/block/sda",
801                 exp_name        => "symlink-only2",
802                 exp_target      => "link",
803                 conf            => <<EOF
804 BUS="scsi", KERNEL="sda", SYMLINK="symlink-only1"
805 BUS="scsi", KERNEL="sda", SYMLINK="symlink-only2"
806 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK="symlink0"
807 EOF
808         },
809         {
810                 desc            => "symlink name empty",
811                 subsys          => "block",
812                 devpath         => "/block/sda",
813                 exp_name        => "",
814                 exp_target      => "link",
815                 exp_error       => "yes",
816                 conf            => <<EOF
817 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK=""
818 EOF
819         },
820         {
821                 desc            => "symlink name '.'",
822                 subsys          => "block",
823                 devpath         => "/block/sda",
824                 exp_name        => ".",
825                 exp_target      => "link",
826                 exp_error       => "yes",
827                 conf            => <<EOF
828 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK="."
829 EOF
830         },
831         {
832                 desc            => "symlink to empty name",
833                 subsys          => "block",
834                 devpath         => "/block/sda",
835                 exp_name        => "symlink",
836                 exp_target      => "",
837                 exp_error       => "yes",
838                 conf            => <<EOF
839 BUS="scsi", KERNEL="sda", NAME="", SYMLINK="symlink"
840 EOF
841         },
842         {
843                 desc            => "symlink and name empty",
844                 subsys          => "block",
845                 devpath         => "/block/sda",
846                 exp_name        => "",
847                 exp_target      => "",
848                 exp_error       => "yes",
849                 conf            => <<EOF
850 BUS="scsi", KERNEL="sda", NAME="", SYMLINK=""
851 EOF
852         },
853         {
854                 desc            => "symlink node to itself",
855                 subsys          => "tty",
856                 devpath         => "/class/tty/tty0",
857                 exp_name        => "link",
858                 exp_target      => "link",
859                 conf            => <<EOF
860 KERNEL="tty0", NAME="link", SYMLINK="link"
861 EOF
862         },
863         {
864                 desc            => "symlink %n substitution",
865                 subsys          => "tty",
866                 devpath         => "/class/tty/ttyUSB0",
867                 exp_name        => "symlink0",
868                 exp_target      => "ttyUSB0",
869                 conf            => <<EOF
870 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink%n"
871 EOF
872         },
873         {
874                 desc            => "symlink %k substitution",
875                 subsys          => "tty",
876                 devpath         => "/class/tty/ttyUSB0",
877                 exp_name        => "symlink-ttyUSB0",
878                 exp_target      => "ttyUSB0",
879                 conf            => <<EOF
880 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink-%k"
881 EOF
882         },
883         {
884                 desc            => "symlink %M:%m substitution",
885                 subsys          => "tty",
886                 devpath         => "/class/tty/ttyUSB0",
887                 exp_name        => "major-188:0",
888                 exp_target      => "ttyUSB0",
889                 conf            => <<EOF
890 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="major-%M:%m"
891 EOF
892         },
893         {
894                 desc            => "symlink %b substitution",
895                 subsys          => "block",
896                 devpath         => "/block/sda",
897                 exp_name        => "symlink-0:0:0:0",
898                 exp_target      => "node",
899                 conf            => <<EOF
900 BUS="scsi", KERNEL="sda", NAME="node", SYMLINK="symlink-%b"
901 EOF
902         },
903         {
904                 desc            => "symlink %c 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 test" NAME="ttyUSB%n", SYMLINK="%c"
911 EOF
912         },
913         {
914                 desc            => "symlink %c{N} substitution",
915                 subsys          => "tty",
916                 devpath         => "/class/tty/ttyUSB0",
917                 exp_name        => "test",
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 %c{N+} substitution",
925                 subsys          => "tty",
926                 devpath         => "/class/tty/ttyUSB0",
927                 exp_name        => "this",
928                 exp_target      => "ttyUSB0",
929                 conf            => <<EOF
930 KERNEL="ttyUSB[0-9]*", PROGRAM="/bin/echo symlink test this" NAME="ttyUSB%n", SYMLINK="%c{2+}"
931 EOF
932         },
933         {
934                 desc            => "symlink only rule with %c{N+}",
935                 subsys          => "block",
936                 devpath         => "/block/sda",
937                 exp_name        => "test",
938                 exp_target      => "link",
939                 conf            => <<EOF
940 BUS="scsi", KERNEL="sda", PROGRAM="/bin/echo link test this" SYMLINK="%c{2+}"
941 BUS="scsi", KERNEL="sda", NAME="link", SYMLINK="symlink0"
942 EOF
943         },
944         {
945                 desc            => "symlink %s{filename} substitution",
946                 subsys          => "tty",
947                 devpath         => "/class/tty/ttyUSB0",
948                 exp_name        => "188:0",
949                 exp_target      => "ttyUSB0",
950                 conf            => <<EOF
951 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="%s{dev}"
952 EOF
953         },
954         {
955                 desc            => "symlink %Ns{filename} substitution",
956                 subsys          => "tty",
957                 devpath         => "/class/tty/ttyUSB0",
958                 exp_name        => "188",
959                 exp_target      => "ttyUSB0",
960                 conf            => <<EOF
961 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="%3s{dev}"
962 EOF
963         },
964         {
965                 desc            => "symlink with '%' in name",
966                 subsys          => "tty",
967                 devpath         => "/class/tty/ttyUSB0",
968                 exp_name        => "percent%sign",
969                 exp_target      => "ttyUSB0",
970                 conf            => <<EOF
971 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="percent%%sign"
972 EOF
973         },
974         {
975                 desc            => "symlink with '%' in name",
976                 subsys          => "tty",
977                 devpath         => "/class/tty/ttyUSB0",
978                 exp_name        => "%ttyUSB0_name",
979                 exp_target      => "ttyUSB0",
980                 conf            => <<EOF
981 KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="%%%k_name"
982 EOF
983         },
984         {
985                 desc            => "program result substitution (numbered part of)",
986                 subsys          => "block",
987                 devpath         => "/block/sda/sda3",
988                 exp_name        => "link1",
989                 exp_target      => "node",
990                 conf            => <<EOF
991 BUS="scsi", PROGRAM="/bin/echo -n node link1 link2", RESULT="node *", NAME="%c{1}", SYMLINK="%c{2} %c{3}"
992 EOF
993         },
994         {
995                 desc            => "program result substitution (numbered part of+)",
996                 subsys          => "block",
997                 devpath         => "/block/sda/sda3",
998                 exp_name        => "link4",
999                 exp_target      => "node",
1000                 conf            => <<EOF
1001 BUS="scsi", PROGRAM="/bin/echo -n node link1 link2 link3 link4", RESULT="node *", NAME="%c{1}", SYMLINK="%c{2+}"
1002 EOF
1003         },
1004 );
1005
1006 # set env
1007 $ENV{UDEV_TEST} = "yes";
1008 $ENV{SYSFS_PATH} = $sysfs;
1009 $ENV{UDEV_CONFIG_FILE} = $main_conf;
1010 $ENV{UDEV_NO_SLEEP} = "yes";
1011 $ENV{UDEV_NO_DEVD} = "yes";
1012
1013
1014 sub udev {
1015         my ($action, $subsys, $devpath, $config) = @_;
1016
1017         $ENV{DEVPATH} = $devpath;
1018
1019         # create temporary config
1020         open CONF, ">$conf_tmp" || die "unable to create config file: $conf_tmp";
1021         print CONF $$config;
1022         close CONF;
1023
1024         $ENV{ACTION} = $action;
1025         system("$udev_bin $subsys");
1026 }
1027
1028 my $error = 0;
1029
1030 sub permissions_test {
1031         my($config, $uid, $gid, $mode) = @_;
1032
1033         my $wrong = 0;
1034         $config->{exp_perms} =~ m/^(.*):(.*):(.*)$/;
1035         if ($1 ne "") {
1036                 if ($uid != $1) { $wrong = 1; };
1037         }
1038         if ($2 ne "") {
1039                 if ($gid != $2) { $wrong = 1; };
1040         }
1041         if ($3 ne "") {
1042                 if (($mode & 07777) != oct($3)) { $wrong = 1; };
1043         }
1044         if ($wrong == 0) {
1045                 print "permissions: ok    ";
1046         } else {
1047                 printf "expected permissions are: %i:%i:%#o\n", $1, $2, oct($3);
1048                 printf "created permissions are : %i:%i:%#o\n", $uid, $gid, $mode & 07777;
1049                 $error++;
1050         }
1051 }
1052
1053 sub major_minor_test {
1054         my($config, $rdev) = @_;
1055
1056         my $major = ($rdev >> 8) & 0xfff;
1057         my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00);
1058         my $wrong = 0;
1059
1060         $config->{exp_majorminor} =~ m/^(.*):(.*)$/;
1061         if ($1 ne "") {
1062                 if ($major != $1) { $wrong = 1; };
1063         }
1064         if ($2 ne "") {
1065                 if ($minor != $2) { $wrong = 1; };
1066         }
1067         if ($wrong == 0) {
1068                 print "major:minor: ok    ";
1069         } else {
1070                 printf "expected major:minor is: %i:%i\n", $1, $2;
1071                 printf "created major:minor is : %i:%i\n", $major, $minor;
1072                 print "major:minor: error    ";
1073                 $error++;
1074         }
1075 }
1076
1077 sub symlink_test {
1078         my ($config) = @_;
1079
1080         my $output = `ls -l $PWD/$udev_root$config->{exp_name}`;
1081
1082         if ($output =~ m/(.*)-> (.*)/) {
1083                 if ($2 eq $config->{exp_target}) {
1084                         print "symlink: ok    ";
1085                 } else {
1086                         print "expected symlink from: \'$config->{exp_name}\' to \'$config->{exp_target}\'\n";
1087                         print "created symlink from: \'$config->{exp_name}\' to \'$2\'\n";
1088                         if ($config->{exp_error}) {
1089                                 print "as expected    ";
1090                         } else {
1091                                 $error++;
1092                         }
1093                 }
1094         } else {
1095                 print "expected symlink from: \'$config->{exp_name}\' to \'$config->{exp_target}\'\n";
1096                 print "symlink: not created ";
1097                 if ($config->{exp_error}) {
1098                         print "as expected    ";
1099                 } else {
1100                         $error++;
1101                 }
1102         }
1103 }
1104
1105 sub run_test {
1106         my ($config, $number) = @_;
1107
1108         print "TEST $number: $config->{desc}\n";
1109
1110         if ($config->{exp_target}) {
1111                 print "device \'$config->{devpath}\' expecting symlink '$config->{exp_name}' to node \'$config->{exp_target}\'\n";
1112         } else {
1113                 print "device \'$config->{devpath}\' expecting node \'$config->{exp_name}\'\n";
1114         }
1115
1116
1117         udev("add", $config->{subsys}, $config->{devpath}, \$config->{conf});
1118
1119         if ((-e "$PWD/$udev_root$config->{exp_name}") ||
1120             (-l "$PWD/$udev_root$config->{exp_name}")) {
1121
1122                 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
1123                     $atime, $mtime, $ctime, $blksize, $blocks) = stat("$PWD/$udev_root$config->{exp_name}");
1124
1125                 if (defined($config->{exp_perms})) {
1126                         permissions_test($config, $uid, $gid, $mode);
1127                 }
1128                 if (defined($config->{exp_majorminor})) {
1129                         major_minor_test($config, $rdev);
1130                 }
1131                 if (defined($config->{exp_target})) {
1132                         symlink_test($config);
1133                 }
1134                 print "add: ok    ";
1135         } else {
1136                 print "add: error ";
1137                 if ($config->{exp_error}) {
1138                         print "as expected    ";
1139                 } else {
1140                         print "\n\n";
1141                         system("tree $udev_root");
1142                         print "\n";
1143                         $error++;
1144                 }
1145         }
1146
1147         udev("remove", $config->{subsys}, $config->{devpath}, \$config->{conf});
1148         if ((-e "$PWD/$udev_root$config->{exp_name}") ||
1149             (-l "$PWD/$udev_root$config->{exp_name}")) {
1150                 print "remove: error ";
1151                 if ($config->{exp_error}) {
1152                         print "as expected\n\n";
1153                 } else {
1154                         print "\n\n";
1155                         system("tree $udev_root");
1156                         print "\n";
1157                         $error++;
1158                 }
1159         } else {
1160                 print "remove: ok\n\n";
1161         }
1162 }
1163
1164 # prepare
1165 system("rm -rf $udev_root");
1166 mkdir($udev_root) || die "unable to create udev_root: $udev_root\n";
1167
1168 # create initial config file
1169 open CONF, ">$main_conf" || die "unable to create config file: $main_conf";
1170 print CONF "udev_root=\"$udev_root\"\n";
1171 print CONF "udev_db=\"$udev_db\"\n";
1172 print CONF "udev_rules=\"$conf_tmp\"\n";
1173 print CONF "udev_permissions=\"$perm\"\n";
1174 close CONF;
1175
1176 my $test_num = 1;
1177
1178 if ($ARGV[0]) {
1179         # only run one test
1180         $test_num = $ARGV[0];
1181         print "udev-test will run test number $test_num only\n";
1182
1183         run_test($tests[$test_num-1], $test_num);
1184 } else {
1185         # test all
1186         print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
1187
1188         foreach my $config (@tests) {
1189                 run_test($config, $test_num);
1190                 $test_num++;
1191
1192         }
1193 }
1194
1195 print "$error errors occured\n\n";
1196
1197 # cleanup
1198 unlink($udev_db);
1199 system("rm -rf $udev_root");
1200 unlink($conf_tmp);
1201 unlink($main_conf);
1202