DB-Handy

 view release on metacpan or  search on metacpan

t/1017_regression.t  view on Meta::CPAN

# Embedded test harness (no Test::More dependency)
###############################################################################
my($PASS, $FAIL, $T) = (0, 0, 0);
sub ok {
    my($c, $n) = @_;
    $T++;
    $c ? ($PASS++, print "ok $T - $n\n")
       : ($FAIL++, print "not ok $T - $n\n");
}
sub is {
    my($g, $e, $n) = @_;
    my $got = defined($g) ? $g : 'undef';
    $T++;
    ("$got" eq "$e")
        ? ($PASS++, print "ok $T - $n\n")
        : ($FAIL++, print "not ok $T - $n  (got='$got', exp='$e')\n");
}

my $BASE = File::Spec->catdir(File::Spec->tmpdir, "dbhandy_regr_$$");
File::Path::rmtree($BASE) if -d $BASE;

# Remove the scratch directory however the script leaves: a normal exit,
# a die in mid-file, or an interrupt.  Without this an aborted run left a
# stale tree behind in the system temp directory.
END { File::Path::rmtree($BASE) if defined($BASE) && -d $BASE }

my $db = DB::Handy->new(base_dir => $BASE);
$db->create_database('regr');
$db->use_database('regr');

# Collect any warning the engine emits, so R8 can assert on it.
my @WARN;
$SIG{__WARN__} = sub { push @WARN, $_[0] };

# Flatten a result row set into a comparable string.
sub rowstr {
    my($r, @cols) = @_;
    return 'ERROR' unless $r && ($r->{type} eq 'rows');
    my @out;
    for my $row (@{$r->{data}}) {
        push @out, join(',', map { defined($row->{$_}) ? $row->{$_} : 'NULL' } @cols);
    }
    return join('|', @out);
}

###############################################################################
# Test bodies.  The plan count is derived from this list, never hard-coded.
###############################################################################
my @tests = (

    # -------------------------------------------------------------------
    # R1 -- _load_schema() must not touch the caller's $_
    # -------------------------------------------------------------------
    sub {
        $db->execute('CREATE TABLE r1 (id INT)');
        my @ids = (11, 22, 33);
        for (@ids) { $db->execute("INSERT INTO r1 (id) VALUES ($_)") }
        is(join(',', @ids), '11,22,33', 'R1 - caller @_ array survives execute()');
    },
    sub {
        my $alive = 1;
        # A read-only value would die with "Modification of a read-only value".
        eval {
            $db->{_tables} = {};
            for (44) { $db->execute("INSERT INTO r1 (id) VALUES ($_)") }
        };
        $alive = 0 if $@;
        ok($alive, 'R1 - constant list element is not modified');
    },
    sub {
        $db->{_tables} = {};
        my @seen = map { $db->execute('SELECT id FROM r1 WHERE id = 11'); $_ } (1, 2, 3);
        is(join(',', @seen), '1,2,3', 'R1 - $_ intact inside map');
    },

    # -------------------------------------------------------------------
    # R2 -- LIMIT / OFFSET with no WHERE / ORDER BY / GROUP BY
    # -------------------------------------------------------------------
    sub {
        $db->execute('CREATE TABLE r2 (id INT, s VARCHAR(10))');
        $db->execute("INSERT INTO r2 (id,s) VALUES ($_,'v$_')") for 1 .. 5;
        my $r = $db->execute('SELECT id FROM r2 LIMIT 2');
        is(scalar(@{$r->{data}}), 2, 'R2 - bare LIMIT is honoured');
    },
    sub {
        my $r = $db->execute('SELECT id FROM r2 OFFSET 3');
        is(scalar(@{$r->{data}}), 2, 'R2 - bare OFFSET is honoured');
    },
    sub {
        my $r = $db->execute('SELECT * FROM r2 LIMIT 1');
        is(scalar(@{$r->{data}}), 1, 'R2 - SELECT * with bare LIMIT');
    },
    sub {
        my $r = $db->execute('SELECT id FROM r2 ORDER BY id LIMIT 2 OFFSET 1');
        is(rowstr($r, 'id'), '2|3', 'R2 - ORDER BY with LIMIT/OFFSET still works');
    },
    sub {
        my $r = $db->execute('SELECT id FROM r2 WHERE id > 1 LIMIT 2');
        is(scalar(@{$r->{data}}), 2, 'R2 - WHERE with LIMIT still works');
    },

    # -------------------------------------------------------------------
    # R3 -- CHECK constraint versus NULL
    # -------------------------------------------------------------------
    sub {
        $db->execute('CREATE TABLE r3 (id INT, age INT CHECK (age >= 0))');
        my $r = $db->execute('INSERT INTO r3 (id,age) VALUES (1,5)');
        is($r->{type}, 'ok', 'R3 - value satisfying CHECK is accepted');
    },
    sub {
        my $r = $db->execute('INSERT INTO r3 (id) VALUES (2)');
        is($r->{type}, 'ok', 'R3 - omitted checked column is accepted');
    },
    sub {
        my $r = $db->execute('INSERT INTO r3 (id,age) VALUES (3,NULL)');
        is($r->{type}, 'ok', 'R3 - explicit NULL passes CHECK');
    },
    sub {
        my $r = $db->execute('INSERT INTO r3 (id,age) VALUES (4,-1)');
        is($r->{type}, 'error', 'R3 - value violating CHECK is still rejected');
    },
    sub {
        my $r = $db->execute('UPDATE r3 SET age = -9 WHERE id = 1');
        is($r->{type}, 'error', 'R3 - UPDATE violating CHECK is still rejected');
    },
    sub {
        my $r = $db->execute('UPDATE r3 SET age = 7 WHERE id = 1');
        is($r->{type}, 'ok', 'R3 - UPDATE satisfying CHECK is accepted');



( run in 1.866 second using v1.01-cache-2.11-cpan-14f38c9f855 )