allow dynamic selection of which dbs we will test
[bioperl-db.git] / t / DBTestHarness.pm
blob73a262d908c58b215758212d75941e61da214911
2 =pod
4 =head1 NAME - DBTestHarness.pm
6 =head1 SYNOPSIS
8 # Add test dir to lib search path
9 use lib 't';
11 use DBTestHarness;
13 my $harness = DBTestHarness->new();
15 # Load some data into the db
16 $ens_test->do_sql_file("some_data.sql");
18 # Get an Overlap db object for the test db
19 my $db = $harness->db();
21 =head1 DESCRIPTION
23 This is a direct copy-and-paste from the Ensembl
24 EnsTestDB system.
26 It provides an encapsulation of creating, loading
27 and dropping databases for testing
29 =head1 METHODS
31 =cut
33 package DBTestHarness;
35 use strict;
36 use Sys::Hostname 'hostname';
38 use DBI;
39 use Carp;
41 #Package variable for unique database name
42 my $counter=0;
45 # This is a list of possible entries in the config
46 # file "EnsTestDB.conf"
47 my %known_field = map {$_, 1} qw(
48 driver
49 host
50 user
51 port
52 password
53 schema_sql
54 module
57 sub new {
58 my( $pkg,$db ) = @_;
60 $counter++;
61 # Get config from file, or use default values
62 my $self;
63 if( ! $db || $db eq 'basicseqdb' ) {
64 $self = do 'DBHarness.conf' || {
65 'driver' => 'mysql',
66 'host' => 'localhost',
67 'user' => 'root',
68 'port' => undef,
69 'password' => undef,
70 'schema_sql' => ['./sql/basicseqdb-mysql.sql'],
71 'module' => 'Bio::DB::SQL::DBAdaptor'
73 } elsif ( $db eq 'markerdb' ) {
74 $self = do 'DBHarness.markerdb.conf' || {
75 'driver' => 'mysql',
76 'host' => 'localhost',
77 'user' => 'root',
78 'port' => undef,
79 'password' => undef,
80 'schema_sql' => ['./sql/markerdb.sql'],
81 'module' => 'Bio::DB::Map::SQL::DBAdaptor'
84 foreach my $f (keys %$self) {
85 confess "Unknown config field: '$f'" unless $known_field{$f};
87 bless $self, $pkg;
88 $self->create_db;
90 return $self;
94 sub driver {
95 my( $self, $value ) = @_;
97 if ($value) {
98 $self->{'driver'} = $value;
100 return $self->{'driver'} || confess "driver not set";
103 sub host {
104 my( $self, $value ) = @_;
106 if ($value) {
107 $self->{'host'} = $value;
109 return $self->{'host'} || confess "host not set";
112 sub user {
113 my( $self, $value ) = @_;
115 if ($value) {
116 $self->{'user'} = $value;
118 return $self->{'user'} || confess "user not set";
121 sub port {
122 my( $self, $value ) = @_;
124 if ($value) {
125 $self->{'port'} = $value;
127 return $self->{'port'};
130 sub password {
131 my( $self, $value ) = @_;
133 if ($value) {
134 $self->{'password'} = $value;
136 return $self->{'password'};
139 sub schema_sql {
140 my( $self, $value ) = @_;
142 if ($value) {
143 push(@{$self->{'schema_sql'}}, $value);
145 return $self->{'schema_sql'} || confess "schema_sql not set";
148 sub dbname {
149 my( $self ) = @_;
151 $self->{'_dbname'} ||= $self->_create_db_name();
152 return $self->{'_dbname'};
155 # convenience method: by calling it, you get the name of the database,
156 # which you can cut-n-paste into another window for doing some mysql
157 # stuff interactively
158 sub pause {
159 my ($self) = @_;
160 my $db = $self->{'_dbname'};
161 print STDERR "pausing to inspect database; name of databse is: $db\n";
162 print STDERR "press ^D to continue\n";
163 `cat `;
166 sub module {
167 my ($self, $value) = @_;
168 $self->{'module'} = $value if ($value);
169 return $self->{'module'};
172 sub _create_db_name {
173 my( $self ) = @_;
175 my $host = hostname();
176 my $db_name = "_test_db_${host}_$$".$counter;
177 $db_name =~ s{\W}{_}g;
178 return $db_name;
181 sub create_db {
182 my( $self ) = @_;
184 ### FIXME: not portable between different drivers
185 my $locator = 'dbi:'. $self->driver .':host='. $self->host .';database=mysql';
186 my $db = DBI->connect(
187 $locator, $self->user, $self->password, {RaiseError => 1}
188 ) or confess "Can't connect to server";
189 my $db_name = $self->dbname;
190 $db->do("CREATE DATABASE $db_name");
191 $db->disconnect;
193 $self->do_sql_file(@{$self->schema_sql});
196 sub test_locator {
197 my( $self ) = @_;
199 my $locator = 'dbi:'. $self->driver .':database='. $self->dbname;
200 foreach my $meth (qw{ host port }) {
201 if (my $value = $self->$meth()) {
202 $locator .= ";$meth=$value";
205 return $locator;
209 sub db_handle {
210 my( $self ) = @_;
212 unless ($self->{'_db_handle'}) {
213 $self->{'_db_handle'} = DBI->connect(
214 $self->test_locator, $self->user, $self->password, {RaiseError => 1}
215 ) or confess "Can't connect to server";
217 return $self->{'_db_handle'};
220 sub get_DBAdaptor {
221 my( $self ) = @_;
223 my $module = $self->module;
225 return $module->new(
226 -dbname => $self->dbname,
227 -host => $self->host,
228 -user => $self->user,
229 -pass => $self->password,
230 -port => $self->port
235 sub do_sql_file {
236 my( $self, @files ) = @_;
237 local *SQL;
238 my $i = 0;
239 my $dbh = $self->db_handle;
241 foreach my $file (@files)
243 my $sql = '';
244 open SQL, $file or die "Can't read SQL file '$file' : $!";
245 while (<SQL>) {
246 s/(#|--).*//; # Remove comments
247 next unless /\S/; # Skip lines which are all space
248 $sql .= $_;
249 $sql .= ' ';
251 close SQL;
253 #Modified split statement, only semicolumns before end of line,
254 #so we can have them inside a string in the statement
255 foreach my $s (grep /\S/, split /;\n/, $sql) {
256 $self->validate_sql($s);
257 $dbh->do($s);
258 $i++
261 return $i;
264 sub validate_sql {
265 my ($self, $statement) = @_;
266 if ($statement =~ /insert/i)
268 $statement =~ s/\n/ /g; #remove newlines
269 die ("INSERT should use explicit column names (-c switch in mysqldump)\n$statement\n")
270 unless ($statement =~ /insert.+into.*\(.+\).+values.*\(.+\)/i);
274 sub DESTROY {
275 my( $self, $file ) = @_;
277 if (my $dbh = $self->db_handle) {
278 my $db_name = $self->dbname;
279 $dbh->do("DROP DATABASE $db_name");
280 $dbh->disconnect;
287 __END__
289 =head1 AUTHOR
291 James Gilbert B<email> jgrg@sanger.ac.uk