1# -*- cperl -*-
2
3package My::Exec;
4
5use strict;
6use warnings;
7use Carp;
8use File::Basename;
9use IO::File;
10
11use base qw(Exporter);
12our @EXPORT= qw(exec_print_on_error);
13
14# Generate a logfile name from a command
15sub get_logfile_name {
16    my $cmd = shift;
17
18    # Get logfile name
19    my @cmd_parts = split(' ', $cmd);
20    my $logfile_base = fileparse($cmd_parts[0]);
21    my $logfile_name = "";
22    my $log_dir = $ENV{MYSQLTEST_VARDIR};
23    for my $i (1..100)
24    {
25        my $proposed_logfile_name = "$log_dir/$logfile_base" . '_' . $i . ".log";
26        if (! -f $proposed_logfile_name)
27	{
28	    # We can use this file name
29	    $logfile_name = $proposed_logfile_name;
30            last;
31	}
32    }
33
34    return $logfile_name;
35}
36
37# Save a set of lines to a file
38sub save_file {
39    my $filename = shift;
40    my $lines    = shift;
41
42    my $F = IO::File->new($filename, "w") or die "Can't write to '$filename': $!";
43    foreach my $line (@$lines) {
44        print $F $line
45    }
46    $F->close();
47}
48
49#
50# exec_print_on_error - executes command, and prints n last lines of output
51#                       from the command only if the command fails. If the command runs
52#                       successfully, no output is written.
53#
54# Parameters:
55#              cmd       - the command to run
56#              max_lines - the maximum number of lines of output to show on error (default 200)
57# Returns:
58#              1 on success, 0 on error.
59# Example:
60#              use My::Exec;
61#              my $res = exec_print_on_error("./mtr --suite=ndb ndb_dd_varsize");
62#
63sub exec_print_on_error {
64    my $cmd       = shift;
65    my $max_lines = shift || 200;
66
67    my $logfile_name = get_logfile_name($cmd);
68
69    $cmd .= " 2>&1";
70    my @output = `$cmd`;
71    print "Result of '$cmd': $?, logfile: '$logfile_name'\n";
72    save_file($logfile_name, \@output);
73    if ($? == 0)
74    {
75	# Test program suceeded
76	return 1;
77    }
78
79    # Test program failed
80    if ($? == -1)
81    {
82	# Failed to execute program
83	print "Failed to execute '$cmd': $!\n";
84    }
85    elsif ($?)
86    {
87	# Test program failed
88	my $sig = $? & 127;
89	my $return = $? >> 8;
90	print "Command that failed: '$cmd'\n";
91	print "Test program killed by signal $sig\n" if $sig;
92	print "Test program failed with error $return\n" if $return;
93
94	# Show the last lines of the output
95	my $lines = scalar(@output);
96	$lines = $max_lines if $lines > $max_lines;
97	print "Last '$lines' lines of output from command:\n";
98	foreach my $line (splice(@output, -$lines))
99	{
100	    print $line;
101	}
102    }
103    return 0;
104}
105