File Coverage

blib/lib/Test/PlugAuth/Plugin/Authz.pm
Criterion Covered Total %
statement 230 232 99.1
branch 31 62 50.0
condition 21 61 34.4
subroutine 14 14 100.0
pod 1 1 100.0
total 297 370 80.2


line stmt bran cond sub pod time code
1             package Test::PlugAuth::Plugin::Authz;
2              
3 2     2   2203 use strict;
  2         5  
  2         119  
4 2     2   16 use warnings;
  2         5  
  2         104  
5 2     2   1326 use Test::PlugAuth::Plugin;
  2         6  
  2         102  
6 2     2   54 use 5.010001;
  2         8  
7 2     2   1788 use Test::Builder;
  2         148741  
  2         73  
8 2     2   2170 use Role::Tiny ();
  2         10854  
  2         49  
9 2     2   1328 use PlugAuth;
  2         9  
  2         36  
10 2     2   103 use File::Temp qw( tempdir );
  2         2  
  2         261  
11 2     2   10 use YAML::XS qw( DumpFile );
  2         3  
  2         157  
12 2     2   13 use base qw( Exporter );
  2         4  
  2         709  
13              
14             our @EXPORT = qw( run_tests );
15              
16             # ABSTRACT: Test a PlugAuth Authz plugin for correctness
17             our $VERSION = '0.35'; # VERSION
18              
19              
20             my $Test = Test::Builder->new;
21              
22             sub run_tests
23             {
24 2     2 1 356 my($class, $global_config, $plugin_config) = @_;
25 2 50       18 $class = "PlugAuth::Plugin::$class" unless $class =~ /::/;
26 2     2   1517 eval qq{ use $class };
  2         9  
  2         70  
  2         179  
27 2 50       25 die $@ if $@;
28            
29 2         23 $Test->plan( tests => 65 );
30            
31 2   50     2969 $global_config //= {};
32            
33 2         5 local $ENV{CLUSTERICIOUS_CONF_DIR} = do {
34 2         17 my $dir = tempdir(CLEANUP => 1);
35 2         1386 my $list_fn = File::Spec->catfile($dir, 'user_list.txt');
36 2         6 do {
37 2     2   27 use autodie;
  2         3  
  2         17  
38 2         14 open my $fh, '>', $list_fn;
39 2         8247 say $fh "optimus";
40 2         9 say $fh "primus";
41 2         8 say $fh "megatron";
42 2         6 say $fh "grimlock";
43 2         14 close $fh;
44             };
45            
46 2         2983 DumpFile(File::Spec->catfile($dir, 'PlugAuth.conf'), {
47             %$global_config,
48             plugins => [
49             {
50             'PlugAuth::Plugin::FlatUserList' => {
51             user_list_file => $list_fn,
52             },
53             }
54             ],
55             });
56 2         731 $dir;
57             };
58            
59             $global_config = Clustericious::Config->new($global_config)
60 2 50       7 unless eval { $global_config->isa('Clustericious::Config') };
  2         70  
61 2   50     2104 $plugin_config //= {};
62            
63 2         6 my $object = eval { $class->new($global_config, $plugin_config, PlugAuth->new()) };
  2         47  
64 2         9 my $error = $@;
65 2 50       12 if(ref $object)
66             {
67 2         21 $Test->ok(1, "New returns a reference");
68             }
69             else
70             {
71 0         0 $Test->ok(0, "New returns a reference");
72 0         0 $Test->diag("ERROR: $error");
73             }
74            
75 2         1957 $Test->ok( Role::Tiny::does_role($object, 'PlugAuth::Role::Plugin'), 'does Plugin');
76 2         1038 $Test->ok( Role::Tiny::does_role($object, 'PlugAuth::Role::Authz'), 'does Auth');
77            
78 2 50   12   1001 my $refresh = Role::Tiny::does_role($object, 'PlugAuth::Role::Refresh') ? sub { $object->refresh } : sub {};
  24         119  
79 2         60 $refresh->();
80            
81 2         7 foreach my $username (qw( optimus primus megatron grimlock ))
82             {
83 8         3095 my $groups = $object->groups_for_user($username);
84 8   33     87 my $pass = ref($groups) eq 'ARRAY' && $#$groups == 0 && $groups->[0] eq $username;
85 8         47 $Test->ok( $pass, "user $username belongs to exactly one group: $username" );
86             }
87            
88 2         1039 do {
89 2         4 do {
90 2         15 my @groups = $object->all_groups;
91 2         10 $Test->ok( $#groups == -1, "no groups" );
92             };
93            
94 2         989 $Test->ok( eval { $object->create_group( 'group1', 'optimus,primus' ) } == 1, "create_group returned 1" );
  2         18  
95 2 50       1414 $Test->diag($@) if $@;
96 2         12 $refresh->();
97            
98 2         5 do {
99 2         15 my @groups = $object->all_groups;
100 2   33     33 $Test->ok( $#groups == 0 && $groups[0] eq 'group1', 'group1 exists' );
101            
102 2         1083 my @optimus = sort @{ $object->groups_for_user('optimus') };
  2         14  
103 2         9 my @primus = sort @{ $object->groups_for_user('primus') };
  2         10  
104 2         8 my @megatron = sort @{ $object->groups_for_user('megatron') };
  2         52  
105            
106 2   33     42 $Test->ok( $#optimus == 1 && $optimus[0] eq 'group1' && $optimus[1] eq 'optimus',
107             "optimus groups = optimus,group1");
108 2   33     1102 $Test->ok( $#primus == 1 && $primus[0] eq 'group1' && $primus[1] eq 'primus',
109             "primus groups = primus,group1");
110 2   33     1093 $Test->ok( $#megatron == 0 && $megatron[0] eq 'megatron',
111             "megatron groups = megatron" );
112            
113 2         1036 my @users = sort @{ $object->users_in_group('group1') };
  2         17  
114 2   33     30 my $pass = $#users == 1 && $users[0] eq 'optimus' && $users[1] eq 'primus';
115 2         12 $Test->ok( $pass, "group1 = optimus, primus" );
116 2 50       987 $Test->diag("group1 actually = [ ", join(', ', @users) , " ]")
117             unless $pass;
118             };
119            
120 2         9 $Test->ok( eval { $object->update_group('group1', "optimus,megatron") } == 1, "update_group returned 1" );
  2         21  
121 2 50       1052 $Test->diag($@) if $@;
122 2         11 $refresh->();
123              
124 2         6 do {
125 2         10 my @groups = $object->all_groups;
126 2   33     27 $Test->ok( $#groups == 0 && $groups[0] eq 'group1', 'group1 exists' );
127            
128 2         1048 my @optimus = sort @{ $object->groups_for_user('optimus') };
  2         14  
129 2         10 my @primus = sort @{ $object->groups_for_user('primus') };
  2         13  
130 2         9 my @megatron = sort @{ $object->groups_for_user('megatron') };
  2         11  
131            
132 2   33     34 $Test->ok( $#optimus == 1 && $optimus[0] eq 'group1' && $optimus[1] eq 'optimus',
133             "optimus groups = optimus,group1");
134 2   33     1055 $Test->ok( $#primus == 0 && $primus[0] eq 'primus',
135             "primus groups = primus");
136 2   33     1136 $Test->ok( $#megatron == 1 && $megatron[0] eq 'group1' && $megatron[1] eq 'megatron',
137             "megatron groups = group1,megatron" );
138            
139 2         1034 my @users = sort @{ $object->users_in_group('group1') };
  2         13  
140 2   33     39 my $pass = $#users == 1 && $users[0] eq 'megatron' && $users[1] eq 'optimus';
141 2         15 $Test->ok( $pass, "group1 = megatron, optimus" );
142 2 50       987 $Test->diag("group1 actually = [ ", join(', ', @users) , " ]")
143             unless $pass;
144             };
145            
146 2         8 $Test->ok( eval { $object->delete_group('group1') } == 1, "delete_group returned 1" );
  2         16  
147 2 50       921 $Test->diag($@) if $@;
148 2         8 $refresh->();
149            
150 2         5 do {
151 2         12 my @groups = $object->all_groups;
152 2         15 $Test->ok( $#groups == -1, 'group1 DOES NOT exists' );
153            
154 2         930 my @optimus = sort @{ $object->groups_for_user('optimus') };
  2         14  
155 2         9 my @primus = sort @{ $object->groups_for_user('primus') };
  2         10  
156 2         8 my @megatron = sort @{ $object->groups_for_user('megatron') };
  2         8  
157            
158 2   33     26 $Test->ok( $#optimus == 0 && $optimus[0] eq 'optimus',
159             "optimus groups = group1");
160 2   33     916 $Test->ok( $#primus == 0 && $primus[0] eq 'primus',
161             "primus groups = primus");
162 2   33     891 $Test->ok( $#megatron == 0 && $megatron[0] eq 'megatron',
163             "megatron groups = megatron" );
164            
165 2         831 my $users = $object->users_in_group('group1');
166 2         8 my $pass = ! defined $users;
167 2         10 $Test->ok( $pass, "group1 is empty" );
168             };
169             };
170            
171 2         790 do {
172 2         19 $Test->ok( !defined(eval { $object->can_user_action_resource('grimlock', 'be', '/bigbozo') }), "grimlock is not big bozo" );
  2         16  
173 2 50       995 $Test->diag($@) if $@;
174            
175 2         7 $Test->ok( eval { $object->grant('grimlock', 'be', '/bigbozo') } == 1, 'grant returns 1' );
  2         17  
176 2 50       923 $Test->diag($@) if $@;
177 2         10 $refresh->();
178            
179 2         5 $Test->ok( defined(eval { $object->can_user_action_resource('grimlock', 'be', '/bigbozo') }), "grimlock is a big bozo" );
  2         11  
180 2 50       940 $Test->diag($@) if $@;
181            
182 2         7 $Test->ok( !defined(eval { $object->can_user_action_resource('primus', 'be', '/bigbozo') }), "primus is not a big bozo" );
  2         15  
183 2 50       950 $Test->diag($@) if $@;
184            
185 2         16 my @actions = $object->actions;
186            
187 2   33     19 my $pass = $#actions == 0 && $actions[0] eq 'be';
188 2         12 $Test->ok( $pass, "actions = be" );
189 2 50       883 $Test->diag("actions is actually = ", join(', ', @actions))
190             unless $pass;
191             };
192              
193 2         6 do {
194            
195 2         12 $object->create_group( 'public', '*' );
196 2         9 $refresh->();
197 2         6 my @public = sort @{ $object->users_in_group('public') };
  2         11  
198            
199             # grimlock megatron optimus primus
200            
201 2   33     48 my $pass = $#public == 3
202             && $public[0] eq 'grimlock'
203             && $public[1] eq 'megatron'
204             && $public[2] eq 'optimus'
205             && $public[3] eq 'primus';
206 2         13 $Test->ok($pass, "public = [ grimlock, megatron, optimus, primus ]");
207 2 50       1099 $Test->diag("actual public = [ ", join(', ', @public), " ]")
208             unless $pass;
209             };
210              
211 2         6 do {
212            
213 2         8 foreach my $username (qw( optimus primus megatron grimlock ))
214             {
215 8         23 $Test->ok( !defined(eval { $object->can_user_action_resource($username, 'dislike', '/gobots') }), "$username likes gobots");
  8         37  
216 8 50       3024 $Test->diag($@) if $@;
217             }
218            
219 2         9 $Test->ok( eval { $object->grant('public', 'dislike', '/gobots') } == 1, 'grant returns 1' );
  2         22  
220 2 50       725 $Test->diag($@) if $@;
221 2         11 $refresh->();
222            
223 2         6 foreach my $username (qw( optimus primus megatron grimlock ))
224             {
225 8         15 $Test->ok( defined(eval { $object->can_user_action_resource($username, 'dislike', '/gobots') }), "$username dislikes gobots");
  8         29  
226 8 50       2703 $Test->diag($@) if $@;
227             }
228            
229 2         15 my @actions = $object->actions;
230            
231 2   33     28 my $pass = $#actions == 1 && $actions[0] eq 'be' && $actions[1] eq 'dislike';
232 2         10 $Test->ok( $pass, "actions = be, dislike" );
233 2 50       663 $Test->diag("actions is actually = ", join(', ', @actions))
234             unless $pass;
235            
236             };
237            
238 2         5 do {
239 2         10 $object->create_group( 'group2', 'grimlock,primus' );
240 2         6 $refresh->();
241 2         4 my @group2 = sort @{ $object->users_in_group('group2') };
  2         9  
242            
243 2   33     27 my $pass = $#group2 == 1
244             && $group2[0] eq 'grimlock'
245             && $group2[1] eq 'primus';
246 2         10 $Test->ok($pass, "group2 = [ grimlock, primus ]");
247             };
248            
249 2         704 do {
250            
251 2         7 foreach my $username (qw( optimus primus megatron grimlock ))
252             {
253 8         13 $Test->ok( !defined(eval { $object->can_user_action_resource($username, 'have', '/bighead') }), "$username does not have a big head");
  8         30  
254 8 50       2641 $Test->diag($@) if $@;
255             }
256            
257 2         7 $Test->ok( eval { $object->grant('group2', 'have', '/bighead') } == 1, 'grant returns 1' );
  2         12  
258 2 50       740 $Test->diag($@) if $@;
259 2         9 $refresh->();
260            
261 2         8 foreach my $username (qw( primus grimlock ))
262             {
263 4         9 $Test->ok( defined(eval { $object->can_user_action_resource($username, 'have', '/bighead') }), "$username does have a big head");
  4         14  
264 4 50       1375 $Test->diag($@) if $@;
265             }
266            
267 2         9 foreach my $username (qw( megatron optimus ))
268             {
269 4         9 $Test->ok( !defined(eval { $object->can_user_action_resource($username, 'have', '/bighead') }), "$username does not have a big head");
  4         18  
270 4 50       1472 $Test->diag($@) if $@;
271             }
272              
273 2         12 my @actions = $object->actions;
274            
275 2   33     38 my $pass = $#actions == 2 && $actions[0] eq 'be' && $actions[1] eq 'dislike' && $actions[2] eq 'have';
276 2         11 $Test->ok( $pass, "actions = be, dislike, have" );
277 2 50       650 $Test->diag("actions is actually = ", join(', ', @actions))
278             unless $pass;
279             };
280              
281 2         4 do {
282            
283 2         4 $Test->ok( eval { $object->revoke('group2', 'have', '/bighead') } == 1, 'revoke returns 1' );
  2         13  
284 2 50       711 $Test->diag($@) if $@;
285 2         8 $refresh->();
286            
287 2         7 foreach my $username (qw( optimus primus megatron grimlock ))
288             {
289 8         14 $Test->ok( !defined(eval { $object->can_user_action_resource($username, 'have', '/bighead') }), "$username does not have a big head");
  8         27  
290 8 50       2613 $Test->diag($@) if $@;
291             }
292            
293 2         7 $Test->ok( eval { $object->revoke('public', 'dislike', '/gobots') } == 1, 'revoke returns 1' );
  2         12  
294 2 50       676 $Test->diag($@) if $@;
295 2         7 $refresh->();
296              
297 2         7 foreach my $username (qw( optimus primus megatron grimlock ))
298             {
299 8         14 $Test->ok( !defined(eval { $object->can_user_action_resource($username, 'dislike', '/gobots') }), "$username likes gobots");
  8         28  
300 8 50       2681 $Test->diag($@) if $@;
301             }
302            
303 2         7 $Test->ok( eval { $object->revoke('grimlock', 'be', '/bigbozo') } == 1, 'revoke returns 1' );
  2         10  
304 2 50       668 $Test->diag($@) if $@;
305 2         157 $refresh->();
306              
307 2         5 $Test->ok( !defined(eval { $object->can_user_action_resource('grimlock', 'be', '/bigbozo') }), "grimlock is not big bozo" );
  2         11  
308 2 50       838 $Test->diag($@) if $@;
309              
310             };
311              
312             # These two do not have a write RESTful API yet and cannot be
313             # tested.
314             # TODO: match_resources
315             # TODO: host_has_tag
316             }
317              
318             1;
319              
320             __END__
321              
322             =pod
323              
324             =encoding UTF-8
325              
326             =head1 NAME
327              
328             Test::PlugAuth::Plugin::Authz - Test a PlugAuth Authz plugin for correctness
329              
330             =head1 VERSION
331              
332             version 0.35
333              
334             =head1 SYNOPSIS
335              
336             use Test::PlugAuth::Plugin::Authz;
337             run_tests 'MyPlugin'; # runs tests against PlugAuth::Plugin::MyPlugin
338              
339             =head1 FUNCTIONS
340              
341             =head2 run_tests $plugin_name, [ $global_config, [ $plugin_config ] ]
342              
343             Run the specification tests against the given plugin. The configuration
344             arguments are optional. The first is the hash which is usually found in
345             ~/etc/PlugAuth.conf and the second is the plugin config.
346              
347             =head1 SEE ALSO
348              
349             L<PlugAuth>,
350             L<PlugAuth::Guide::Plugin>
351              
352             =head1 AUTHOR
353              
354             Graham Ollis <gollis@sesda3.com>
355              
356             =head1 COPYRIGHT AND LICENSE
357              
358             This software is copyright (c) 2012 by NASA GSFC.
359              
360             This is free software; you can redistribute it and/or modify it under
361             the same terms as the Perl 5 programming language system itself.
362              
363             =cut