8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / perl / contrib / Sun / Solaris / Project / t / Project.t
blob8991614ed68c185394460e4b71f68fdf5ae6ed2c
2 # Copyright (c) 2000, 2005 Oracle and/or its affiliates. All rights reserved.
6 # test script for Sun::Solaris::Project
9 use warnings;
10 use strict;
11 use Data::Dumper;
12 $Data::Dumper::Terse = 1;
13 $Data::Dumper::Indent = 0;
15 sub cleanup {
16         unlink("/tmp/project.$$.1");
17         unlink("/tmp/project.$$.2");
18         unlink("/tmp/project.$$.3");
19         unlink("/tmp/project.$$.4");
20         unlink("/tmp/project.$$.5");
21         unlink("/tmp/project.$$.1.w");
22         unlink("/tmp/project.$$.2.w");
23         unlink("/tmp/project.$$.3.w");
24         unlink("/tmp/project.$$.4.w");
25         unlink("/tmp/project.$$.5.w");
26         unlink("/tmp/projent.$$");
29 # 'use Sun::Solaris::Project;' counts as test 1
30 our $test = 1;
31 our $intest = 1;
32 our $loaded = 0;
35 # Status reporting utils
37 # Expected calling sequence is:
38 #       start()
39 #       pass() or fail()
40 #       start()
41 #       pass() or fail()
42 #       ...
43 #       ...
45 #       Calling start() twice in a row will fail test.
46 #       Calling start() and then exiting will fail test.
48 sub start
50         if ($intest != 0) {
51                 fatal("Started new test before finishing previous.");
52         }
53         $test++;
54         $intest = 1;
55         print "# Starting Test $test: @_\n" if (@_);
58 sub pass
60         if ($intest == 0) {
61                 fatal("pass() without start()");
62         }
63         print("ok $test @_\n");
64         $intest = 0;
67 sub fail
69         if ($intest == 0) {
70                 fatal("fail() without start()");
71         }
72         print("not ok $test @_\n");
73         $intest = 0;
76 sub fatal
78         print(STDERR "FATAL!\n");
79         print("not ok $test @_\n");
80         exit(1);
83 sub comment
85         print("# @_\n");
89 # Read in a project file and build into the same data structure that we will
90 # get if we do the same with the getXXX functions
93 sub read_pfile
95         my ($fh) = @_;
96         my ($line, @a1, @a2);
97         while (defined($line = <$fh>)) {
98                 chomp($line);
99                 @a2 = split(/:/, $line, 6);
100                 $a2[2] = '' if (! defined($a2[2]));
101                 $a2[3] = defined($a2[3]) ? [ split(/,/, $a2[3]) ] : [];
102                 $a2[4] = defined($a2[4]) ? [ split(/,/, $a2[4]) ] : [];
103                 $a2[5] = '' if (! defined($a2[5]));
104                 push(@a1, [ @a2 ]);
105         }
106         return(\@a1);
110 # Compare two arrays of project structures & check for equivalence.
111 # Converts each into a string using Data::Dumper and then does a string
112 # comparison.  Dirty but effective :-)
115 sub cmp_recs
117         my ($a1, $a2) = @_;
118         my $s1 = Dumper($a1);
119         my $s2 = Dumper($a2);
121         # Make sure numbers and quoted numbers compare the same
122         $s1 =~ s/'([+-]?[\d.]+)'/$1/g;
123         $s2 =~ s/'([+-]?[\d.]+)'/$1/g;
125         return($s1 eq $s2);
128 sub hash2string
130         my ($key, $value);
131         my @strings;
132         my $string;
133         my $hash = $_[0];
134         foreach $key (keys(%$hash)) {
135                 push(@strings, "$key => $hash->{$key}");
136         }
137         $string = "{ " . join(", ", @strings) . " }";
138         return ($string);
142 # Main body of tests starts here.
145 # Check the module loads.
146 BEGIN {
147         $| = 1;
148         print "1..548\n";
151 END {
152         fail("not ok 1") unless ($loaded);
153         fail("Exited during test!") if ($intest == 1);
154         cleanup();
157 use Sun::Solaris::Project qw(:ALL :PRIVATE);
158 $loaded = 1;
159 pass();
161 start("Check the constants.");
162 my ($fh, $line, $n1, $n2, $n3, $s);
163 open($fh, "</usr/include/project.h") || fatal($!);
164 while (defined($line = <$fh>)) {
165         $n1 = $1 if ($line =~ /#define\s+PROJNAME_MAX\s+(\d+)/);
166         $n2 = $1 if ($line =~ /#define\s+PROJECT_BUFSZ\s+(\d+)/);
167         $s = $1 if ($line =~ /#define\s+PROJF_PATH\s+"([^"]+)"/);
169 close($fh);
170 open($fh, "</usr/include/sys/param.h") || fatal($!);
171 while (defined($line = <$fh>)) {
172         $n3 = $1 if ($line =~ /#define\s+MAXUID\s+(\d+)/);
174 close($fh);
175 if (! defined($s) || ! defined($n1) || ! defined($n2)) {
176         fail();
177 } else {
178         if ($n1 == &PROJNAME_MAX && $n2 == &PROJECT_BUFSZ &&
179             $n3 == &MAXPROJID && $s eq &PROJF_PATH) {
180                 pass();
181         } else {
182                 fail();
183         }
187 # projf_read on various files with various flags.
189 # This table represents when projf_read should fail given a file
190 # and flags.
192 # file/flags  # {}      validate        validate,res    validate,dup    
193 # ###################################################################
194 # parse error # no      no              no              no
195 # dup names   # yes     no              no              no      
196 # dup ids     # yes     no              no              yes
197 # system ids  # yes     no              yes             no
198 # all user    # yes     yes             yes             yes
201 my $flags1 = {};
202 my $flags2 = { "validate" => "true" };
203 my $flags3 = { "validate" => "true", "res" => 1 };
204 my $flags4 = { "validate" => "true", "dup" => 1 };
206 # Make a temporary project files.
207 my ($ret, $file1, $file2, $file3, $file4, $file5, $pass);
209 # file1, parse error (extra ":") on group.staff project.
210 open($file1, "+>/tmp/project.$$.1") || fatal($!);
211 print $file1 <<EOF;
212 test1:123:project one:root,bin:adm:attr1=a;attr2=b
213 user.test2:456:project two:adm,uucp:staff:attr1=p;attr2=q
214 group.test3:678:project three::root,nobody:root,lp:attr1=y;attr2=z
215 test4:678:project four:root:root:
216 test5:679:project five::sys:
217 test6:690::::
220 # file2, duplicate project names.
221 open($file2, "+>/tmp/project.$$.2") || fatal($!);
222 print $file2 <<EOF;
223 test1:123:project one:root,bin:adm:attr1=a;attr2=b
224 user.test2:456:project two:adm,uucp:staff:attr1=p;attr2=q
225 group.test3:677:project three:root,nobody:root,lp:attr1=y;attr2=z
226 test1:678:project four:root:root:
227 test5:679:project five::sys:
228 test6:690::::
231 # file3, duplicate project ids.
232 open($file3, "+>/tmp/project.$$.3") || fatal($!);
233 print $file3 <<EOF;
234 test1:123:project one:root,bin:adm:attr1=a;attr2=b
235 user.test2:456:project two:adm,uucp:staff:attr1=p;attr2=q
236 group.test3:677:project three:root,nobody:root,lp:attr1=y;attr2=z
237 test4:678:project four:root:root:
238 test5:678:project five::sys:
239 test6:690::::
242 # file4, system project ids.
243 open($file4, "+>/tmp/project.$$.4") || fatal($!);
244 print $file4 <<EOF;
245 system:0::::
246 user.root:1::::
247 noproject:2::::
248 default:3::::
249 group.staff:10::::
250 test1:123:project one:root,bin:adm:attr1=a;attr2=b
251 user.test2:456:project two:adm,uucp:staff:attr1=p;attr2=q
252 group.test3:677:project three:root,nobody:root,lp:attr1=y;attr2=z
253 test4:678:project four:root:root:
254 test5:679:project five::sys:
255 test6:690::::
258 # file5, all unique user projects.
259 open($file5, "+>/tmp/project.$$.5") || fatal($!);
260 print $file5 <<EOF;
261 test1:123:project one:root,bin:adm:attr1=a;attr2=b
262 user.test2:456:project two:adm,uucp:staff:attr1=p;attr2=q
263 group.test3:677:project three:root,nobody:root,lp:attr1=y;attr2=z
264 test4:678:project four:root:root:
265 test5:679:project five::sys:
266 test6:690::::
270 # Each test is the file description, input file, filename, flags, and the expected
271 # return value.
273 my @read_tests = (
274         [ "parse error", $file1, "/tmp/project.$$.1", $flags1, 1 ],
275         [ "parse error", $file1, "/tmp/project.$$.1", $flags2, 1 ],
276         [ "parse error", $file1, "/tmp/project.$$.1", $flags3, 1 ],
277         [ "parse error", $file1, "/tmp/project.$$.1", $flags4, 1 ],
278         [ "dup names", $file2, "/tmp/project.$$.2", $flags1, 0 ],
279         [ "dup names", $file2, "/tmp/project.$$.2", $flags2, 1 ],
280         [ "dup names", $file2, "/tmp/project.$$.2", $flags3, 1 ],
281         [ "dup names", $file2, "/tmp/project.$$.2", $flags4, 1 ],
282         [ "dup ids", $file3, "/tmp/project.$$.3", $flags1, 0 ],
283         [ "dup ids", $file3, "/tmp/project.$$.3", $flags2, 1 ],
284         [ "dup ids", $file3, "/tmp/project.$$.3", $flags3, 1 ],
285         [ "dup ids", $file3, "/tmp/project.$$.3", $flags4, 0 ],
286         [ "sys ids", $file4, "/tmp/project.$$.4", $flags1, 0 ],
287         [ "sys ids", $file4, "/tmp/project.$$.4", $flags2, 1 ],
288         [ "sys ids", $file4, "/tmp/project.$$.4", $flags3, 0 ],
289         [ "sys ids", $file4, "/tmp/project.$$.4", $flags4, 1 ],
290         [ "unique users", $file5, "/tmp/project.$$.5", $flags1, 0 ],
291         [ "unique users", $file5, "/tmp/project.$$.5", $flags2, 0 ],
292         [ "unique users", $file5, "/tmp/project.$$.5", $flags3, 0 ],
293         [ "unique users", $file5, "/tmp/project.$$.5", $flags4, 0 ]
296 my $projents;
297 my @goodprojents;
298 my $read_test;
299 my $desc;
300 my $file;
301 my $filename;
302 my $flags;
303 my $flagstring;
304 my $exp;
305 my $error;
307 # Do projf_read tests.
308 foreach $read_test (@read_tests) {
310         ($desc, $file, $filename, $flags, $exp) = @$read_test;
311         $flagstring = hash2string($flags);
312         start("projf_read(): $desc, flags: $flagstring, file: $filename");
314         seek($file, 0, 0);
316         ($ret, $projents) = projf_read($file, $flags);
317         # check return is expected result
318         if ($ret != $exp) {
319                 fail("Expected $exp, Returned $ret");
320                 if ($ret) {
321                         foreach $error (@$projents) {
322                                 comment("# " . join(", ", @$error));;
323                         }
324                 }
325                 next;
326         }
327         # verify either projents or error messages were returned
328         if (!(@$projents)) {
329                 fail("Missing projents or error messages");
330                 next;
331         }
332         pass();
334         # Save projents from successful reads for testing projf_write.
335         if ($ret == 0) {
336                 push(@goodprojents, [$desc, $flags, $projents, $filename]);
337         }
340 close($file1);
341 close($file2);
342 close($file3);
343 close($file4);
344 close($file5);
346 # Test projf_write, write each successfully read file.
348 my @write_tests;
349 my $write_test;
351 foreach $write_test (@goodprojents) {
353         ($desc, $flags, $projents, $filename) = @$write_test;
354         $flagstring = hash2string($flags);
355         start("projf_write(): $desc, flags: $flagstring, file: $filename");
357         open($fh, ">$filename.w") || fatal($!);
359         projf_write($fh, $projents);
360         close($fh);
361         system("cmp -s $filename $filename.w") == 0 ? pass() :
362             fail("Written file $filename.w does not match file $filename");
365 # Tests for projent_parse and projent_validate.
367 my @projent_tests;
368 my $projent_test;
371 # Tests, in format:
373 #  [ parse_result_expected, validate_result_expected, flags, project-line ]
375 @projent_tests = (
377 # positive
379         [ 0, 0, { "res" => 1 }, "system:0::::" ],
380         [ 0, 0, { "res" => 1 }, "user.root:1::::" ],
381         [ 0, 0, { "res" => 1 }, "noproject:2::::" ],
382         [ 0, 0, { "res" => 1 }, "default:3::::" ],
383         [ 0, 0, { "res" => 1 }, "group.staff:10::::" ],
384         [ 0, 0, {}, "long:100::::" . "a" x 2048 ],
385         [ 0, 0, {}, "Validname:101::::" ],
386         [ 0, 0, {}, "Validname2:102::::" ],
387         [ 0, 0, {}, "valid3name:103::::" ],
388         [ 0, 0, {}, "VALIDNAME:104::::" ],
389         [ 0, 0, {}, "VALIDNAME5:105::::" ],
390         [ 0, 0, {}, "vAlid5name:106::::" ],
391         [ 0, 0, {}, "valid.name:107::::" ],
392         [ 0, 0, {}, "valid8.NAME:108::::" ],
393         [ 0, 0, {}, "Valid_name9:109::::" ],
394         [ 0, 0, {}, "V_alid.name10:110::::" ],
395         [ 0, 0, {}, "valid12345678901234567890123456789012345678901234567890123456789:111::::" ],
396         [ 0, 0, {}, "projid:2147483647::::" ],
397         [ 0, 0, {}, "comment:111: this is ! & my crazy  !@#$%^&*()_+|~`\=-][ 0, 0, {},}{';\"/.,?>< comment:::" ],
398         [ 0, 0, {}, "user1:112::*::" ],
399         [ 0, 0, {}, "user2:113::!*::" ],
400         [ 0, 0, {}, "user3:114::root::" ],
401         [ 0, 0, {}, "user4:115::!root::" ],
402         [ 0, 0, {}, "user5:116::*,!sys::" ],
403         [ 0, 0, {}, "user6:117::!*,daemon::" ],
404         [ 0, 0, {}, "user7:118::root,sys,daemon,bin::" ],
405         [ 0, 0, {}, "user8:119::root,!sys,daemon,!bin::" ],
406         [ 0, 0, { "allowspaces" => 1 }, "user9:116::*, !sys::" ],
407         [ 0, 0, { "allowspaces" => 1 }, "user10:117::!* ,daemon::" ],
408         [ 0, 0, { "allowspaces" => 1 }, "user11:118::root ,sys ,daemon, bin::" ],
409         [ 0, 0, { "allowspaces" => 1 }, "user12:119::root, !sys, daemon ,!bin::" ],
410         [ 0, 0, {}, "group1:120:::*:" ],
411         [ 0, 0, {}, "group2:121:::!*:" ],
412         [ 0, 0, {}, "group3:122:::root:" ],
413         [ 0, 0, {}, "group4:123:::!root:" ],
414         [ 0, 0, {}, "group5:124:::*,!sys:" ],
415         [ 0, 0, {}, "group6:125:::!*,daemon:" ],
416         [ 0, 0, {}, "group7:126:::root,sys,daemon,bin:" ],
417         [ 0, 0, {}, "group8:127:::root,!sys,daemon,!bin:" ],
418         [ 0, 0, { "allowspaces" => 1 }, "group9:124:::*, !sys:" ],
419         [ 0, 0, { "allowspaces" => 1 }, "group10:125:::!* ,daemon:" ],
420         [ 0, 0, { "allowspaces" => 1 }, "group11:126:::root, sys ,daemon, bin:" ],
421         [ 0, 0, { "allowspaces" => 1 }, "group12:127:::root ,!sys, daemon ,!bin:" ],
422         [ 0, 0, {}, "group9:128:::sys:" ],
423         [ 0, 0, {}, "attrib1:129::::one" ],
424         [ 0, 0, {}, "attrib2:130::::One" ],
425         [ 0, 0, {}, "attrib3:131::::ONE" ],
426         [ 0, 0, {}, "attrib4:132::::attrib10" ],
427         [ 0, 0, {}, "attrib5:133::::attrib.attrib=" ],
428         [ 0, 0, {}, "attrib6:134::::attib_" ],
429         [ 0, 0, {}, "attrib7:135::::a10-._attib" ],
430         [ 0, 0, {}, "attrib8:136::::SUNW,attrib" ],
431         [ 0, 0, {}, "attrib9:137::::A,A10=" ],
432         [ 0, 0, {}, "attrib10:138::::FIVEE,name" ],
433         [ 0, 0, {}, "attrib11:139::::one;two" ],
434         [ 0, 0, {}, "attrib12:140::::one=1;two=four" ],
435         [ 0, 0, {}, "attrib13:141::::one;two=;three=four" ],
436         [ 0, 0, {}, "value1:142::::one=foo,bar" ],
437         [ 0, 0, {}, "value2:143::::one=,bar," ],
438         [ 0, 0, {}, "value3:144::::one=(foo,bar)" ],
439         [ 0, 0, {}, "value4:145::::one=(foo,bar,baz),boo" ],
440         [ 0, 0, {}, "value5:146::::one;two=bar,(baz),foo,((baz)),(,)" ],
441         [ 0, 0, {}, "value6:147::::one=100/200" ],
442         [ 0, 0, {}, "value7:148::::two=.-_/=" ],
443         [ 0, 0, {}, "value8:149::::name=one=two" ],
444         [ 0, 0, { "allowunits" => 1 }, "value9:150::::task.max-lwps=(priv,1000M,deny,signal=SIGHUP),(priv,1000k,deny,signal=SIGKILL)" ],
445         [ 0, 0, {}, "comma1:151::,::" ],
446         [ 0, 0, {}, "comma2:152::,,::" ],
447         [ 0, 0, {}, "comma3:153::root,::" ],
448         [ 0, 0, {}, "comma4:154::bin,root,,::" ],
449         [ 0, 0, {}, "comma5:155:::,:" ],
450         [ 0, 0, {}, "comma6:156:::,,:" ],
451         [ 0, 0, {}, "comma7:157:::bin,root,:" ],
452         [ 0, 0, {}, "comma8:158:::root,,:" ],
453         [ 0, 0, {}, "semi1:159::::;" ],
454         [ 0, 0, {}, "semi2:160::::;;" ],
455         [ 0, 0, {}, "semi3:161::::foo=(one,two);" ],
456         [ 0, 0, {}, "semi4:162::::foo;;" ],
457         [ 0, 0, { "allowunits" => 1 }, "rctl1:163::::task.max-lwps=(priv,1000,deny,signal=HUP),(priv,1000k,deny,signal=15)" ],
458         [ 0, 0, {}, "rctl1:163::::task.max-lwps=(priv,1000,deny,signal=HUP),(priv,10001,deny,signal=15)" ],
459         [ 0, 0, {}, "rctl2:164::::process.max-port-events=(basic,1000,deny)" ],
460         [ 0, 0, { "allowunits" => 1 }, "rctl3:165::::project.max-crypto-memory=(priv,2.2gb,deny)" ],
461         [ 0, 0, {}, "rctl3:165::::project.max-crypto-memory=(priv,10,deny)" ],
462         [ 0, 0, { "allowunits" => 1 }, "rctl4:166::::project.max-crypto-memory=(privileged,100m,deny)" ],
463         [ 0, 0, {}, "rctl4:166::::project.max-crypto-memory=(privileged,100,deny)" ],
464         [ 0, 0, { "allowunits" => 1 }, "rctl5:167::::project.max-crypto-memory=(priv,1000m,deny)" ],
465         [ 0, 0, {}, "rctl5:167::::project.max-crypto-memory=(priv,1000,deny)" ],
466         [ 0, 0, { "allowunits" => 1 }, "rctl6:168::::project.max-crypto-memory=(priv,1000k,deny)" ],
467         [ 0, 0, { "allowunits" => 1 }, "rctl6:168::::project.max-crypto-memory=(priv,1000m,deny)" ],
468         [ 0, 0, {}, "rctl7:169::::process.max-msg-messages=(priv,10,deny)" ],
469         [ 0, 0, { "allowunits" => 1 }, "rctl8:170::::process.max-msg-qbytes=(priv,10000kb,deny)" ],
470         [ 0, 0, {}, "rctl8:170::::process.max-msg-qbytes=(priv,10000,deny)" ],
471         [ 0, 0, {}, "rctl9:171::::process.max-sem-ops=(priv,10000000,deny)" ],
472         [ 0, 0, {}, "rctl10:172::::process.max-sem-nsems=(basic,1,deny)" ],
473         [ 0, 0, { "allowunits" => 1 }, "rctl11:173::::process.max-address-space=(priv,2GB,deny)" ],
474         [ 0, 0, { "allowunits" => 1 }, "rctl12:174::::process.max-file-descriptor=(basic,1K,deny),(basic,2K,deny)" ],
475         [ 0, 0, { "allowunits" => 1 }, "rctl13:175::::process.max-core-size=(priv,10Mb,deny),(priv,2GB,deny)" ],
476         [ 0, 0, { "allowunits" => 1 }, "rctl14:176::::process.max-stack-size=(priv,1.8Gb,deny),(priv,100MB,deny)" ],
477         [ 0, 0, {}, "rctl15:177::::process.max-data-size=(priv,1010100101,deny)" ],
478         [ 0, 0, { "allowunits" => 1 }, "rctl16:178::::process.max-file-size=(priv,100mb,deny,signal=SIGXFSZ),(priv,1000mb,deny,signal=31)" ],
479         [ 0, 0, { "allowunits" => 1 }, "rctl17:179::::process.max-cpu-time=(priv,1t,signal=XCPU),(priv,100ms,sig=30)" ],
480         [ 0, 0, { "allowunits" => 1 }, "rctl18:180::::task.max-cpu-time=(priv,1M,sig=SIGKILL)" ],
481         [ 0, 0, { "allowunits" => 1 }, "rctl19:181::::task.max-lwps=(basic,10,signal=1),(priv,100,deny,signal=KILL)" ],
482         [ 0, 0, {}, "rctl20:182::::project.max-device-locked-memory=(priv,1000,deny,sig=TERM)" ],
483         [ 0, 0, {}, "rctl21:183::::project.max-port-ids=(priv,100,deny)" ],
484         [ 0, 0, { "allowunits" => 1 }, "rctl22:184::::project.max-shm-memory=(priv,1000mb,deny)" ],
485         [ 0, 0, { "allowunits" => 1 }, "rctl23:185::::project.max-shm-ids=(priv,1k,deny,signal=SIGSTOP)" ],
486         [ 0, 0, { "allowunits" => 1 }, "rctl24:186::::project.max-msg-ids=(priv,1m,deny,signal=XRES)" ],
487         [ 0, 0, {}, "rctl25:187::::project.max-sem-ids=(priv,10,deny,signal=ABRT)" ],
488         [ 0, 0, { "allowunits" => 1 }, "rctl26:188::::project.cpu-shares=(priv,63k,none)" ],
489         [ 0, 0, { "allowunits" => 1 }, "rctl27:189::::zone.cpu-shares=(priv,20k,none)" ],
490         [ 0, 0, {}, "rctl28:190::::zone.cpu-shares=(priv,100,none)" ],
491         [ 0, 0, { "allowunits" => 1 }, "rctl29:191::::project.max-shm-memory=(priv,200G,deny)" ],
492         [ 0, 0, { "allowunits" => 1 }, "rctl30:192::::project.max-shm-memory=(priv,200Gb,deny)" ],
493         [ 0, 0, { "allowunits" => 1 }, "rctl31:193::::project.max-shm-memory=(priv,2000B,deny)" ],
494         [ 0, 0, {}, "rctl32:194::::project.max-shm-memory=(priv,2000,deny)" ],
495         [ 0, 0, {}, "rctl33:195::::task.max-cpu-time=(priv,2000,none)" ],
496         [ 0, 0, { "allowunits" => 1 }, "rctl34:196::::task.max-cpu-time=(priv,2000s,none)" ],
497         [ 0, 0, { "allowunits" => 1 }, "rctl35:197::::task.max-cpu-time=(priv,20.1ps,none)" ],
498         [ 0, 0, { "allowunits" => 1 }, "rctl36:198::::task.max-cpu-time=(priv,20T,none)" ],
500 # negative
502         [ 0, 1, {}, "system:0::::" ],
503         [ 0, 1, {}, "user.root:1::::" ],
504         [ 0, 1, {}, "noproject:2::::" ],
505         [ 0, 1, {}, "default:3::::" ],
506         [ 0, 1, {}, "group.staff:10::::" ],
507         [ 0, 1, {}, "long:100::::" . "a" x 4096 ],
508         [ 1, 0, {}, "extrafields:101:::::" ],
509         [ 1, 0, {}, "missingfields:102:::" ],
510         [ 1, 0, {}, "_invalidname:103::::" ],
511         [ 1, 0, {}, "10invlidname:104::::" ],
512         [ 1, 0, {}, "invalid%name:105::::" ],
513         [ 1, 0, {}, "invalid/name:106::::" ],
514         [ 1, 0, {}, ".invalidname:107::::" ],
515         [ 1, 0, {}, "=invalidName:108::::" ],
516         [ 1, 0, {}, "invalid=name:109::::" ],
517         [ 1, 0, {}, "invalid/name:110::::" ],
518         [ 1, 0, {}, "/invalidname:111::::" ],
519         [ 1, 0, {}, "/invalidname:112::::" ],
520         [ 1, 0, {}, "invalidname*:113::::" ],
521         [ 1, 0, {}, "invalid?name:114::::" ],
522         [ 1, 0, {}, ":115:invalid name comment:::" ],
523         [ 1, 0, {}, "invalid!name:116::::" ],
524         [ 1, 0, {}, "invalidname!:117::::" ],
525         [ 1, 0, {}, "invalid12345678901234567890123456789012345678901234567890123456789:118::::" ],
526         [ 1, 0, {}, "projid:-1::::" ],
527         [ 1, 0, {}, "projid:abc::::" ],
528         [ 1, 0, {}, "projid:2147483648::::" ],
529         [ 1, 0, {}, "projid:::::" ],
530         [ 1, 0, {}, "user1:118::*!::" ],
531         [ 1, 0, {}, "user2:119::10user::" ],
532         [ 0, 1, {}, "user3:120::NOLOWER::" ],
533         [ 0, 1, {}, "user4:121::toooolong::" ],
534         [ 1, 0, {}, "user5:122::root!::" ],
535         [ 1, 0, {}, "user6:123::root;sys::" ],
536         [ 0, 1, {}, "user7:124::sys,NOLOWER::" ],
537         [ 1, 0, {}, "user8:125::sys/bin,root::" ],
538         [ 1, 0, {}, "user9:116::*, !sys::" ],
539         [ 1, 0, {}, "user10:117::!* ,daemon::" ],
540         [ 1, 0, {}, "user11:118::root ,sys ,daemon, bin::" ],
541         [ 1, 0, {}, "user12:119::root, !sys, daemon ,!bin::" ],
542         [ 1, 0, {}, "group1:126:::*!:" ],
543         [ 0, 1, {}, "group2:127:::oneUpper:" ],
544         [ 0, 1, {}, "group3:128:::NOLOWER:" ],
545         [ 0, 1, {}, "group4:129:::toooolong:" ],
546         [ 1, 0, {}, "group5:130:::root!:" ],
547         [ 1, 0, {}, "group6:131:::root;sys:" ],
548         [ 0, 1, {}, "group7:132:::sys,NOLOWER:" ],
549         [ 1, 0, {}, "group8:133:::sys-bin,root:" ],
550         [ 1, 0, {}, "group9:124:::*, !sys:" ],
551         [ 1, 0, {}, "group10:125:::!* ,daemon:" ],
552         [ 1, 0, {}, "group11:126:::root, sys ,daemon, bin:" ],
553         [ 1, 0, {}, "group12:127:::root ,!sys, daemon ,!bin:" ],
554         [ 1, 0, {}, "attrib1:134::::10" ],
555         [ 1, 0, {}, "attrib2:135::::_foo=" ],
556         [ 1, 0, {}, "attrib3:136::::,foo" ],
557         [ 1, 0, {}, "attrib4:137::::sun,foo" ],
558         [ 1, 0, {}, "attrib6:139::::!attrib" ],
559         [ 1, 0, {}, "attrib7:140::::_attrib" ],
560         [ 1, 0, {}, "attrib8:141::::attib,attrib" ],
561         [ 1, 0, {}, "attrib9:142::::attrib/attrib" ],
562         [ 1, 0, {}, "attrib10:143::::one;two,three" ],
563         [ 1, 0, {}, "attrib11:144::::one=two;three/" ],
564         [ 1, 0, {}, "value1:145::::one=foo%" ],
565         [ 1, 0, {}, "value2:146::::one= two" ],
566         [ 1, 0, {}, "value3:147::::var=foo?" ],
567         [ 1, 0, {}, "value4:148::::name=value;name=value2)" ],
568         [ 1, 0, {}, "value5:149::::(foo)" ],
569         [ 1, 0, {}, "value6:150::::name=(foo,bar" ],
570         [ 1, 0, {}, "value7:151::::name=(value)(value)" ],
571         [ 1, 0, {}, "value8:152::::name=)" ],
572         [ 1, 0, {}, "value9:153::::name=value,(value value)" ],
573         [ 1, 0, {}, "value10:154::::name=(value(value))" ],
574         [ 1, 0, {}, "value11:155::::name=(value)value" ],
575         [ 1, 0, {}, "value11:156::::name=va?lue" ],
576         [ 1, 0, {}, "value12:157::::name=(value,value))" ],
577         [ 1, 0, {}, "value13:158::::name=(value),value)" ],
578         [ 1, 0, {}, "space1 :159::::" ],
579         [ 1, 0, {}, " space2:160::::" ],
580         [ 1, 0, {}, "space3: 161::::" ],
581         [ 1, 0, {}, "space4:162 ::::" ],
582         [ 1, 0, {}, "space 5:163::::" ],
583         [ 1, 0, {}, "space6:1 64::::" ],
584         [ 1, 0, {}, "space7:165:: root::" ],
585         [ 1, 0, {}, "space8:166::root ::" ],
586         [ 1, 0, {}, "space9:167::daemon, root::" ],
587         [ 1, 0, {}, "space10:168::bin root::" ],
588         [ 1, 0, {}, "space11:169::daemon ,root::" ],
589         [ 1, 0, {}, "space12 :170::::" ],
590         [ 1, 0, {}, " space13:171::::" ],
591         [ 1, 0, {}, "space14: 172::::" ],
592         [ 1, 0, {}, "space15:173 ::::" ],
593         [ 1, 0, {}, "space 16:174::::" ],
594         [ 1, 0, {}, "space17:1 75::::" ],
595         [ 1, 0, {}, "space18:176::: root:" ],
596         [ 1, 0, {}, "space19:177:::root :" ],
597         [ 1, 0, {}, "space20:178:::daemon, root:" ],
598         [ 1, 0, {}, "space21:179:::bin root:" ],
599         [ 1, 0, {}, "space22:180:::daemon ,root:" ],
600         [ 1, 0, {}, "space23:181:::: foo" ],
601         [ 1, 0, {}, "space34:182::::foo =one" ],
602         [ 1, 0, {}, "space35:183::::foo= (one)" ],
603         [ 1, 0, {}, "space36:184::::foo=(one, two)" ],
604         [ 1, 0, {}, "space37:185::::foo=(one ,two)" ],
605         [ 1, 0, {}, "space38:186::::foo=( one)" ],
606         [ 1, 0, {}, "space39:187::::foo=(one )" ],
607         [ 1, 0, {}, "space40:188::::foo=(one) ,two" ],
608         [ 1, 0, {}, "space41:189::::foo=one, (two)" ],
609         [ 1, 0, {}, "comma1:190::,root,bin::" ],
610         [ 1, 0, {}, "comma2:191::root,,bin::" ],
611         [ 1, 0, {}, "comma3:192::,,root,bin::" ],
612         [ 1, 0, {}, "comma4:193:::,root,bin:" ],
613         [ 1, 0, {}, "comma5:194:::root,,bin:" ],
614         [ 1, 0, {}, "comma6:195:::,,root,bin:" ],
615         [ 1, 0, {}, "semi1:196::::;foo" ],
616         [ 1, 0, {}, "semi2:197::::foo;;bar=1" ],
617         [ 1, 0, {}, "semi3:198::::;;bar=(10)" ],
618         [ 0, 1, {}, "rctl1:199::::task.max-lwps=," ],
619         [ 0, 1, {}, "rctl2:200::::task.max-lwps=" ],
620         [ 0, 1, {}, "rctl3:201::::task.max-lwps=priv" ],
621         [ 0, 1, {}, "rctl4:202::::task.max-lwps=priv,1000" ],
622         [ 0, 1, {}, "rctl5:203::::task.max-lwps=priv,1000,deny" ],
623         [ 0, 1, {}, "rctl6:204::::task.max-lwps=(priv)" ],
624         [ 0, 1, {}, "rctl7:205::::task.max-lwps=(priv,1000)" ],
625         [ 0, 1, {}, "rctl8:206::::task.max-lwps=(foo,100,deny)" ],
626         [ 0, 1, {}, "rctl9:207::::task.max-lwps=(priv,foo,none)" ],
627         [ 1, 0, { "allowunits" => 1 }, "rctl9:207::::task.max-lwps=(priv,foo,none)" ],
628         [ 1, 0, { "allowunits" => 1 }, "rctl10:208::::task.max-lwps=(priv,100foo,none)" ],
629         [ 0, 1, {}, "rctl11:209::::task.max-lwps=(priv,1000,foo)" ],
630         [ 0, 1, { "allowunits" => 1 }, "rctl12:210::::task.max-lwps=(priv,1000k,deny,signal)" ],
631         [ 0, 1, {}, "rctl13:211::::task.max-lwps=(priv,1000,deny,signal=)" ],
632         [ 0, 1, {}, "rctl14:212::::task.max-lwps=(priv,1000,deny,signal=foo)" ],
633         [ 0, 1, {}, "rctl15:213::::task.max-lwps=(priv,1000,deny,signal=1fo)" ],
634         [ 0, 1, {}, "rctl16:214::::task.max-lwps=(priv,1000,deny,signal=100)" ],
635         [ 0, 1, {}, "rctl17:215::::task.max-lwps=(priv,1000,deny,signal=SIG)" ],
636         [ 0, 1, {}, "rctl18:216::::task.max-lwps=(priv,1000,deny,signal=SIG1)" ],
637         [ 0, 1, {}, "rctl19:217::::task.max-lwps=(priv,1000,deny,signal=SIGhup)" ],
638         [ 0, 1, {}, "rctl20:218::::task.max-lwps=(priv,1000,deny,signal=SIGHU)" ],
639         [ 0, 1, {}, "rctl21:219::::task.max-lwps=(priv,1000,deny,signal=SIGHUPP)" ],
640         [ 0, 1, {}, "rctl22:220::::task.max-lwps=(priv,1000,deny,signal=SIGURG)" ],
641         [ 0, 1, {}, "rctl23:221::::task.max-lwps=(priv,1000,deny,signal=SIGXCPU)" ],
642         [ 0, 1, {}, "rctl24:222::::task.max-lwps=(priv,1000,deny,signal=SIGKILL,10)" ],
643         [ 0, 1, {}, "rctl25:223::::task.max-lwps=(priv,1000,deny,signal=SIGKILL,foo)" ],
644         [ 0, 1, {}, "rctl26:224::::process.max-port-events=(priv,1000,none)" ],
645         [ 0, 1, { "allowunits" => 1 }, "rctl27:225::::process.max-address-space=(basic,1024mb,deny,signal=TERM)" ],
646         [ 0, 1, {}, "rctl28:226::::process.max-cpu-time=(basic,3600,deny)" ],
647         [ 0, 1, {}, "rctl29:227::::task.max-lwps=()" ],
648         [ 0, 1, {}, "rctl30:228::::task.max-lwps=((priv),deny)" ],
649         [ 0, 1, {}, "rctl31:229::::task.max-lwps=((priv,1000,deny))" ],
650         [ 0, 1, {}, "rctl32:230::::task.max-lwps=(priv,((1000,2000,1000)),deny)" ],
651         [ 0, 1, {}, "rctl33:231::::task.max-lwps=(,,,)" ],
652         [ 0, 1, {}, "rctl34:232::::task.max-lwps=(priv,1000,(deny))" ],
653         [ 0, 1, {}, "rctl35:233::::task.max-lwps=(priv,1000,deny),foo" ],
654         [ 0, 1, {}, "rctl36:234::::task.max-lwps=(priv,1000,deny),(priv,1000)" ],
655         [ 1, 0, { "allowunits" => 1 }, "rctl37:235::::project.max-msg-ids=(priv,15EB,deny)" ],
656         [ 1, 0, { "allowunits" => 1 }, "rctl38:236::::process.max-address-space=(priv,16.1EB,deny)" ],
657         [ 1, 0, { "allowunits" => 1 }, "rctl39:237::::process.max-address-space=(priv,18000000000gb,deny)" ],
658         [ 1, 0, { "allowunits" => 1 }, "rctl40:238::::zone.cpu-shares=(priv,10kb,none)" ],
659         [ 1, 0, { "allowunits" => 1 }, "rctl41:239::::zone.cpu-shares=(priv,10Ks,none)" ],
660         [ 1, 0, { "allowunits" => 1 }, "rctl42:240::::zone.cpu-shares=(priv,10s,none)" ],
661         [ 1, 0, { "allowunits" => 1 }, "rctl43:241::::zone.cpu-shares=(priv,100000b,none)" ],
662         [ 1, 0, { "allowunits" => 1 }, "rctl44:242::::project.max-shm-memory=(priv,200Ts,deny)" ],
663         [ 1, 0, { "allowunits" => 1 }, "rctl45:243::::project.max-shm-memory=(priv,200s,deny)" ],
664         [ 1, 0, { "allowunits" => 1 }, "rctl46:244::::task.max-cpu-time=(priv,20B,none)" ],
665         [ 1, 0, { "allowunits" => 1 }, "rctl47:245::::task.max-cpu-time=(priv,20Kb,none)" ],
666         [ 0, 1, { "allowunits" => 1 }, "rctl48:246::::project.cpu-shares=(priv,100k,none)" ],
667         [ 0, 1, {}, "rctl147:150::::task.max-lwps=(priv,1000M,deny,signal=SIGHUP),(priv,1000k,deny,signal=SIGKILL)" ],
668         [ 0, 1, {}, "rctl148:163::::task.max-lwps=(priv,1000,deny,signal=HUP),(priv,1000k,deny,signal=15)" ],
669         [ 0, 1, {}, "rctl3:165::::project.max-crypto-memory=(priv,10eb,deny)" ],
670         [ 0, 1, {}, "rctl4:166::::project.max-crypto-memory=(privileged,100p,deny)" ],
671         [ 0, 1, {}, "rctl5:167::::project.max-crypto-memory=(priv,1000t,deny)" ],
672         [ 0, 1, {}, "rctl6:168::::project.max-crypto-memory=(priv,1000g,deny)" ],
673         [ 0, 1, {}, "rctl7:169::::process.max-msg-messages=(priv,10m,deny)" ],
674         [ 0, 1, {}, "rctl8:170::::process.max-msg-qbytes=(priv,10000kb,deny)" ],
675         [ 0, 1, {}, "rctl11:173::::process.max-address-space=(priv,10EB,deny)" ],
676         [ 0, 1, {}, "rctl12:174::::process.max-file-descriptor=(basic,1K,deny),(basic,2K,deny)" ],
677         [ 0, 1, {}, "rctl13:175::::process.max-core-size=(priv,1Eb,deny),(priv,10PB,deny)" ],
678         [ 0, 1, {}, "rctl14:176::::process.max-stack-size=(priv,10Tb,deny),(priv,10TB,deny)" ],
679         [ 0, 1, {}, "rctl16:178::::process.max-file-size=(priv,100mb,deny,signal=SIGXFSZ),(priv,1000mb,deny,signal=31)" ],
680         [ 0, 1, {}, "rctl17:179::::process.max-cpu-time=(priv,1t,signal=XCPU),(priv,100ms,sig=30)" ],
681         [ 0, 1, {}, "rctl18:180::::task.max-cpu-time=(priv,1M,sig=SIGKILL)" ],
682         [ 0, 1, {}, "rctl22:184::::project.max-shm-memory=(priv,1000mb,deny)" ],
683         [ 0, 1, {}, "rctl23:185::::project.max-shm-ids=(priv,1k,deny,signal=SIGSTOP)" ],
684         [ 0, 1, {}, "rctl24:186::::project.max-msg-ids=(priv,1m,deny,signal=XRES)" ],
685         [ 0, 1, {}, "rctl26:188::::project.cpu-shares=(priv,63k,none)" ],
686         [ 0, 1, {}, "rctl27:189::::zone.cpu-shares=(priv,20k,none)" ],
687         [ 0, 1, {}, "rctl29:191::::project.max-shm-memory=(priv,200G,deny)" ],
688         [ 0, 1, {}, "rctl30:192::::project.max-shm-memory=(priv,200Gb,deny)" ],
689         [ 0, 1, {}, "rctl31:193::::project.max-shm-memory=(priv,2000B,deny)" ],
690         [ 0, 1, {}, "rctl34:196::::task.max-cpu-time=(priv,2000s,none)" ],
691         [ 0, 1, {}, "rctl35:197::::task.max-cpu-time=(priv,20.1ps,none)" ],
692         [ 0, 1, {}, "rctl36:198::::task.max-cpu-time=(priv,20T,none)" ],
695 my $parse_exp;
696 my $parse_ret;
697 my $validate_exp;
698 my $validate_ret;
699 my $project;
700 my $projent;
701 my $errors;
703 foreach $projent_test ( @projent_tests) {
705         ($parse_exp, $validate_exp, $flags, $project) = @$projent_test;
706         $flagstring = hash2string($flags);      
707         start("projent_parse(): flags: $flagstring, project: $project"); 
708         ($ret, $projent) = projent_parse($project, $flags);
709         if ($ret != $parse_exp) {
710                 fail("Expected $parse_exp, Returned $ret");
711                 if ($ret) {
712                         foreach $error (@$projent) {
713                                 comment("# " . join(", ", @$error));
714                         }       
715                 }
716                 next;
717         }
718         pass();
720         # projent_validate() can only be successfully parsed projents
721         if ($ret) {
722                 next;
723         }
725         start("projent_validate():  flags: $flagstring, project: $project");
726         ($ret, $errors) = projent_validate($projent, $flags);
727         if ($ret != $validate_exp) {
728                 fail("Expected $validate_exp, Returned $ret");
729                 if ($ret) {
730                         foreach $error (@$errors) {
731                                 comment("# " . join(", ", @$error));
732                         }       
733                 }
734                 next;
735         }
736         pass();
739 my $pf1;
740 my $pf2;
741 my $fh1;
742 my $fh2;
743 my @lines;
745 # get projects and make local copy
746 open($fh1, "/usr/bin/getent project |") || fatal($!);
747 open($fh2, ">/tmp/projent.$$") || fatal($!);
748 @lines = <$fh1>;
749 print $fh2 @lines;
750 close($fh1);
751 close($fh2);
753 open($fh1, "</tmp/projent.$$") || fatal($!);
754 $pf1 = read_pfile($fh1);
755 close($fh1);
758 start("Test getprojid");
759 ($s) = `/usr/xpg4/bin/id -p` =~ /projid=(\d+)/;
760 defined($s) && $s == getprojid() ? pass() : fail();
762 start("Test fgetprojent");
763 $pf2 = [];
764 open($fh, "</tmp/projent.$$") || fatal($!);
765 while (my @proj = fgetprojent($fh)) {
766         push(@$pf2, [ @proj ]);
768 close($fh);
769 cmp_recs($pf1, $pf2) ? pass() : fail();
771 my %pf_byname = map({ $_->[0] => $_} @$pf1);
772 my %pf_byid = map({ $_->[1] => $_} @$pf1);
773 my (%h, @a1, @a2, $k, $v);
775 start("Test getprojent.  Don't assume anything about the order it returns stuff in");
776 %h = %pf_byname;
777 $pass = 1;
778 @a2 = ();
779 while (@a1 = getprojent()) {
780         @a2 = @a1 if (! scalar(@a2));
781         if (exists($h{$a1[0]})) {
782                 $pass = 0 if (! cmp_recs(\@a1, $h{$a1[0]}));
783                 delete($h{$a1[0]});
784         } else {
785                 $pass = 0;
786         }
788 $pass && ! %h ? pass() : fail();
790 start("Test getprojent when at end");
791 @a1 = getprojent();
792 cmp_recs(\@a1, []) ? pass() : fail();
795 start("Test endprojent/getprojent");
796 endprojent();
797 @a1 = getprojent();
798 cmp_recs(\@a1, \@a2) ? pass() : fail();
800 start("Test setprojent/getprojent");
801 setprojent();
802 @a1 = getprojent();
803 cmp_recs(\@a1, \@a2) ? pass() : fail();
804 setprojent();
806 start("Test getprojbyname");
807 $pass = 1;
808 while (($k, $v) = each(%pf_byname)) {
809         @a1 = getprojbyname($k);
810         $pass = 0 if (! cmp_recs(\@a1, $v));
812 $pass ? pass() : fail();
814 start("Test getprojbyid");
815 $pass = 1;
816 while (($k, $v) = each(%pf_byid)) {
817         @a1 = getprojbyid($k);
818         $pass = 0 if (! cmp_recs(\@a1, $v));
820 $pass ? pass() : fail();
822 start("Test getprojidbyname");
823 $pass = 1;
824 while (($k, $v) = each(%pf_byname)) {
825         $pass = 0 if (getprojidbyname($k) != $v->[1]);
827 $pass ? pass() : fail();
829 start("Test getdefaultproj");
830 my $username = getpwuid($>);
831 my $projid; 
832 $s = `/usr/bin/id -p` ;
833 ($projid) = $s =~ /projid=\d+\(([^)]+)\)/;
834 defined($projid) && $projid eq getdefaultproj($username) ? pass() : fail();
836 start("test inproj");
837 $s = `/usr/bin/projects`;
838 ($s) = split(/\s+/, $s);
839 inproj($username, $s) ? pass() : fail();
841 exit(0);