use strict;
use CGI::Wiki;
use CGI::Wiki::Setup::SQLite;
use CGI::Wiki::Store::SQLite;
use CGI::Wiki::TestConfig;
use Test::More tests => 9;
my $class = "CGI::Wiki::Store::SQLite";
eval { $class->new; };
ok( $@, "Failed creation dies" );
my $dbname = $CGI::Wiki::TestConfig::config{SQLite}{dbname};
SKIP: {
skip "No SQLite database configured for testing", 8 unless $dbname;
CGI::Wiki::Setup::SQLite::cleardb( $dbname );
CGI::Wiki::Setup::SQLite::setup( $dbname );
my $store = eval { $class->new( dbname => $dbname ) };
is( $@, "", "Creation doesn't die when given connection parameters" );
isa_ok( $store, $class );
ok( $store->dbh, "...and has set up a database handle" );
my $dbh = DBI->connect( "dbi:SQLite:dbname=$dbname" );
my $store2 = eval { $class->new( dbh => $dbh ) };
is( $@, "", "Creation doesn't die when given dbh" );
isa_ok( $store2, $class );
ok( $store2->dbh, "...and we can access the database handle" );
SKIP: {
eval { require Hook::LexWrap; require Test::MockObject; };
skip "either Hook::LexWrap or Test::MockObject not installed", 2 if $@;
my $wiki = CGI::Wiki->new( store => $store );
# Write some test data.
$wiki->write_node( "Home", "This is the home node." )
or die "Couldn't setup";
# White box testing - override verify_node_checksum to first verify the
# checksum and then if it's OK set up a new wiki object that sneakily
# writes to the node before letting us have control back.
my $temp;
$temp = Hook::LexWrap::wrap( # fully qualify since we're requiring
'CGI::Wiki::Store::Database::verify_checksum',
post => sub {
undef $temp; # Don't want to wrap our sneaking-in
my $node = $_[1];
my $evil_store = $class->new( dbname => $dbname );
my $evil_wiki = CGI::Wiki->new( store => $evil_store );
my %node_data = $evil_wiki->retrieve_node($node);
$evil_wiki->write_node($node, "foo", $node_data{checksum})
or die "Evil wiki got conflict on writing";
} );
# Now try to write to a node -- it should fail.
my %node_data = $wiki->retrieve_node("Home");
ok( ! $wiki->write_node("Home", "bar", $node_data{checksum}),
"write_node handles overlapping write attempts correctly" );
# Check actual real database errors croak rather than flagging conflict
%node_data = $wiki->retrieve_node("Home");
my $dbh = $store->dbh;
$dbh->disconnect;
# Mock a database handle. Need to mock rollback() and disconnect()
# as well to avoid warnings that an unmocked method has been called
# (we don't actually care).
my $fake_dbh = Test::MockObject->new();
$fake_dbh->mock("do", sub { die "Dave told us to"; });
$fake_dbh->set_true("rollback");
$fake_dbh->set_true("disconnect");
$store->{_dbh} = $fake_dbh;
eval {
$store->check_and_write_node( node => "Home",
content => "This is a node.",
checksum => $node_data{checksum} );
};
ok( $@ =~ /Dave told us to/, "...and croaks on database error" );
}
}