Run the entire test suite under replicated SQLite on DBICTEST_VIA_REPLICATED
[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 # testing various invocations of connect_info ([ ... ])
31
32 my $coderef = sub { 42 };
33 my $invocations = {
34   'connect_info ([ $d, $u, $p, \%attr, \%extra_attr])' => {
35       args => [
36           'foo',
37           'bar',
38           undef,
39           {
40             on_connect_do => [qw/a b c/],
41             PrintError => 0,
42           },
43           {
44             AutoCommit => 1,
45             on_disconnect_do => [qw/d e f/],
46           },
47           {
48             unsafe => 1,
49             auto_savepoint => 1,
50           },
51         ],
52       dbi_connect_info => [
53           'foo',
54           'bar',
55           undef,
56           {
57             %{$storage->_default_dbi_connect_attributes || {} },
58             PrintError => 0,
59             AutoCommit => 1,
60           },
61       ],
62   },
63
64   'connect_info ([ \%code, \%extra_attr ])' => {
65       args => [
66           $coderef,
67           {
68             on_connect_do => [qw/a b c/],
69             PrintError => 0,
70             AutoCommit => 1,
71             on_disconnect_do => [qw/d e f/],
72           },
73           {
74             unsafe => 1,
75             auto_savepoint => 1,
76           },
77         ],
78       dbi_connect_info => [
79           $coderef,
80       ],
81   },
82
83   'connect_info ([ \%attr ])' => {
84       args => [
85           {
86             on_connect_do => [qw/a b c/],
87             PrintError => 1,
88             AutoCommit => 0,
89             on_disconnect_do => [qw/d e f/],
90             user => 'bar',
91             dsn => 'foo',
92           },
93           {
94             unsafe => 1,
95             auto_savepoint => 1,
96           },
97       ],
98       dbi_connect_info => [
99           'foo',
100           'bar',
101           undef,
102           {
103             %{$storage->_default_dbi_connect_attributes || {} },
104             PrintError => 1,
105             AutoCommit => 0,
106           },
107       ],
108       warn => qr/\QYou provided explicit AutoCommit => 0 in your connection_info/,
109   },
110   'connect_info ([ \%attr_with_coderef ])' => {
111       args => [ {
112         dbh_maker => $coderef,
113         dsn => 'blah',
114         user => 'bleh',
115         on_connect_do => [qw/a b c/],
116         on_disconnect_do => [qw/d e f/],
117       } ],
118       dbi_connect_info => [
119         $coderef
120       ],
121       warn => qr/Attribute\(s\) 'dsn', 'user' in connect_info were ignored/,
122   },
123 };
124
125 for my $type (keys %$invocations) {
126   local $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK};
127
128   # we can not use a cloner portably because of the coderef
129   # so compare dumps instead
130   local $Data::Dumper::Sortkeys = 1;
131   my $arg_dump = Dumper ($invocations->{$type}{args});
132
133   warnings_exist (
134     sub { $storage->connect_info ($invocations->{$type}{args}) },
135      $invocations->{$type}{warn} || [],
136     'Warned about ignored attributes',
137   );
138
139   is ($arg_dump, Dumper ($invocations->{$type}{args}), "$type didn't modify passed arguments");
140
141   is_deeply ($storage->_dbi_connect_info, $invocations->{$type}{dbi_connect_info}, "$type produced correct _dbi_connect_info");
142   ok ( (not $storage->auto_savepoint and not $storage->unsafe), "$type correctly ignored extra hashref");
143
144   is_deeply (
145     [$storage->on_connect_do, $storage->on_disconnect_do ],
146     [ [qw/a b c/], [qw/d e f/] ],
147     "$type correctly parsed DBIC specific on_[dis]connect_do",
148   );
149 }
150
151 $schema->storage->_dbh->disconnect;
152
153 # make sure connection-less storages do not throw on _determine_driver
154 # but work with ENV at the same time
155 SKIP: for my $env_dsn (undef, (DBICTest->_database)[0] ) {
156   skip 'Subtest relies on being connected to SQLite', 1
157     if $env_dsn and $env_dsn !~ /\:SQLite\:/;
158
159   local $ENV{DBI_DSN} = $env_dsn || '';
160
161   my $s = DBICTest::Schema->connect();
162   is_deeply (
163     $s->storage->connect_info,
164     [],
165     'Starting with no explicitly passed in connect info'
166   . ($env_dsn ? ' (with DBI_DSN)' : ''),
167   );
168
169   my $sm = $s->storage->sql_maker;
170
171   ok (! $s->storage->connected, 'Storage does not appear connected after SQLMaker instance is taken');
172
173   if ($env_dsn) {
174     isa_ok($sm, 'DBIx::Class::SQLMaker');
175
176     ok ( $s->storage->_driver_determined, 'Driver determined (with DBI_DSN)');
177     isa_ok ( $s->storage, 'DBIx::Class::Storage::DBI::SQLite' );
178   }
179   else {
180     isa_ok($sm, 'DBIx::Class::SQLMaker');
181
182     ok (! $s->storage->_driver_determined, 'Driver undetermined');
183
184     throws_ok {
185       $s->storage->ensure_connected
186     } qr/You did not provide any connection_info/,
187     'sensible exception on empty conninfo connect';
188   }
189 }
190
191 done_testing;