Commit 37763a79 authored by Matthieu Muffato's avatar Matthieu Muffato
Browse files

The SqlHealthcheck runnable can now perform multiple tests

parent e8133a9e
......@@ -9,7 +9,8 @@ Bio::EnsEMBL::Hive::RunnableDB::SqlHealthcheck
standaloneJob.pl Bio::EnsEMBL::Hive::RunnableDB::SqlHealthcheck \
-db_conn mysql://ensro@compara1/mm14_compara_homology_71 \
-inputquery 'SELECT * FROM member WHERE genome_db_id = 90 AND source_name = "ENSEMBLGENE"'
-description 'We expect at least 20,000 human genes' \
-query 'SELECT * FROM member WHERE genome_db_id = 90 AND source_name = "ENSEMBLGENE"' \
-expected_size '>= 20000'
=head1 DESCRIPTION
......@@ -20,15 +21,26 @@ The query is passed by the parameter 'inputquery' (param substituted)
The expected size is passed by the parameter 'expected_size' as a string "CONDITION VALUE" (CONDITION defaults to equality, VALUE defaults to 0).
Currently, CONDITION is one of: = == < <= > >= <> !=
TODO: implement a "expected_value" test
=cut
package Bio::EnsEMBL::Hive::RunnableDB::SqlHealthcheck;
use strict;
use warnings;
use base ('Bio::EnsEMBL::Hive::Process');
sub param_defaults {
return {
description => '/no description/',
}
}
=head2 fetch_input
Description : Implements fetch_input() interface method of Bio::EnsEMBL::Hive::Process that is used to read in parameters and load data.
......@@ -38,73 +50,87 @@ use base ('Bio::EnsEMBL::Hive::Process');
sub fetch_input {
my $self = shift @_;
$self->param_required('inputquery');
$self->param('inputquery') && warn "'inputquery' is deprecated in SqlHealthcheck. Use 'query' instead\n";
my $expected_size = $self->param('expected_size');
unless ($expected_size =~ /^\s*(=|==|>|>=|<|<=|<>|!=|)\s*(\d*)\s*$/) {
die "Cannot interpret the 'expected_size' parameter: '$expected_size'";
}
$self->param('logical_test', $1 || '=');
$self->param('reference_number', $2 || '0');
my $test = {
description => $self->param('description'),
query => $self->param('inputquery') || $self->param_required('query'),
expected_size => $self->param('expected_size'),
};
$self->param('tests', [$test]);
$self->_validate_tests;
}
=head2 run
Description : Implements run() interface method of Bio::EnsEMBL::Hive::Process that is used to perform the main bulk of the job (minus input and output).
=head2 _validate_tests
Description : Checks that the tests are properly defined, and parses the "expected_size"
=cut
sub run {
sub _validate_tests {
my $self = shift @_;
my $reference_number = $self->param('reference_number');
my $logical_test = $self->param('logical_test');
warn "logical test: '$logical_test', $reference_number: '$reference_number'" if ($self->debug());
my $maxrow = $reference_number;
$maxrow++ if grep {$_ eq $logical_test} qw(= == > <= <> !=);
foreach my $test (@{$self->param('tests')}) {
die "The SQL query must be provided" unless $test->{query};
die "The description must be provided" unless $test->{description};
$test->{query} = $self->param_substitute($test->{query});
my $expected_size = $test->{expected_size} || '';
unless ($expected_size =~ /^\s*(=|==|>|>=|<|<=|<>|!=|)\s*(\d*)\s*$/) {
die "Cannot interpret the 'expected_size' parameter: '$expected_size'";
}
$test->{logical_test} = $1 || '=';
$test->{reference_size} = $2 || '0';
delete $test->{expected_size};
}
}
my $nrow = $self->_get_rowcount_bound($maxrow);
=head2 run
if ($logical_test eq '=' or $logical_test eq '==') {
die "At least $nrow rows, different than $reference_number" if $nrow != $reference_number;
Description : Implements run() interface method of Bio::EnsEMBL::Hive::Process
Iterate through the tests and run them all. Report the failed tests at the end
} elsif ($logical_test eq '<' or $logical_test eq '<=') {
die "At least $nrow rows, more then the maximum authorized value" if $nrow >= $maxrow;
} elsif ($logical_test eq '>' or $logical_test eq '>=') {
die "$nrow rows returned in total, less than the minimum authorized value ($maxrow)" if $nrow < $maxrow;
=cut
} elsif ($logical_test eq '<>' or $logical_test eq '!=') {
die "$nrow rows returned in total, exactly the non-authorized value ($reference_number)" if $nrow == $reference_number;
sub run {
my $self = shift @_;
} else {
die "This should not happen. A logical test is not checked";
my @failures = ();
foreach my $test (@{$self->param('tests')}) {
push @failures, $test unless $self->_run_test($test);
}
warn "$nrow rows returned: the test is successful" if ($self->debug());
die "The following tests have failed:\n".join('', map {sprintf(" - %s\n > %s\n", $_->{description}, $_->{query})} @failures) if @failures;
}
=head2 _get_rowcount_bound
=head2 _run_test
Description: Tries to fetch at least $maxrow rows from the database. Returns the actual number of fetched rows.
param('inputquery'); SQL query (against the production database by default) : 'inputquery' => 'SELECT object_id FROM object WHERE x=y'
Description : Runs a single test, defined in a hash with the following keys:
description, query, reference_size, logical_test
=cut
sub _get_rowcount_bound {
my $self = shift @_;
my $maxrow = shift @_;
sub _run_test {
my $self = shift @_;
my $test = shift @_;
my $description = $test->{description};
my $query = $test->{query};
my $reference_size = $test->{reference_size};
my $logical_test = $test->{logical_test};
my $inputquery = $self->param_required('inputquery');
warn "Testing at least '$maxrow' rows of the input query: '$inputquery'" if ($self->debug());
$inputquery .= " LIMIT $maxrow" unless $inputquery =~ /LIMIT/i;
print "Test description: $description\n";
print "Checking whether the number of rows $logical_test $reference_size\n";
my $sth = $self->data_dbc()->prepare($inputquery);
# This could benefit from 'switch' once we move to a more recent version of Perl
my $maxrow = $reference_size;
$maxrow++ if grep {$_ eq $logical_test} qw(= == > <= <> !=);
$query .= " LIMIT $maxrow" unless $query =~ /LIMIT/i;
print "Query: $query\n";
my $sth = $self->data_dbc()->prepare($query);
$sth->{mysql_use_result} = 1 if $self->data_dbc->driver eq 'mysql';
$sth->execute();
......@@ -114,7 +140,28 @@ sub _get_rowcount_bound {
}
$sth->finish;
return $nrow;
print "$nrow rows returned".($nrow == $maxrow ? " (test aborted, there could be more rows)" : "")."\n";
# This could benefit from 'switch' once we move to a more recent version of Perl
my $success = 0;
if ($logical_test eq '=' or $logical_test eq '==') {
$success = 1 if $nrow == $reference_size;
} elsif ($logical_test eq '<' or $logical_test eq '<=') {
$success = 1 if $nrow < $maxrow;
} elsif ($logical_test eq '>' or $logical_test eq '>=') {
$success = 1 if $nrow >= $maxrow;
} elsif ($logical_test eq '<>' or $logical_test eq '!=') {
$success = 1 if $nrow != $reference_size;
} else {
die "This should not happen. A logical test is not checked";
}
warn $success ? "Success\n\n" : "Failure\n\n";
return $success;
}
1;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment