File Coverage

blib/lib/CGI/Session/Test/Default.pm
Criterion Covered Total %
statement 243 251 96.8
branch 14 28 50.0
condition 2 6 33.3
subroutine 31 31 100.0
pod 3 8 37.5
total 293 324 90.4


line stmt bran cond sub pod time code
1             package CGI::Session::Test::Default;
2              
3 15     15   1107450 use strict;
  15         23  
  15         463  
4 15     15   62 use Carp;
  15         23  
  15         881  
5 15     15   688 use Test::More ();
  15         77504  
  15         245  
6 15     15   7439 use Data::Dumper;
  15         105289  
  15         1000  
7 15     15   109 use Scalar::Util "refaddr";
  15         20  
  15         27205  
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 254275 my $class = shift;
35 2         17 my $self = bless {
36             dsn => "driver:file",
37             args => undef,
38             tests => 101,
39             test_number => 0,
40             @_
41             }, $class;
42            
43 2 50       11 if($self->{skip}) {
44 0         0 $self->{_skip} = { map { $_ => $_ } @{$self->{skip}} };
  0         0  
  0         0  
45             } else {
46 2         6 $self->{_skip} = {};
47             }
48              
49 2         5 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 has been called and before C.
58              
59             =cut
60              
61             sub number_of_tests {
62 2     2 1 9 my $self = shift;
63              
64 2 50       8 if ( @_ ) {
65 0         0 $self->{tests} = $_[0];
66             }
67              
68 2         23 return $self->{tests};
69             }
70              
71             =head2 run()
72              
73             $t->run();
74              
75             Run the test suite. See C for setting related options.
76              
77             =cut
78              
79             sub run {
80 2     2 1 5 my $self = shift;
81              
82 2         4 $CURRENT = $self;
83 2         9 use_ok("CGI::Session", "CGI::Session loaded successfully!");
84              
85 2         744 my $sid = undef;
86             FIRST: {
87 2         5 ok(1, "=== 1 ===");
  2         10  
88 2 50       587 my $session = CGI::Session->load() or die CGI::Session->errstr;
89 2         11 ok($session, "empty session should be created");
90 2         900 ok(!$session->id, 'Id is empty');
91 2         654 ok($session->is_empty, 'Session is empty');
92 2         567 ok(!$session->is_expired, 'Session is not expired');
93              
94 2         624 undef $session;
95              
96 2 50       18 $session = CGI::Session->new($self->{dsn}, '_DOESN\'T EXIST_', $self->{args}) or die CGI::Session->errstr;
97 2         8 ok( $session, "Session created successfully!");
98              
99             #
100             # checking if the driver object created is really the driver requested:
101             #
102 2         648 my $dsn = $session->parse_dsn( $self->{dsn} );
103 2         38 ok( ref $session->_driver eq "CGI::Session::Driver::" . $dsn->{driver}, ref $dsn->{Driver} );
104              
105 2   33     601 ok( $session->ctime && $session->atime, "ctime & atime are set");
106 2         686 ok( $session->atime == $session->ctime, "ctime == atime");
107 2         630 ok( !$session->etime, "etime not set yet");
108              
109 2         645 ok( $session->id, "session id is " . $session->id);
110              
111 2         607 $session->param('author', "Sherzod Ruzmetov");
112 2         62 $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         6 ok( ($session->param) == 3, "session holds 3 params" . scalar $session->param );
119 2         616 ok( $session->param('author') eq "Sherzod Ruzmetov", "My name's correct!");
120              
121 2         584 ok( ref ($session->param('emails')) eq 'ARRAY', "'emails' holds list of values" );
122 2         622 ok( @{ $session->param('emails') } == 2, "'emails' holds list of two values");
  2         8  
123 2         624 ok( $session->param('emails')->[0] eq 'sherzodr@cpan.org', "first value of 'emails' is correct!");
124 2         687 ok( $session->param('emails')->[1] eq 'sherzodr@cpan.org', "second value of 'emails' is correct!");
125              
126 2         588 ok( ref( $session->param('blogs') ) eq 'HASH', "'blogs' holds a hash");
127 2         617 ok( $session->param('blogs')->{'./lost+found'} eq 'http://author.cpan.org/', "first blog is correct");
128 2         576 ok( $session->param('blogs')->{'Yigitlik sarguzashtlari'} eq 'http://author.cpan.org/uz/', "second blog is correct");
129              
130 2         584 $sid = $session->id;
131 2         9 $session->flush();
132             }
133              
134 2         2000365 sleep(1);
135              
136             SECOND: {
137 2         27 SKIP: {
138 2         6 ok(1, "=== 2 ===");
  2         31  
139 2         1009 my $session;
140 2         5 eval { $session = CGI::Session->load($self->{dsn}, $sid, $self->{args}) };
  2         24  
141              
142 2 50 33     18 if ($@ || CGI::Session->errstr) {
143 0         0 Test::More::skip("couldn't load session, bailing out: SQLite/Storable support is TODO", 56);
144             }
145              
146 2         6 is($@.CGI::Session->errstr,'','survived eval without error.');
147 2         592 ok($session, "Session was retrieved successfully");
148 2         446 ok(!$session->is_expired, "session isn't expired yet");
149              
150 2         390 is($session->id,$sid, "session IDs are consistent");
151 2         522 ok($session->atime > $session->ctime, "ctime should be older than atime");
152 2         414 ok(!$session->etime, "etime shouldn't be set yet");
153              
154 2         501 ok( ($session->param) == 3, "session should hold params" );
155 2         495 ok( $session->param('author') eq "Sherzod Ruzmetov", "my name's correct");
156              
157 2         462 ok( ref ($session->param('emails')) eq 'ARRAY', "'emails' should hold list of values" );
158 2         431 ok( @{ $session->param('emails') } == 2, "'emails' should hold list of two values");
  2         8  
159 2         426 ok( $session->param('emails')->[0] eq 'sherzodr@cpan.org', "first value is correct!");
160 2         481 ok( $session->param('emails')->[1] eq 'sherzodr@cpan.org', "second value is correct!");
161              
162 2         441 ok( ref( $session->param('blogs') ) eq 'HASH', "'blogs' holds a hash");
163 2         419 ok( $session->param('blogs')->{'./lost+found'} eq 'http://author.cpan.org/', "first blog is correct!");
164 2         397 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 2         442 $session->expire('+1s');
168 2         5 ok($session->etime == 1, "etime set to 1 second");
169              
170 2         503 $session->expire("+1m");
171 2         5 ok($session->etime == 60, "etime set to one minute");
172              
173 2         466 $session->expires("2h");
174 2         6 ok($session->etime == 7200, "etime set to two hours");
175              
176 2         393 $session->expires("5d");
177 2         5 ok($session->etime == 432000, "etime set to 5 days");
178              
179 2         462 $session->expires("-10s");
180 2         6 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 2         558 $session->expire("1s");
187 2         6 ok($session->etime == 1, "etime set back to one second");
188 2         517 eval { $session->close(); };
  2         10  
189 2         9 is($@, '', 'calling close method survives eval');
190             }
191             }
192              
193 2         2000298 sleep(1); # <-- letting the time tick
194              
195 2         30 my $driver;
196             THREE: {
197 2         5 ok(1, "=== 3 ===");
  2         18  
198 2 50       1024 my $session = CGI::Session->load($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
199 2         8 ok($session, "Session instance loaded ");
200 2         631 ok(!$session->id, "session doesn't have ID");
201 2         441 ok($session->is_empty, "session is empty, which is the same as above");
202             #print $session->dump;
203 2         417 ok($session->is_expired, "session was expired");
204 2         435 ok(!$session->param('author'), "session data cleared");
205              
206 2         2000672 sleep(1);
207              
208 2 50       57 $session = $session->new() or die CGI::Session->errstr;
209             #print $session->dump();
210 2         12 ok($session, "new session created");
211 2         1006 ok($session->id, "session has id :" . $session->id );
212 2         505 ok(!$session->is_expired, "session isn't expired");
213 2         447 ok(!$session->is_empty, "session isn't empty");
214 2         444 ok($session->atime == $session->ctime, "access and creation times are same");
215              
216 2         428 ok($session->id ne $sid, "it's a completely different session than above");
217              
218 2         441 $driver = $session->_driver();
219 2         6 $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 2         5 ok(1, "=== 4 ===");
  2         10  
230              
231 2         542 ok($driver->remove( $sid ), "Session '$sid' removed from datastore successfully");
232              
233 2 50       715 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args} ) or die CGI::Session->errstr;
234 2         9 ok($session, "session object created successfully");
235 2         601 ok($session->id ne $sid, "claimed ID ($sid) couldn't be recovered. New ID is: " . $session->id);
236 2         514 $sid = $session->id;
237             }
238              
239              
240              
241             FIVE: {
242 2         5 ok(1, "=== 5 ===");
  2         23  
243 2 50       549 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
244 2         9 ok($session, "Session object created successfully");
245 2         698 ok($session->id eq $sid, "claimed id ($sid) was recovered successfully!");
246              
247             # Remove the object, finally!
248 2         570 $session->delete();
249             }
250              
251              
252             SIX: {
253 2         5 ok(1, "=== 6 ===");
  2         8  
254 2 50       518 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
255 2         8 ok($session, "Session object created successfully");
256 2         560 ok($session->id ne $sid, "New object created, because previous object was deleted");
257 2         497 $sid = $session->id;
258              
259             #
260             # creating a simple object to be stored into session
261 2         63 my $simple_class = CGI::Session::Test::SimpleObjectClass->new();
262 2         116 ok($simple_class, "CGI::Session::Test::SimpleObjectClass created successfully");
263              
264 2         497 $simple_class->name("Sherzod Ruzmetov");
265 2         45 $simple_class->emails(0, 'sherzodr@cpan.org');
266 2         43 $simple_class->emails(1, 'sherzodr@cpan.org');
267 2         31 $simple_class->blogs('lost+found', 'http://author.cpan.org/');
268 2         33 $simple_class->blogs('yigitlik', 'http://author.cpan.org/uz/');
269 2         33 $session->param('simple_object', $simple_class);
270              
271 2         6 ok($session->param('simple_object')->name eq "Sherzod Ruzmetov");
272 2         460 ok($session->param('simple_object')->emails(1) eq 'sherzodr@cpan.org');
273 2         486 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 2         487 my $overloaded_class = OverloadedClass->new("ABCDEFG");
278 2         6 ok($overloaded_class, "OverloadedClass created successfully");
279 2         349 ok(overload::Overloaded($overloaded_class) , "OverloadedClass is properly overloaded");
280 2         501 ok(ref ($overloaded_class) eq "OverloadedClass", "OverloadedClass is an object");
281 2         434 $session->param("overloaded_object", $overloaded_class);
282            
283 2         6 ok($session->param("overloaded_object") eq "ABCDEFG");
284            
285 2         529 my $simple_class2 = CGI::Session::Test::SimpleObjectClass->new();
286 2         81 ok($simple_class2, "CGI::Session::Test::SimpleObjectClass created successfully");
287              
288 2         731 $simple_class2->name("Sherzod Ruzmetov");
289 2         31 $simple_class2->emails(0, 'sherzodr@cpan.org');
290 2         32 $simple_class2->emails(1, 'sherzodr@cpan.org');
291 2         30 $simple_class2->blogs('lost+found', 'http://author.cpan.org/');
292 2         32 $simple_class2->blogs('yigitlik', 'http://author.cpan.org/uz/');
293 2         16 my $embedded = OverloadedClass->new("Embedded");
294 2         10 $session->param("embedded_simple_and_overloaded",[ undef, $simple_class2, $embedded, $embedded ]);
295              
296 2         5 ok(!defined($session->param("embedded_simple_and_overloaded")->[0]),"First element of anonymous array undef");
297              
298 2         1234 ok($session->param("embedded_simple_and_overloaded")->[1]->name eq "Sherzod Ruzmetov");
299 2         462 ok($session->param("embedded_simple_and_overloaded")->[1]->emails(1) eq 'sherzodr@cpan.org');
300 2         464 ok($session->param("embedded_simple_and_overloaded")->[1]->blogs('yigitlik') eq 'http://author.cpan.org/uz/');
301            
302 2         495 ok($session->param("embedded_simple_and_overloaded")->[2] eq "Embedded");
303            
304 2         462 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 2         9 ok(1, "=== 7 ===");
  2         8  
311 2 50       548 my $session = CGI::Session->new($self->{dsn}, $sid, $self->{args}) or die CGI::Session->errstr;
312 2         7 ok($session, "Session object created successfully");
313 2         560 ok($session->id eq $sid, "Previously stored object loaded successfully");
314              
315              
316 2         454 my $simple_object = $session->param("simple_object");
317 2         10 ok(ref $simple_object eq "CGI::Session::Test::SimpleObjectClass", "CGI::Session::Test::SimpleObjectClass loaded successfully");
318              
319 2         547 my $dsn = CGI::Session->parse_dsn($self->{dsn});
320 2     2   16 ok_later { $simple_object->name eq "Sherzod Ruzmetov" };
  2         46  
321 2     2   470 ok_later { $simple_object->emails(1) eq 'sherzodr@cpan.org' };
  2         40  
322 2     2   555 ok_later { $simple_object->emails(0) eq 'sherzodr@cpan.org' };
  2         47  
323 2     2   485 ok_later { $simple_object->blogs('lost+found') eq 'http://author.cpan.org/' };
  2         39  
324 2         509 ok(ref $session->param("overloaded_object") );
325 2         411 ok($session->param("overloaded_object") eq "ABCDEFG", "Object is still overloaded");
326 2         520 ok(overload::Overloaded($session->param("overloaded_object")), "Object is really overloaded");
327              
328 2         525 ok(!defined($session->param("embedded_simple_and_overloaded")->[0]),"First element of anonymous array undef");
329            
330 2         466 my $simple_object2 = $session->param("embedded_simple_and_overloaded")->[1];
331 2         8 ok(ref $simple_object2 eq "CGI::Session::Test::SimpleObjectClass", "CGI::Session::Test::SimpleObjectClass loaded successfully");
332              
333 2     2   480 ok_later { $simple_object2->name eq "Sherzod Ruzmetov" };
  2         67  
334 2     2   483 ok_later { $simple_object2->emails(1) eq 'sherzodr@cpan.org' };
  2         93  
335 2     2   466 ok_later { $simple_object2->emails(0) eq 'sherzodr@cpan.org' };
  2         38  
336 2     2   421 ok_later { $simple_object2->blogs('lost+found') eq 'http://author.cpan.org/' };
  2         36  
337              
338            
339 2         553 ok($session->param("embedded_simple_and_overloaded")->[2] eq "Embedded");
340 2         406 ok(overload::Overloaded($session->param("embedded_simple_and_overloaded")->[2]), "Object is really overloaded");
341            
342 2         399 ok(refaddr($session->param("embedded_simple_and_overloaded")->[2]) == refaddr($session->param("embedded_simple_and_overloaded")->[3]),
343             "Overloaded objects have matching addresses");
344 2         464 $session->delete();
345             }
346            
347 2         7 $CURRENT = undef;
348 2         8 $self->{test_number} = 0;
349             }
350              
351             sub skip_or_run {
352 186     186 0 358 my $test = shift;
353            
354 186         400 $CURRENT->{test_number} ++;
355              
356             SKIP: {
357 186 50       209 if($CURRENT->{_skip}->{$CURRENT->{test_number}}) {
  186         519  
358 0         0 Test::More::skip("Test does not apply to this setup.", 1);
359             }
360            
361 15     15   102 no strict 'refs';
  15         27  
  15         3924  
362 2     2   1782 &{"Test::More::$test"}(@_);
  2         5  
  2         3  
  2         14  
  186         230  
  186         714  
363             }
364             }
365              
366 178     178 0 735 sub ok { skip_or_run("ok", @_); }
367 2     2 0 9 sub use_ok { skip_or_run("use_ok", @_); }
368 6     6 0 14 sub is { skip_or_run("is", @_); }
369              
370             sub ok_later (&;$) {
371 16     16 0 32 my($code, $name) = @_;
372            
373 16         28 $CURRENT->{test_number} ++;
374 16 50       34 $name = '' unless $name;
375              
376             SKIP: {
377 16 50       16 if($CURRENT->{_skip}->{$CURRENT->{test_number}}) {
  16         38  
378 0         0 Test::More::skip("Test does not apply to this setup.", 1);
379 0         0 fail($name);
380             } else {
381 16         30 Test::More::ok($code->(), $name);
382             }
383             }
384             }
385              
386 2     2   216 sub DESTROY { 1; }
387              
388              
389             package CGI::Session::Test::SimpleObjectClass;
390 15     15   116 use strict;
  15         27  
  15         398  
391 15     15   7161 use Class::Struct;
  15         24610  
  15         79  
392              
393             struct (
394             name => '$',
395             emails => '@',
396             blogs => '%'
397             );
398              
399              
400              
401             package OverloadedClass;
402              
403 15     15   2387 use strict;
  15         24  
  15         549  
404             use overload (
405 15         124 '""' => \&as_string,
406             'eq' => \&equals
407 15     15   7571 );
  15         20274  
408              
409             sub new {
410 4     4   14 return bless {
411             str_value => $_[1]
412             }, $_[0];
413             }
414              
415              
416             sub as_string {
417 10     10   285 return $_[0]->{str_value};
418             }
419              
420             sub equals {
421 8     8   13 my ($self, $arg) = @_;
422              
423 8         40 return ($self->as_string eq $arg);
424             }
425              
426             1;