]> git.donarmstrong.com Git - debbugs.git/blob - t/lib/DebbugsTest.pm
use Test::PostgreSQL to test whether the postgresql database works at all
[debbugs.git] / t / lib / DebbugsTest.pm
1
2 package DebbugsTest;
3
4 =head1 NAME
5
6 DebbugsTest
7
8 =head1 SYNOPSIS
9
10 use DebbugsTest
11
12
13 =head1 DESCRIPTION
14
15 This module contains various testing routines used to test debbugs in
16 a "pseudo install"
17
18 =head1 FUNCTIONS
19
20 =cut
21
22 use warnings;
23 use strict;
24 use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
25 use base qw(Exporter);
26
27 use IO::File;
28 use File::Temp qw(tempdir);
29 use Cwd qw(getcwd);
30 use Debbugs::MIME qw(create_mime_message);
31 use File::Basename qw(dirname basename);
32 use IPC::Open3;
33 use IO::Handle;
34 use Test::More;
35 use Test::PostgreSQL;
36
37 use Params::Validate qw(validate_with :types);
38
39 BEGIN{
40      $VERSION = 1.00;
41      $DEBUG = 0 unless defined $DEBUG;
42
43      @EXPORT = ();
44      %EXPORT_TAGS = (configuration => [qw(dirsize create_debbugs_configuration send_message)],
45                      mail          => [qw(num_messages_sent)],
46                      database => [qw(create_postgresql_database update_postgresql_database)]
47                     );
48      @EXPORT_OK = ();
49      Exporter::export_ok_tags(keys %EXPORT_TAGS);
50      $EXPORT_TAGS{all} = [@EXPORT_OK];
51 }
52
53 # First, we're going to send mesages to receive.
54 # To do so, we'll first send a message to submit,
55 # then send messages to the newly created bugnumber.
56
57
58
59 sub create_debbugs_configuration {
60      my %param = validate_with(params => \@_,
61                                spec   => {debug => {type => BOOLEAN,
62                                                     default => exists $ENV{DEBUG}?
63                                                     $ENV{DEBUG}:0,
64                                                    },
65                                           cleanup => {type => BOOLEAN,
66                                                       optional => 1,
67                                                      },
68                                          },
69                               );
70      $param{cleanup} = $param{debug}?0:1 if not exists $param{cleanup};
71      my $sendmail_dir = tempdir(CLEANUP => $param{cleanup});
72      my $spool_dir = tempdir(CLEANUP => $param{cleanup});
73      my $config_dir = tempdir(CLEANUP => $param{cleanup});
74
75
76      $ENV{DEBBUGS_CONFIG_FILE}  ="$config_dir/debbugs_config";
77      $ENV{PERL5LIB} = getcwd();
78      $ENV{SENDMAIL_TESTDIR} = $sendmail_dir;
79      eval {
80      my $sendmail_tester = getcwd().'/t/sendmail_tester';
81      unless (-x $sendmail_tester) {
82           die q(t/sendmail_tester doesn't exist or isn't executable. You may be in the wrong directory.);
83      }
84      my %files_to_create = ("$config_dir/debbugs_config" => <<END,
85 \$gSendmail='$sendmail_tester';
86 \$gSpoolDir='$spool_dir';
87 \$gLibPath='@{[getcwd()]}/scripts';
88 \$gTemplateDir='@{[getcwd()]}/templates';
89 \$gWebDir='@{[getcwd()]}/html';
90 \$gWebHost='localhost';
91 1;
92 END
93                             "$spool_dir/nextnumber" => qq(1\n),
94                             "$config_dir/Maintainers" => qq(foo Blah Bleargh <foo\@baz.com>\nbar Bar Bleargh <bar\@baz.com>\n),
95                             "$config_dir/Maintainers.override" => qq(),
96                             "$config_dir/Source_maintainers" => qq(foo Blah Bleargh <foo\@baz.com>\nbar Bar Bleargh <bar\@baz.com>\n),
97                             "$config_dir/indices/sources" => <<END,
98 foo main foo
99 END
100                             "$config_dir/pseudo-packages.description" => '',
101                             "$config_dir/pseudo-packages.maintainers" => '',
102                            );
103      while (my ($file,$contents) = each %files_to_create) {
104           system('mkdir','-p',dirname($file));
105           my $fh = IO::File->new($file,'w') or
106                die "Unable to create $file: $!";
107           print {$fh} $contents or die "Unable to write $contents to $file: $!";
108           close $fh or die "Unable to close $file: $!";
109      }
110
111      system('touch',"$spool_dir/index.db.realtime");
112      system('ln','-s','index.db.realtime',
113             "$spool_dir/index.db");
114      system('touch',"$spool_dir/index.archive.realtime");
115      system('ln','-s','index.archive.realtime',
116             "$spool_dir/index.archive");
117
118      # create the spool files and sub directories
119      for my $dir (0..99) {
120          for my $archive (qw(db-h archive)) {
121              system('mkdir','-p',"$spool_dir/$archive/".sprintf('%02d',$dir));
122          }
123      }
124      system('mkdir','-p',"$spool_dir/incoming");
125      system('mkdir','-p',"$spool_dir/lock");
126      eval '
127 END{
128      if ($ENV{DEBUG}) {
129           diag("spool_dir:   $spool_dir\n");
130           diag("config_dir:   $config_dir\n",);
131           diag("sendmail_dir: $sendmail_dir\n");
132      }
133 }';
134
135      };
136      BAIL_OUT ($@) if ($@);
137      return (spool_dir => $spool_dir,
138              sendmail_dir => $sendmail_dir,
139              config_dir => $config_dir,
140             );
141 }
142
143 sub dirsize{
144      my ($dir) = @_;
145      opendir(DIR,$dir);
146      my @content = grep {!/^\.\.?$/} readdir(DIR);
147      closedir(DIR);
148      return scalar @content;
149 }
150
151
152 # We're going to use create mime message to create these messages, and
153 # then just send them to receive.
154 # First, check that submit@ works
155
156 sub send_message{
157      my %param = validate_with(params => \@_,
158                                spec   => {to => {type => SCALAR,
159                                                  default => 'submit@bugs.something',
160                                                 },
161                                           headers => {type => ARRAYREF,
162                                                      },
163                                           body    => {type => SCALAR,
164                                                      },
165                                           attachments => {type => ARRAYREF,
166                                                           default => [],
167                                                          },
168                                           run_processall =>{type => BOOLEAN,
169                                                             default => 1,
170                                                            },
171                                          }
172                               );
173      $ENV{LOCAL_PART} = $param{to};
174      my ($rfd,$wfd);
175      my $output='';
176      my $pipe_handler = $SIG{PIPE};
177      $SIG{PIPE} = 'IGNORE';
178      $SIG{CHLD} = 'DEFAULT';
179      my $pid = open3($wfd,$rfd,$rfd,'scripts/receive')
180           or die "Unable to start receive: $!";
181      print {$wfd} create_mime_message($param{headers},
182                                       $param{body},
183                                       $param{attachments}) or
184                                           die "Unable to to print to receive";
185      close($wfd) or die "Unable to close receive";
186      $SIG{PIPE} = $pipe_handler;
187      my $err = $? >> 8;
188      my $childpid = waitpid($pid,0);
189      if ($childpid != -1) {
190           $err = $? >> 8;
191           print STDERR "receive pid: $pid doesn't match childpid: $childpid\n" if $childpid != $pid;
192      }
193      if ($err != 0 ) {
194           my $rfh =  IO::Handle->new_from_fd($rfd,'r') or die "Unable to create filehandle: $!";
195           $rfh->blocking(0);
196           my $rv;
197           while ($rv = $rfh->sysread($output,1000,length($output))) {}
198           if (not defined $rv) {
199                print STDERR "Reading from STDOUT/STDERR would have blocked.";
200           }
201           print STDERR $output,qq(\n);
202           die "receive failed with exit status $err";
203      }
204      # now we should run processall to see if the message gets processed
205      if ($param{run_processall}) {
206           system('scripts/processall') == 0 or die "processall failed";
207      }
208 }
209
210 $SIG{CHLD} = sub {};
211
212 {
213      package DebbugsTest::HTTPServer;
214      use base qw(HTTP::Server::Simple::CGI HTTP::Server::Simple::CGI::Environment);
215
216      our $child_pid = undef;
217      our $webserver = undef;
218      our $server_handler = undef;
219
220      END {
221           if (defined $child_pid) {
222                # stop the child
223                my $temp_exit = $?;
224                kill(15,$child_pid);
225                waitpid(-1,0);
226                $? = $temp_exit;
227           }
228      }
229
230      sub fork_and_create_webserver {
231           my ($handler,$port) = @_;
232           $port ||= 8080;
233           if (defined $child_pid) {
234                die "We appear to have already forked once";
235           }
236           $server_handler = $handler;
237           my $pid = fork;
238           return 0 if not defined $pid;
239           if ($pid) {
240                $child_pid = $pid;
241                # Wait here for a second to let the child start up
242                sleep 1;
243                return $pid;
244           }
245           else {
246                $webserver = DebbugsTest::HTTPServer->new($port);
247                $webserver->run;
248           }
249
250      }
251
252      sub handle_request {
253           if (defined $server_handler) {
254                $server_handler->(@_);
255           }
256           else {
257                warn "No handler defined\n";
258                print "No handler defined\n";
259           }
260      }
261 }
262
263 =head2 num_messages_sent
264
265      $SD_SIZE = num_messages_sent($SD_SIZE,2,$sendmail_dir,'2 messages have been sent properly');
266
267 Tests to make sure that at least a certain number of messages have
268 been sent since the last time this command was run. Usefull to test to
269 make sure that mail has been sent.
270
271 =cut
272
273 sub num_messages_sent {
274     my ($prev_size,$num_messages,$sendmail_dir,$test_name) = @_;
275     my $cur_size = dirsize($sendmail_dir);
276     ## print STDERR "sendmail: $sendmail_dir, want: $num_messages,
277     ## size: $cur_size, prev_size: $prev_size\n";
278     ok($cur_size-$prev_size >= $num_messages, $test_name);
279     return $cur_size;
280 }
281
282 =head2 create_postgresql_database
283
284 C<my $pgsql = create_postgresql_database();>
285
286 Create a postgresql database for testing; when the L<Test::PostgreSQL> object it
287 returns is destroyed (or goes out of scope) the database will be removed.
288
289 =cut
290
291 sub create_postgresql_database {
292     my $pgsql = Test::PostgreSQL->new(use_socket => 1) or
293         return undef;
294     my $installsql =
295         File::Spec->rel2abs(dirname(__FILE__).'/../..').
296             '/bin/debbugs-installsql';
297     # create the debversion extension
298     print STDERR $pgsql->dsn;
299     print STDERR "\n";
300     my $dbh = DBI->connect($pgsql->dsn);
301     $dbh->do(<<END) or die "Unable to create extension";
302 CREATE EXTENSION IF NOT EXISTS debversion;
303 END
304     # create the schema for the bug tracking system
305     my $dep_dir = File::Temp::tempdir(CLEANUP=>1);
306     system($installsql,
307            '--dsn',$pgsql->dsn,
308            '--install',
309            '--deployment-dir',$dep_dir);
310
311     initialize_postgresql_database($pgsql,@_);
312     return $pgsql;
313 }
314
315 =item iniitalize_postgresql_database
316
317 C<initialize_postgresql_database();>
318
319 Initialize postgresql database by calling debbugs-loadsql appropriately.
320
321 =cut
322
323 sub initialize_postgresql_database {
324     my ($pgsql,@options) = @_;
325     my $loadsql =
326         File::Spec->rel2abs(dirname(__FILE__).'/../..').
327             '/bin/debbugs-loadsql';
328
329     my $ftpdists =
330         File::Spec->rel2abs(dirname(__FILE__).'/../debian/dist');
331     my $debinfo_dir =
332         File::Spec->rel2abs(dirname(__FILE__).'/../debian/debinfo');
333     my %loadsql_commands =
334         (configuration => [],
335          suites => ['--ftpdists',$ftpdists],
336          debinfo => ['--debinfo-dir',$debinfo_dir],
337          packages => ['--ftpdists',$ftpdists],
338          maintainers => [],
339         );
340     for my $command (keys %loadsql_commands) {
341         system($loadsql,$command,
342                '--dsn',$pgsql->dsn,
343                @options,
344                @{$loadsql_commands{$command}}) == 0 or
345                    die "Unable to load $command";
346     }
347 }
348
349
350 =item update_postgresql_database
351
352 C<update_postgresql_database();>
353
354 Update the postgresql database by calling debbugs-loadsql appropriately.
355
356 =cut
357 sub update_postgresql_database {
358     my ($pgsql,@options) = @_;
359     my $loadsql =
360         File::Spec->rel2abs(dirname(__FILE__).'/../..').
361             '/bin/debbugs-loadsql';
362
363     my %loadsql_commands =
364         (bugs_and_logs => [],
365         );
366     for my $command (keys %loadsql_commands) {
367         system($loadsql,$command,
368                '--dsn',$pgsql->dsn,
369                @options,
370                @{$loadsql_commands{$command}}) == 0 or
371                    die "Unable to load $command";
372     }
373 }
374
375
376
377 1;
378
379 __END__
380
381
382