remove File::Slurp as we don't need it
[gitmo/MooseX-Daemonize.git] / lib / Test / MooseX / Daemonize.pm
1 use strict;
2
3 package Test::MooseX::Daemonize;
4 use Proc::Daemon;
5
6 # BEGIN CARGO CULTING
7 use Sub::Exporter;
8 use Test::Builder;
9 our $VERSION   = '0.02';
10 our $AUTHORITY = 'cpan:PERIGRIN';
11
12 {
13     my @exports = qw[
14       daemonize_ok
15       check_test_output
16     ];
17
18     Sub::Exporter::setup_exporter(
19         {
20             exports => \@exports,
21             groups  => { default => \@exports }
22         }
23     );
24 }
25
26 our $Test = Test::Builder->new;
27
28 sub daemonize_ok {
29     my ( $daemon, $msg ) = @_;
30     unless ( my $pid = Proc::Daemon::Fork ) {
31         $daemon->start();
32         exit;
33     }
34     else {
35         sleep(1);    # Punt on sleep time, 1 seconds should be enough
36         $Test->ok( -e $daemon->pidfile->file, $msg )
37           || $Test->diag(
38             'Pidfile (' . $daemon->pidfile->file . ') not found.' );
39     }
40 }
41
42 sub check_test_output {
43     my ($app) = @_;
44     open( my $stdout_in, '<', $app->test_output )
45       or die "can't open test output: $!";
46     while ( my $line = <$stdout_in> ) {
47         $line =~ s/\s+\z//;
48         my $label;
49         if ( $line =~ /\A((not\s+)?ok)(?:\s+-)(?:\s+(.*))\z/ ) {
50             my ( $status, $not, $text ) = ( $1, $2, $3 );
51             $text ||= '';
52
53            # We don't just call ok(!$not), because that generates diagnostics of
54            # its own for failures. We only want the diagnostics from the child.
55             my $num = $Test->current_test;
56             $Test->current_test( ++$num );
57             $Test->_print("$status $num - $text\n");
58         }
59         elsif ( $line =~ s/\A#\s?// ) {
60             $Test->diag($line);
61         }
62         else {
63             $Test->_print_diag("$label: $line (unrecognised)\n");
64         }
65     }
66 }
67
68 package Test::MooseX::Daemonize::Testable;
69 use Moose::Role;
70
71 has test_output => (
72     isa      => 'Str',
73     is       => 'ro',
74     required => 1,
75 );
76
77 after daemonize => sub {
78     $Test->use_numbers(0);
79     $Test->no_ending(1);
80     open my $out, '>', $_[0]->test_output or die "Cannot open test output: $!";
81     my $fileno = fileno $out;
82     open STDERR, ">&=", $fileno
83       or die "Can't redirect STDERR";
84
85     open STDOUT, ">&=", $fileno
86       or die "Can't redirect STDOUT";
87
88     $Test->output($out);
89     $Test->failure_output($out);
90     $Test->todo_output($out);
91 };
92
93 1;
94 __END__
95
96
97 =head1 NAME
98
99 Test::MooseX::Daemonize - provides a Role that daemonizes your Moose based application.
100
101
102 =head1 VERSION
103
104 This document describes MooseX::Daemonize version 0.0.1
105
106
107 =head1 SYNOPSIS
108     
109     package main;
110     use Cwd;
111
112     ## Try to make sure we are in the test directory
113     chdir 't' if ( Cwd::cwd() !~ m|/t$| );
114     my $cwd = Cwd::cwd();
115
116     my $file = join( '/', $cwd, 'im_alive' );
117     my $daemon = FileMaker->new( pidbase => '.', filename => $file );
118
119     daemonize_ok( $daemon, 'child forked okay' );
120     ok( -e $file, "$file exists" );
121     unlink($file);
122
123 =head1 DESCRIPTION
124
125 Often you want to write a persistant daemon that has a pid file, and responds appropriately to Signals. 
126 This module helps provide the basic infrastructure to do that.
127
128 =head1 ATTRIBUTES
129
130 =over
131
132 =item progname Str
133
134 The name of our daemon, defaults to $0
135
136 =item pidbase Str
137
138 The base for our bid, defaults to /var/run/$progname
139
140 =item pidfile Str
141
142 The file we store our PID in, defaults to /var/run/$progname/ 
143
144 =item foreground Bool
145
146 If true, the process won't background. Useful for debugging. This option can be set via Getopt's -f.
147
148 =back
149
150 =head1 METHODS 
151
152 =over
153
154 =item check()
155
156 Check to see if an instance is already running.
157
158 =item start()
159
160 Setup a pidfile, fork, then setup the signal handlers.
161
162 =item stop()
163
164 Stop the process matching the pidfile, and unlinks the pidfile.
165
166 =item restart()
167
168 Litterally 
169
170     $self->stop();
171     $self->start();
172
173 =item daemonize()
174
175 Calls C<Proc::Daemon::Init> to daemonize this process. 
176
177 =item kill($pid)
178
179 Kills the process for $pid. This will try SIGINT, and SIGTERM before falling back to SIGKILL and finally giving up.
180
181 =item setup_signals()
182
183 Setup the signal handlers, by default it only sets up handlers for SIGINT and SIGHUP
184
185 =item handle_sigint()
186
187 Handle a INT signal, by default calls C<$self->stop()>;
188
189 =item handle_sighup()
190
191 Handle a HUP signal. Nothing is done by default.
192
193 =item meta()
194
195 the C<meta()> method from L<Class::MOP::Class>
196
197 =item daemonize_ok()
198
199 =item check_test_output()
200
201 =back
202
203 =head1 DEPENDENCIES
204
205 =for author to fill in:
206     A list of all the other modules that this module relies upon,
207     including any restrictions on versions, and an indication whether
208     the module is part of the standard Perl distribution, part of the
209     module's distribution, or must be installed separately. ]
210
211 Obviously L<Moose>, also L<Carp>, L<Proc::Daemon>, L<File::Flock>, L<File::Slurp>
212
213 =head1 INCOMPATIBILITIES
214
215 =for author to fill in:
216     A list of any modules that this module cannot be used in conjunction
217     with. This may be due to name conflicts in the interface, or
218     competition for system or program resources, or due to internal
219     limitations of Perl (for example, many modules that use source code
220     filters are mutually incompatible).
221
222 None reported.
223
224
225 =head1 BUGS AND LIMITATIONS
226
227 =for author to fill in:
228     A list of known problems with the module, together with some
229     indication Whether they are likely to be fixed in an upcoming
230     release. Also a list of restrictions on the features the module
231     does provide: data types that cannot be handled, performance issues
232     and the circumstances in which they may arise, practical
233     limitations on the size of data sets, special cases that are not
234     (yet) handled, etc.
235
236 No bugs have been reported.
237
238 Please report any bugs or feature requests to
239 C<bug-acme-dahut-call@rt.cpan.org>, or through the web interface at
240 L<http://rt.cpan.org>.
241
242 =head1 SEE ALSO
243
244 L<Proc::Daemon>, L<Daemon::Generic>, L<MooseX::Getopt>
245
246 =head1 AUTHOR
247
248 Chris Prather  C<< <perigrin@cpan.org> >>
249
250
251 =head1 LICENCE AND COPYRIGHT
252
253 Copyright (c) 2007, Chris Prather C<< <perigrin@cpan.org> >>. All rights reserved.
254
255 This module is free software; you can redistribute it and/or
256 modify it under the same terms as Perl itself. See L<perlartistic>.
257
258
259 =head1 DISCLAIMER OF WARRANTY
260
261 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
262 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
263 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
264 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
265 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
266 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
267 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
268 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
269 NECESSARY SERVICING, REPAIR, OR CORRECTION.
270
271 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
272 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
273 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
274 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
275 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
276 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
277 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
278 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
279 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
280 SUCH DAMAGES.