Rewire OptDeps to not attempt any module loads under missing envvars
[dbsrgits/DBIx-Class.git] / xt / extra / internals / optional_deps.t
CommitLineData
c052f3dd 1my ($inc_before, $inc_after);
be68095d 2BEGIN {
c052f3dd 3 $inc_before = [ keys %INC ];
4 require DBIx::Class::Optional::Dependencies;
5 $inc_after = [ keys %INC ];
be68095d 6}
7
cb551b07 8use strict;
9use warnings;
10no warnings qw/once/;
11
c052f3dd 12use Test::More;
13use Test::Exception;
e3a7746c 14
15# load before we break require()
16use Scalar::Util();
17use MRO::Compat();
cb551b07 18use Carp 'confess';
d1f653cf 19use List::Util 'shuffle';
05c0614b 20
c052f3dd 21ok ( (! grep { $_ =~ m|DBIx/Class| } @$inc_before ), 'Nothing DBIC related was loaded before inc-test')
22 unless $ENV{PERL5OPT}; # a defined PERL5OPT may inject extra deps crashing this test
3c3e76bd 23
24is_deeply (
25 [ sort @$inc_after],
cb551b07 26 [ sort (@$inc_before, qw( DBIx/Class/Optional/Dependencies.pm if.pm )) ],
3c3e76bd 27 'Nothing loaded other than DBIx::Class::OptDeps',
cb551b07 28) unless $ENV{RELEASE_TESTING};
3c3e76bd 29
31c31b8d 30# check the project-local groups for sanity
31lives_ok {
32 DBIx::Class::Optional::Dependencies->req_group_list
33} "The entire optdep list is well formed";
34
05c0614b 35is_deeply (
31c31b8d 36 [ keys %{ DBIx::Class::Optional::Dependencies->req_list_for ('deploy') } ],
05c0614b 37 [ 'SQL::Translator' ],
38 'Correct deploy() dependency list',
39);
40
31c31b8d 41# scope to break require()
d8799bab 42{
31c31b8d 43
44# make module loading impossible, regardless of actual libpath contents
250d9e55 45 local @INC;
d8799bab 46
31c31b8d 47# basic test using the deploy target
48 for ('deploy', ['deploy']) {
49
50 # explicitly blow up cache
51 %DBIx::Class::Optional::Dependencies::req_unavailability_cache = ();
52
53 ok (
54 ! DBIx::Class::Optional::Dependencies->req_ok_for ($_),
55 'deploy() deps missing',
56 );
57
58 like (
e3a7746c 59 DBIx::Class::Optional::Dependencies->modreq_missing_for ($_),
60 qr/
61 \A
62 " SQL::Translator \~ \>\= [\d\.]+ "
63 \z
64 /x,
65 'expected modreq missing string contents',
66 );
67
68 like (
31c31b8d 69 DBIx::Class::Optional::Dependencies->req_missing_for ($_),
70 qr/
e3a7746c 71 \A
31c31b8d 72 " SQL::Translator \~ \>\= [\d\.]+ "
e3a7746c 73 \Q (see DBIx::Class::Optional::Dependencies documentation for details)\E
31c31b8d 74 \z
75 /x,
76 'expected missing string contents',
77 );
78
79 like (
5ffa39c7 80 DBIx::Class::Optional::Dependencies->modreq_errorlist_for ($_)->{'SQL::Translator'},
250d9e55 81 qr|\QCan't locate SQL/Translator.pm|,
82 'correct "unable to locate" exception found in errorlist',
31c31b8d 83 );
84
85 #make it so module appears loaded
86 local $INC{'SQL/Translator.pm'} = 1;
87 local $SQL::Translator::VERSION = 999;
88
89 ok (
90 ! DBIx::Class::Optional::Dependencies->req_ok_for ($_),
91 'deploy() deps missing cached properly from previous run',
92 );
93
94 # blow cache again
95 %DBIx::Class::Optional::Dependencies::req_unavailability_cache = ();
96
97 ok (
98 DBIx::Class::Optional::Dependencies->req_ok_for ($_),
99 'deploy() deps present',
100 );
101
102 is (
103 DBIx::Class::Optional::Dependencies->req_missing_for ($_),
104 '',
105 'expected null missing string',
106 );
107
108 is_deeply (
5ffa39c7 109 # use the deprecated method name
31c31b8d 110 DBIx::Class::Optional::Dependencies->req_errorlist_for ($_),
111 undef,
112 'expected empty errorlist',
113 );
114 }
115
e3a7746c 116# test single-db text
117 local $ENV{DBICTEST_MYSQL_DSN};
118 is_deeply(
119 DBIx::Class::Optional::Dependencies->req_list_for('test_rdbms_mysql'),
120 undef,
121 'unknown optional dependencies list for testing MySQL without ENV var',
122 );
31c31b8d 123 is_deeply(
e3a7746c 124 DBIx::Class::Optional::Dependencies->modreq_list_for('test_rdbms_mysql'),
125 { 'DBD::mysql' => 0 },
126 'correct optional module dependencies list for testing MySQL without ENV var',
127 );
128
129 local $ENV{DBICTEST_MYSQL_DSN};
130 local $ENV{DBICTEST_PG_DSN};
131
2baba3d9 132# regular
e3a7746c 133 is_deeply(
134 DBIx::Class::Optional::Dependencies->modreq_list_for('test_rdbms_pg'),
135 { 'DBD::Pg' => '2.009002' },
136 'optional dependencies list for testing Postgres without envvar',
137 );
138
139 is_deeply(
140 DBIx::Class::Optional::Dependencies->req_list_for('test_rdbms_pg'),
141 undef,
142 'optional dependencies list for testing Postgres without envvar',
d8799bab 143 );
144
31c31b8d 145 is_deeply(
146 DBIx::Class::Optional::Dependencies->req_list_for('rdbms_pg'),
147 { 'DBD::Pg' => '0', },
148 'optional dependencies list for using Postgres matches',
d8799bab 149 );
150
d1f653cf 151 is_deeply(
152 DBIx::Class::Optional::Dependencies->req_missing_for('rdbms_pg'),
153 'DBD::Pg (see DBIx::Class::Optional::Dependencies documentation for details)',
154 'optional dependencies missing list for using Postgres matches',
155 );
156
e3a7746c 157# test combination of different requirements on same module (pg's are relatively stable)
31c31b8d 158 is_deeply (
d1f653cf 159 DBIx::Class::Optional::Dependencies->req_list_for([shuffle qw( rdbms_pg test_rdbms_pg )]),
e3a7746c 160 { 'DBD::Pg' => '0' },
161 'optional module dependencies list for testing Postgres matches without envvar',
162 );
163
164 is(
165 DBIx::Class::Optional::Dependencies->req_missing_for([qw( rdbms_pg test_rdbms_pg )]),
166 '"DBD::Pg~>=2.009002" as well as the following group(s) of environment variables: DBICTEST_PG_DSN/..._USER/..._PASS',
167 'optional dependencies for testing Postgres without envvar'
168 );
169
170 is(
d1f653cf 171 DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( test_rdbms_mysql test_rdbms_pg )]),
e3a7746c 172 'DBD::mysql "DBD::Pg~>=2.009002" as well as the following group(s) of environment variables: DBICTEST_MYSQL_DSN/..._USER/..._PASS and DBICTEST_PG_DSN/..._USER/..._PASS',
173 'optional dependencies for testing Postgres+MySQL without envvars'
174 );
175
176 $ENV{DBICTEST_PG_DSN} = 'boo';
177 is_deeply (
d1f653cf 178 DBIx::Class::Optional::Dependencies->modreq_list_for([shuffle qw( rdbms_pg test_rdbms_pg )]),
31c31b8d 179 { 'DBD::Pg' => '2.009002' },
e3a7746c 180 'optional module dependencies list for testing Postgres matches with envvar',
d8799bab 181 );
05c0614b 182
31c31b8d 183 is(
d1f653cf 184 DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( rdbms_pg test_rdbms_pg )]),
31c31b8d 185 '"DBD::Pg~>=2.009002"',
e3a7746c 186 'optional dependencies error text for testing Postgres matches with evvar',
31c31b8d 187 );
05c0614b 188
2baba3d9 189# ICDT augmentation
190 my $mysql_icdt = [shuffle qw( test_rdbms_mysql icdt )];
191
192 is_deeply(
193 DBIx::Class::Optional::Dependencies->modreq_list_for($mysql_icdt),
194 {
195 'DateTime' => '0.55',
196 'DBD::mysql' => 0,
197 'DateTime::Format::MySQL' => 0,
198 },
199 'optional module dependencies list for testing ICDT MySQL without envvar',
200 );
201
202 is_deeply(
203 DBIx::Class::Optional::Dependencies->req_list_for($mysql_icdt),
204 {
205 'DateTime' => '0.55',
206 },
207 'optional dependencies list for testing ICDT MySQL without envvar',
208 );
209
210 is(
211 DBIx::Class::Optional::Dependencies->req_missing_for($mysql_icdt),
212 '"DateTime~>=0.55" DateTime::Format::MySQL DBD::mysql as well as the following group(s) of environment variables: DBICTEST_MYSQL_DSN/..._USER/..._PASS',
213 'missing optional dependencies for testing ICDT MySQL without envvars'
214 );
215
d1f653cf 216# test multi-level include with a variable and mandatory part converging on same included dep
217 local $ENV{DBICTEST_MSACCESS_ODBC_DSN};
218 local $ENV{DBICTEST_MSSQL_ODBC_DSN} = 'foo';
2baba3d9 219 my $msaccess_mssql_icdt = [ shuffle qw( test_rdbms_msaccess_odbc test_rdbms_mssql_odbc icdt ) ];
d1f653cf 220 is_deeply(
2baba3d9 221 DBIx::Class::Optional::Dependencies->req_missing_for($msaccess_mssql_icdt),
222 'Data::GUID "DateTime~>=0.55" "DateTime::Format::Strptime~>=1.2" DBD::ODBC as well as the following group(s) of environment variables: DBICTEST_MSACCESS_ODBC_DSN/..._USER/..._PASS',
d1f653cf 223 'Correct req_missing_for on multi-level converging include',
224 );
225
226 is_deeply(
2baba3d9 227 DBIx::Class::Optional::Dependencies->modreq_missing_for($msaccess_mssql_icdt),
228 'Data::GUID "DateTime~>=0.55" "DateTime::Format::Strptime~>=1.2" DBD::ODBC',
d1f653cf 229 'Correct modreq_missing_for on multi-level converging include',
230 );
231
232 is_deeply(
2baba3d9 233 DBIx::Class::Optional::Dependencies->req_list_for($msaccess_mssql_icdt),
d1f653cf 234 {
235 'DBD::ODBC' => 0,
2baba3d9 236 'DateTime' => '0.55',
237 'DateTime::Format::Strptime' => '1.2',
d1f653cf 238 },
239 'Correct req_list_for on multi-level converging include',
240 );
241
242 is_deeply(
2baba3d9 243 DBIx::Class::Optional::Dependencies->modreq_list_for($msaccess_mssql_icdt),
d1f653cf 244 {
245 'DBD::ODBC' => 0,
246 'Data::GUID' => 0,
2baba3d9 247 'DateTime' => '0.55',
248 'DateTime::Format::Strptime' => '1.2',
d1f653cf 249 },
250 'Correct modreq_list_for on multi-level converging include',
251 );
252
31c31b8d 253}
05c0614b 254
be68095d 255# test multiple times to find autovivification bugs
e3a7746c 256for my $meth (qw(req_list_for modreq_list_for)) {
be68095d 257 throws_ok {
e3a7746c 258 DBIx::Class::Optional::Dependencies->$meth();
be68095d 259 } qr/\Qreq_list_for() expects a requirement group name/,
e3a7746c 260 "$meth without groupname throws exception";
be68095d 261
262 throws_ok {
e3a7746c 263 DBIx::Class::Optional::Dependencies->$meth('');
264 } qr/\Q$meth() expects a requirement group name/,
265 "$meth with empty groupname throws exception";
be68095d 266
267 throws_ok {
e3a7746c 268 DBIx::Class::Optional::Dependencies->$meth('invalid_groupname');
31c31b8d 269 } qr/Requirement group 'invalid_groupname' is not defined/,
e3a7746c 270 "$meth with invalid groupname throws exception";
be68095d 271}
272
05c0614b 273done_testing;