File Coverage

blib/lib/CGI/Session/Test/Default.pm
Criterion Covered Total %
statement 244 251 97.2
branch 16 28 57.1
condition 3 6 50.0
subroutine 31 31 100.0
pod 3 8 37.5
total 297 324 91.6


line stmt bran cond sub pod time code
1             package CGI::Session::Test::Default;
2              
3 15     15   518647 use strict;
  15         34  
  15         641  
4 15     15   123 use Carp;
  15         28  
  15         1514  
5 15     15   4241 use Test::More ();
  15         55847  
  15         257  
6 15     15   18287 use Data::Dumper;
  15         190739  
  15         1192  
7 15     15   140 use Scalar::Util "refaddr";
  15         32  
  15         50807  
8              
9             our $AUTOLOAD;
10             our $CURRENT;
11             sub ok_later (&;$);
12            
13              
14             $CGI::Session::Test::Default::VERSION = '4.47';
15              
16             =head1 NAME
17              
18             CGI::Session::Test::Default - Run a suite of tests for a given CGI::Session::Driver
19              
20             =head2 new()
21              
22             my $t = CGI::Session::Test::Default->new(
23             # These are all optional, with default as follows
24             dsn => "driver:file",
25             args => undef,
26             tests => 77,
27             );
28              
29             Create a new test object, possibly overriding some defaults.
30              
31             =cut
32              
33             sub new {
34 2     2 1 5205 my $class = shift;
35 2         21 my $self = bless {
36             dsn => "driver:file",
37             args => undef,
38             tests => 101,
39             test_number => 0,
40             @_
41             }, $class;
42            
43 2 50       20 if($self->{skip}) {
44 0         0 $self->{_skip} = { map { $_ => $_ } @{$self->{skip}} };
  0         0  
  0         0  
45             } else {
46 2         8 $self->{_skip} = {};
47             }
48              
49 2         8 return $self;
50             }
51              
52             =head2 number_of_tests()
53              
54             my $new_num = $t->number_of_tests($new_num);
55              
56             A setter/accessor method to affect the number of tests to run,
57             after C<new()> has been called and before C<run()>.
58              
59             =cut
60              
61             sub number_of_tests {
62 2     2 1 16 my $self = shift;
63              
64 2 50       10 if ( @_ ) {
65 0         0 $self->{tests} = $_[0];
66             }
67              
68 2         16 return $self->{tests};
69             }
70              
71             =head2 run()
72              
73             $t->run();
74              
75             Run the test suite. See C<new()> for setting related options.
76              
77             =cut
78              
79             sub run {
80 2     2 1 7 my $self = shift;
81              
82 2         6 $CURRENT = $self;
83 2         12 use_ok("CGI::Session", "CGI::Session loaded successfully!");
84              
85 2         1431 my $sid = undef;
86 2         9 FIRST: {
87 2         6 ok(1, "=== 1 ===");
88 2 50       789 my $session = CGI::Session->load() or die CGI::Session->errstr;
89 2         12 ok($session, "empty session should be created");
90 2         1280 ok(!$session->id, 'Id is empty');
91 2         763 ok($session->is_empty, 'Session is empty');
92 2         821 ok(!$session->is_expired, 'Session is not expired');
93              
94 2         710 undef $session;
95              
96 2 50       14 $session = CGI::Session->new($self->{dsn}, '_DOESN\'T EXIST_', $self->{args}) or die CGI::Session->errstr;
97 2         9 ok( $session, "Session created successfully!");
98              
99             #
100             # checking if the driver object created is really the driver requested:
101             #
102 2         1021 my $dsn = $session->parse_dsn( $self->{dsn} );
103 2         11 ok( ref $session->_driver eq "CGI::Session::Driver::" . $dsn->{driver}, ref $dsn->{Driver} );
104              
105 2   33     968 ok( $session->ctime && $session->atime, "ctime & atime are set");
106 2         897 ok( $session->atime == $session->ctime, "ctime == atime");
107 2         861 ok( !$session->etime, "etime not set yet");
108              
109 2         813 ok( $session->id, "session id is " . $session->id);
110              
111 2         863 $session->param('author', "Sherzod Ruzmetov");
112 2         14 $session->param(-name=>'emails', -value=>['sherzodr@cpan.org', 'sherzodr@cpan.org']);
113 2         13 $session->param('blogs', {
114             './lost+found' => 'http://author.cpan.org/',
115             'Yigitlik sarguzashtlari' => 'http://author.cpan.org/uz/'
116             });
117              
118 2         8 ok( ($session->param) == 3, "session holds 3 params" . scalar $session->param );
119 2         761 ok( $session->param('author') eq "Sherzod Ruzmetov", "My name's correct!");
120              
121 2         756 ok( ref ($session->param('emails')) eq 'ARRAY', "'emails' holds list of values" );
122 2         721 ok( @{ $session->param('emails') } == 2, "'emails' holds list of two values");
  2         10  
123 2         791 ok( $session->param('emails')->[0] eq 'sherzodr@cpan.org', "first value of 'emails' is correct!");
124 2         746 ok( $session->param('emails')->[1] eq 'sherzodr@cpan.org', "second value of 'emails' is correct!");
125              
126 2         799 ok( ref( $session->param('blogs') ) eq 'HASH', "'blogs' holds a hash");
127 2         794 ok( $session->param('blogs')->{'./lost+found'} eq 'http://author.cpan.org/', "first blog is correct");
128 2         770 ok( $session->param('blogs')->{'Yigitlik sarguzashtlari'} eq 'http://author.cpan.org/uz/', "second blog is correct");
129              
130 2         787 $sid = $session->id;
131 2         12 $session->flush();
132             }
133              
134 2         2000392 sleep(1);
135              
136 2         21 SECOND: {
137 2         22 SKIP: {
138 2         10 ok(1, "=== 2 ===");
139 2         3297 my $session;
140 2         7 eval { $session = CGI::Session->load($self->{dsn}, $sid, $self->{args}) };
  2         31  
141              
142 2 100 66     23 if ($@ || CGI::Session->errstr) {
143 1         8 Test::More::skip("couldn't load session, bailing out: SQLite/Storable support is TODO", 56);
144             }
145              
146 1         6 is($@.CGI::Session->errstr,'','survived eval without error.');
147 1         922 ok($session, "Session was retrieved successfully");
148 1         679 ok(!$session->is_expired, "session isn't expired yet");
149              
150 1         593 is($session->id,$sid, "session IDs are consistent");
151 1         2773 ok($session->atime > $session->ctime, "ctime should be older than atime");
152 1         956 ok(!$session->etime, "etime shouldn't be set yet");
153              
154 1         546 ok( ($session->param) == 3, "session should hold params" );
155 1         532 ok( $session->param('author') eq "Sherzod Ruzmetov", "my name's correct");
156              
157 1         601 ok( ref ($session->param('emails')) eq 'ARRAY', "'emails' should hold list of values" );
158 1         517 ok( @{ $session->param('emails') } == 2, "'emails' should hold list of two values");
  1         6  
159 1         623 ok( $session->param('emails')->[0] eq 'sherzodr@cpan.org', "first value is correct!");
160 1         680 ok( $session->param('emails')->[1] eq 'sherzodr@cpan.org', "second value is correct!");
161              
162 1         477 ok( ref( $session->param('blogs') ) eq 'HASH', "'blogs' holds a hash");
163 1         510 ok( $session->param('blogs')->{'./lost+found'} eq 'http://author.cpan.org/', "first blog is correct!");
164 1         392 ok( $session->param('blogs')->{'Yigitlik sarguzashtlari'} eq 'http://author.cpan.org/uz/', "second blog is correct!");
165              
166             # TODO: test many any other variations of expire() syntax
167 1         451 $session->expire('+1s');
168 1         5 ok($session->etime == 1, "etime set to 1 second");
169              
170 1         396 $session->expire("+1m");
171 1         4 ok($session->etime == 60, "etime set to one minute");
172              
173 1         456 $session->expires("2h");
174 1         3 ok($session->etime == 7200, "etime set to two hours");
175              
176 1         403 $session->expires("5d");
177 1         3 ok($session->etime == 432000, "etime set to 5 days");
178              
179 1         470 $session->expires("-10s");
180 1         4 ok($session->etime == -10, "etime set to 10 seconds in the past");
181              
182             #
183             # Setting the expiration time back to 1s, so that subsequent tests
184             # relying on this value pass
185             #
186 1         362 $session->expire("1s");
187 1         4 ok($session->etime == 1, "etime set back to one second");
188 1         447 eval { $session->close(); };
  1         8  
189 1         5 is($@, '', 'calling close method survives eval');
190             }
191             }
192              
193 2         2017343 sleep(1); # <-- letting the time tick
194              
195 2         18 my $driver;
196 2         17 THREE: {
197 2         8 ok(1, "=== 3 ===");
198 2 100       6892 my $session = CGI::Session->load($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
199 1         5 ok($session, "Session instance loaded ");
200 1         748 ok(!$session->id, "session doesn't have ID");
201 1         413 ok($session->is_empty, "session is empty, which is the same as above");
202             #print $session->dump;
203 1         524 ok($session->is_expired, "session was expired");
204 1         427 ok(!$session->param('author'), "session data cleared");
205              
206 1         1000571 sleep(1);
207              
208 1 50       28 $session = $session->new() or die CGI::Session->errstr;
209             #print $session->dump();
210 1         5 ok($session, "new session created");
211 1         725 ok($session->id, "session has id :" . $session->id );
212 1         426 ok(!$session->is_expired, "session isn't expired");
213 1         416 ok(!$session->is_empty, "session isn't empty");
214 1         457 ok($session->atime == $session->ctime, "access and creation times are same");
215              
216 1         539 ok($session->id ne $sid, "it's a completely different session than above");
217              
218 1         505 $driver = $session->_driver();
219 1         4 $sid = $session->id;
220             }
221              
222              
223              
224             FOUR: {
225             # We are intentionally removing the session stored in the datastore and will be requesting
226             # re-initialization of that id. This test is necessary since I noticed weird behaviors in
227             # some of my web applications that kept creating new sessions when the object requested
228             # wasn't in the datastore.
229 1         5 ok(1, "=== 4 ===");
  1         5  
230              
231 1         673 ok($driver->remove( $sid ), "Session '$sid' removed from datastore successfully");
232              
233 1 50       487 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args} ) or die CGI::Session->errstr;
234 1         5 ok($session, "session object created successfully");
235 1         589 ok($session->id ne $sid, "claimed ID ($sid) couldn't be recovered. New ID is: " . $session->id);
236 1         422 $sid = $session->id;
237             }
238              
239              
240              
241             FIVE: {
242 1         4 ok(1, "=== 5 ===");
  1         4  
243 1 50       539 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
244 1         4 ok($session, "Session object created successfully");
245 1         469 ok($session->id eq $sid, "claimed id ($sid) was recovered successfully!");
246              
247             # Remove the object, finally!
248 1         388 $session->delete();
249             }
250              
251              
252             SIX: {
253 1         3 ok(1, "=== 6 ===");
  1         4  
254 1 50       354 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
255 1         3 ok($session, "Session object created successfully");
256 1         366 ok($session->id ne $sid, "New object created, because previous object was deleted");
257 1         357 $sid = $session->id;
258              
259             #
260             # creating a simple object to be stored into session
261 1         29 my $simple_class = CGI::Session::Test::SimpleObjectClass->new();
262 1         50 ok($simple_class, "CGI::Session::Test::SimpleObjectClass created successfully");
263              
264 1         366 $simple_class->name("Sherzod Ruzmetov");
265 1         21 $simple_class->emails(0, 'sherzodr@cpan.org');
266 1         25 $simple_class->emails(1, 'sherzodr@cpan.org');
267 1         22 $simple_class->blogs('lost+found', 'http://author.cpan.org/');
268 1         24 $simple_class->blogs('yigitlik', 'http://author.cpan.org/uz/');
269 1         11 $session->param('simple_object', $simple_class);
270              
271 1         4 ok($session->param('simple_object')->name eq "Sherzod Ruzmetov");
272 1         389 ok($session->param('simple_object')->emails(1) eq 'sherzodr@cpan.org');
273 1         438 ok($session->param('simple_object')->blogs('yigitlik') eq 'http://author.cpan.org/uz/');
274            
275             #
276             # creating an overloaded object to be stored into session
277 1         471 my $overloaded_class = OverloadedClass->new("ABCDEFG");
278 1         5 ok($overloaded_class, "OverloadedClass created successfully");
279 1         481 ok(overload::Overloaded($overloaded_class) , "OverloadedClass is properly overloaded");
280 1         555 ok(ref ($overloaded_class) eq "OverloadedClass", "OverloadedClass is an object");
281 1         12539 $session->param("overloaded_object", $overloaded_class);
282            
283 1         5 ok($session->param("overloaded_object") eq "ABCDEFG");
284            
285 1         488 my $simple_class2 = CGI::Session::Test::SimpleObjectClass->new();
286 1         55 ok($simple_class2, "CGI::Session::Test::SimpleObjectClass created successfully");
287              
288 1         316 $simple_class2->name("Sherzod Ruzmetov");
289 1         40 $simple_class2->emails(0, 'sherzodr@cpan.org');
290 1         34 $simple_class2->emails(1, 'sherzodr@cpan.org');
291 1         30 $simple_class2->blogs('lost+found', 'http://author.cpan.org/');
292 1         31 $simple_class2->blogs('yigitlik', 'http://author.cpan.org/uz/');
293 1         14 my $embedded = OverloadedClass->new("Embedded");
294 1         9 $session->param("embedded_simple_and_overloaded",[ undef, $simple_class2, $embedded, $embedded ]);
295              
296 1         5 ok(!defined($session->param("embedded_simple_and_overloaded")->[0]),"First element of anonymous array undef");
297              
298 1         284 ok($session->param("embedded_simple_and_overloaded")->[1]->name eq "Sherzod Ruzmetov");
299 1         267 ok($session->param("embedded_simple_and_overloaded")->[1]->emails(1) eq 'sherzodr@cpan.org');
300 1         256 ok($session->param("embedded_simple_and_overloaded")->[1]->blogs('yigitlik') eq 'http://author.cpan.org/uz/');
301            
302 1         5888 ok($session->param("embedded_simple_and_overloaded")->[2] eq "Embedded");
303            
304 1         258 ok(refaddr($session->param("embedded_simple_and_overloaded")->[2]) == refaddr($session->param("embedded_simple_and_overloaded")->[3] ),
305             "Overloaded objects have matching addresses");
306             }
307              
308              
309             SEVEN: {
310 1         4 ok(1, "=== 7 ===");
  1         5  
311 1 50       245 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
312 1         5 ok($session, "Session object created successfully");
313 1         249 ok($session->id eq $sid, "Previously stored object loaded successfully");
314              
315              
316 1         261 my $simple_object = $session->param("simple_object");
317 1         4 ok(ref $simple_object eq "CGI::Session::Test::SimpleObjectClass", "CGI::Session::Test::SimpleObjectClass loaded successfully");
318              
319 1         6769 my $dsn = CGI::Session->parse_dsn($self->{dsn});
320 1     1   13 ok_later { $simple_object->name eq "Sherzod Ruzmetov" };
  1         44  
321 1     1   803 ok_later { $simple_object->emails(1) eq 'sherzodr@cpan.org' };
  1         95  
322 1     1   435 ok_later { $simple_object->emails(0) eq 'sherzodr@cpan.org' };
  1         31  
323 1     1   1137 ok_later { $simple_object->blogs('lost+found') eq 'http://author.cpan.org/' };
  1         32  
324 1         663 ok(ref $session->param("overloaded_object") );
325 1         604 ok($session->param("overloaded_object") eq "ABCDEFG", "Object is still overloaded");
326 1         519 ok(overload::Overloaded($session->param("overloaded_object")), "Object is really overloaded");
327              
328 1         672 ok(!defined($session->param("embedded_simple_and_overloaded")->[0]),"First element of anonymous array undef");
329            
330 1         692 my $simple_object2 = $session->param("embedded_simple_and_overloaded")->[1];
331 1         6 ok(ref $simple_object2 eq "CGI::Session::Test::SimpleObjectClass", "CGI::Session::Test::SimpleObjectClass loaded successfully");
332              
333 1     1   1102 ok_later { $simple_object2->name eq "Sherzod Ruzmetov" };
  1         41  
334 1     1   476 ok_later { $simple_object2->emails(1) eq 'sherzodr@cpan.org' };
  1         30  
335 1     1   704 ok_later { $simple_object2->emails(0) eq 'sherzodr@cpan.org' };
  1         29  
336 1     1   639 ok_later { $simple_object2->blogs('lost+found') eq 'http://author.cpan.org/' };
  1         29  
337              
338            
339 1         530 ok($session->param("embedded_simple_and_overloaded")->[2] eq "Embedded");
340 1         509 ok(overload::Overloaded($session->param("embedded_simple_and_overloaded")->[2]), "Object is really overloaded");
341            
342 1         742 ok(refaddr($session->param("embedded_simple_and_overloaded")->[2]) == refaddr($session->param("embedded_simple_and_overloaded")->[3]),
343             "Overloaded objects have matching addresses");
344 1         736 $session->delete();
345             }
346            
347 1         3 $CURRENT = undef;
348 1         5 $self->{test_number} = 0;
349             }
350              
351             sub skip_or_run {
352 116     116 0 204 my $test = shift;
353            
354 116         248 $CURRENT->{test_number} ++;
355              
356             SKIP: {
357 116 50       144 if($CURRENT->{_skip}->{$CURRENT->{test_number}}) {
  116         388  
358 0         0 Test::More::skip("Test does not apply to this setup.", 1);
359             }
360            
361 15     15   137 no strict 'refs';
  15         30  
  15         4968  
362 2     2   2041 &{"Test::More::$test"}(@_);
  2         6  
  2         5  
  2         15  
  116         190  
  116         718  
363             }
364             }
365              
366 111     111 0 2513 sub ok { skip_or_run("ok", @_); }
367 2     2 0 11 sub use_ok { skip_or_run("use_ok", @_); }
368 3     3 0 12 sub is { skip_or_run("is", @_); }
369              
370             sub ok_later (&;$) {
371 8     8 0 20 my($code, $name) = @_;
372            
373 8         15 $CURRENT->{test_number} ++;
374 8 50       23 $name = '' unless $name;
375              
376             SKIP: {
377 8 50       11 if($CURRENT->{_skip}->{$CURRENT->{test_number}}) {
  8         25  
378 0         0 Test::More::skip("Test does not apply to this setup.", 1);
379 0         0 fail($name);
380             } else {
381 8         19 Test::More::ok($code->(), $name);
382             }
383             }
384             }
385              
386 1     1   114 sub DESTROY { 1; }
387              
388              
389             package CGI::Session::Test::SimpleObjectClass;
390 15     15   90 use strict;
  15         29  
  15         554  
391 15     15   26544 use Class::Struct;
  15         48228  
  15         96  
392              
393             struct (
394             name => '$',
395             emails => '@',
396             blogs => '%'
397             );
398              
399              
400              
401             package OverloadedClass;
402              
403 15     15   3390 use strict;
  15         32  
  15         799  
404             use overload (
405 15         166 '""' => \&as_string,
406             'eq' => \&equals
407 15     15   229 );
  15         28  
408              
409             sub new {
410 2     2   14 return bless {
411             str_value => $_[1]
412             }, $_[0];
413             }
414              
415              
416             sub as_string {
417 5     5   108 return $_[0]->{str_value};
418             }
419              
420             sub equals {
421 4     4   10 my ($self, $arg) = @_;
422              
423 4         19 return ($self->as_string eq $arg);
424             }
425              
426             1;