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