391 Serge Kozlov 2011-02-19
WL#5576. The test case for NUTS added as combination for stress::basic_stress
added:
suites/stress/
suites/stress/basic/
suites/stress/basic/create_table_select.pl
suites/stress/basic_stress.pm
modified:
lib/My/Nuts/Library/Kernel/ServerResult.pm
390 Serge Kozlov 2011-01-31
rep_func::crash_safe_master
do not compare databases for MyISAM storage engine
modified:
suites/rep_func/crash_safe_master.pm
=== modified file 'lib/My/Nuts/Library/Kernel/ServerResult.pm'
--- a/lib/My/Nuts/Library/Kernel/ServerResult.pm 2011-01-30 21:09:31 +0000
+++ b/lib/My/Nuts/Library/Kernel/ServerResult.pm 2011-02-18 21:07:39 +0000
@@ -3,7 +3,7 @@ use Exporter;
our @ISA = qw(Exporter);
our @EXPORT =
qw(ok_diff_databases diff_databases get_supported_engines get_table_list get_variable get_status
- get_errmsg_by_num ok_wait_status ok_wait_sql dump_sql dump_server_state);
+ get_errmsg_by_num ok_wait_status ok_wait_sql dump_sql dump_server_state sql_result sql_results);
use strict;
use warnings;
use My;
@@ -198,6 +198,29 @@ sub sql_result
return $result;
}
+sub sql_results
+{
+ my ($server, $query) = @_;
+ my $result = undef;
+ my $rs = sql ( $server, $query );
+ if ($rs)
+ {
+ my @rs_data;
+ $result = "";
+ @rs_data = get_next($rs);
+ while (defined($rs_data[0]))
+ {
+ foreach my $item (@rs_data)
+ {
+ $result .= " " . $item;
+ }
+ $result .= "\n";
+ @rs_data = get_next($rs);
+ }
+ }
+ return $result;
+}
+
sub get_supported_engines
{
my ($conn, $filter) = @_;
=== added directory 'suites/stress'
=== added directory 'suites/stress/basic'
=== added file 'suites/stress/basic/create_table_select.pl'
--- a/suites/stress/basic/create_table_select.pl 1970-01-01 00:00:00 +0000
+++ b/suites/stress/basic/create_table_select.pl 2011-02-18 21:07:39 +0000
@@ -0,0 +1,113 @@
+#!/usr/bin/perl -w
+
+# Simple mysql client
+# Parameters:
+# ./create_table_select_client.pl dsn id max_client_num path
+# dsn - dsn of the server
+# id - client id
+# max_client_num - max number of clients
+# path - path to file with list of regular queries
+# (a query per line)
+
+use DBI;
+use strict;
+use warnings;
+
+# Variables
+
+# Command line arguments
+my $dsn = $ARGV[0];
+my $id = $ARGV[1];
+my $max_client_num = $ARGV[2];
+my $qfile = $ARGV[3];
+
+# Variables
+my $dbname = "test_$id";
+my $table_prefix = "ct$id"."_";
+my $sth;
+
+# Connect to DB
+my $dbh = DBI->connect($dsn, "root") or die ("Cannot open connection to mysql server $dsn");
+$dbh->{PrintError} = 0;
+$dbh->{RaiseError} = 0;
+
+# Read queries from file
+open F, $qfile or die ("Cannot open $qfile");
+my @qlines = <F>;
+close F;
+
+# Prepare database
+$dbh->do("DROP DATABASE IF EXISTS $dbname");
+$dbh->do("CREATE DATABASE $dbname");
+$dbh->do("USE $dbname");
+
+# Create functions
+my $create_func = qq{
+ CREATE FUNCTION f1()
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ DELETE FROM t1;
+ RETURN 1;
+ END
+};
+
+$dbh->do($create_func);
+for (my $i = 2; $i <= 10; $i++)
+{
+ my $call_func = $i-1;
+ $create_func = qq{
+ CREATE FUNCTION f$i()
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN f$call_func();
+ END
+ };
+ $dbh->do($create_func);
+}
+
+# Wait until all clients started and connected to server
+# and try to execute statements at same time for all clients
+$dbh->do("INSERT INTO nuts.run_clients VALUES($id)");
+my $cur_client_num = 0;
+until ($cur_client_num == $max_client_num)
+{
+ $sth = $dbh->prepare("SELECT COUNT(*) FROM nuts.run_clients");
+ $sth->execute();
+ ($cur_client_num) = $sth->fetchrow_array();
+ $sth->finish();
+ sleep 1;
+}
+
+# Execute statements
+my $idx= 1;
+foreach my $query (@qlines)
+{
+ $dbh->do($query);
+ # We randomly try run CREATE TABLE SELECT f();
+ if (rand(10) > 7)
+ {
+ my $deep = int(rand(9)) + 1;
+ my $test_query= "CREATE TABLE $table_prefix$idx SELECT f$deep()";
+ my $err_str= undef;
+ $dbh->do($test_query) or $err_str= $dbh->errstr();
+ # We expects an error
+ if (defined($err_str))
+ {
+ # Check text of given error
+ if ($err_str !~ /update table .+while.+is being created/i)
+ {
+ $err_str =~s/\'/\\'/g;
+ $dbh->do("INSERT INTO nuts.client_failures(client_id, client_text) VALUES ($id, '$test_query is failed with another error: $err_str')");
+ }
+ }
+ else
+ {
+ $dbh->do("INSERT INTO nuts.client_failures(client_id, client_text) VALUES ($id, '$test_query is passed but shoud be failed')");
+ }
+ $idx++;
+ }
+}
+
+# Close connection
+$dbh->disconnect;
+
=== added file 'suites/stress/basic_stress.pm'
--- a/suites/stress/basic_stress.pm 1970-01-01 00:00:00 +0000
+++ b/suites/stress/basic_stress.pm 2011-02-18 21:07:39 +0000
@@ -0,0 +1,191 @@
+package stress::basic_stress;
+use Exporter;
+our @ISA = qw(Exporter My::Nuts::Library::Tests::SimpleTest);
+use strict;
+use warnings;
+use IO::File;
+use My;
+use My::Nuts::Library::Kernel::Server;
+use My::Nuts::Library::Kernel::ServerResult;
+use My::Nuts::Library::Kernel::Manager;
+use My::Nuts::Library::Kernel::Result;
+use My::Nuts::Library::Tests::SimpleTest;
+use My::Nuts::Library::DataSource;
+use Test::More;
+
+
+my @client_num = (
+ "5", "20", "50"
+);
+
+my @client_scripts = (
+ "create_table_select"
+);
+
+sub combinations
+{
+ my @combinations= ();
+ foreach my $script ( @client_scripts )
+ {
+ foreach my $num ( @client_num )
+ {
+ push(@combinations, "$script-$num");
+ }
+ }
+ return @combinations;
+}
+
+sub prepare
+{
+ return;
+}
+
+sub startup
+{
+ return;
+}
+
+sub fire
+{
+ my ($test) = @_;
+ my ($client_script, $client_num)= split(/-/, get_combination($test));
+
+ # Read list of statements from data source
+ my $data = get_data_from_source();
+
+ # Store queries to file for clients
+ my $qfile = File::Spec->catfile(get_test_tmp_dir(), "data_source.sql");
+ my $dump_file = new IO::File($qfile, "w+");
+ print $dump_file join("\n", @$data);
+ $dump_file = undef;
+
+ # Subtests
+ plan tests => 5;
+
+ # Run server
+ my $server = ok_server ($test);
+
+ # Create the table which used for start of execution of queries
+ # and for collect results
+ ok_sql ( $server, "CREATE DATABASE IF NOT EXISTS nuts");
+ ok_sql ( $server, "CREATE TABLE nuts.run_clients (run_clients INT NOT NULL DEFAULT 0)");
+ ok_sql ( $server, "CREATE TABLE nuts.client_failures (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, client_id INT NOT NULL, client_text TEXT NOT NULL)");
+ # Main test
+ my @pids = ();
+ my $i;
+ my $dsn = get_dsn($server);
+
+ # Start clients
+ for ($i = 1; $i <= $client_num; $i++)
+ {
+ my $pid = fork();
+ if ( defined ($pid) )
+ {
+ if ( $pid )
+ {
+ # Store pid of client
+ push (@pids, $pid)
+ }
+ else
+ {
+ # Run the client
+ my $client_path= File::Spec->catfile(get_suites_dir(), "stress", "basic", "$client_script.pl");
+ exec($client_path . " $dsn $i $client_num $qfile")
+ or die("Cannot exec $client_path $dsn $i $client_num $qfile");
+ }
+ }
+ else
+ {
+ die("Cannot fork process for client $i");
+ }
+ }
+
+ # Wait until all clients are finished
+ foreach (@pids)
+ {
+ waitpid($_, 0);
+ }
+
+ # Check results
+ my $res_num= sql_result($server, "SELECT COUNT(*) FROM nuts.client_failures");
+ if (!ok ($res_num == 0, "Number of failures generated by clients: $res_num"))
+ {
+ diag(sql_results($server, "SELECT client_id, client_text FROM nuts.client_failures ORDER BY id"));
+ }
+}
+
+sub shutdown
+{
+ return;
+}
+
+1;
+__END__;
+
+=head1 NAME
+
+stress::basic_stress - General stress test for MySQL server
+
+=head1 PURPOSE
+
+The purpose is testing of a given SQL statement in stress environmet
+as part of regular statements.
+
+=head1 SYNOPSYS
+
+Main test (basic_stress )prepares list of regular queries from
+DataSource, stores them into a dump file, start several clients
+(the number depends by current combination) and connect clients to
+MySQL server.
+
+The test creates two tables:
+
+nuts.run_clients - a client puts a row with its id when it is ready
+nuts.client_failures - a client puts rows if a failure happend
+
+The client command line contains the list of following options:
+dsn - DSN to MySQL server
+id - id of this client (it will be inserted into nuts.run_clients by a client)
+num - total number of clients (the client reqiures to know that)
+path - path to DataSource dump
+
+
+Each client starts, connects to DB, inserts its ID into nuts.run_clients
+and waits until numbers of rows of nuts.run_clients will be equal
+total number of running clients.
+Then each client executes statements from dump and randomly adds test queries.
+Client analyzes the results of execution of test queries and insert
+information into nuts.client_failures about the failure.
+
+The test case waits until all clients are finished. Then check
+nuts.client_failures and print its contents if the table is not
+empty.
+
+=head1 HOW TO TEST A NEW SQL STATEMENT?
+
+=over
+
+=item Create own client based on create_table_select.pl in directory 'suites/stress/basic'
+
+=item Add name of client to stress::basic_stress, array @client_scripts
+
+=back
+
+==head1 REFERENCES
+
+=over
+
+=item * WL#5576
+
+=back
+
+=head1 AUTHOR
+
+Serge Kozlov S<< <Serge.Kozlov@stripped> >>
+
+
+=head1 COPYRIGHT
+
+Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+=cut
Attachment: [text/bzr-bundle] bzr/serge.kozlov@oracle.com-20110218210739-r0495yve0nxaw8sf.bundle
| Thread |
|---|
| • bzr push into nuts branch (Serge.Kozlov:390 to 391) WL#5576 | Serge Kozlov | 18 Feb |