Sometimes I miss these functions and then I write them each time again. Index: Apache-Test/t/log_watch.t =================================================================== --- Apache-Test/t/log_watch.t (revision 0) +++ Apache-Test/t/log_watch.t (revision 0) @@ -0,0 +1,73 @@ +use strict; +use warnings FATAL => 'all'; + +use Apache::Test; +use Apache::TestUtil qw/t_start_file_watch + t_read_file_watch + t_finish_file_watch + t_write_file + t_append_file + t_catfile + t_cmp/; + +plan tests => 11; + +my $fn=t_catfile(Apache::Test::vars->{t_logs}, 'watch'); +unlink $fn; + +t_start_file_watch 'watch'; + +t_write_file $fn, "1\n2\n"; + +ok t_cmp [t_read_file_watch 'watch'], ["1\n", "2\n"], + "t_read_file_watch on previously non-existing file"; + +t_append_file $fn, "3\n4\n"; + +ok t_cmp [t_read_file_watch 'watch'], ["3\n", "4\n"], + "subsequent t_read_file_watch"; + +t_append_file $fn, "5\n6\n"; + +ok t_cmp [t_finish_file_watch 'watch'], ["5\n", "6\n"], + "subsequent t_finish_file_watch"; + +ok t_cmp [t_finish_file_watch 'watch'], ["1\n","2\n","3\n","4\n","5\n","6\n"], + "t_finish_file_watch w/o start"; + +ok t_cmp [t_read_file_watch 'watch'], ["1\n","2\n","3\n","4\n","5\n","6\n"], + "t_read_file_watch w/o start"; + +ok t_cmp [t_read_file_watch 'watch'], [], + "subsequent t_read_file_watch"; + +t_append_file $fn, "7\n8\n"; +unlink $fn; + +ok t_cmp [t_read_file_watch 'watch'], ["7\n","8\n"], + "subsequent t_read_file_watch file unlinked"; + +t_write_file $fn, "1\n2\n3\n4\n5\n6\n7\n8\n"; + +ok t_cmp [t_finish_file_watch 'watch'], [], + "subsequent t_finish_file_watch - new file exists but fh is cached"; + +t_start_file_watch 'watch'; + +ok t_cmp [t_read_file_watch 'watch'], [], + "t_read_file_watch at EOF"; + +unlink $fn; +t_start_file_watch 'watch'; + +t_write_file $fn, "1\n2\n3\n4\n5\n6\n7\n8\n"; + +{ + local $/=\4; + + ok t_cmp [scalar t_read_file_watch 'watch'], ["1\n2\n"], + "t_read_file_watch fixed record length / scalar context"; + + ok t_cmp [t_finish_file_watch 'watch'], ["3\n4\n","5\n6\n","7\n8\n"], + "t_finish_file_watch fixed record length"; +} Index: Apache-Test/lib/Apache/TestUtil.pm =================================================================== --- Apache-Test/lib/Apache/TestUtil.pm (revision 931462) +++ Apache-Test/lib/Apache/TestUtil.pm (working copy) @@ -43,8 +43,9 @@ ); @EXPORT_OK = qw(t_write_perl_script t_write_shell_script t_chown - t_catfile_apache t_catfile - t_start_error_log_watch t_finish_error_log_watch); + t_catfile_apache t_catfile + t_start_error_log_watch t_finish_error_log_watch + t_start_file_watch t_read_file_watch t_finish_file_watch); %CLEAN = (); @@ -55,24 +56,59 @@ use constant INDENT => 4; { - my $f; - sub t_start_error_log_watch { + my %files; + sub t_start_file_watch (;$) { + my $name = @_ ? $_[0] : 'error_log'; + $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name) + unless (File::Spec->file_name_is_absolute($name)); - my $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, 'error_log'); - open $f, "$name" or die "ERROR: Cannot open $name: $!\n"; - seek $f, 0, SEEK_END; + if (open my $fh, '<', $name) { + seek $fh, 0, SEEK_END; + $files{$name} = $fh; + } + else { + delete $files{$name}; + } return; } - sub t_finish_error_log_watch { + sub t_finish_file_watch (;$) { + my $name = @_ ? $_[0] : 'error_log'; + $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name) + unless (File::Spec->file_name_is_absolute($name)); - local $/ = "\n"; - my @lines = <$f>; - undef $f; + my $fh = delete $files{$name}; + unless (defined $fh) { + open $fh, '<', $name or return; + return readline $fh; + } - return @lines; + return readline $fh; + } + + sub t_read_file_watch (;$) { + my $name = @_ ? $_[0] : 'error_log'; + $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name) + unless (File::Spec->file_name_is_absolute($name)); + + my $fh = $files{$name}; + unless (defined $fh) { + open $fh, '<', $name or return; + $files{$name} = $fh; + } + + return readline $fh; } + + sub t_start_error_log_watch { + t_start_file_watch undef; + } + + sub t_finish_error_log_watch { + local $/ = "\n"; + return my @lines = t_finish_file_watch; + } } # because of the prototype and recursive call to itself a forward @@ -432,6 +468,7 @@ 1; __END__ +=encoding utf8 =head1 NAME @@ -829,13 +866,63 @@ t_start_error_log_watch(); do_it; - ok grep {...} t_finish_error_log_watch() + ok grep {...} t_finish_error_log_watch(); +Another usage case could be a handler that emits some debugging messages +to the error_log. Now, if this handler is called in a series of other +test cases it can be hard to find the relevant messages manually. In such +cases the following sequence in the test file may help: + + t_start_error_log_watch(); + GET '/this/or/that'; + t_debug t_finish_error_log_watch(); + +=item t_start_file_watch() + + Apache::TestUtil::t_start_file_watch('access_log'); + +This function is similar to C<t_start_error_log_watch()> but allows for +other files than C<error_log> to be watched. It opens the given file +and positions the file pointer at its end. Subsequent calls to +C<t_read_file_watch()> or C<t_finish_file_watch()> will read lines that +have been appended after this call. + +A file name can be passed as parameter. If omitted +or undefined the C<error_log> is opened. Relative file name are +evaluated relative to the directory containing C<error_log>. + +If the specified file does not exist (yet) no error is returned. It is +assumed that it will appear soon. In this case C<t_{read,finish}_file_watch()> +will open the file silently and read from the beginning. + +=item t_read_file_watch(), t_finish_file_watch() + + local $/ = "\n"; + $line1=Apache::TestUtil::t_read_file_watch('access_log'); + $line2=Apache::TestUtil::t_read_file_watch('access_log'); + + @lines=Apache::TestUtil::t_finish_file_watch('access_log'); + +This pair of functions reads the file opened by C<t_start_error_log_watch()>. + +As does the core C<readline> function, they return one line if called in +scalar context, otherwise all lines until end of file. + +Before calling C<readline> these functions do not set C<$/> as does +C<t_finish_error_log_watch>. So, if the file has for example a fixed +record length use this: + + { + local $/=\$record_length; + @lines=t_finish_file_watch($name); + } + =back =head1 AUTHOR -Stas Bekman <s...@stason.org> +Stas Bekman <s...@stason.org>, +Torsten Förtsch <torsten.foert...@gmx.net> =head1 SEE ALSO
Torsten Förtsch -- Need professional modperl support? Hire me! (http://foertsch.name) Like fantasy? http://kabatinte.net
Index: Apache-Test/t/log_watch.t =================================================================== --- Apache-Test/t/log_watch.t (revision 0) +++ Apache-Test/t/log_watch.t (revision 0) @@ -0,0 +1,73 @@ +use strict; +use warnings FATAL => 'all'; + +use Apache::Test; +use Apache::TestUtil qw/t_start_file_watch + t_read_file_watch + t_finish_file_watch + t_write_file + t_append_file + t_catfile + t_cmp/; + +plan tests => 11; + +my $fn=t_catfile(Apache::Test::vars->{t_logs}, 'watch'); +unlink $fn; + +t_start_file_watch 'watch'; + +t_write_file $fn, "1\n2\n"; + +ok t_cmp [t_read_file_watch 'watch'], ["1\n", "2\n"], + "t_read_file_watch on previously non-existing file"; + +t_append_file $fn, "3\n4\n"; + +ok t_cmp [t_read_file_watch 'watch'], ["3\n", "4\n"], + "subsequent t_read_file_watch"; + +t_append_file $fn, "5\n6\n"; + +ok t_cmp [t_finish_file_watch 'watch'], ["5\n", "6\n"], + "subsequent t_finish_file_watch"; + +ok t_cmp [t_finish_file_watch 'watch'], ["1\n","2\n","3\n","4\n","5\n","6\n"], + "t_finish_file_watch w/o start"; + +ok t_cmp [t_read_file_watch 'watch'], ["1\n","2\n","3\n","4\n","5\n","6\n"], + "t_read_file_watch w/o start"; + +ok t_cmp [t_read_file_watch 'watch'], [], + "subsequent t_read_file_watch"; + +t_append_file $fn, "7\n8\n"; +unlink $fn; + +ok t_cmp [t_read_file_watch 'watch'], ["7\n","8\n"], + "subsequent t_read_file_watch file unlinked"; + +t_write_file $fn, "1\n2\n3\n4\n5\n6\n7\n8\n"; + +ok t_cmp [t_finish_file_watch 'watch'], [], + "subsequent t_finish_file_watch - new file exists but fh is cached"; + +t_start_file_watch 'watch'; + +ok t_cmp [t_read_file_watch 'watch'], [], + "t_read_file_watch at EOF"; + +unlink $fn; +t_start_file_watch 'watch'; + +t_write_file $fn, "1\n2\n3\n4\n5\n6\n7\n8\n"; + +{ + local $/=\4; + + ok t_cmp [scalar t_read_file_watch 'watch'], ["1\n2\n"], + "t_read_file_watch fixed record length / scalar context"; + + ok t_cmp [t_finish_file_watch 'watch'], ["3\n4\n","5\n6\n","7\n8\n"], + "t_finish_file_watch fixed record length"; +} Index: Apache-Test/lib/Apache/TestUtil.pm =================================================================== --- Apache-Test/lib/Apache/TestUtil.pm (revision 931462) +++ Apache-Test/lib/Apache/TestUtil.pm (working copy) @@ -43,8 +43,9 @@ ); @EXPORT_OK = qw(t_write_perl_script t_write_shell_script t_chown - t_catfile_apache t_catfile - t_start_error_log_watch t_finish_error_log_watch); + t_catfile_apache t_catfile + t_start_error_log_watch t_finish_error_log_watch + t_start_file_watch t_read_file_watch t_finish_file_watch); %CLEAN = (); @@ -55,24 +56,59 @@ use constant INDENT => 4; { - my $f; - sub t_start_error_log_watch { + my %files; + sub t_start_file_watch (;$) { + my $name = @_ ? $_[0] : 'error_log'; + $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name) + unless (File::Spec->file_name_is_absolute($name)); - my $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, 'error_log'); - open $f, "$name" or die "ERROR: Cannot open $name: $!\n"; - seek $f, 0, SEEK_END; + if (open my $fh, '<', $name) { + seek $fh, 0, SEEK_END; + $files{$name} = $fh; + } + else { + delete $files{$name}; + } return; } - sub t_finish_error_log_watch { + sub t_finish_file_watch (;$) { + my $name = @_ ? $_[0] : 'error_log'; + $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name) + unless (File::Spec->file_name_is_absolute($name)); - local $/ = "\n"; - my @lines = <$f>; - undef $f; + my $fh = delete $files{$name}; + unless (defined $fh) { + open $fh, '<', $name or return; + return readline $fh; + } - return @lines; + return readline $fh; + } + + sub t_read_file_watch (;$) { + my $name = @_ ? $_[0] : 'error_log'; + $name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name) + unless (File::Spec->file_name_is_absolute($name)); + + my $fh = $files{$name}; + unless (defined $fh) { + open $fh, '<', $name or return; + $files{$name} = $fh; + } + + return readline $fh; } + + sub t_start_error_log_watch { + t_start_file_watch undef; + } + + sub t_finish_error_log_watch { + local $/ = "\n"; + return my @lines = t_finish_file_watch; + } } # because of the prototype and recursive call to itself a forward @@ -432,6 +468,7 @@ 1; __END__ +=encoding utf8 =head1 NAME @@ -829,13 +866,63 @@ t_start_error_log_watch(); do_it; - ok grep {...} t_finish_error_log_watch() + ok grep {...} t_finish_error_log_watch(); +Another usage case could be a handler that emits some debugging messages +to the error_log. Now, if this handler is called in a series of other +test cases it can be hard to find the relevant messages manually. In such +cases the following sequence in the test file may help: + + t_start_error_log_watch(); + GET '/this/or/that'; + t_debug t_finish_error_log_watch(); + +=item t_start_file_watch() + + Apache::TestUtil::t_start_file_watch('access_log'); + +This function is similar to C<t_start_error_log_watch()> but allows for +other files than C<error_log> to be watched. It opens the given file +and positions the file pointer at its end. Subsequent calls to +C<t_read_file_watch()> or C<t_finish_file_watch()> will read lines that +have been appended after this call. + +A file name can be passed as parameter. If omitted +or undefined the C<error_log> is opened. Relative file name are +evaluated relative to the directory containing C<error_log>. + +If the specified file does not exist (yet) no error is returned. It is +assumed that it will appear soon. In this case C<t_{read,finish}_file_watch()> +will open the file silently and read from the beginning. + +=item t_read_file_watch(), t_finish_file_watch() + + local $/ = "\n"; + $line1=Apache::TestUtil::t_read_file_watch('access_log'); + $line2=Apache::TestUtil::t_read_file_watch('access_log'); + + @lines=Apache::TestUtil::t_finish_file_watch('access_log'); + +This pair of functions reads the file opened by C<t_start_error_log_watch()>. + +As does the core C<readline> function, they return one line if called in +scalar context, otherwise all lines until end of file. + +Before calling C<readline> these functions do not set C<$/> as does +C<t_finish_error_log_watch>. So, if the file has for example a fixed +record length use this: + + { + local $/=\$record_length; + @lines=t_finish_file_watch($name); + } + =back =head1 AUTHOR -Stas Bekman <s...@stason.org> +Stas Bekman <s...@stason.org>, +Torsten Förtsch <torsten.foert...@gmx.net> =head1 SEE ALSO
--------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@perl.apache.org For additional commands, e-mail: dev-h...@perl.apache.org