#!/usr/bin/perl # # Tests MySQL. Output is given to the stderr. Use # diff to check the possible differencies. # use DBI; use Getopt::Long; $VER = "1.9"; $| = 1; $opt_db = "test"; $opt_user = $opt_password = $opt_without = ""; $opt_host = "localhost"; $opt_port = "3306"; $opt_socket = "/tmp/mysql.sock"; $opt_help = 0; $NO_ERR = 0; # No error $EXP_ERR = 1; # Expect error $MAY_ERR = 2; # Maybe error $HS = 0; # Horizontal style of output $VS = 1; # Vertical style of output $VERBOSE = 0; # Print the results $SILENT = 1; # No output @test_packages = ("FUNC", "PROC", "SHOW"); #### #### main program #### main(); sub main() { GetOptions("help", "db=s", "port=i", "host=s", "password=s", "user=s", "socket=s", "without=s") || usage(); usage() if ($opt_help); $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host:port=$opt_port:mysql_socket=$opt_socket", $opt_user, $opt_password, { PrintError => 0 }) || die $DBI::errstr; ## QQ ###################################### $sth = $dbh->prepare("show felds from t2") || die "Couldn't prepare query: $DBI::errstr\n"; if (!$sth->execute) { print "Couldn't execute query: $DBI::errstr\n"; $sth->finish; die; } while (($row = $sth->fetchrow_arrayref)) { print "$row->[1]\n"; } exit(0); ## QQ ###################################### printf("####\n#### THIS IS mysql-test script RUNNING\n"); printf("#### mysql-test version $VER\n####\n"); test_mysql_functions() if (&chk_package($opt_without, $test_packages[0])); test_mysql_procedures() if (&chk_package($opt_without, $test_packages[1])); test_mysql_show() if (&chk_package($opt_without, $test_packages[2])); print "\n"; return; } #### #### test show -command of MySQL #### sub test_mysql_show { my ($query, $i); $query = create_show_tables(); &exec_query(["drop table my_t"], $MAY_ERR, $SILENT); for ($i = 0; $query[$i]; $i++) { &exec_query([$query[$i]], $NO_ERR, $VERBOSE, $HS); &exec_query(["show fields from my_t"], $NO_ERR, $VERBOSE, $HS); &exec_query(["show keys from my_t"], $NO_ERR, $VERBOSE, $HS); &exec_query(["drop table my_t"], $NO_ERR, $SILENT); } } sub create_show_tables { my ($query, $i); $query[0] = <[0][0]) { printf("No function found!\n"); if (!$force) { die; } } for ($i = 0; $func->[$i][0]; $i++) { $tbused = 0; $no_arg = 0; for ($j = 0; $j < $count && !$no_arg; $j++) { if ($tbused || $no_arg) { next; } $query = "select $func->[$i][0]("; #search the values for the args for ($k = 0; $k < length($func->[$i][1]) && !$no_arg; $k++) { if ($mix) { $arg = $j + 1 + $k; } else { $arg = $j + 1; } if (substr($func->[$i][1], $k, 1) eq 'E') { $no_arg = 1; next; } if ($k) { $query .= ','; } if (substr($func->[$i][1], $k, 1) eq 'S') { $query .= &find_value(\@value, 'S', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'N') { $query .= &find_value(\@value, 'N', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'Z') { $query .= &find_value(\@value, 'Z', $arg); } elsif ((substr($func->[$i][1], $k, 1) eq 'R')) { $query .= &find_value(\@value, 'R', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'T') { $query .= &find_value(\@value, 'T', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'D') { $query .= &find_value(\@value, 'D', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'B') { $query .= &find_value(\@value, 'B', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'C') { $query .= &find_value(\@value, 'C', $arg); } elsif (substr($func->[$i][1], $k, 1) eq 'F') { $query .= &find_value(\@value, 'F', $arg); } elsif (substr($func->[$i][1], $k, 1) eq '.') { chop($query); for ($ulimit = 0; $ulimit < $ulargs; $ulimit++) { $query .= ','; $query .= &find_value(\@value, substr($func->[$i][1], $k - 1, 1), $j + $ulimit + 2); } } elsif (substr($func->[$i][1], $k, 1) eq 'A') { for ($tbinfo = 1; substr($table_info->[$tbinfo], 0, 1) ne substr($func->[$i][1], $k + 1, 1); $tbinfo++) { if (!defined($table_info->[$tbinfo])) { printf("Illegal function structure!\n"); printf("A table was needed, but no type specified!\n"); printf("Unready query was: $query\n"); if (!$force) { die; } else { next; } } } if ($k) { $query .= ","; } $query .= substr($table_info->[$tbinfo], 1, length($table_info->[$tbinfo]) - 1); $k++; $tbused = 1; } else { printf("Not a valid type: \n"); printf(substr($func->[$i][1], $k, 1)); printf("\nAttempted to be used with unready query: \n"); printf("$query\n"); } } $query .= ")"; if ($tbused) { $query .= " from "; $query .= $table_info->[0]; } if (!($sth = $dbh->prepare($query))) { printf("Couldn't prepare: $query\n"); if (!$force) { die; } } if (!$sth->execute) { printf("Execution failed: $DBI::errstr\n"); printf("Attempted query was:\n$query\n"); $sth->finish; if (!$force) { die; } } else { printf("mysql> $query;\n"); display($sth, 1); printf("Query OK\n\n"); } } } } #### #### mk_str returns a string where the first arg is repeated second arg times #### if repeat is 1, return the original str #### sub mk_str() { my ($str, $repeat) = @_; my ($res_str); if ($repeat <= 0) { die "Invalid repeat times!\n"; } for ($repeat--, $res_str = $str; $repeat > 0; $repeat--) { $res_str .= $str; } return $res_str; } #### #### find_value: returns a value from list of values #### args: $values: list of values #### $type: type of argument (S = string, N = integer etc.) #### $ordinal: the ordinal number of an argument in the list #### sub find_value() { my ($values, $type, $ordinal) = @_; my ($total, $i, $j, $tmp, $val); $total = -1; # The first one is the type for ($i = 0; $values[$i][0]; $i++) { if ($values[$i][0] eq $type) { $tmp = $values[$i]; foreach $val (@$tmp) { $total++; } for ( ;$total < $ordinal; ) { $ordinal -= $total; } return $values[$i][$ordinal]; } } printf("No type '$type' found in values\n"); die; } #### #### exec_query: execute a query, print information if wanted and exit #### args: $queries: list of queries to be executed #### $expect_error: if 0, error is not expected. In this case if an #### error occurs, inform about it and quit #### if 1, error is expected. In this case if sql server #### doesn't give an error message, inform about it #### and quit #### if 2, error may happen or not, don't care #### $silent: if true, reduce output #### $style: type of output, 0 == horizontal, 1 == vertical #### sub exec_query() { my ($queries, $expect_error, $silent, $style) = @_; my ($query); foreach $query (@$queries) { if (!($sth = $dbh->prepare($query))) { printf("Couldn't prepare: $query\n"); die; } if (!$sth->execute) { if ($expect_error == 1) { printf("An invalid instruction was purposely made,\n"); printf("server failed succesfully:\n"); printf("$DBI::errstr\n"); printf("Everything OK, continuing...\n"); return; } if ($expect_error != 2) { printf("Execution failed: $DBI::errstr\n"); printf("Attempted query was:\n$query\n"); die; } } if ($expect_error == 1) { printf("An invalid instruction was purposely made,\n"); printf("server didn't note, ALARM!\n"); printf("The query made was: $query\n"); printf("The output from the server:\n"); } if ($expect_error == 2) { return; } if (!$silent) { printf("mysql> $query;\n"); } display($sth, $style); if (!$silent) { printf("Query OK\n\n"); } if ($expect_error) { die; } } return; } #### #### Display to stderr #### Args: 1: ($sth) statememt handler #### 2: ($style) 0 == horizontal style, 1 == vertical style #### sub display() { my ($sth, $style) = @_; my (@data, @max_length, $row, $nr_rows, $nr_cols, $i, $j, $tmp, $mxl); # Store the field names and values in @data. # Store the max field lengths in @max_length for ($i = 0; ($row = $sth->fetchrow_arrayref); $i++) { if (!$i) { $nr_cols = $#$row; for ($j = 0; $j <= $#$row; $j++) { $data[$i][$j] = $sth->{NAME}->[$j]; $max_length[$j] = length($data[$i][$j]); } $i++; } for ($j = 0; $j <= $#$row; $j++) { $data[$i][$j] = $row->[$j]; $max_length[$j] = $tmp if ($max_length[$j] < ($tmp = length($data[$i][$j]))); } } if (!($nr_rows = $i)) { return; } # Display data if ($style == 0) { for ($i = 0; $i < $nr_rows; $i++) { if (!$i) { for ($j = 0; $j <= $nr_cols; $j++) { print "+"; print "-" x ($max_length[$j] + 2); } print "+\n"; } print "|"; for ($j = 0; $j <= $nr_cols; $j++) { print " "; if (defined($data[$i][$j])) { print $data[$i][$j]; $tmp = length($data[$i][$j]); } else { print "NULL"; $tmp = 4; } print " " x ($max_length[$j] - $tmp); print " |"; } print "\n"; if (!$i) { for ($j = 0; $j <= $nr_cols; $j++) { print "+"; print "-" x ($max_length[$j] + 2); } print "+\n"; } } for ($j = 0; $j <= $nr_cols; $j++) { print "+"; print "-" x ($max_length[$j] + 2); } print "+\n"; return; } if ($style == 1) { for ($i = 0; $max_length[$i]; $i++) { $mxl = $max_length[$i] if ($mxl < $max_length[$i]); } for ($i = 1; $i < $nr_rows; $i++) { print "*" x 27; print " " . $i . ". row "; print "*" x 27; print "\n"; for ($j = 0; $j <= $nr_cols; $j++) { print " " x ($mxl - length($data[0][$j])); print "$data[0][$j]: "; if (defined($data[$i][$j])) { print "$data[$i][$j] \n"; } else { print "NULL\n"; } } } return; } } #### #### usage #### sub usage { print <", "#__#"], ["N", -1000, -500, -100, -1, 0, 1, 40, 50, 70, 90, 100, 500, 1000], ["Z", -100, -50, 200, 1000], ["R", -500.5, -10.333, 100.667, 400.0], ["T", 19980728154204, 19980728154205, 19980728154206, 19980728154207], ["D", "'1997-12-06'", "'1997-12-07'", "'1997-12-08'", "'1997-12-09'"], ["B", 1, 0, 0, 1], ["C", "'a'", "'e'", "'r'", "'q'"], ["F", "'%a'", "'%b'", "'%d'", "'%H'"]); &test_func(\@functions, \@values, 4, 5, ["mysql_test1","Zi","Rd"]); printf("\n####\n#### Second basic test part\n####\n\n"); @values = (["S", "'a'", "'BC'", "'def'", "'HIJK'", "'lmnop'", "'QRSTUV'"], ["N", 0, 1, 2, 3, 4, 5], ["Z", 0, 1, 2, 3, 4, 5], ["R", 0, 1, 2, 3, 4, 5], ["T", 19990608234530, 20000709014631, 20010810024732, 20020911034833, 20031012044934, 20041113055035], ["D", "'1999-06-08'", "'2000-07-09'", "'2001-08-10'", "'2002-09-11'", "'2003-10-12'", "'2004-11-13'"], ["B", 0, 1, 0, 1, 0, 1], ["C", "'a'", "'BC'", "'def'", "'HIJK'", "'lmnop'", "'QRSTUV'"], ["F", "'%a'", "'%b'", "'%d'", "'%h'", "'%H'", "'%i'"]); &test_func(\@functions, \@values, 6, 6, ["mysql_test1","Zi","Rd"], 0, 1); printf("\n####\n#### Third basic test part\n####\n\n"); @values = (["S", "'Monty'", "'Jani'", "'MySQL'", "''"], ["N", 10, 54, -70, -499], ["Z", 11.03, "'Abo'", 54.333, "''"], ["R", 12, "'gnome'", -34.211, "''"], ["T", 3, "'Redhat'", -19984021774433, "''"], ["D", "'1990-01-31'", "'-3333-10-23'", -5631_23_12, "''"], ["B", 0, "'asb'", -4, "''"], ["C", "'a'", 503, -45353453, "''"], ["F", "'%a'", -231, "'Mitsubishi'", "''"]); &test_func(\@functions, \@values, 3, 3, ["mysql_test1","Zi","Rd"], 0, 1); &exec_query(["delete from mysql_test1"], $NO_ERR, $SILENT); #### #### Null tests #### printf("\n\n####\n#### NULL TESTS FOR FUNCTIONS\n####\n\n\n"); &exec_query(["insert into mysql_test1 values(null,null)"], $NO_ERR, $SILENT); @values = (["S", "NULL"], ["N", "NULL"], ["Z", "NULL"], ["R", "NULL"], ["T", "NULL"], ["D", "NULL"], ["B", "NULL"], ["C", "NULL"], ["F", "NULL"]); &test_func(\@functions, \@values, 1, 5, ["mysql_test1","Zi","Rd"], 1); &exec_query(["delete from mysql_test1"], $NO_ERR, $SILENT); #### #### Tests to fulfill the main part of function tests above #### printf("\n\n####\n#### FULFILL TESTS \n####\n\n\n"); &exec_query(["drop table my_t"], $MAY_ERR, $SILENT); &exec_query(["create table my_t (s1 char(64), s2 char(64))"], $NO_ERR, $VERBOSE, $HS); $query = <