Author: timbo
Date: Tue Oct 19 14:21:34 2010
New Revision: 14502

Added:
   dbi/trunk/xt/
   dbi/trunk/xt/README
   dbi/trunk/xt/dbixha-goperf.pl   (contents, props changed)
   dbi/trunk/xt/goferdemo.pl
   dbi/trunk/xt/leak.pl
   dbi/trunk/xt/tests.pl   (contents, props changed)

Log:
Add xt directory with assorted stuff I had not checked in before

Added: dbi/trunk/xt/README
==============================================================================
--- (empty file)
+++ dbi/trunk/xt/README Tue Oct 19 14:21:34 2010
@@ -0,0 +1,2 @@
+This directory contains assorted 'extra tests' and random development stuff
+that doesn't have a better home. Feel free to ignore.

Added: dbi/trunk/xt/dbixha-goperf.pl
==============================================================================
--- (empty file)
+++ dbi/trunk/xt/dbixha-goperf.pl       Tue Oct 19 14:21:34 2010
@@ -0,0 +1,166 @@
+#!perl -w
+# vim:sw=4:ts=8
+$|=1;
+
+use strict;
+use warnings;
+
+use Cwd;
+use Time::HiRes qw(time);
+use Data::Dumper;
+use Getopt::Long;
+
+use DBI;
+
+GetOptions(
+    'c|count=i' => \(my $opt_count = 100),
+    'dsn=s'     => \(my $opt_dsn   = "dbi:NullP:"),
+    'timeout=i' => \(my $opt_timeout = 10),
+    'p|policy=s' => \(my $opt_policy = "pedantic,classic,rush"),
+) or exit 1;
+
+if ($ENV{DBI_AUTOPROXY}) {
+    # this means we have DBD::Gofer => DBD::Gofer => DBD::DBM!
+    # rather than disable it we let it run because we're twisted
+    # and because it helps find more bugs (though debugging can be painful)
+    warn "\n$0 is running with DBI_AUTOPROXY enabled ($ENV{DBI_AUTOPROXY})\n";
+}
+
+# ensure subprocess (for pipeone and stream transport) will use the same 
modules as us, ie ./blib
+local $ENV{PERL5LIB} = join ":", @INC;
+
+my %durations;
+my $username = eval { getpwuid($>) } || ''; # fails on windows
+my $can_ssh = ($username && $username eq 'timbo' && -d '.svn');
+my $perl = "$^X"; # ensure sameperl and our blib (note two spaces)
+   # ensure blib (note two spaces)
+   $perl .= sprintf "  -Mblib=%s/blib", getcwd() if $ENV{PERL5LIB} =~ 
m{/blib/};
+
+my %trials = (
+    null       => {},
+    pipeone    => { perl=>$perl, timeout=>$opt_timeout },
+    stream     => { perl=>$perl, timeout=>$opt_timeout },
+    stream_ssh => ($can_ssh)
+                ? { perl=>$perl, timeout=>$opt_timeout, url => 
"ssh:$userna...@localhost" }
+                : undef,
+    http       => { url => "http://localhost:8001/gofer"; },
+);
+
+my $dbixha_attr = { RaiseError => 1 };
+$DATABASE::conf{'test'} = {
+    max_retries => 2,
+    db_stack => [
+        [ 'dbi:NullP:server=prod1;database=test', 'user1', 'password1', 
$dbixha_attr ],
+        [ 'dbi:NullP:server=prod2;database=test', 'user2', 'password2', 
$dbixha_attr ],
+        [ 'dbi:NullP:server=prod3;database=test', 'user3', 'password3', 
$dbixha_attr ],
+        ],
+    pingtimeout     => -1,
+    failoverlevel   => 'application',
+    connecttimeout  => 1,
+    executetimeout  => 8,
+    callback_function => sub { 1 },
+};
+
+use DBIx::HA;
+DBIx::HA->initialize();
+my $dbixha_dbh = DBIx::HA->connect('test');
+run_tests('foo', 'bar', $dbixha_dbh);
+
+# to get baseline for comparisons
+my $d = connect_and_run_tests('no', {}, 'no')->clone;
+
+run_tests('no2', 'no2', $d);
+run_tests('no3', 'no3', $d);
+
+run_tests('foo2', 'bar2', $dbixha_dbh);
+
+for my $trial (@ARGV) {
+    (my $transport = $trial) =~ s/_.*//;
+    my $trans_attr = $trials{$trial} or do {
+        warn "No trial '$trial' defined - skipped";
+        next;
+    };
+
+    for my $policy_name (split /\s*,\s*/, $opt_policy) {
+        eval { connect_and_run_tests($transport, $trans_attr, $policy_name) };
+        warn $@ if $@;
+    }
+}
+
+while ( my ($activity, $stats_hash) = each %durations ) {
+    print "\n";
+    $stats_hash->{'~baseline~'} = delete $stats_hash->{"no+no"};
+    for my $perf_tag (reverse sort keys %$stats_hash) {
+        my $dur = $stats_hash->{$perf_tag};
+        printf "  %6s %-16s: %.6fsec (%5d/sec)",
+            $activity, $perf_tag, $dur/$opt_count, $opt_count/$dur;
+        my $baseline_dur = $stats_hash->{'~baseline~'};
+        printf " %+6.2fms", (($dur-$baseline_dur)/$opt_count)*1000
+            unless $perf_tag eq '~baseline~';
+        print "\n";
+    }
+}
+
+
+sub connect_and_run_tests {
+    my ($transport, $trans_attr, $policy_name) = @_;
+
+    my $test_run_tag = "Testing $transport transport with $policy_name policy";
+    print "\n$test_run_tag\n";
+
+    my $dsn = $opt_dsn;
+    if ($policy_name ne 'no') {
+        my $driver_dsn = "transport=$transport;policy=$policy_name";
+        $driver_dsn .= join ";", '', map { "$_=$trans_attr->{$_}" } keys 
%$trans_attr
+            if %$trans_attr;
+        $dsn = "dbi:Gofer:$driver_dsn;dsn=$opt_dsn";
+    }
+    print " $dsn\n";
+
+    my $dbh = DBI->connect($dsn, undef, undef, { RaiseError => 1 } );
+    run_tests($transport, $policy_name, $dbh);
+    $dbh->disconnect;
+    return $dbh;
+}
+
+sub run_tests {
+    my ($transport, $policy_name, $dbh) = @_;
+    $dbh->do("DROP TABLE IF EXISTS fruit");
+    $dbh->do("CREATE TABLE fruit (dKey INT, dVal VARCHAR(10))");
+    my $ins_sth = $dbh->prepare("INSERT INTO fruit VALUES (?,?)");
+    $ins_sth->execute(1, 'apples');
+    $ins_sth->execute(2, 'oranges');
+    $ins_sth->execute(3, 'lemons');
+    $ins_sth->execute(4, 'limes');
+
+    my $start = time();
+    $dbh->selectall_arrayref("SELECT dKey, dVal FROM fruit")
+        for (1000..1000+$opt_count);
+    $durations{select}{"$transport+$policy_name"} = time() - $start;
+
+    # insert some rows in to get a (*very* rough) idea of overheads
+    $start = time();
+    $ins_sth->execute($_, 'speed')
+        for (1000..1000+$opt_count);
+    $durations{insert}{"$transport+$policy_name"} = time() - $start;
+    $dbh->do("DROP TABLE fruit");
+}
+
+sub get_policy {
+    my ($policy_class) = @_;
+    $policy_class = "DBD::Gofer::Policy::$policy_class" unless $policy_class 
=~ /::/;
+    _load_class($policy_class) or die $@;
+    return $policy_class->new();
+}
+
+sub _load_class { # return true or false+$@
+    my $class = shift;
+    (my $pm = $class) =~ s{::}{/}g;
+    $pm .= ".pm"; 
+    return 1 if eval { require $pm };
+    delete $INC{$pm}; # shouldn't be needed (perl bug?) and assigning undef 
isn't enough
+    undef; # error in $@
+}   
+
+
+1;

Added: dbi/trunk/xt/goferdemo.pl
==============================================================================
--- (empty file)
+++ dbi/trunk/xt/goferdemo.pl   Tue Oct 19 14:21:34 2010
@@ -0,0 +1,48 @@
+#!perl -w
+$|=1;
+
+use strict;
+use File::Path;
+use File::Spec;
+use Cwd;
+
+use DBI;
+
+$ENV{DBI_SQL_NANO}=1;
+
+my $dir = File::Spec->catdir(getcwd(),'test_output');
+rmtree $dir;
+mkpath $dir;
+
+my $dtype = 'SDBM_File';
+
+my $dbh = DBI->connect( "dbi:DBM:dbm_type=$dtype;lockfile=0" );
+
+for my $sql ( split /\s*;\n/, join '',<DATA> ) {
+    $sql =~ s/\S*fruit/${dtype}_fruit/; # include dbm type in table name
+    $sql =~ s/;$//;  # in case no final \n on last line of __DATA__
+    print " $sql\n";
+    my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+    $sth->execute;
+    die $sth->errstr if $sth->err and $sql !~ /DROP/;
+    next unless $sql =~ /SELECT/;
+    while (my ($key, $value) = $sth->fetchrow_array) {
+        print "$key: $value\n";
+    }
+}
+$dbh->disconnect;
+
+rmtree $dir;
+exit 0;
+1;
+__DATA__
+DROP TABLE IF EXISTS fruit;
+CREATE TABLE fruit (dKey INT, dVal VARCHAR(10));
+INSERT INTO  fruit VALUES (1,'oranges'   );
+INSERT INTO  fruit VALUES (2,'to_change' );
+INSERT INTO  fruit VALUES (3, NULL       );
+INSERT INTO  fruit VALUES (4,'to delete' );
+UPDATE fruit SET dVal='apples' WHERE dKey=2;
+DELETE FROM  fruit WHERE dVal='to delete';
+SELECT * FROM fruit;
+SELECT * FROM fruit;

Added: dbi/trunk/xt/leak.pl
==============================================================================
--- (empty file)
+++ dbi/trunk/xt/leak.pl        Tue Oct 19 14:21:34 2010
@@ -0,0 +1,82 @@
+#!/usr/bin/env perl
+    use strict;
+    use warnings;
+    use DBI;
+    use Devel::Leak;
+    use Test::More;
+    
+    # some dsn configuration
+    my %dsn = (
+        sqlite => [ 'dbi:SQLite:dbname=test.sql', '', '' ],
+        #mysql  => [ 'dbi:mysql:test',             '', '' ],
+        #csv    => [ 'dbi:CSV:',                   '', '' ],
+    );
+    
+    # generic SQL
+    my %SQL = (
+        drop   => 'DROP TABLE IF EXISTS tok',
+        create => 'CREATE TABLE tok (kuk INT, zat INT, sob TEXT)',
+        insert => 'INSERT INTO tok (kuk, zat, sob) VALUES (?,?,?)',
+        select => 'SELECT kuk, zat, sob FROM tok',
+    );
+    
+    my @tests = (
+        q{my $sanity = 1;},    # simple sanity test (eval "" doesn't leak)
+        q{my $s = $dbh->trace(0) },
+        q{my $s = $dbh->prepare($sql) },
+        q{my $s = $dbh->prepare($sql); $s->execute(); },
+        q{my $s = $dbh->prepare( $sql ); $s->execute(); 1 while 
$s->fetchrow_arrayref(); $s->finish;},
+        q{my $s = $dbh->prepare_cached( $sql ); $s->execute(); 1 while 
$s->fetchrow_arrayref(); $s->finish;},
+        q{my $c = $dbh->selectcol_arrayref( $sql, { Column => [1] } )},
+        q{my @a = $dbh->selectrow_array( $sql )},
+        q{my $a = $dbh->selectrow_arrayref( $sql )},
+    );
+    
+    # plan
+    plan tests => @tests * keys %dsn;
+    
+    my $empty = "";
+    for my $dbd ( sort keys %dsn ) {
+    
+      SKIP: {
+    
+            # connect to the test db
+            my $dbh =
+              eval { DBI->connect( @{ $dsn{$dbd} }, { RaiseError => 1 } ); };
+    
+            skip "Connection to $dbd failed: $@", scalar @tests if !$dbh;
+    
+            # initialize the table
+            $dbh->do( $SQL{drop} );
+            $dbh->do( $SQL{create} );
+    
+            # fill in some data
+            my $sth;
+            $sth = $dbh->prepare( $SQL{insert} );
+            $sth->execute( $_, 100 - $_, 'x' x $_ ) for 1 .. 30;
+    
+            # test each command
+            for my $cmd (@tests) {
+    
+                # get the SQL statement
+                my $sql = $SQL{select};
+                $cmd = $cmd.q{; $dbh->{Statement}="";};
+    
+                # run once, in case some internal structures get initialized
+                eval $cmd;
+    
+                # now look for leakage
+                my $c1 = Devel::Leak::NoteSV( my $h );
+                {
+                    eval $cmd;
+                }
+                my $c2 = Devel::Leak::CheckSV($h);
+                diag $@ if $@;
+    
+                my $leak = $c2 - $c1;
+                is( $leak, 0, sprintf "\tleak=%2d for %-8s%s", $leak, $dbd, 
$cmd );
+            }
+            warn 
"##########################################################################\n";
+    
+        }
+    }

Added: dbi/trunk/xt/tests.pl
==============================================================================
--- (empty file)
+++ dbi/trunk/xt/tests.pl       Tue Oct 19 14:21:34 2010
@@ -0,0 +1,201 @@
+#!/usr/local/bin/perl -w
+
+# $Id: test.pl 6734 2006-07-30 22:42:07Z timbo $
+#
+# Copyright (c) 1994-1998 Tim Bunce
+#
+# See COPYRIGHT section in DBI.pm for usage and distribution rights.
+
+
+# This is now mostly an empty shell I experiment with.
+# The real tests have moved to t/*.t
+# See t/*.t for more detailed tests.
+
+
+BEGIN {
+    print "$0 @ARGV\n";
+    print q{DBI test application $Revision: 11.7 $}."\n";
+    $| = 1;
+}
+
+use blib;
+
+use DBI;
+
+use DBI::DBD;  # simple test to make sure it's okay
+
+use Config;
+use Getopt::Long;
+use strict;
+
+our $has_devel_leak = eval {
+    local $^W = 0; # silence "Use of uninitialized value $DynaLoader::args[0] 
in subroutine entry";
+    require Devel::Leak;
+};
+
+$::opt_d = 0;
+$::opt_l = '';
+$::opt_h = 0;
+$::opt_m = 0;          # basic memory leak test: "perl test.pl -m NullP"
+$::opt_t = 0;          # thread test
+$::opt_n = 0;          # counter for other options
+
+GetOptions(qw(d=i h=i l=s m=i t=i n=i))
+    or die "Usage: $0 [-d n] [-h n] [-m] [-t n] [-n n] [drivername]\n";
+
+my $count = 0;
+my $ps = (-d '/proc') ? "ps -lp " : "ps -l";
+my $driver = $ARGV[0] || ($::opt_m ? 'NullP' : 'ExampleP');
+
+# Now ask for some information from the DBI Switch
+my $switch = DBI->internal;
+$switch->debug($::opt_h); # 2=detailed handle trace
+
+DBI->trace($::opt_d, $::opt_l) if $::opt_d || $::opt_l;
+
+print "Switch: $switch->{'Attribution'}, $switch->{'Version'}\n";
+
+print "Available Drivers: ",join(", ",DBI->available_drivers(1)),"\n";
+
+
+my $dbh = DBI->connect("dbi:$driver:", '', ''); # old-style connect syntax
+$dbh->debug($::opt_h);
+
+if (0) {
+    DBI->trace(3);
+    my $h = DBI->connect('dbi:NullP:','','', { RootClass=>'MyTestDBI', 
DbTypeSubclass=>'foo, bar' });
+    DBI->trace(0);
+    { # only works after 5.004_04:
+       warn "RaiseError= '$h->{RaiseError}' (pre local)\n";
+       local($h->{RaiseError});# = undef;
+       warn "RaiseError= '$h->{RaiseError}' (post local)\n";
+    }
+    warn "RaiseError= '$h->{RaiseError}' (post local block)\n";
+    exit 1;
+}
+
+if ($::opt_m) {
+    #$dbh->trace(9);
+    my $level = $::opt_m;
+    my $cnt = 10000;
+    print "Using $driver, same dbh...\n";
+    for (my $i=0; $i<$cnt; ++$i) { mem_test($dbh, undef, $level, undef, undef, 
undef) }
+    print "Using NullP, reconnecting each time...\n";
+    for (my $i=0; $i<$cnt; ++$i) { mem_test(undef, ['dbi:NullP:'], $level, 
undef, undef, undef) }
+    print "Using ExampleP, reconnecting each time...\n";
+    my $r_develleak = 0;
+    mem_test(undef, ['dbi:NullP:'], $level, undef, undef, \$r_develleak) while 
1;
+    #mem_test(undef, ['dbi:mysql:VC'], $level, "select * from campaigns where 
length(?)>0", 0, undef) while 1;
+}
+elsif ($::opt_t) {
+       thread_test();
+}
+else {
+    
+    # new experimental connect_test_perf method
+    DBI->connect_test_perf("dbi:$driver:", '', '', {
+       dbi_loops=>5, dbi_par=>20, dbi_verb=>1
+    });
+
+    require Benchmark;
+    print "Testing handle creation speed...\n";
+    my $null_dbh = DBI->connect('dbi:NullP:','','');
+    my $null_sth = $null_dbh->prepare('');     # create one to warm up
+    $count = 10_000;
+    my $i = $count;
+    my $t1 = new Benchmark;
+    $null_dbh->prepare('') while $i--;
+    my $td = Benchmark::timediff(Benchmark->new, $t1);
+    my $tds= Benchmark::timestr($td);
+    my $dur = $td->cpu_a || (1/$count); # fudge if cpu_a==0
+
+    printf "%5d NullP sth/s perl %8s %s (%s %s %s)\n\n",
+           $count/$dur, $], $Config{archname},
+           $Config{gccversion} ? 'gcc' : $Config{cc},
+           (split / /, $Config{gccversion}||$Config{ccversion}||'')[0]||'',
+           $Config{optimize};
+
+  if (0) {
+    $null_dbh = DBI->connect('dbi:mysql:VC_log','','',{RaiseError=>1});
+    $null_sth = $null_dbh->prepare('select * from big');
+    $null_sth->execute();
+    $t1 = new Benchmark;
+    1 while ($null_sth->fetchrow_hashref());
+    #1 while ($null_sth->fetchrow_arrayref());
+    $td = Benchmark::timediff(Benchmark->new, $t1);
+    $tds= Benchmark::timestr($td);
+    $dur = $td->cpu_a;
+    printf "$DBI::rows in $tds\n";
+  }
+}
+
+#DBI->trace(4);
+print "$0 done\n";
+exit 0;
+
+
+sub mem_test { # harness to help find basic leaks
+    my ($orig_dbh, $connect, $level, $select, $params, $r_develleak) = @_;
+    $select ||= "select mode,ino,name from ?";
+    $params ||= [ '.' ];
+
+    # this can be used to force a 'leak' to check memory use reporting
+    #$main::leak .= " " x 1000;
+    system("echo $count; $ps$$") if (($count++ % 500) == 0);
+
+    my $dbh = $orig_dbh || DBI->connect(@$connect);
+    $dbh->{RaiseError} = 1;
+    my $cursor_a;
+
+    my ($dl_count, $dl_handle);
+    if ($$r_develleak++) {
+        $dbh->trace(2);
+        $dl_count = Devel::Leak::NoteSV($dl_handle);
+    }
+
+    $cursor_a = $dbh->prepare($select)         if $level >= 2;
+    $cursor_a->execute(@$params)               if $level >= 3;
+    $cursor_a->fetchrow_hashref()              if $level >= 4;
+    my $rows = $cursor_a->fetchall_arrayref({})        if $level >= 4;
+    $cursor_a->finish if $cursor_a && $cursor_a->{Active};
+    undef $cursor_a;
+
+    @{$dbh->{ChildHandles}} = ();
+
+    die Devel::Leak::CheckSV($dl_handle)-$dl_count
+        if $dl_handle;
+
+    $dbh->disconnect unless $orig_dbh;
+    undef $dbh;
+
+}
+
+
+sub thread_test {
+    require Thread;
+    my $dbh = DBI->connect("dbi:ExampleP:.", "", "") || die $DBI::err;
+    #$dbh->trace(4);
+    my @t;
+    print "Starting $::opt_t threads:\n";
+    foreach(1..$::opt_t) {
+       print "$_\n";
+       push @t, Thread->new(\&thread_test_loop, $dbh, $::opt_n||99);
+    }
+    print "Small sleep to allow threads to progress\n";
+    sleep 2;
+    print "Joining threads:\n";
+    foreach(@t) {
+       print "$_\n";
+       $_->join
+    }
+}
+
+sub thread_test_loop {
+    my $dbh = shift;
+    my $i = shift || 10;
+    while($i-- > 0) {
+       $dbh->selectall_arrayref("select * from ?", undef, ".");
+    }
+}
+
+# end.

Reply via email to