0.67.305
by Bernt M. Johnsen
Copyright headres and license added |
1 |
# Copyright (C) 2008-2009 Sun Microsystems, Inc. All rights reserved. |
2 |
# Use is subject to license terms. |
|
3 |
#
|
|
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. |
|
7 |
#
|
|
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. |
|
12 |
#
|
|
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 |
|
16 |
# USA |
|
17 |
||
0.82.2
by Bernt M. Johnsen
New config |
18 |
use strict; |
0.67.1
by Philip Stoev
initial import from internal tree |
19 |
use lib 'lib'; |
20 |
use lib '../lib'; |
|
21 |
use DBI; |
|
0.82.2
by Bernt M. Johnsen
New config |
22 |
use Carp; |
23 |
use Getopt::Long; |
|
24 |
use Data::Dumper; |
|
0.67.1
by Philip Stoev
initial import from internal tree |
25 |
|
26 |
use GenTest; |
|
27 |
use GenTest::Constants; |
|
0.67.9
by Philip Stoev
merge from internal tree |
28 |
use GenTest::Grammar; |
0.82.2
by Bernt M. Johnsen
New config |
29 |
use GenTest::Properties; |
0.67.1
by Philip Stoev
initial import from internal tree |
30 |
use GenTest::Simplifier::Grammar; |
31 |
use Time::HiRes; |
|
32 |
||
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
33 |
#
|
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
34 |
# RQG grammar simplification with an oracle() function based on |
0.82.2
by Bernt M. Johnsen
New config |
35 |
# 1. RQG exit status codes (-> desired_status_codes) |
36 |
# 2. expected RQG protocol output (-> expected_output) |
|
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
37 |
# Hint: 2. will be not checked if 1. already failed |
38 |
#
|
|
0.82.2
by Bernt M. Johnsen
New config |
39 |
# You need to adjust parameters to your use case and environment. |
40 |
# 1. Copy simplify-grammar_template.cfg to for example 1.cfg |
|
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
41 |
# 2. Adjust the settings |
0.82.2
by Bernt M. Johnsen
New config |
42 |
# 2. perl util/simplify-grammar.pl --config 1.cfg |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
43 |
#
|
0.82.2
by Bernt M. Johnsen
New config |
44 |
# This script is used to simplify grammar files to the smallest form |
45 |
# that will still reproduce the desired outcome |
|
46 |
# For the purpose, the GenTest::Simplifier::Grammar module provides |
|
47 |
# progressively simple grammars, and we define an oracle() function |
|
48 |
# that runs those grammars with the RQG and reports if the RQG returns |
|
49 |
# the desired status code (usually something like |
|
50 |
# STATUS_SERVER_CRASHED |
|
0.67.1
by Philip Stoev
initial import from internal tree |
51 |
#
|
52 |
# For more information, please see: |
|
53 |
#
|
|
54 |
# http://forge.mysql.com/wiki/RandomQueryGeneratorSimplification |
|
55 |
#
|
|
56 |
||
0.82.2
by Bernt M. Johnsen
New config |
57 |
# get configuration |
58 |
||
59 |
my $options = {}; |
|
0.82.5
by Matthias Leich
Cleanup in grammar simplification |
60 |
GetOptions($options, 'config=s', 'trials=i','storage_prefix=s','expected_output=s@'); |
0.82.9
by Bernt M. Johnsen
Ported dump-test.pl + some improvements |
61 |
my $config = GenTest::Properties->new( |
62 |
options => $options, |
|
0.82.2
by Bernt M. Johnsen
New config |
63 |
legal => ['desired_status_codes', |
64 |
'expected_output', |
|
65 |
'initial_grammar_file', |
|
0.67.392
by Philip Stoev
allow grammar simplification to work with mask and mask-level |
66 |
'mask', |
67 |
'mask-level', |
|
0.82.2
by Bernt M. Johnsen
New config |
68 |
'grammar_flags', |
69 |
'trials', |
|
70 |
'initial_seed', |
|
71 |
'search_var_size', |
|
72 |
'rqg_options', |
|
73 |
'vardir_prefix', |
|
0.82.5
by Matthias Leich
Cleanup in grammar simplification |
74 |
'storage_prefix'], |
0.82.9
by Bernt M. Johnsen
Ported dump-test.pl + some improvements |
75 |
required=>['rqg_options', |
76 |
'initial_grammar_file', |
|
77 |
'vardir_prefix', |
|
78 |
'storage_prefix'], |
|
0.85.2
by Matthias Leich
- Corrections in messages |
79 |
defaults => {expected_output => [], |
80 |
desired_status_codes => [+STATUS_ANY_ERROR]} |
|
0.82.2
by Bernt M. Johnsen
New config |
81 |
);
|
82 |
||
83 |
# Dump settings |
|
84 |
say("SIMPLIFY RQG GRAMMAR BASED ON EXPECTED CONTENT WITHIN SOME FILE"); |
|
85 |
say("---------------------------------------------------------------"); |
|
86 |
$config->printProps; |
|
87 |
say("---------------------------------------------------------------"); |
|
88 |
||
89 |
## Calculate mysqld and rqg options |
|
90 |
||
91 |
my $mysqlopt = $config->genOpt('--mysqld=--', $config->rqg_options->{mysqld}); |
|
92 |
||
93 |
## The one below is a hack.... Need support for nested options like these |
|
94 |
delete $config->rqg_options->{mysqld}; |
|
95 |
||
96 |
my $rqgoptions = $config->genOpt('--', 'rqg_options'); |
|
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
97 |
|
98 |
# Determine some runtime parameter, check parameters, .... |
|
0.67.1
by Philip Stoev
initial import from internal tree |
99 |
|
100 |
my $run_id = time(); |
|
101 |
||
102 |
say("The ID of this run is $run_id."); |
|
103 |
||
0.67.392
by Philip Stoev
allow grammar simplification to work with mask and mask-level |
104 |
my $initial_grammar; |
105 |
||
106 |
if ($config->property('mask') > 0) { |
|
107 |
my $initial_grammar_obj = GenTest::Grammar->new( 'grammar_file' => $config->initial_grammar_file ); |
|
108 |
my $top_grammar = $initial_grammar_obj->topGrammar($config->property('mask-level'), "query", "query_init"); |
|
109 |
my $masked_top = $top_grammar->mask($config->property('mask')); |
|
110 |
$initial_grammar = $initial_grammar_obj->patch($masked_top); |
|
111 |
} else { |
|
112 |
open(INITIAL_GRAMMAR, $config->initial_grammar_file) or croak "Unable to open initial_grammar_file '" . $config->initial_grammar_file . "' : $!"; |
|
113 |
read(INITIAL_GRAMMAR, $initial_grammar , -s $config->initial_grammar_file); |
|
114 |
close(INITIAL_GRAMMAR); |
|
115 |
}
|
|
0.67.1
by Philip Stoev
initial import from internal tree |
116 |
|
0.82.2
by Bernt M. Johnsen
New config |
117 |
if ( ! -d $config->vardir_prefix ) { |
0.85.2
by Matthias Leich
- Corrections in messages |
118 |
croak("vardir_prefix '" . $config->vardir_prefix . "' is not an existing directory"); |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
119 |
}
|
0.82.2
by Bernt M. Johnsen
New config |
120 |
|
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
121 |
# Calculate a unique vardir (use $MTR_BUILD_THREAD or $run_id) |
0.82.2
by Bernt M. Johnsen
New config |
122 |
|
0.85.2
by Matthias Leich
- Corrections in messages |
123 |
my $vardir = $config->vardir_prefix . '/var_' . $run_id; |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
124 |
mkdir ($vardir); |
0.82.2
by Bernt M. Johnsen
New config |
125 |
push my @mtr_options, "--vardir=$vardir"; |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
126 |
|
0.82.5
by Matthias Leich
Cleanup in grammar simplification |
127 |
if ( ! -d $config->storage_prefix) { |
0.85.2
by Matthias Leich
- Corrections in messages |
128 |
croak("storage_prefix '" . $config->storage_prefix . "' is not an existing directory"); |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
129 |
}
|
0.82.5
by Matthias Leich
Cleanup in grammar simplification |
130 |
my $storage = $config->storage_prefix.'/'.$run_id; |
0.82.2
by Bernt M. Johnsen
New config |
131 |
say "Storage is $storage"; |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
132 |
mkdir ($storage); |
133 |
||
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
134 |
my $errfile = $vardir . '/log/master.err'; |
0.67.121
by Bernt M. Johnsen
Matthias' grammar simplification improvements |
135 |
|
0.67.1
by Philip Stoev
initial import from internal tree |
136 |
my $iteration; |
0.82.2
by Bernt M. Johnsen
New config |
137 |
my $good_seed = $config->initial_seed; |
0.67.1
by Philip Stoev
initial import from internal tree |
138 |
|
139 |
my $simplifier = GenTest::Simplifier::Grammar->new( |
|
0.82.2
by Bernt M. Johnsen
New config |
140 |
grammar_flags => $config->grammar_flags, |
141 |
oracle => sub { |
|
142 |
$iteration++; |
|
143 |
my $oracle_grammar = shift; |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
144 |
|
145 |
my $current_grammar = $storage . '/' . $iteration . '.yy'; |
|
146 |
open (GRAMMAR, ">$current_grammar") |
|
147 |
or croak "unable to create $current_grammar : $!"; |
|
148 |
print GRAMMAR $oracle_grammar; |
|
149 |
close (GRAMMAR); |
|
150 |
||
151 |
||
0.82.2
by Bernt M. Johnsen
New config |
152 |
foreach my $trial (1..$config->trials) { |
153 |
say("run_id = $run_id; iteration = $iteration; trial = $trial"); |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
154 |
|
0.82.2
by Bernt M. Johnsen
New config |
155 |
# $current_seed -- The seed value to be used for the next run. |
156 |
# The test results of many grammars are quite sensitive to the |
|
157 |
# seed value. |
|
158 |
# 1. Run the first trial on the initial grammar with |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
159 |
# $config->initial_seed . This should raise the chance |
160 |
# that the initial oracle check passes. |
|
0.82.2
by Bernt M. Johnsen
New config |
161 |
# 2. Run the first trial on a just simplified grammar with the |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
162 |
# last successfull seed value. In case the last |
163 |
# simplification did remove some random determined we |
|
164 |
# should have a bigger likelihood to reach the expected |
|
165 |
# result. |
|
0.82.2
by Bernt M. Johnsen
New config |
166 |
# 3. In case of "threads = 1" it turned out that after a minor |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
167 |
# simplification the desired bad effect disappeared |
168 |
# sometimes on the next run with the same seed value |
|
169 |
# whereas a different seed value was again |
|
170 |
# successful. Therefore we manipulate the seed value. In |
|
171 |
# case of "threads > 1" this manipulation might be not |
|
172 |
# required, but it will not make the conditions worse. |
|
0.82.2
by Bernt M. Johnsen
New config |
173 |
my $current_seed = $good_seed - 1 + $trial; |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
174 |
|
0.85.2
by Matthias Leich
- Corrections in messages |
175 |
my $current_rqg_log = $storage . '/' . $iteration . '-'. $trial . '.log'; |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
176 |
|
0.82.2
by Bernt M. Johnsen
New config |
177 |
my $start_time = Time::HiRes::time(); |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
178 |
|
0.82.2
by Bernt M. Johnsen
New config |
179 |
# Note(mleich): In case of "threads = 1" it turned out that |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
180 |
# after a minor simplification the desired bad effect |
181 |
# disappeared sometimes on the next run with the same |
|
182 |
# seed value whereas a different seed value was again |
|
183 |
# successful. Therefore we manipulate the seed value. In |
|
184 |
# case of "threads > 1" this manipulation might be not |
|
185 |
# required, but it will not make the conditions worse. |
|
186 |
||
0.82.2
by Bernt M. Johnsen
New config |
187 |
my $rqgcmd = |
188 |
"perl runall.pl $rqgoptions $mysqlopt ". |
|
189 |
"--grammar=$current_grammar ". |
|
190 |
"--vardir=$vardir ". |
|
0.67.458
by Matthias Leich
Minor correction so that we catch all errors |
191 |
"--seed=$current_seed >$current_rqg_log 2>&1"; |
0.82.2
by Bernt M. Johnsen
New config |
192 |
|
193 |
say($rqgcmd); |
|
194 |
my $rqg_status = system($rqgcmd); |
|
195 |
$rqg_status = $rqg_status >> 8; |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
196 |
|
0.82.2
by Bernt M. Johnsen
New config |
197 |
my $end_time = Time::HiRes::time(); |
198 |
my $duration = $end_time - $start_time; |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
199 |
|
0.82.2
by Bernt M. Johnsen
New config |
200 |
say("rqg_status = $rqg_status; duration = $duration"); |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
201 |
|
202 |
return ORACLE_ISSUE_NO_LONGER_REPEATABLE |
|
0.82.2
by Bernt M. Johnsen
New config |
203 |
if $rqg_status == STATUS_ENVIRONMENT_FAILURE; |
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
204 |
|
0.82.2
by Bernt M. Johnsen
New config |
205 |
foreach my $desired_status_code (@{$config->desired_status_codes}) { |
206 |
if (($rqg_status == $desired_status_code) || |
|
207 |
(($rqg_status != 0) && ($desired_status_code == STATUS_ANY_ERROR))) { |
|
208 |
# "backtrace" output (independend of server crash |
|
209 |
# or RQG kills the server) is in $current_rqg_log |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
210 |
open (my $my_logfile,'<'.$current_rqg_log) |
0.82.2
by Bernt M. Johnsen
New config |
211 |
or croak "unable to open $current_rqg_log : $!"; |
212 |
# If open (above) did not fail than size |
|
213 |
# determination must be successful. |
|
214 |
my @filestats = stat($current_rqg_log); |
|
215 |
my $filesize = $filestats[7]; |
|
216 |
my $offset = $filesize - $config->search_var_size; |
|
217 |
# Of course read fails if $offset < 0 |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
218 |
$offset = 0 if $offset < 0; |
0.82.2
by Bernt M. Johnsen
New config |
219 |
read($my_logfile, my $rqgtest_output, $config->search_var_size, $offset ); |
220 |
close ($my_logfile); |
|
221 |
# Debug print("$rqgtest_output"); |
|
0.67.459
by Matthias Leich
There is the loop over the trials to get the desired bad effect. |
222 |
|
0.82.2
by Bernt M. Johnsen
New config |
223 |
# Every element of @expected_output must be found |
224 |
# in $rqgtest_output. |
|
225 |
my $success = 1; |
|
226 |
foreach my $expected_output (@{$config->expected_output}) { |
|
227 |
if ($rqgtest_output =~ m{$expected_output}sio) { |
|
228 |
say ("###### Found pattern: $expected_output ######"); |
|
229 |
} else { |
|
230 |
say ("###### Not found pattern: $expected_output ######"); |
|
231 |
$success = 0; |
|
232 |
last; |
|
233 |
}
|
|
234 |
}
|
|
235 |
if ( $success ) { |
|
236 |
say ("###### SUCCESS with $current_grammar ######"); |
|
237 |
$good_seed = $current_seed; |
|
238 |
return ORACLE_ISSUE_STILL_REPEATABLE; |
|
239 |
}
|
|
240 |
} # End of check if the output matches given string patterns |
|
241 |
} # End of loop over desired_status_codes |
|
0.85.2
by Matthias Leich
- Corrections in messages |
242 |
if ($rqg_status == STATUS_OK) { |
243 |
# Run with exit status 0 -> RQG output is not of interest |
|
244 |
unlink($current_rqg_log); |
|
245 |
}
|
|
0.82.2
by Bernt M. Johnsen
New config |
246 |
} # End of loop over the trials |
247 |
return ORACLE_ISSUE_NO_LONGER_REPEATABLE; |
|
248 |
}
|
|
249 |
);
|
|
0.67.1
by Philip Stoev
initial import from internal tree |
250 |
|
251 |
my $simplified_grammar = $simplifier->simplify($initial_grammar); |
|
252 |
||
0.67.9
by Philip Stoev
merge from internal tree |
253 |
print "Simplified grammar:\n\n$simplified_grammar;\n\n" if defined $simplified_grammar; |