One Hat Cyber Team
Your IP :
216.73.216.135
Server IP :
194.44.31.54
Server :
Linux zen.imath.kiev.ua 4.18.0-553.77.1.el8_10.x86_64 #1 SMP Fri Oct 3 14:30:23 UTC 2025 x86_64
Server Software :
Apache/2.4.37 (Rocky Linux) OpenSSL/1.1.1k
PHP Version :
5.6.40
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
home
/
vo
/
perl
/
mod
/
Msql-Mysql-modules-1.2211
/
tests
/
View File Name :
mysql.t
#!/my/gnu/bin/perl -w # very slightly modified version of msql.t as in the MsqlPerl version # 1.16 # Running the testscript with a hostname as $ARGV[0] runs the test via # a TCP socket. Per default we connect to the unix socket to avoid # problems you might have with resolving "localhost". Too many systems # are configured wrong in this respect. But you're welcome to test it # out. my $host = shift @ARGV || $ENV{'DBI_HOST'} || "~~test_host~~"; my $user = shift @ARGV || $ENV{'DBI_USER'} || "~~test_user~~"; my $password = shift @ARGV || $ENV{'DBI_PASS'} || "~~test_pass~~"; my $dbname = shift @ARGV || $ENV{'DBI_DB'} || "~~test_db~~"; # That's the standard perl way tostart a testscript. It announces that # that many tests are to follow. And it does so before anything can go # wrong; BEGIN { do ((-f "lib.pl") ? "lib.pl" : "t/lib.pl"); if ($mdriver ne "mysql") { print "1..0\n"; exit 0; } print "1..68\n"; } use Mysql; # Force yourself to strict programming. See man strict for details. # use strict; # Variables we're going to use my( $query, $firsttable, $secondtable, $dbh, $dbh2, $dbh3, $sth, $i, @row, %hash, ); # You may connect in two steps: (1) Connect and (2) SelectDB... if ($dbh = Mysql->connect($host, $dbname, $user, $password)){ print "ok 1\n"; } else { $Mysql::db_errstr ||= ""; my $onhost = $host ? " (on $host)" : ""; print STDERR qq{not ok 1: $Mysql::db_errstr \tIt looks as if your server$onhost is not up and running. \tThis test requires a running server. \tPlease make sure your server is running and retry. }; exit; } if ($dbh->selectdb($dbname)){ print("ok 2\n"); } else { die qq{not ok 2: $Mysql::db_errstr Please make sure that a database \"$dbname\" exists and that you have permission to read and write on it }; } # Or you may call connect with two arguments, the first being the # host, and the second being the DB if ($dbh = Mysql->connect($host,$dbname,$user,$password)){ print("ok 3\n"); } else { die "not ok 3: $Mysql::db_errstr\n"; } # For the error messages we're going to produce within this script we # write a subroutine, so the typical error message will always look # more or less similar: sub test_error { my($id,$query,$error) = @_; $id ||= "?"; # Newer Test::Harness will accept that $query ||= ""; # query is optional $query = "\n\tquery $query" if $query; $error ||= Mysql->errmsg; # without error we ask Mysql print qq{Not ok $id:\n\terrmsg $error$query\n}; } # Now we create two tables that are certainly not in the test database # If you don't understand the trickery here, just skip this section, No big deal. { my $goodtable = "TABLE00"; my(%foundtable,@foundtable); @foundtable = $dbh->listtables; @foundtable{@foundtable} = (1) x @foundtable; # all existing tables are now keys in %foundtable my $limit = 0; for ($firsttable, $secondtable) { while () { next if $foundtable{++$goodtable}; my $query = qq{ create table $goodtable ( she char(32), him char(32) not null, who char (32) ) }; unless ($dbh->query($query)){ die "Cannot create table: query [$query] message [$Mysql::db_errstr]\n" if $limit++ > 1000; next; } $_ = $goodtable; last; } } # For the tests in this script we have two tablenames that we can # peruse: $firsttable and $secondtable } # Now we write some test records into the two tables. Note, we *know*, # these tables are empty print "Writing some test records.\n"; for $query ( "insert into $firsttable values ('Anna', 'Franz', 'Otto')" , "insert into $firsttable values ('Sabine', 'Thomas', 'Pauline')" , "insert into $firsttable values ('Jane', 'Paul', 'Jah')" , "insert into $secondtable values ('Henry', 'Francis', 'James')" , "insert into $secondtable values ('Cashrel', 'Beco', 'Lotic')" ) { $dbh->query($query) or test_error(0,$query); } $query = "select * from $firsttable"; $sth = $dbh->query($query) or test_error(0,$query); ($sth->numrows == 3) and print("ok 4\n") or print("not ok 4\n"); # three rows ($sth->numfields == 3) and print("ok 5\n") or print("not ok 5\n"); # three columns # There is the array reference $sth->name. It has to have as many # fields as $sth->numfields tells us print "Checking numfields.\n"; (@{$sth->name} == $sth->numfields) and print ("ok 6\n") or print("not ok 6\n"); # There is the array reference $sth->table. We expect, that all three # fields in the array have the same value, as we only selected from # $firsttable print "Checking table.\n"; $sth->table->[0] eq $firsttable and print ("ok 7\n") or print("not ok 7\n"); $sth->table->[1] eq $sth->table->[2] and print ("ok 8\n") or print("not ok 8\n"); # CHAR_TYPE, NUM_TYPE and REAL_TYPE are exported functions from # Mysql. That is why you have to say 'use Mysql'. The functions are # really constants, but that's the way headerfile constants are # handled in perl5 up to 5.001m (will probably change soon) print "Checking type.\n"; CHAR_TYPE() == $sth->type->[0] and print ("ok 9\n") or print("not ok 9\n"); print "Checking number of rows.\n"; { # Now we count the rows ourselves, we don't trust anybody my $rowcnt=0; while (@row = $sth->fetchrow()){ $rowcnt++; } # We haven't yet tested DataSeek, so lets count again $sth->dataseek(0); while (@row = $sth->fetchrow()){ $rowcnt++; } # $rowcount now==6, twice the number of rows we've seen ($rowcnt/2 == $sth->numrows) and print ("ok 10\n") or print("not ok 10\n"); } # let's see the second table $sth = $dbh->query("select * from $secondtable") or test_error(); # We set the second field "not null". Does the API know that? $sth->is_not_null->[1] > 0 and print ("ok 11\n") or print("not ok 11\n"); # Are we able to just reconnect with the *same* scalar ($dbh) playing # the role of the db-handle? if ($dbh = Mysql->connect($host,$dbname,$user,$password)){ print("ok 12\n"); } else { print "not ok 12: $Mysql::db_errstr\n"; } # We may have an arbitrary number of statementhandles. Each # statementhandle consumes memory, so in reality we try to scope them # with my() within a block or we reuse them or we undef them. { # Declare the statement handle as lexically scoped (see man # perlfunc and search for 'my EXPR') Don't forget to scope other # variables too, that you won't need outside the block my($sth1,$sth2,@row1,$count); $sth1 = $dbh->query("select * from $firsttable") or warn "Query had some problem: $Mysql::db_errstr\n"; $sth2 = $dbh->query("select * from $secondtable") or warn "Query had some problem: $Mysql::db_errstr\n"; # You have seen this above, so NO COMMENT :) $count=0; while ($sth2->fetchrow and @row1 = $sth1->fetchrow){ $count++; } $count == 2 and print ("ok 13\n") or print("not ok 13\n"); # When we undef this handle, the memory associated with it is # freed undef ($sth2); $count=0; while (@row1 = $sth1->fetchrow){ $count++; } $count == 1 and print ("ok 14\n") or print("not ok 14\n"); # When we leave this block, the memory associated with $sth1 is # freed } # What happens, when we have errors? # Yes, there's a typo: we add a paren to the statement { # The use of the -w switch is really a good idea in general, but # if you want the -w switch but do NOT want to see Mysql's error # messages, you can turn them off using $Mysql::QUIET local($Mysql::QUIET) = 1; # In reality we would say "or die ...", but in this case we forgot it: $sth = $dbh->query ("select * from $firsttable where him = 'Thomas')"); # $Mysql::db_errstr should contain the word "error" now $dbh->errmsg =~ /error/ and print("ok 15\n") or print("not ok 15\n"); } # Now $sth should be undefined, because the query above failed. If we # try to use this statementhandle, we should die. We don't want to # die, because we are in atest script. So we check what happens with # eval eval "\@row = \$sth->fetchrow;"; if ($@){print "ok 16\n"} else {print "not ok 16\n"} # Remember, we inserted a row into table $firsttable ('Sabine', # 'Thomas', 'Pauline'). Let's see, if they are still there. $sth = $dbh->query ("select * from $firsttable where him = 'Thomas'") or warn "query had some problem: $Mysql::db_errstr\n"; @row = $sth->fetchrow or warn "$firsttable didn't find a matching row"; $row[2] eq "Pauline" and print ("ok 17\n") or print("not ok 17\n"); { # %fieldnum is a hash that associates the index number for each field # name: my %fieldnum; @fieldnum{@{$sth->name}} = 0..@{$sth->name}-1; # %fieldnum is now (she => 0, him => 1, who => 2) # So we do not have to hard-code the zero for "she" here $row[$fieldnum{"she"}] eq 'Sabine' and print ("ok 18\n") or print("not ok 18\n"); } # After 18 tests, the database handle may feel the desire to rest. Or # maybe the writer of this script has forgotten, that he is already # connected # While in reality you should use your database connections # economically -- they cost you a slot in the server connection table, # and you can easily run out of available slots -- we, in the test # script want to know what happens with more than one handle if ($dbh2 = Mysql->connect($host,$dbname,$user,$password)){ print("ok 19\n"); } else { print "not ok 19\n"; } # Some quick checks about the contents of the handle... $dbh2->database eq $dbname and print("ok 20\n") or print("not ok 20\n"); $dbh2->sock =~ /^\d+$/ and print("ok 21\n") or print("not ok 21\n"); # Is $dbh2 able to drop a table, while we are connected with $dbh? # Sure it can... $dbh2->query("drop table $secondtable") and print("ok 22\n") or print("not ok 22\n"); { # Does ListDBs find the test database? Sure... my @array = $dbh2->listdbs; grep( /^$dbname$/, @array ) and print("ok 23\n") or print("not ok 23\n"); # Does ListTables now find our $firsttable? @array = $dbh2->listtables; grep( /^$firsttable$/, @array ) and print("ok 24\n") or print("not ok 24\n"); } # The third connection within a single script. I promise, this will do... if ($dbh3 = Connect Mysql($host,$dbname,$user,$password)){ print("ok 25\n"); } else { test_error(25,"connect->$host"); } $dbh3->host eq $host and print("ok 26\n") or print "not ok 26\n"; $dbh3->database eq $dbname and print("ok 27\n") or print "not ok 27\n"; # For what it's worth, we have a tough job for the server here. First # we define two simple subroutines. The goal of these is to make the # create table statement independent of what happens on the server # side. If the table cannot be created we magic increment the # suggested name and retry. We return the incremented table name. With # this setting we can run the test script in parallel in many # processes. sub create { my($db,$tablename,$createexpression) = @_; my($query) = "create table $tablename $createexpression"; my $limit = 0; while (! $db->query($query)){ die "Cannot create table: query [$query] message [$Mysql::db_errstr]\n" if $limit++ > 1000; $tablename++; $query = "create table $tablename $createexpression"; } $tablename; } sub drop { shift->query("drop table $_[0]"); } # Then we insert some nonsense changing the dbhandle quickly { my $C="AAAA"; my $N=1; drop($dbh2,$firsttable); $firsttable = create($dbh2,$firsttable,"( name char(40) not null, num int, country char(4), mytime real )"); for (1..5){ $dbh2->query("insert into $firsttable values ('".$C++."',".$N++.",'".$C++."',".rand().")") or test_error(); $dbh3->query("insert into $firsttable values ('".$C++."',".$N++.",'".$C++."',".rand().")") or test_error(); } } # I haven't shown you yet a cute (and dirty) trick to save memory. As # ->query returns an object you can reference this object in a single # chain of -> operators. The statement handle is not preserved, and # the memory associated with it is cleaned up within a single # statement. 'Course you never know, which part of the statement # failed--if something fails. $dbh2->query("select * from $firsttable")->numrows == 10 and print("ok 28\n") or print("not ok 28\n"); # Interesting the following test. Creating and dropping of tables via # two different database handles in quick alteration. There was really # a version of Mysql that messed up with this for (1..3){ drop($dbh2,$firsttable); $secondtable = create($dbh3,$secondtable,"( name char(40) not null, num int, country char(4), mytime real )"); drop($dbh2,$secondtable); $firsttable = create($dbh3,$firsttable,"( name char(40) not null, num int, country char(4), mytime real )"); } drop($dbh2,$firsttable) and print("ok 29\n") or print("not ok 29\n"); # A quick check, if the array @{$sth->length} is available and # correct. See man perlref for an explanation of this kind of # referencing/dereferencing. Watch out, that we still use an old # statement handle here. The corresponding table has been overwritten # quite a few times, but as we are dealing with an in-memeory copy, we # still have it available if ("@{$sth->length}" eq "32 32 32"){ print "ok 30\n"; } else { print "not ok 30\n"; } # Here were two useless tests a while back that didn't please me after # a while print "ok 31\n"; print "ok 32\n"; # The following tests show, that NULL fields (introduced with # Mysql-1.0.6) are handled correctly: if ($dbh->getserverinfo lt 2) { # Before version 2 we have the "primary key" syntax $firsttable = create($dbh,$firsttable,"( she char(14) primary key not null, him int, who char(1))") or test_error(); } else { $firsttable = create($dbh,$firsttable,"( she char(14) not null, him int, who char(1))") or test_error(); $dbh->query("create unique index she_index on $firsttable ( she )") or test_error(); } # As you see, we don't insert a value for "him" and "who", so we can # test the undefinedness $dbh->query("insert into $firsttable (she) values ('jazz')") or test_error; $sth = $dbh->query("select * from $firsttable") or test_error; @row = $sth->fetchrow() or test_error; # "she" is "jazz", thusly defined if (defined $row[0]) { print "ok 33\n"; } else { print "not ok 33\n"; } # field "him", a character field, should not be defined if (defined $row[1]) { print "not ok 34\n"; } else { print "ok 34\n"; } # field "who", an integer field, should not be defined if (defined $row[2]) { print "not ok 35\n"; } else { print "ok 35\n"; } # So far we have evaluated metadata in scalar context. Let's see, # if array context works $i = 35; foreach (qw/table name type is_not_null is_pri_key length/) { my @arr = $sth->$_(); if (@arr == 3){ print "ok ", ++$i, "\n"; } else { print "not ok ", ++$i, ": @arr\n"; } } # mSQL: A non-select should return TRUE, and if anybody tries to use this # mSQL: return value as an object reference, we should not core dump # In mysql a query always return an object! { local($Mysql::QUIET) = 1; $sth = $dbh->query("insert into $firsttable values (\047x\047,2,\047y\047)"); if (!defined($sth->fetchrow)) { print "ok 42\n"; } } { my($sth_query,$sth_listf,$method); # So many people have problems using the ListFields method, # so we finally provide a simple example. $sth_query = $dbh->query("select * from $firsttable"); $sth_listf = $dbh->listfields($firsttable); $i = 43; for $method (qw/name table length type is_not_null is_pri_key/) { for (0..$sth_query->numfields -1) { # whatever we do to the one statementhandle, the other one has # to behave exactly the same way if ($sth_query->$method()->[$_] eq $sth_listf->$method()->[$_]) { print "ok $i\n" ; } else { print "not ok $i\n"; } $i++; } } # The only difference: the ListFields sth must not have a row associated with local($^W) = 0; my($got) = $sth_listf->numrows; if (!defined $got or $got == 0) { print "ok 61\n"; } else { print "not ok 61 - got [$got]\n"; } if ($sth_query->numrows > 0) { print "ok 62\n"; } else { print "not ok 62\n"; } # Please understand that features that were added later to the module # are tested later. Here's a very nice test. Should be easier to # understand than the others: $sth_query->dataseek(0); $i = 63; while (%hash = $sth_query->fetchhash) { # fetchhash stuffs the contents of the row directly into a hash # instead of a row. We have only two lines to check. Column she # has to be either 'jazz' or 'x'. if ($hash{she} eq 'jazz' or $hash{she} eq 'x') { print "ok $i\n"; } else { print "not ok $i\n"; } $i++; } } $dbh->query("drop table $firsttable") or test_error; # Although it is a bad idea to specify constants in lowercase, # I have to test if it is supported as it has been documented: if (Mysql::int___type() == INT_TYPE) { print "ok 65\n"; } else { print "not ok 65\n"; } # Let's create another table where we inspect if we can insert # 8 bit characters: # For mysql, changed character to charactr and char(1) to blob $query = "create table $firsttable (ascii int, charactr blob)"; $dbh->query($query) or test_error; my $nchar; for $nchar (1..255) { my $chr = $dbh->quote(chr($nchar)); $query = qq{ insert into $firsttable values ($nchar, $chr) }; unless ($dbh->query($query)) { $query = unctrl($query); print "not ok 66 (q[$query] err[$Mysql::db_errstr])\n"; # well, could happen more thn once, but ... } } sub unctrl { my $str = shift; $str =~ s/([\000-\037\177])/ '^' . pack('c', ord($1) ^ 64) /eg; return $str; } $sth = $dbh->query("select * from $firsttable") or test_error; if ($sth->numrows() == 255){ print "ok 66\n"; } else { print "not ok 66\n"; } while (%hash = $sth->fetchhash) { $hash{charactr} eq chr($hash{ascii}) or print "not ok 67 [char no $hash{ascii}]\n"; } print "ok 67\n"; $dbh->query("drop table $firsttable") or test_error; # mSQL up to 1.0.16 had this annoying lost table bug, so I try to # force our users to upgrade to 1.0.17 { my @created = (); local($Mysql::QUIET) = 1; # create 8 tables for (1..8) { push @created, create($dbh,$firsttable,q{(foo char(1))}); } # reference all 8 so they are cached for (@created) { $dbh->listfields($_); } # reference a non existant table my $nonexist = "NONEXIST"; $nonexist++ while grep /^$nonexist$/, $dbh->listtables; $dbh->listfields($nonexist); # reference the first table in the cache: 1.0.16 did not know the contents if ( $dbh->listfields($created[0])->numfields == 0) { my $version = $dbh->getserverinfo; print "not ok 68\n"; print STDERR "Your version $version of the mSQL has a serious bug, \teither upgrade the server to > 1.0.16 or read the file patch.lost.tables\n"; } else { print "ok 68\n"; } # drop the eight tables for (@created) { drop($dbh,$_); } }