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