1
# Copyright (c) 2008,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::Mixer;
26
use GenTest::Constants;
28
use GenTest::Validator;
30
use constant MIXER_GENERATOR => 0;
31
use constant MIXER_EXECUTORS => 1;
32
use constant MIXER_VALIDATORS => 2;
33
use constant MIXER_FILTERS => 3;
34
use constant MIXER_PROPERTIES => 4;
43
my $mixer = $class->SUPER::new({
44
'generator' => MIXER_GENERATOR,
45
'executors' => MIXER_EXECUTORS,
46
'validators' => MIXER_VALIDATORS,
47
'properties' => MIXER_PROPERTIES,
48
'filters' => MIXER_FILTERS
51
foreach my $executor (@{$mixer->executors()}) {
52
my $init_result = $executor->init();
53
return undef if $init_result > STATUS_OK;
54
$executor->cacheMetaData();
57
my @validators = @{$mixer->validators()};
60
# If a Validator was specified by name, load the class and create an object.
62
foreach my $i (0..$#validators) {
63
my $validator = $validators[$i];
64
if (ref($validator) eq '') {
65
$validator = "GenTest::Validator::".$validator;
66
say("Loading Validator $validator.");
67
eval "use $validator" or print $@;
68
$validators[$i] = $validator->new();
70
$validators[$i]->configure($mixer->properties);
72
$validators{ref($validators[$i])}++;
75
# Query every object for its prerequisies. If one is not loaded, load it and place it
76
# in front of the Validators array.
79
foreach my $validator (@validators) {
80
my $prerequisites = $validator->prerequsites();
81
next if not defined $prerequisites;
82
foreach my $prerequisite (@$prerequisites) {
83
next if exists $validators{$prerequisite};
84
$prerequisite = "GenTest::Validator::".$prerequisite;
85
# say("Loading Prerequisite $prerequisite, required by $validator.");
86
eval "use $prerequisite" or print $@;
87
push @prerequisites, $prerequisite->new();
91
my @validators = (@prerequisites, @validators);
92
$mixer->setValidators(\@validators);
94
foreach my $validator (@validators) {
95
return undef if not defined $validator->init($mixer->executors());
104
my $executors = $mixer->executors();
105
my $filters = $mixer->filters();
107
my $queries = $mixer->generator()->next($executors);
108
if (not defined $queries) {
109
say("Internal grammar problem. Terminating.");
110
return STATUS_ENVIRONMENT_FAILURE;
111
} elsif ($queries->[0] eq '') {
112
# say("Your grammar generated an empty query.");
113
# return STATUS_ENVIRONMENT_FAILURE;
116
my $max_status = STATUS_OK;
118
query: foreach my $query (@$queries) {
119
next if $query =~ m{^\s*$}o;
121
if (defined $filters) {
122
foreach my $filter (@$filters) {
123
my $explain = Dumper $executors->[0]->execute("EXPLAIN $query") if $query =~ m{^\s*SELECT}sio;
124
my $filter_result = $filter->filter($query." ".$explain);
125
next query if $filter_result == STATUS_SKIP;
129
my @execution_results;
130
foreach my $executor (@$executors) {
131
my $execution_result = $executor->execute($query);
132
$max_status = $execution_result->status() if $execution_result->status() > $max_status;
133
push @execution_results, $execution_result;
135
# If one server has crashed, do not send the query to the second one in order to preserve consistency
136
if ($execution_result->status() == STATUS_SERVER_CRASHED) {
137
say("Server crash reported at dsn ".$executor->dsn());
142
foreach my $validator (@{$mixer->validators()}) {
143
my $validation_result = $validator->validate($executors, \@execution_results);
144
$max_status = $validation_result if ($validation_result != STATUS_WONT_HANDLE) && ($validation_result > $max_status);
149
# Record the lowest (best) status achieved for all participating rules. The goal
150
# is for all rules to generate at least some STATUS_OK queries. If not, the offending
151
# rules will be reported on DESTROY.
154
if ((rqg_debug()) && (ref($mixer->generator()) eq 'GenTest::Generator::FromGrammar')) {
155
my $participating_rules = $mixer->generator()->participatingRules();
156
foreach my $participating_rule (@$participating_rules) {
158
(not exists $rule_status{$participating_rule}) ||
159
($rule_status{$participating_rule} > $max_status)
161
$rule_status{$participating_rule} = $max_status
172
foreach my $rule (keys %rule_status) {
173
push @rule_failures, "$rule (".status2text($rule_status{$rule}).")" if $rule_status{$rule} > STATUS_OK;
176
if ($#rule_failures > -1) {
177
say("The following rules produced no STATUS_OK queries: ".join(', ', @rule_failures));
182
return $_[0]->[MIXER_GENERATOR];
186
return $_[0]->[MIXER_EXECUTORS];
190
return $_[0]->[MIXER_VALIDATORS];
194
return $_[0]->[MIXER_PROPERTIES];
198
return $_[0]->[MIXER_FILTERS];
202
$_[0]->[MIXER_VALIDATORS] = $_[1];