Institute a central "load this first in testing" package
[dbsrgits/DBIx-Class-Historic.git] / t / lib / DBICTest / RunMode.pm
CommitLineData
4bea1fe7 1package # hide from PAUSE
39c9c72d 2 DBICTest::RunMode;
ab340f7f 3
4use strict;
5use warnings;
6
7use Path::Class qw/file dir/;
fa19e5d6 8use Fcntl ':DEFAULT';
9use File::Spec ();
10use File::Temp ();
e3be2b6f 11use DBICTest::Util qw( local_umask find_co_root );
12
13# Try to determine the root of a checkout/untar if possible
14# return a Path::Class::Dir object or undef
15sub _find_co_root { eval { dir( find_co_root() ) } }
ab340f7f 16
17_check_author_makefile() unless $ENV{DBICTEST_NO_MAKEFILE_VERIFICATION};
18
9b871b00 19# PathTools has a bug where on MSWin32 it will often return / as a tmpdir.
20# This is *really* stupid and the result of having our lockfiles all over
21# the place is also rather obnoxious. So we use our own heuristics instead
22# https://rt.cpan.org/Ticket/Display.html?id=76663
23my $tmpdir;
24sub tmpdir {
85143769 25 dir ($tmpdir ||= do {
9b871b00 26
fa19e5d6 27 # works but not always
9b871b00 28 my $dir = dir(File::Spec->tmpdir);
fa19e5d6 29 my $reason_dir_unusable;
9b871b00 30
31 my @parts = File::Spec->splitdir($dir);
6bbdf31d 32 if (@parts == 2 and $parts[1] =~ /^ [\/\\]? $/x ) {
fa19e5d6 33 $reason_dir_unusable =
34 'File::Spec->tmpdir returned a root directory instead of a designated '
35 . 'tempdir (possibly https://rt.cpan.org/Ticket/Display.html?id=76663)';
36 }
37 else {
38 # make sure we can actually create and sysopen a file in this dir
39 local $@;
0a03f539 40 my $u = local_umask(0); # match the umask we use in DBICTest(::Schema)
3ba92e4a 41 my $tempfile = '<NONCREATABLE>';
fa19e5d6 42 eval {
3ba92e4a 43 $tempfile = File::Temp->new(
44 TEMPLATE => '_dbictest_writability_test_XXXXXX',
fa19e5d6 45 DIR => "$dir",
46 UNLINK => 1,
47 );
3ba92e4a 48 close $tempfile or die "closing $tempfile failed: $!\n";
49
50 sysopen (my $tempfh2, "$tempfile", O_RDWR) or die "reopening $tempfile failed: $!\n";
51 print $tempfh2 'deadbeef' x 1024 or die "printing to $tempfile failed: $!\n";
52 close $tempfh2 or die "closing $tempfile failed: $!\n";
fa19e5d6 53 1;
54 } or do {
55 chomp( my $err = $@ );
3ba92e4a 56 my @x_tests = map { (defined $_) ? ( $_ ? 1 : 0 ) : 'U' } map {(-e, -d, -f, -r, -w, -x, -o)} ("$dir", "$tempfile");
0a03f539 57 $reason_dir_unusable = sprintf <<"EOE", "$tempfile"||'', $err, scalar $>, scalar $), umask(), (stat($dir))[4,5,2], @x_tests;
fa19e5d6 58File::Spec->tmpdir returned a directory which appears to be non-writeable:
59Error encountered while testing '%s': %s
60Process EUID/EGID: %s / %s
0a03f539 61Effective umask: %o
fa19e5d6 62TmpDir UID/GID: %s / %s
63TmpDir StatMode: %o
64TmpDir X-tests: -e:%s -d:%s -f:%s -r:%s -w:%s -x:%s -o:%s
65TmpFile X-tests: -e:%s -d:%s -f:%s -r:%s -w:%s -x:%s -o:%s
66EOE
67 };
68 }
69
70 if ($reason_dir_unusable) {
9b871b00 71 # Replace with our local project tmpdir. This will make multiple runs
72 # from different runs conflict with each other, but is much better than
fa19e5d6 73 # polluting the root dir with random crap or failing outright
74 my $local_dir = _find_co_root()->subdir('t')->subdir('var');
75 $local_dir->mkpath;
76
77 warn "\n\nUsing '$local_dir' as test scratch-dir instead of '$dir': $reason_dir_unusable\n";
78 $dir = $local_dir;
9b871b00 79 }
80
85143769 81 $dir->stringify;
82 });
9b871b00 83}
84
85
ab340f7f 86# Die if the author did not update his makefile
87#
88# This is pretty heavy handed, so the check is pretty solid:
89#
90# 1) Assume that this particular module is loaded from -I <$root>/t/lib
91# 2) Make sure <$root>/Makefile.PL exists
92# 3) Make sure we can stat() <$root>/Makefile.PL
93#
94# If all of the above is satisfied
95#
96# *) die if <$root>/inc does not exist
97# *) die if no stat() results for <$root>/Makefile (covers no Makefile)
98# *) die if Makefile.PL mtime > Makefile mtime
99#
100sub _check_author_makefile {
101
102 my $root = _find_co_root()
103 or return;
104
7159a456 105 my $optdeps = file('lib/DBIx/Class/Optional/Dependencies.pm');
106
ab340f7f 107 # not using file->stat as it invokes File::stat which in turn breaks stat(_)
7159a456 108 my ($mf_pl_mtime, $mf_mtime, $optdeps_mtime) = ( map
50360f3e 109 { (stat ($root->file ($_)) )[9] || undef } # stat returns () on nonexistent files
7159a456 110 (qw|Makefile.PL Makefile|, $optdeps)
ab340f7f 111 );
112
113 return unless $mf_pl_mtime; # something went wrong during co_root detection ?
114
7159a456 115 my @fail_reasons;
ab340f7f 116
7159a456 117 if(not -d $root->subdir ('inc')) {
118 push @fail_reasons, "Missing ./inc directory";
119 }
ab340f7f 120
a256e995 121 if(not $mf_mtime) {
7159a456 122 push @fail_reasons, "Missing ./Makefile";
123 }
a256e995 124 else {
125 if($mf_mtime < $mf_pl_mtime) {
126 push @fail_reasons, "./Makefile.PL is newer than ./Makefile";
127 }
128 if($mf_mtime < $optdeps_mtime) {
129 push @fail_reasons, "./$optdeps is newer than ./Makefile";
130 }
7159a456 131 }
132
133 if (@fail_reasons) {
134 print STDERR <<'EOE';
ab340f7f 135
ab340f7f 136!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
137======================== FATAL ERROR ===========================
138!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
139
140We have a number of reasons to believe that this is a development
141checkout and that you, the user, did not run `perl Makefile.PL`
142before using this code. You absolutely _must_ perform this step,
0424d17a 143to ensure you have all required dependencies present. Not doing
dc4600b2 144so often results in a lot of wasted time for other contributors
23b2c49b 145trying to assist you with spurious "its broken!" problems.
ab340f7f 146
6e22e629 147By default DBICs Makefile.PL turns all optional dependencies into
0424d17a 148*HARD REQUIREMENTS*, in order to make sure that the entire test
149suite is executed, and no tests are skipped due to missing modules.
150If you for some reason need to disable this behavior - supply the
151--skip_author_deps option when running perl Makefile.PL
152
ab340f7f 153If you are seeing this message unexpectedly (i.e. you are in fact
dc4600b2 154attempting a regular installation be it through CPAN or manually),
155please report the situation to either the mailing list or to the
156irc channel as described in
ab340f7f 157
158http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class.pm#GETTING_HELP/SUPPORT
159
ab340f7f 160The DBIC team
161
162
7159a456 163Reasons you received this message:
ab340f7f 164
165EOE
166
7159a456 167 foreach my $r (@fail_reasons) {
168 print STDERR " * $r\n";
169 }
170 print STDERR "\n\n\n";
171
1439bf15 172 require Time::HiRes;
173 Time::HiRes::sleep(0.005);
174 print STDOUT "\nBail out!\n";
ab340f7f 175 exit 1;
176 }
177}
178
dc4600b2 179# Mimic $Module::Install::AUTHOR
180sub is_author {
181
182 my $root = _find_co_root()
183 or return undef;
184
185 return (
186 ( not -d $root->subdir ('inc') )
187 or
39c9c72d 188 ( -e $root->subdir ('inc')->subdir ($^O eq 'VMS' ? '_author' : '.author') )
dc4600b2 189 );
190}
191
39c9c72d 192sub is_smoker {
6853e2c3 193 return (
1a08c5ed 194 ( $ENV{AUTOMATED_TESTING} && ! $ENV{PERL5_CPANM_IS_RUNNING} && ! $ENV{RELEASE_TESTING} )
6853e2c3 195 or
196 __PACKAGE__->is_ci
197 );
39c9c72d 198}
199
81b29c8d 200sub is_ci {
201 return (
202 ($ENV{TRAVIS}||'') eq 'true'
203 and
1ab8de44 204 ($ENV{TRAVIS_REPO_SLUG}||'') =~ m|\w+/dbix-class$|
81b29c8d 205 )
206}
207
39c9c72d 208sub is_plain {
6853e2c3 209 return (
210 ! $ENV{RELEASE_TESTING}
211 and
212 ! $ENV{DBICTEST_RUN_ALL_TESTS}
213 and
214 ! __PACKAGE__->is_smoker
215 and
216 ! __PACKAGE__->is_author
217 )
39c9c72d 218}
219
ab340f7f 2201;