dbccc4479176c6c82df022040939635d3f9f4c9b
[gitmo/MooseX-Daemonize.git] / lib / Test / MooseX / Daemonize.pm
1 use strict;
2 use warnings;
3 package Test::MooseX::Daemonize;
4
5 # BEGIN CARGO CULTING
6 use Sub::Exporter::ForMethods 'method_installer';
7 use Sub::Exporter -setup => {
8     exports => [ qw(daemonize_ok check_test_output) ],
9     groups  => { default => [ qw(daemonize_ok check_test_output) ] },
10     installer => method_installer,
11 };
12
13 use Test::Builder;
14
15 our $Test = Test::Builder->new;
16
17 sub daemonize_ok {
18     my ( $daemon, $msg ) = @_;
19     unless ( my $pid = fork ) {
20         $daemon->start();
21         exit;
22     }
23     else {
24         sleep(1);    # Punt on sleep time, 1 seconds should be enough
25         $Test->ok( $daemon->pidfile->does_file_exist, $msg )
26           || $Test->diag(
27             'Pidfile (' . $daemon->pidfile->file . ') not found.' );
28     }
29 }
30
31 sub check_test_output {
32     my ($app) = @_;
33     open( my $stdout_in, '<', $app->test_output )
34       or die "can't open test output: $!";
35     while ( my $line = <$stdout_in> ) {
36         $line =~ s/\s+\z//;
37         my $label;
38         if ( $line =~ /\A((not\s+)?ok)(?:\s+-)(?:\s+(.*))\z/ ) {
39             my ( $status, $not, $text ) = ( $1, $2, $3 );
40             $text ||= '';
41
42            # We don't just call ok(!$not), because that generates diagnostics of
43            # its own for failures. We only want the diagnostics from the child.
44             my $orig_no_diag = $Test->no_diag;
45             $Test->no_diag(1);
46             $Test->ok(!$not, $text);
47             $Test->no_diag($orig_no_diag);
48         }
49         elsif ( $line =~ s/\A#\s?// ) {
50             $Test->diag($line);
51         }
52         else {
53             $Test->diag("$label: $line (unrecognised)\n");
54         }
55     }
56 }
57
58 package Test::MooseX::Daemonize::Testable;
59
60 use Moose::Role;
61
62 has test_output => (
63     isa      => 'Str',
64     is       => 'ro',
65     required => 1,
66 );
67
68 after daemonize => sub {
69     $Test->use_numbers(0);
70     $Test->no_ending(1);
71     open my $out, '>', $_[0]->test_output or die "Cannot open test output: $!";
72     my $fileno = fileno $out;
73     open STDERR, ">&=", $fileno
74       or die "Can't redirect STDERR";
75
76     open STDOUT, ">&=", $fileno
77       or die "Can't redirect STDOUT";
78
79     $Test->output($out);
80     $Test->failure_output($out);
81     $Test->todo_output($out);
82 };
83
84 1;
85 __END__
86
87 =pod
88
89 =head1 NAME
90
91 Test::MooseX::Daemonize - Tool to help test MooseX::Daemonize applications
92
93 =head1 SYNOPSIS
94
95     use File::Spec::Functions;
96     use File::Temp qw(tempdir);
97
98     my $dir = tempdir( CLEANUP => 1 );
99
100     ## Try to make sure we are in the test directory
101
102     my $file = catfile( $dir, "im_alive" );
103     my $daemon = FileMaker->new( pidbase => $dir, filename => $file );
104
105     daemonize_ok( $daemon, 'child forked okay' );
106     ok( -e $file, "$file exists" );
107
108 =head1 DESCRIPTION
109
110 This module provides some basic Test::Builder compatible test methods to
111 use when writing tests for you MooseX::Daemonize based modules.
112
113 =head1 EXPORTED FUNCTIONS
114
115 =over 4
116
117 =item B<daemonize_ok ( $daemon, ?$msg )>
118
119 This will attempt to daemonize your C<$daemon> returning ok on
120 success and not ok on failure.
121
122 =item B<check_test_output ( $daemon )>
123
124 This is expected to be used with a C<$daemon> which does the
125 B<Test::MooseX::Daemonize::Testable> role (included in this package
126 see the source for more info). It will collect the test output
127 from your daemon and apply it in the parent process by mucking
128 around with L<Test::Builder> stuff, again, read the source for
129 more info. If we get time we will document this more thoroughly.
130
131 =back
132
133 =head1 INCOMPATIBILITIES
134
135 None reported.
136
137 =head1 BUGS AND LIMITATIONS
138
139 No bugs have been reported.
140
141 Please report any bugs or feature requests to
142 C<bug-acme-dahut-call@rt.cpan.org>, or through the web interface at
143 L<http://rt.cpan.org>.
144
145 =head1 SEE ALSO
146
147 L<MooseX::Daemonize>
148
149 =head1 AUTHOR
150
151 Chris Prather  C<< <perigrin@cpan.org> >>
152
153 =head1 LICENCE AND COPYRIGHT
154
155 Copyright (c) 2007-2011, Chris Prather C<< <perigrin@cpan.org> >>. All rights reserved.
156
157 This module is free software; you can redistribute it and/or
158 modify it under the same terms as Perl itself. See L<perlartistic>.
159
160 =head1 DISCLAIMER OF WARRANTY
161
162 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
163 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
164 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
165 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
166 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
167 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
168 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
169 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
170 NECESSARY SERVICING, REPAIR, OR CORRECTION.
171
172 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
173 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
174 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
175 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
176 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
177 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
178 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
179 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
180 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
181 SUCH DAMAGES.
182
183 =cut