Make sure Win32-like DBICTest checks are not tripped by repeated disconnects
[dbsrgits/DBIx-Class.git] / t / storage / base.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Test::Warn;
6 use Test::Exception;
7 use lib qw(t/lib);
8 use DBICTest;
9 use Data::Dumper;
10
11 my $schema = DBICTest->init_schema( sqlite_use_file => 1 );
12
13 my $storage = $schema->storage;
14
15 is(
16   ref($storage),
17   'DBIx::Class::Storage::DBI::SQLite',
18   'Storage reblessed correctly into DBIx::Class::Storage::DBI::SQLite'
19 ) unless $ENV{DBICTEST_VIA_REPLICATED};
20
21 throws_ok {
22     $schema->storage->throw_exception('test_exception_42');
23 } qr/\btest_exception_42\b/, 'basic exception';
24
25 throws_ok {
26     $schema->resultset('CD')->search_literal('broken +%$#$1')->all;
27 } qr/prepare_cached failed/, 'exception via DBI->HandleError, etc';
28
29
30 # make sure repeated disconnection works
31 {
32   my $fn = DBICTest->_sqlite_dbfilename;
33
34   lives_ok {
35     $schema->storage->ensure_connected;
36     my $dbh = $schema->storage->dbh;
37     $schema->storage->disconnect for 1,2;
38     unlink $fn;
39     $dbh->disconnect;
40   };
41
42   lives_ok {
43     $schema->storage->ensure_connected;
44     $schema->storage->disconnect for 1,2;
45     unlink $fn;
46     $schema->storage->disconnect for 1,2;
47   };
48
49   lives_ok {
50     $schema->storage->ensure_connected;
51     $schema->storage->_dbh->disconnect;
52     unlink $fn;
53     $schema->storage->disconnect for 1,2;
54   };
55 }
56
57
58 # testing various invocations of connect_info ([ ... ])
59
60 my $coderef = sub { 42 };
61 my $invocations = {
62   'connect_info ([ $d, $u, $p, \%attr, \%extra_attr])' => {
63       args => [
64           'foo',
65           'bar',
66           undef,
67           {
68             on_connect_do => [qw/a b c/],
69             PrintError => 0,
70           },
71           {
72             AutoCommit => 1,
73             on_disconnect_do => [qw/d e f/],
74           },
75           {
76             unsafe => 1,
77             auto_savepoint => 1,
78           },
79         ],
80       dbi_connect_info => [
81           'foo',
82           'bar',
83           undef,
84           {
85             %{$storage->_default_dbi_connect_attributes || {} },
86             PrintError => 0,
87             AutoCommit => 1,
88           },
89       ],
90   },
91
92   'connect_info ([ \%code, \%extra_attr ])' => {
93       args => [
94           $coderef,
95           {
96             on_connect_do => [qw/a b c/],
97             PrintError => 0,
98             AutoCommit => 1,
99             on_disconnect_do => [qw/d e f/],
100           },
101           {
102             unsafe => 1,
103             auto_savepoint => 1,
104           },
105         ],
106       dbi_connect_info => [
107           $coderef,
108       ],
109   },
110
111   'connect_info ([ \%attr ])' => {
112       args => [
113           {
114             on_connect_do => [qw/a b c/],
115             PrintError => 1,
116             AutoCommit => 0,
117             on_disconnect_do => [qw/d e f/],
118             user => 'bar',
119             dsn => 'foo',
120           },
121           {
122             unsafe => 1,
123             auto_savepoint => 1,
124           },
125       ],
126       dbi_connect_info => [
127           'foo',
128           'bar',
129           undef,
130           {
131             %{$storage->_default_dbi_connect_attributes || {} },
132             PrintError => 1,
133             AutoCommit => 0,
134           },
135       ],
136       warn => qr/\QYou provided explicit AutoCommit => 0 in your connection_info/,
137   },
138   'connect_info ([ \%attr_with_coderef ])' => {
139       args => [ {
140         dbh_maker => $coderef,
141         dsn => 'blah',
142         user => 'bleh',
143         on_connect_do => [qw/a b c/],
144         on_disconnect_do => [qw/d e f/],
145       } ],
146       dbi_connect_info => [
147         $coderef
148       ],
149       warn => qr/Attribute\(s\) 'dsn', 'user' in connect_info were ignored/,
150   },
151 };
152
153 for my $type (keys %$invocations) {
154   local $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK};
155
156   # we can not use a cloner portably because of the coderef
157   # so compare dumps instead
158   local $Data::Dumper::Sortkeys = 1;
159   my $arg_dump = Dumper ($invocations->{$type}{args});
160
161   warnings_exist (
162     sub { $storage->connect_info ($invocations->{$type}{args}) },
163      $invocations->{$type}{warn} || [],
164     'Warned about ignored attributes',
165   );
166
167   is ($arg_dump, Dumper ($invocations->{$type}{args}), "$type didn't modify passed arguments");
168
169   is_deeply ($storage->_dbi_connect_info, $invocations->{$type}{dbi_connect_info}, "$type produced correct _dbi_connect_info");
170   ok ( (not $storage->auto_savepoint and not $storage->unsafe), "$type correctly ignored extra hashref");
171
172   is_deeply (
173     [$storage->on_connect_do, $storage->on_disconnect_do ],
174     [ [qw/a b c/], [qw/d e f/] ],
175     "$type correctly parsed DBIC specific on_[dis]connect_do",
176   );
177 }
178
179 # make sure connection-less storages do not throw on _determine_driver
180 # but work with ENV at the same time
181 SKIP: for my $env_dsn (undef, (DBICTest->_database)[0] ) {
182   skip 'Subtest relies on being connected to SQLite', 1
183     if $env_dsn and $env_dsn !~ /\:SQLite\:/;
184
185   local $ENV{DBI_DSN} = $env_dsn || '';
186
187   my $s = DBICTest::Schema->connect();
188   is_deeply (
189     $s->storage->connect_info,
190     [],
191     'Starting with no explicitly passed in connect info'
192   . ($env_dsn ? ' (with DBI_DSN)' : ''),
193   );
194
195   my $sm = $s->storage->sql_maker;
196
197   ok (! $s->storage->connected, 'Storage does not appear connected after SQLMaker instance is taken');
198
199   if ($env_dsn) {
200     isa_ok($sm, 'DBIx::Class::SQLMaker');
201
202     ok ( $s->storage->_driver_determined, 'Driver determined (with DBI_DSN)');
203     isa_ok ( $s->storage, 'DBIx::Class::Storage::DBI::SQLite' );
204   }
205   else {
206     isa_ok($sm, 'DBIx::Class::SQLMaker');
207
208     ok (! $s->storage->_driver_determined, 'Driver undetermined');
209
210     throws_ok {
211       $s->storage->ensure_connected
212     } qr/You did not provide any connection_info/,
213     'sensible exception on empty conninfo connect';
214   }
215 }
216
217 done_testing;