a50fffc92d5e8e87e157539a76ecadb527c92a9a
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 23dumpmore.t
1 use strict;
2 use Test::More;
3 use lib qw(t/lib);
4 use File::Path;
5 use IPC::Open3;
6 use make_dbictest_db;
7 require DBIx::Class::Schema::Loader;
8
9 $^O eq 'MSWin32' && plan(skip_all =>
10 "ActiveState perl produces additional warnings, and this test uses unix paths"
11 );
12
13 my $DUMP_PATH = './t/_dump';
14
15 sub dump_directly {
16     my %tdata = @_;
17
18     my $schema_class = $tdata{classname};
19
20     no strict 'refs';
21     @{$schema_class . '::ISA'} = ('DBIx::Class::Schema::Loader');
22     $schema_class->loader_options(%{$tdata{options}});
23
24     my @warns;
25     eval {
26         local $SIG{__WARN__} = sub { push(@warns, @_) };
27         $schema_class->connect($make_dbictest_db::dsn);
28     };
29     my $err = $@;
30     $schema_class->storage->disconnect if !$err && $schema_class->storage;
31     undef *{$schema_class};
32
33     is($err, $tdata{error});
34
35     return @warns;
36 }
37
38 sub dump_dbicdump {
39     my %tdata = @_;
40
41     # use $^X so we execute ./script/dbicdump with the same perl binary that the tests were executed with
42     my @cmd = ($^X, qw(./script/dbicdump));
43
44     while (my ($opt, $val) = each(%{ $tdata{options} })) {
45         push @cmd, '-o', "$opt=$val";
46     }
47
48     push @cmd, $tdata{classname}, $make_dbictest_db::dsn;
49
50     # make sure our current @INC gets used by dbicdump
51     local $ENV{PERL5LIB} = join ":", @INC, $ENV{PERL5LIB};
52
53     my ($in, $out, $err);
54     my $pid = open3($in, $out, $err, @cmd);
55
56     my @warns = <$out>;
57     waitpid($pid, 0);
58
59     return @warns;
60 }
61
62 sub do_dump_test {
63     my %tdata = @_;
64     
65     $tdata{options}{dump_directory} = $DUMP_PATH;
66
67     for my $dumper (\&dump_directly, \&dump_dbicdump) {
68         test_dumps(\%tdata, $dumper->(%tdata));
69     }
70 }
71
72 sub test_dumps {
73     my ($tdata, @warns) = @_;
74
75     my %tdata = %{$tdata};
76
77     my $schema_class = $tdata{classname};
78     my $check_warns = $tdata{warnings};
79     is(@warns, @$check_warns, "$schema_class warning count");
80     for(my $i = 0; $i <= $#$check_warns; $i++) {
81         like($warns[$i], $check_warns->[$i], "$schema_class warning $i");
82     }
83
84     my $file_regexes = $tdata{regexes};
85     my $file_neg_regexes = $tdata{neg_regexes} || {};
86     my $schema_regexes = delete $file_regexes->{schema};
87     
88     my $schema_path = $DUMP_PATH . '/' . $schema_class;
89     $schema_path =~ s{::}{/}g;
90     dump_file_like($schema_path . '.pm', @$schema_regexes);
91     foreach my $src (keys %$file_regexes) {
92         my $src_file = $schema_path . '/' . $src . '.pm';
93         dump_file_like($src_file, @{$file_regexes->{$src}});
94     }
95     foreach my $src (keys %$file_neg_regexes) {
96         my $src_file = $schema_path . '/' . $src . '.pm';
97         dump_file_not_like($src_file, @{$file_neg_regexes->{$src}});
98     }
99 }
100
101 sub dump_file_like {
102     my $path = shift;
103     open(my $dumpfh, '<', $path) or die "Failed to open '$path': $!";
104     my $contents = do { local $/; <$dumpfh>; };
105     close($dumpfh);
106     my $num = 1;
107     like($contents, $_, "like $path " . $num++) for @_;
108 }
109
110 sub dump_file_not_like {
111     my $path = shift;
112     open(my $dumpfh, '<', $path) or die "Failed to open '$path': $!";
113     my $contents = do { local $/; <$dumpfh>; };
114     close($dumpfh);
115     my $num = 1;
116     unlike($contents, $_, "unlike $path ". $num++) for @_;
117 }
118
119 sub append_to_class {
120     my ($class, $string) = @_;
121     $class =~ s{::}{/}g;
122     $class = $DUMP_PATH . '/' . $class . '.pm';
123     open(my $appendfh, '>>', $class) or die "Failed to open '$class' for append: $!";
124     print $appendfh $string;
125     close($appendfh);
126 }
127
128 rmtree($DUMP_PATH, 1, 1);
129
130 do_dump_test(
131     classname => 'DBICTest::DumpMore::1',
132     options => { },
133     error => '',
134     warnings => [
135         qr/Dumping manual schema for DBICTest::DumpMore::1 to directory /,
136         qr/Schema dump completed/,
137     ],
138     regexes => {
139         schema => [
140             qr/package DBICTest::DumpMore::1;/,
141             qr/->load_classes/,
142         ],
143         Foo => [
144             qr/package DBICTest::DumpMore::1::Foo;/,
145             qr/=head1 NAME/,
146             qr/=head1 ACCESSORS/,
147             qr/->set_primary_key/,
148             qr/1;\n$/,
149         ],
150         Bar => [
151             qr/package DBICTest::DumpMore::1::Bar;/,
152             qr/=head1 NAME/,
153             qr/=head1 ACCESSORS/,
154             qr/->set_primary_key/,
155             qr/1;\n$/,
156         ],
157     },
158 );
159
160 append_to_class('DBICTest::DumpMore::1::Foo',q{# XXX This is my custom content XXX});
161
162 do_dump_test(
163     classname => 'DBICTest::DumpMore::1',
164     options => { },
165     error => '',
166     warnings => [
167         qr/Dumping manual schema for DBICTest::DumpMore::1 to directory /,
168         qr/Schema dump completed/,
169     ],
170     regexes => {
171         schema => [
172             qr/package DBICTest::DumpMore::1;/,
173             qr/->load_classes/,
174         ],
175         Foo => [
176             qr/package DBICTest::DumpMore::1::Foo;/,
177             qr/->set_primary_key/,
178             qr/1;\n# XXX This is my custom content XXX/,
179         ],
180         Bar => [
181             qr/package DBICTest::DumpMore::1::Bar;/,
182             qr/->set_primary_key/,
183             qr/1;\n$/,
184         ],
185     },
186 );
187
188 do_dump_test(
189     classname => 'DBICTest::DumpMore::1',
190     options => { really_erase_my_files => 1 },
191     error => '',
192     warnings => [
193         qr/Dumping manual schema for DBICTest::DumpMore::1 to directory /,
194         qr/Deleting existing file /,
195         qr/Deleting existing file /,
196         qr/Deleting existing file /,
197         qr/Schema dump completed/,
198     ],
199     regexes => {
200         schema => [
201             qr/package DBICTest::DumpMore::1;/,
202             qr/->load_classes/,
203         ],
204         Foo => [
205             qr/package DBICTest::DumpMore::1::Foo;/,
206             qr/->set_primary_key/,
207             qr/1;\n$/,
208         ],
209         Bar => [
210             qr/package DBICTest::DumpMore::1::Bar;/,
211             qr/->set_primary_key/,
212             qr/1;\n$/,
213         ],
214     },
215     neg_regexes => {
216         Foo => [
217             qr/# XXX This is my custom content XXX/,
218         ],
219     },
220 );
221
222 do_dump_test(
223     classname => 'DBICTest::DumpMore::1',
224     options => { use_namespaces => 1 },
225     error => '',
226     warnings => [
227         qr/Dumping manual schema for DBICTest::DumpMore::1 to directory /,
228         qr/Schema dump completed/,
229     ],
230     regexes => {
231         schema => [
232             qr/package DBICTest::DumpMore::1;/,
233             qr/->load_namespaces/,
234         ],
235         'Result/Foo' => [
236             qr/package DBICTest::DumpMore::1::Result::Foo;/,
237             qr/->set_primary_key/,
238             qr/1;\n$/,
239         ],
240         'Result/Bar' => [
241             qr/package DBICTest::DumpMore::1::Result::Bar;/,
242             qr/->set_primary_key/,
243             qr/1;\n$/,
244         ],
245     },
246 );
247
248 do_dump_test(
249     classname => 'DBICTest::DumpMore::1',
250     options => { use_namespaces => 1,
251                  result_namespace => 'Res',
252                  resultset_namespace => 'RSet',
253                  default_resultset_class => 'RSetBase',
254              },
255     error => '',
256     warnings => [
257         qr/Dumping manual schema for DBICTest::DumpMore::1 to directory /,
258         qr/Schema dump completed/,
259     ],
260     regexes => {
261         schema => [
262             qr/package DBICTest::DumpMore::1;/,
263             qr/->load_namespaces/,
264             qr/result_namespace => 'Res'/,
265             qr/resultset_namespace => 'RSet'/,
266             qr/default_resultset_class => 'RSetBase'/,
267         ],
268         'Res/Foo' => [
269             qr/package DBICTest::DumpMore::1::Res::Foo;/,
270             qr/->set_primary_key/,
271             qr/1;\n$/,
272         ],
273         'Res/Bar' => [
274             qr/package DBICTest::DumpMore::1::Res::Bar;/,
275             qr/->set_primary_key/,
276             qr/1;\n$/,
277         ],
278     },
279 );
280
281 do_dump_test(
282     classname => 'DBICTest::DumpMore::1',
283     options => { use_namespaces => 1,
284                  result_namespace => '+DBICTest::DumpMore::1::Res',
285                  resultset_namespace => 'RSet',
286                  default_resultset_class => 'RSetBase',
287                  result_base_class => 'My::ResultBaseClass',
288                  schema_base_class => 'My::SchemaBaseClass',
289              },
290     error => '',
291     warnings => [
292         qr/Dumping manual schema for DBICTest::DumpMore::1 to directory /,
293         qr/Schema dump completed/,
294     ],
295     regexes => {
296         schema => [
297             qr/package DBICTest::DumpMore::1;/,
298             qr/->load_namespaces/,
299             qr/result_namespace => '\+DBICTest::DumpMore::1::Res'/,
300             qr/resultset_namespace => 'RSet'/,
301             qr/default_resultset_class => 'RSetBase'/,
302             qr/use base 'My::SchemaBaseClass'/,
303         ],
304         'Res/Foo' => [
305             qr/package DBICTest::DumpMore::1::Res::Foo;/,
306             qr/use base 'My::ResultBaseClass'/,
307             qr/->set_primary_key/,
308             qr/1;\n$/,
309         ],
310         'Res/Bar' => [
311             qr/package DBICTest::DumpMore::1::Res::Bar;/,
312             qr/use base 'My::ResultBaseClass'/,
313             qr/->set_primary_key/,
314             qr/1;\n$/,
315         ],
316     },
317 );
318
319 done_testing;
320
321 END { rmtree($DUMP_PATH, 1, 1); }