1
# Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
2
# Use is subject to license terms.
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; version 2 of the License.
8
# This program is distributed in the hope that it will be useful, but
9
# WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
# General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
18
package GenTest::Reporter::ValgrindErrors;
21
@ISA = qw(GenTest::Reporter);
24
use File::Spec::Functions;
26
use GenTest::Reporter;
27
use GenTest::Constants;
30
# This reporter looks for valgrind messages in the server error log, and
31
# prints the messages and returns a failure status if any valgrind errors
39
# Look for error log file
40
my $error_log = $reporter->serverInfo('errorlog');
41
$error_log = $reporter->serverVariable('log_error') if $error_log eq '';
42
if ($error_log eq '') {
43
foreach my $file ('../log/master.err', '../mysql.err') {
44
my $filename = catfile($reporter->serverVariable('datadir'), $file);
46
$error_log = $filename;
52
# Open log file and read valgrind messages...
53
my $LogFile = IO::File->new($error_log)
54
or say("ERROR: $0 could not read log file '$error_log': $!")
55
&& return STATUS_ENVIRONMENT_FAILURE;
57
# We use a set of strings to look for valgrind errors. These are based on
58
# the valgrind manual + code. We compose a regex of all the strings later.
60
# We also try to gather the number of reported errors. Note that not all
61
# issues reported by valgrind are "errors".
63
# These strings need to be matched as case insensitive.
64
# Special characters will be escaped using quotemeta before regex matching.
65
my @valgrind_strings = (
66
'are definitely lost',
69
'bytes inside a block of size',
71
'during client check request',
72
'illegal memory pool address',
74
'invalid read of size',
75
'invalid write of size',
76
'jump to the invalid address',
79
'source and destination',
83
'uninitialised value',
86
# The regular expression is composed as follows:
87
# - sort: Sort strings in array @valgrind_strings by length in reversed order
88
# (to ensure correct matches in case of similar substrings).
89
# - map{quotemeta}: Add escape characters to all non-letter, non-digit characters in the sorted strings,
90
# to avoid special regex interpretation of these characters.
91
# - map("($_)"): Wrap each escaped sting inside a pair of parenthesis (for proper regex alternatives).
92
# - join: Separate each block of parenthesis by the "or" operator (|).
93
# - Add valgrind line prefix.
94
my $regex = "^==[0-9]+==\s+.*".
95
join('|', map("($_)", map{quotemeta} sort {length($b)<=>length($a)} (@valgrind_strings)));
96
$regex = qr/($regex)/i; # quote and compile regex, case insensitive
99
my $issue_detected = 0;
100
while (my $line = <$LogFile>) {
101
push(@valgrind_lines, $line) if $line =~ m{^==[0-9]+==\s+\S};
102
if ($line =~ m{^==[0-9]+==\s+ERROR SUMMARY: ([0-9]+) errors}) {
104
} elsif ($line =~ m{$regex}) {
109
if (($errorcount > 0) or $issue_detected) {
110
say("Valgrind: Issues detected (error count: $errorcount). Relevant messages from log file '$error_log':");
111
foreach my $line (@valgrind_lines) {
114
return STATUS_VALGRIND_FAILURE
116
say("Valgrind: No issues found in file '$error_log'.");
122
return REPORTER_TYPE_ALWAYS ;