Make OptDeps aware of envvars as first-class requirements (test_* groups only)
[dbsrgits/DBIx-Class.git] / xt / optional_deps.t
1 use strict;
2 use warnings;
3 no warnings qw/once/;
4
5 my ($inc_before, $inc_after);
6 BEGIN {
7   require Carp;   # Carp is not used in the test, but in OptDeps, load for proper %INC comparison
8
9   $inc_before = [ keys %INC ];
10   require DBIx::Class::Optional::Dependencies;
11   $inc_after = [ keys %INC ];
12 }
13
14 use Test::More;
15 use Test::Exception;
16
17 # load before we break require()
18 use Scalar::Util();
19 use MRO::Compat();
20
21 ok ( (! 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
23
24 is_deeply (
25   [ sort @$inc_after],
26   [ sort (@$inc_before, 'DBIx/Class/Optional/Dependencies.pm') ],
27   'Nothing loaded other than DBIx::Class::OptDeps',
28 );
29
30
31 # check the project-local groups for sanity
32 lives_ok {
33   DBIx::Class::Optional::Dependencies->req_group_list
34 } "The entire optdep list is well formed";
35
36 is_deeply (
37   [ keys %{ DBIx::Class::Optional::Dependencies->req_list_for ('deploy') } ],
38   [ 'SQL::Translator' ],
39   'Correct deploy() dependency list',
40 );
41
42 # scope to break require()
43 {
44
45 # make module loading impossible, regardless of actual libpath contents
46   local @INC = (sub { Carp::confess('Optional Dep Test') } );
47
48 # basic test using the deploy target
49   for ('deploy', ['deploy']) {
50
51     # explicitly blow up cache
52     %DBIx::Class::Optional::Dependencies::req_unavailability_cache = ();
53
54     ok (
55       ! DBIx::Class::Optional::Dependencies->req_ok_for ($_),
56       'deploy() deps missing',
57     );
58
59     like (
60       DBIx::Class::Optional::Dependencies->modreq_missing_for ($_),
61       qr/
62         \A
63         " SQL::Translator \~ \>\= [\d\.]+ "
64         \z
65       /x,
66       'expected modreq missing string contents',
67     );
68
69     like (
70       DBIx::Class::Optional::Dependencies->req_missing_for ($_),
71       qr/
72         \A
73         " SQL::Translator \~ \>\= [\d\.]+ "
74         \Q (see DBIx::Class::Optional::Dependencies documentation for details)\E
75         \z
76       /x,
77       'expected missing string contents',
78     );
79
80     like (
81       DBIx::Class::Optional::Dependencies->modreq_errorlist_for ($_)->{'SQL::Translator'},
82       qr/Optional Dep Test/,
83       'custom exception found in errorlist',
84     );
85
86     #make it so module appears loaded
87     local $INC{'SQL/Translator.pm'} = 1;
88     local $SQL::Translator::VERSION = 999;
89
90     ok (
91       ! DBIx::Class::Optional::Dependencies->req_ok_for ($_),
92       'deploy() deps missing cached properly from previous run',
93     );
94
95     # blow cache again
96     %DBIx::Class::Optional::Dependencies::req_unavailability_cache = ();
97
98     ok (
99       DBIx::Class::Optional::Dependencies->req_ok_for ($_),
100       'deploy() deps present',
101     );
102
103     is (
104       DBIx::Class::Optional::Dependencies->req_missing_for ($_),
105       '',
106       'expected null missing string',
107     );
108
109     is_deeply (
110       # use the deprecated method name
111       DBIx::Class::Optional::Dependencies->req_errorlist_for ($_),
112       undef,
113       'expected empty errorlist',
114     );
115   }
116
117 # test single-db text
118   local $ENV{DBICTEST_MYSQL_DSN};
119   is_deeply(
120     DBIx::Class::Optional::Dependencies->req_list_for('test_rdbms_mysql'),
121     undef,
122     'unknown optional dependencies list for testing MySQL without ENV var',
123   );
124   is_deeply(
125     DBIx::Class::Optional::Dependencies->modreq_list_for('test_rdbms_mysql'),
126     { 'DBD::mysql' => 0 },
127     'correct optional module dependencies list for testing MySQL without ENV var',
128   );
129
130   local $ENV{DBICTEST_MYSQL_DSN};
131   local $ENV{DBICTEST_PG_DSN};
132
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',
143   );
144
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',
149   );
150
151 # test combination of different requirements on same module (pg's are relatively stable)
152   is_deeply (
153     DBIx::Class::Optional::Dependencies->req_list_for([qw( rdbms_pg test_rdbms_pg )]),
154     { 'DBD::Pg' => '0' },
155     'optional module dependencies list for testing Postgres matches without envvar',
156   );
157
158   is(
159     DBIx::Class::Optional::Dependencies->req_missing_for([qw( rdbms_pg test_rdbms_pg )]),
160     '"DBD::Pg~>=2.009002" as well as the following group(s) of environment variables: DBICTEST_PG_DSN/..._USER/..._PASS',
161     'optional dependencies for testing Postgres without envvar'
162   );
163
164   is(
165     DBIx::Class::Optional::Dependencies->req_missing_for([qw( test_rdbms_mysql test_rdbms_pg )]),
166     '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',
167     'optional dependencies for testing Postgres+MySQL without envvars'
168   );
169
170   $ENV{DBICTEST_PG_DSN} = 'boo';
171   is_deeply (
172     DBIx::Class::Optional::Dependencies->modreq_list_for([qw( rdbms_pg test_rdbms_pg )]),
173     { 'DBD::Pg' => '2.009002' },
174     'optional module dependencies list for testing Postgres matches with envvar',
175   );
176
177   is(
178     DBIx::Class::Optional::Dependencies->req_missing_for([qw( rdbms_pg test_rdbms_pg )]),
179     '"DBD::Pg~>=2.009002"',
180     'optional dependencies error text for testing Postgres matches with evvar',
181   );
182
183 }
184
185 # test multiple times to find autovivification bugs
186 for my $meth (qw(req_list_for modreq_list_for)) {
187   throws_ok {
188     DBIx::Class::Optional::Dependencies->$meth();
189   } qr/\Qreq_list_for() expects a requirement group name/,
190   "$meth without groupname throws exception";
191
192   throws_ok {
193     DBIx::Class::Optional::Dependencies->$meth('');
194   } qr/\Q$meth() expects a requirement group name/,
195   "$meth with empty groupname throws exception";
196
197   throws_ok {
198     DBIx::Class::Optional::Dependencies->$meth('invalid_groupname');
199   } qr/Requirement group 'invalid_groupname' is not defined/,
200   "$meth with invalid groupname throws exception";
201 }
202
203 done_testing;