~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to tests/randgen/util/simplify-grammar.pl

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-10-29 15:43:40 UTC
  • mfrom: (1.2.12) (2.1.19 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131029154340-2gp39el6cv8bwf2o
Tags: 1:7.2.3-2ubuntu1
* Merge from debian, remaining changes:
  - Link against boost_system because of boost_thread.
  - Add required libs to message/include.am
  - Add upstart job and adjust init script to be upstart compatible.
  - Disable -floop-parallelize-all due to gcc-4.8/4.9 compiler ICE
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57732

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
18
 
use strict;
19
 
use lib 'lib';
20
 
use lib '../lib';
21
 
use DBI;
22
 
use Carp;
23
 
use Getopt::Long;
24
 
use Data::Dumper;
25
 
 
26
 
use GenTest;
27
 
use GenTest::Constants;
28
 
use GenTest::Grammar;
29
 
use GenTest::Properties;
30
 
use GenTest::Simplifier::Grammar;
31
 
use Time::HiRes;
32
 
 
33
 
#
34
 
# RQG grammar simplification with an oracle() function based on
35
 
# 1. RQG exit status codes (-> desired_status_codes)
36
 
# 2. expected RQG protocol output (-> expected_output)
37
 
# Hint: 2. will be not checked if 1. already failed
38
 
#
39
 
# You need to adjust parameters to your use case and environment.
40
 
# 1. Copy simplify-grammar_template.cfg to for example 1.cfg
41
 
# 2. Adjust the settings
42
 
# 2. perl util/simplify-grammar.pl --config 1.cfg
43
 
#
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
51
 
#
52
 
# For more information, please see:
53
 
#
54
 
# http://forge.mysql.com/wiki/RandomQueryGeneratorSimplification
55
 
#
56
 
 
57
 
# get configuration
58
 
 
59
 
my $options = {};
60
 
GetOptions($options, 'config=s', 'trials=i','storage_prefix=s','expected_output=s@');
61
 
my $config = GenTest::Properties->new(
62
 
    options => $options,
63
 
    legal => ['desired_status_codes',
64
 
              'expected_output',
65
 
              'initial_grammar_file',
66
 
              'mask',
67
 
              'mask-level',
68
 
              'grammar_flags',
69
 
              'trials',
70
 
              'initial_seed',
71
 
              'search_var_size',
72
 
              'rqg_options',
73
 
              'vardir_prefix',
74
 
              'storage_prefix'],
75
 
    required=>['rqg_options',
76
 
               'initial_grammar_file',
77
 
               'vardir_prefix',
78
 
               'storage_prefix'],
79
 
    defaults => {expected_output => [],
80
 
                 desired_status_codes => [+STATUS_ANY_ERROR]}
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');
97
 
 
98
 
# Determine some runtime parameter, check parameters, ....
99
 
 
100
 
my $run_id = time();
101
 
 
102
 
say("The ID of this run is $run_id.");
103
 
 
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
 
}
116
 
 
117
 
if ( ! -d $config->vardir_prefix ) {
118
 
   croak("vardir_prefix '" . $config->vardir_prefix . "' is not an existing directory");
119
 
}
120
 
 
121
 
# Calculate a unique vardir (use $MTR_BUILD_THREAD or $run_id)
122
 
 
123
 
my $vardir = $config->vardir_prefix . '/var_' . $run_id;
124
 
mkdir ($vardir);
125
 
push my @mtr_options, "--vardir=$vardir";
126
 
 
127
 
if ( ! -d $config->storage_prefix) {
128
 
   croak("storage_prefix '" . $config->storage_prefix . "' is not an existing directory");
129
 
}
130
 
my $storage = $config->storage_prefix.'/'.$run_id;
131
 
say "Storage is $storage";
132
 
mkdir ($storage);
133
 
 
134
 
my $errfile = $vardir . '/log/master.err';
135
 
 
136
 
my $iteration;
137
 
my $good_seed = $config->initial_seed;
138
 
 
139
 
my $simplifier = GenTest::Simplifier::Grammar->new(
140
 
    grammar_flags => $config->grammar_flags,
141
 
    oracle => sub {
142
 
        $iteration++;
143
 
        my $oracle_grammar = shift;
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
 
 
152
 
        foreach my $trial (1..$config->trials) {
153
 
            say("run_id = $run_id; iteration = $iteration; trial = $trial");
154
 
 
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
159
 
            #    $config->initial_seed .  This should raise the chance
160
 
            #    that the initial oracle check passes.
161
 
            # 2. Run the first trial on a just simplified grammar with the
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.
166
 
            # 3. In case of "threads = 1" it turned out that after a minor
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.
173
 
            my $current_seed = $good_seed - 1 + $trial;
174
 
 
175
 
            my $current_rqg_log = $storage . '/' . $iteration . '-'. $trial . '.log';
176
 
 
177
 
            my $start_time = Time::HiRes::time();
178
 
 
179
 
            # Note(mleich): In case of "threads = 1" it turned out that
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
 
 
187
 
            my $rqgcmd =
188
 
                "perl runall.pl $rqgoptions $mysqlopt ".
189
 
                "--grammar=$current_grammar ".
190
 
                "--vardir=$vardir ".
191
 
                "--seed=$current_seed >$current_rqg_log 2>&1";
192
 
 
193
 
            say($rqgcmd);
194
 
            my $rqg_status = system($rqgcmd);
195
 
            $rqg_status = $rqg_status >> 8;
196
 
 
197
 
            my $end_time = Time::HiRes::time();
198
 
            my $duration = $end_time - $start_time;
199
 
 
200
 
            say("rqg_status = $rqg_status; duration = $duration");
201
 
 
202
 
            return ORACLE_ISSUE_NO_LONGER_REPEATABLE
203
 
                if $rqg_status == STATUS_ENVIRONMENT_FAILURE;
204
 
 
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
210
 
                    open (my $my_logfile,'<'.$current_rqg_log)
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
218
 
                    $offset = 0 if $offset < 0;
219
 
                    read($my_logfile, my $rqgtest_output, $config->search_var_size, $offset );
220
 
                    close ($my_logfile);
221
 
                    # Debug print("$rqgtest_output");
222
 
 
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
242
 
            if ($rqg_status == STATUS_OK) {
243
 
               # Run with exit status 0 -> RQG output is not of interest
244
 
               unlink($current_rqg_log);
245
 
            }
246
 
        } # End of loop over the trials
247
 
        return ORACLE_ISSUE_NO_LONGER_REPEATABLE;
248
 
    }
249
 
    );
250
 
 
251
 
my $simplified_grammar = $simplifier->simplify($initial_grammar);
252
 
 
253
 
print "Simplified grammar:\n\n$simplified_grammar;\n\n" if defined $simplified_grammar;