Author: REHSACK
Date: Sun May 23 09:33:32 2010
New Revision: 14014

Modified:
   dbi/trunk/t/50dbm_simple.t

Log:
refactor DBD::DBM simple tests to prove each executed statement


Modified: dbi/trunk/t/50dbm_simple.t
==============================================================================
--- dbi/trunk/t/50dbm_simple.t  (original)
+++ dbi/trunk/t/50dbm_simple.t  Sun May 23 09:33:32 2010
@@ -7,20 +7,15 @@
 use Test::More;
 use Cwd;
 use Config qw(%Config);
+use Storable qw(dclone);
 
 my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||'') =~ /^dbi:Gofer.*transport=/i;
 
 use DBI;
 use vars qw( @mldbm_types @dbm_types );
-my $tests_in_group;
 
 BEGIN {
 
-    # Be conservative about what modules we use here.
-    # We don't want to be tripped up by a badly installed module
-    # so we remove from @INC any version-specific dirs that don't
-    # also have an arch-specific dir. Plus, for 5.8 remove any <=5.7
-
     # 0=SQL::Statement if avail, 1=DBI::SQL::Nano
     # next line forces use of Nano rather than default behaviour
     # $ENV{DBI_SQL_NANO}=1;
@@ -28,14 +23,13 @@
 
     push @mldbm_types, '';
     if (eval { require 'MLDBM.pm'; }) {
-        push @mldbm_types, 'Data::Dumper' if eval { require 'Data/Dumper.pm' };
-        push @mldbm_types, 'Storable'     if eval { require 'Storable.pm' };
+       push @mldbm_types, qw(Data::Dumper Storable); # both in CORE
         push @mldbm_types, 'FreezeThaw'   if eval { require 'FreezeThaw.pm' };
     }
 
     # Potential DBM modules in preference order (SDBM_File first)
     # skip NDBM and ODBM as they don't support EXISTS
-    my @dbms = qw(SDBM_File NDBM_File ODBM_File GDBM_File DB_File BerkeleyDB);
+    my @dbms = qw(SDBM_File GDBM_File DB_File BerkeleyDB NDBM_File ODBM_File);
     my @use_dbms = @ARGV;
     if( !...@use_dbms && $ENV{DBD_DBM_TEST_BACKENDS} ) {
        @use_dbms = split ' ', $ENV{DBD_DBM_TEST_BACKENDS};
@@ -60,21 +54,6 @@
             }
         }
     }
-
-    print "Using DBM modules: @dbm_types\n";
-    print "Using MLDBM serializers: @mldbm_types\n" if @mldbm_types;
-
-    $tests_in_group = 15;
-    my $num_tests = @dbm_types * @mldbm_types * $tests_in_group;
-    printf "Test count: %d x %d x %d = %d\n",
-        scalar @dbm_types, 0...@mldbm_types, $tests_in_group, $num_tests;
-       
-    if (!$num_tests) {
-        plan skip_all => "No DBM modules available";
-    }
-    else {
-        plan tests => $num_tests;
-    }
 }
 
 my $dir = File::Spec->catdir(getcwd(),'test_output');
@@ -82,11 +61,76 @@
 rmtree $dir;
 mkpath $dir;
 
-my( $two_col_sql,$three_col_sql ) = split /\n\n/,join '',<DATA>;
+my %expected_results = (
+    2 => [
+       "DROP TABLE IF EXISTS fruit", undef,
+       "CREATE TABLE fruit (dKey INT, dVal VARCHAR(10))", '0E0',
+       "INSERT INTO  fruit VALUES (1,'oranges'   )", 1,
+       "INSERT INTO  fruit VALUES (2,'to_change' )", 1,
+       "INSERT INTO  fruit VALUES (3, NULL       )", 1,
+       "INSERT INTO  fruit VALUES (4,'to delete' )", 1,
+       "INSERT INTO  fruit VALUES (?,?); #5,via placeholders", 1,
+       "INSERT INTO  fruit VALUES (6,'to delete' )", 1,
+       "INSERT INTO  fruit VALUES (7,'to_delete' )", 1,
+       "DELETE FROM  fruit WHERE dVal='to delete'", 2,
+       "UPDATE fruit SET dVal='apples' WHERE dKey=2", 1,
+       "DELETE FROM  fruit WHERE dKey=7", 1,
+       'SELECT * FROM fruit ORDER BY dKey DESC', [
+           [ 5, 'via placeholders' ],
+           [ 3, '' ],
+           [ 2, 'apples' ],
+           [ 1, 'oranges' ],
+       ],
+       "DROP TABLE fruit", -1,
+    ],
+    3 => [
+       "DROP TABLE IF EXISTS multi_fruit", undef,
+       "CREATE TABLE multi_fruit (dKey INT, dVal VARCHAR(10), qux INT)", '0E0',
+       "INSERT INTO  multi_fruit VALUES (1,'oranges'  , 11 )", 1,
+       "INSERT INTO  multi_fruit VALUES (2,'to_change',  0 )", 1,
+       "INSERT INTO  multi_fruit VALUES (3, NULL      , 13 )", 1,
+       "INSERT INTO  multi_fruit VALUES (4,'to_delete', 14 )", 1,
+       "INSERT INTO  multi_fruit VALUES (?,?,?); #5,via placeholders,15", 1,
+       "INSERT INTO  multi_fruit VALUES (6,'to_delete', 16 )", 1,
+       "INSERT INTO  multi_fruit VALUES (7,'to delete', 17 )", 1,
+       "INSERT INTO  multi_fruit VALUES (8,'to remove', 18 )", 1,
+       "UPDATE multi_fruit SET dVal='apples', qux='12' WHERE dKey=2", 1,
+       "DELETE FROM  multi_fruit WHERE dVal='to_delete'", 2,
+       "DELETE FROM  multi_fruit WHERE qux=17", 1,
+       "DELETE FROM  multi_fruit WHERE dKey=8", 1,
+       'SELECT * FROM multi_fruit ORDER BY dKey DESC', [
+           [ 5, 'via placeholders', 15 ],
+           [ 3, undef, 13 ],
+           [ 2, 'apples', 12 ],
+           [ 1, 'oranges', 11 ],
+       ],
+       "DROP TABLE multi_fruit", -1,
+    ],
+);
+
+print "Using DBM modules: @dbm_types\n";
+print "Using MLDBM serializers: @mldbm_types\n" if @mldbm_types;
+
+my $tests_offsets_group = 5;
+my $ndbm_types = scalar @dbm_types;
+my $nmldbm_types = scalar @mldbm_types;
+my $tests_without_mldbm = $tests_offsets_group + 
scalar(@{$expected_results{2}}) / 2 + 1;
+my $tests_with_mldbm = ( $nmldbm_types - 1 ) * ($tests_offsets_group + 
scalar(@{$expected_results{3}})/2 + 1);
+my $num_tests = $ndbm_types * ( $tests_without_mldbm + $tests_with_mldbm );
+printf "Test count: %d x ( ( %d + %d ) + %d x ( %d + %d ) ) = %d\n",
+    scalar $ndbm_types, $tests_offsets_group, scalar(@{$expected_results{2}}) 
/ 2 + 1,
+                        $nmldbm_types - 1, $tests_offsets_group, 
scalar(@{$expected_results{3}})/2 + 1,
+    $num_tests;
+    
+if (!$num_tests) {
+    plan skip_all => "No DBM modules available";
+}
+else {
+    plan tests => $num_tests;
+}
 
 for my $mldbm ( @mldbm_types ) {
-    my $sql = ($mldbm) ? $three_col_sql : $two_col_sql;
-    my @sql = split /\n/, $sql;
+    my @sql = ($mldbm) ? @{$expected_results{3}} : @{$expected_results{2}};
     for my $dbm_type ( @dbm_types ) {
        print "\n--- Using $dbm_type ($mldbm) ---\n";
         eval { do_test( $dbm_type, $mldbm, @sql) }
@@ -95,8 +139,16 @@
 }
 rmtree $dir;
 
+# XXX from PP part of List::MoreUtils
+sub part(&@) {
+    my ($code, @list) = @_;
+    my @parts;
+    push @{ $parts[$code->($_)] }, $_  for @list;
+    return @parts;
+}
+
 sub do_test {
-    my ($dtype, $mldbm, @sql) = @_;
+    my ($dtype, $mldbm, @sqltests) = @_;
 
     my $test_builder = Test::More->builder;
     my $starting_test_no = $test_builder->current_test;
@@ -106,7 +158,7 @@
     # on systems with broken NFS locking daemons.
     # (This test script doesn't test that locking actually works anyway.)
 
-    my $dsn 
="dbi:DBM(RaiseError=0,PrintError=1):dbm_type=$dtype;mldbm=$mldbm;lockfile=0";
+    my $dsn 
="dbi:DBM(RaiseError=0,PrintError=1):dbm_type=$dtype;dbm_mldbm=$mldbm;dbm_lockfile=1";
 
     if ($using_dbd_gofer) {
         $dsn .= ";f_dir=$dir";
@@ -147,87 +199,49 @@
     };
     ok($@);
 
+    # XXX I would prefer use List::Moreutils::part ...
+    my $i = 0;
+    my @tests = part { $i++ % 2 } @sqltests;
+    my @queries = @{$tests[0]};
+    my @results = @{dclone $tests[1]};
+
     SKIP:
-    for my $sql ( @sql ) {
+    for my $idx ( 0 .. $#queries ) {
+       my $sql = $queries[$idx];
         $sql =~ s/\S*fruit/${dtype}_fruit/; # include dbm type in table name
-        $sql =~ s/;$//;  # in case no final \n on last line of __DATA__
+        $sql =~ s/;$//;
         #diag($sql);
-        my $null = '';
-        my $expected_results = {
-            1 => 'oranges',
-            2 => 'apples',
-            3 => $null,
-            5 => 'via placeholders',
-        };
-        $expected_results = {
-            1 => '11',
-            2 => '12',
-            3 => '13',
-            5 => '15',
-        } if $mldbm;
 
-       print " $sql ...";
+        # XXX FIX INSERT with NULL VALUE WHEN COLUMN NOT NULLABLE
+       $dtype eq 'BerkeleyDB' and !$mldbm and 0 == index($sql, 'INSERT') and 
$sql =~ s/NULL/''/;
+
         $sql =~ s/\s*;\s*(?:#(.*))//;
         my $comment = $1;
 
-        my $sth = $dbh->prepare($sql) or die $dbh->errstr;
-        my @bind;
-        @bind = split /,/, $comment if $sth->{NUM_OF_PARAMS};
+        my $sth = $dbh->prepare($sql);
+       unless( $sth ) {
+            skip "prepare failed: " . $dbh->errstr || 'unknown error',
+               ($sql =~ /SELECT/) ? 2 : 1;
+       }
+        my @bind = split /,/, $comment if $sth->{NUM_OF_PARAMS};
         # if execute errors we will handle it, not PrintError:
         $sth->{PrintError} = 0;
         my $n = $sth->execute(@bind);
-       print DBI::neat($n), "\n"; # execute might fail
-        if ($sth->err and $sql !~ /DROP/) {
+        if ($sth->err and $sql !~ /^DROP/ ) {
             skip "execute failed: " . $sth->errstr || 'unknown error',
-                ($starting_test_no + $tests_in_group - 
$test_builder->current_test);
-            die $sth->errstr if $sth->err and $sql !~ /DROP/;
+               ($sql =~ /SELECT/) ? 2 : 1;
         }
+       is( $n, $results[$idx], $sql ) unless( 'ARRAY' eq ref $results[$idx] );
         next unless $sql =~ /SELECT/;
         my $results='';
         # Note that we can't rely on the order here, it's not portable,
         # different DBMs (or versions) will return different orders.
-       my @key_order;
-        while (my ($key, $value) = $sth->fetchrow_array) {
-            ok exists $expected_results->{$key};
-            is $value, $expected_results->{$key};
-           push @key_order, $key;
-        }
-        is $DBI::rows, keys %$expected_results;
-       is_deeply( \...@key_order, [ 5, 3, 2, 1 ], 'select result order' );
+       my $allrows = $sth->fetchall_arrayref();
+       my $expected_rows = $results[$idx];
+       is( $DBI::rows, scalar( @{$expected_rows} ), $sql );
+       is_deeply( $allrows, $expected_rows, 'SELECT results' );
     }
     $dbh->disconnect;
     return 1;
 }
 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' );
-INSERT INTO  fruit VALUES (?,?); #5,via placeholders
-INSERT INTO  fruit VALUES (6,'to delete' );
-INSERT INTO  fruit VALUES (7,'to_delete' );
-DELETE FROM  fruit WHERE dVal='to delete';
-UPDATE fruit SET dVal='apples' WHERE dKey=2;
-DELETE FROM  fruit WHERE dKey=7;
-SELECT * FROM fruit ORDER BY dKey DESC;
-DROP TABLE fruit;
-
-DROP TABLE IF EXISTS multi_fruit;
-CREATE TABLE multi_fruit (dKey INT, dVal VARCHAR(10), qux INT);
-INSERT INTO  multi_fruit VALUES (1,'oranges'  , 11 );
-INSERT INTO  multi_fruit VALUES (2,'to_change',  0 );
-INSERT INTO  multi_fruit VALUES (3, NULL      , 13 );
-INSERT INTO  multi_fruit VALUES (4,'to_delete', 14 );
-INSERT INTO  multi_fruit VALUES (?,?,?); #5,via placeholders,15
-INSERT INTO  multi_fruit VALUES (6,'to_delete', 16 );
-INSERT INTO  multi_fruit VALUES (7,'to delete', 17 );
-INSERT INTO  multi_fruit VALUES (8,'to remove', 18 );
-UPDATE multi_fruit SET dVal='apples', qux='12' WHERE dKey=2;
-DELETE FROM  multi_fruit WHERE dVal='to_delete';
-DELETE FROM  multi_fruit WHERE qux=17;
-DELETE FROM  multi_fruit WHERE dKey=8;
-SELECT dKey,qux FROM multi_fruit ORDER BY dKey DESC;
-DROP TABLE multi_fruit;

Reply via email to