Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup and unittest Object, Log, Reporter and ReporterMany #103

Merged
merged 11 commits into from
Dec 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/main/perl/FileWriter.pm
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ sub close
my $self = shift;
my ($str, $ret, $cmd, $diff);


# We have to do this because Text::Diff is not present in SL5. :(
if (*$self->{LOG} && $CAF::Reporter::_REP_SETUP->{VERBOSE}
&& -e *$self->{filename} && *$self->{buf}) {
Expand All @@ -173,8 +172,8 @@ sub close
keeps_state => 1);
$cmd->execute();
*$self->{LOG}->verbose ("Changes to ", *$self->{filename}, ":");
$diff = "" if (! defined($diff));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this cause report to log an empty line or is it suppressed by the logging stack? Is an empty line the right way of indicating an empty diff or should we print something standardised such as "(no changes)" ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change is to get rid of some 'undefined' warnings (and i think only in the unittests). there's also #119 to handle empty diffs

*$self->{LOG}->report ($diff);

}

if (*$self->{save}) {
Expand Down
216 changes: 120 additions & 96 deletions src/main/perl/Log.pm
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,29 @@
package CAF::Log;

use strict;
use CAF::Object;
use vars qw(@ISA);
use warnings;

use CAF::Reporter qw($SYSLOG);
use parent qw(CAF::Object Exporter);

use LC::Exception qw (SUCCESS throw_error);
use FileHandle;
use Readonly;

Readonly our $FH => 'FH';
Readonly our $FILENAME => 'FILENAME';
Readonly my $TSTAMP => 'TSTAMP';
Readonly my $OPTS => 'OPTS';

our @EXPORT_OK = qw($FILENAME $FH);

# $FH is used during DESTROY (and close), but might be
# destroyed itself e.g. during global cleanup
my $_FH = $FH;

my $ec = LC::Exception::Context->new->will_store_all;

@ISA = qw(CAF::Object);
# TODO: the pod used to say: INHERITANCE: CAF::Reporter

=pod

Expand All @@ -26,75 +41,70 @@ CAF::Log - Simple class for handling log files

use CAF::Log;

my $log=CAF::Log->new('/foo/bar','at');
my $log = CAF::Log->new('/foo/bar', 'at');

$log->print("this goes to the log file\n");
$log->close();

=head1 INHERITANCE

CAF::Reporter

=head1 DESCRIPTION

The B<CAF::Log> class allows to instantiate objects for writing log files.
A log file line can be prefixed by a time stamp.


=over

=cut

#------------------------------------------------------------
# Public Methods/Functions
#------------------------------------------------------------

=pod

=back

=head2 Public methods

=over 4

=item close(): boolean
=item C<close()>: boolean

closes the log file.
closes the log file, returns SUCCESS on success, undef otherwise
(if no FH attribute exists).

=cut

sub close ($) {
my $self=shift;
# Called during DESTROY, use $_XYZ flavour
sub close ($)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous commits have removed prototypes from function - do the same here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd prefer to do that outside of this work, i opened #114

{
my $self = shift;

return undef unless (defined $self->{'FH'});
# Why adding extra newlines???
# $self->{'FH'}->print("\n");
$self->{'FH'}->close();
$self->{'FH'} = undef;
return unless (defined $self->{$_FH});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it useful to indirect the attribute names in this way? What's wrong with just $self->{FH} ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its mainly to prevent typos. if this has a typo, perl will not complain.
also, FH in your example could be the string FH or a constant.

the $_FH is special due to DESTROY quirks i ran into while testeing this.


return SUCCESS;
$self->{$_FH}->close();
$self->{$_FH} = undef;

return SUCCESS;
}

=pod

=item C<print($msg)>: boolean

=pod
Prints C<$msg> into the log file.

=item print($string):boolean
If C<TSTAMP> attribute is defined (value is irrelevant),
a C<YYYY/MM/DD-HH:mm:ss> timestamp and additional space
are prepended.

prints a line into the log file.
No newline is added to the message.

Returns the return value of invocation of FH print method.

=cut

sub print ($$) {
my ($self,$msg) = @_;
# TODO: use 'if ($self->{$TSTAMP})' rather than only checking if defined

sub print ($$)
{
my ($self, $msg) = @_;

if (defined $self->{'TSTAMP'}) {
# print timestamp the SUE way ;-)
my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
$msg = sprintf("%04d/%02d/%02d-%02d:%02d:%02d %s",
$year+1900, $mon+1, $mday, $hour, $min, $sec,$msg);
}
return $self->{'FH'}->print($msg);
if (defined $self->{$TSTAMP}) {
# print timestamp the SUE way ;-)
my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
$msg = sprintf("%04d/%02d/%02d-%02d:%02d:%02d %s",
$year+1900, $mon+1, $mday, $hour, $min, $sec,$msg);
}

return $self->{$FH}->print($msg);
}


Expand All @@ -106,82 +116,94 @@ sub print ($$) {

=over 4

=item _initialize($filename,$options)
=item C<_initialize($filename, $options)>

C<$options> is a string with magic letters

=over

=item a: append to a logfile

initialize the object. Called by new($filename,$options).
=item w: truncate a loglfile

$options can be 'a' for appending to a logfile, and 'w' for
truncating, and 't' for generating a timestamp on every
print. If the 'w' option is used and there was a previous
=item t: generate a timestamp on every print

=back

Only one of C<w> or C<a> can and has to be set. (There is no default.)

If the C<w> option is used and there was a previous
log file, it is renamed with the extension '.prev'.

Examples:
open('/foo/bar','at'): append, enable timestamp
open('/foo/bar','w') : truncate logfile, no timestamp
CAF::Log->new('/foo/bar', 'at'): append, enable timestamp
CAF::Log->new('/foo/bar', 'w') : truncate logfile, no timestamp

If the filename ends with C<.log>, the C<SYSLOG> attribute is set to
basename of the file without suffix (relevant for L<CAF::Reporter::syslog>).

=cut

sub _initialize ($$$) {
my ($self,$filename,$options) = @_;

$self->{'FILENAME'} = $filename;
$self->{'OPTS'} = $options;

if ($self->{FILENAME} =~ m{([^/]*).log$}) {
$self->{SYSLOG} = $1;
}

unless ($self->{'OPTS'} =~ /^(w|a)t?$/) {
throw_error("Bad options for log ".$self->{'FILENAME'}.
": ".$self->{'OPTS'});
return undef;
}

if ($self->{'OPTS'} =~ /t/) {
$self->{'TSTAMP'}=1;
}

if ($self->{'OPTS'} =~ /w/) {
#
# Move old filename away if mode is 'w'.
#
rename ($self->{'FILENAME'},$self->{'FILENAME'}.'.prev')
if (-e $self->{'FILENAME'});
unless ($self->{'FH'} = FileHandle->new(">".$self->{'FILENAME'})) {
throw_error("Open for write ",$self->{'FILENAME'});
return undef;
sub _initialize ($$$)
{
my ($self, $filename, $options) = @_;

$self->{$FILENAME} = $filename;
$self->{$OPTS} = $options;

if ($self->{$FILENAME} =~ m{([^/]*).log$}) {
$self->{$SYSLOG} = $1;
}

unless ($self->{$OPTS} =~ /^(w|a)t?$/) {

throw_error("Bad options for log ".$self->{$FILENAME}.
": ".$self->{$OPTS});
return;
}

if ($self->{$OPTS} =~ /t/) {
$self->{$TSTAMP} = 1;
}
} else {
#
# Mode is 'a'. Append to (potentially existing) file
#
unless ($self->{'FH'} = FileHandle->new(">> ".$self->{'FILENAME'})) {
throw_error("Open for append: $self->{'FILENAME'}", $!);
return undef;

my ($fhmode, $msg);
if ($self->{$OPTS} =~ /w/) {
# Move old filename away if mode is 'w'.
rename ($self->{$FILENAME}, $self->{$FILENAME}.'.prev')
if (-e $self->{$FILENAME});
$fhmode = ">";
$msg = "write";
} else {
# setting is 'a': append to (potentially existing) file
$fhmode = ">>";
$msg = "append";
}
}
#
# Autoflush on
#
$self->{'FH'}->autoflush();

return SUCCESS;
unless ($self->{$FH} = FileHandle->new("$fhmode ".$self->{$FILENAME})) {
throw_error("Open for $msg " . $self->{$FILENAME} . " $!");
return;
}

# Autoflush on
$self->{$FH}->autoflush();

return SUCCESS;
}

=pod

=item DESTROY

called during garbage collection. Invokes close()
Called during garbage collection. Invokes close().

=cut


# All Readonly here (and in methods called) might be
# cleaned up during global cleanup, so use the $_XYZ
# flavours here (and methods called here).
sub DESTROY {
my $self = shift;
$self->close() if (defined $self->{'FH'});
my $self = shift;
$self->close() if (defined $self->{$_FH});
}

=pod
Expand All @@ -190,6 +212,8 @@ sub DESTROY {

=cut

# TODO: these are only send to STDERR, not logged
# move this to DESTROY?

END {
# report all stored warnings
Expand Down
Loading