line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Wiki::Toolkit::TestLib; |
2
|
|
|
|
|
|
|
|
3
|
39
|
|
|
39
|
|
79459
|
use 5.006; #by perlver |
|
39
|
|
|
|
|
343
|
|
4
|
39
|
|
|
39
|
|
204
|
use strict; |
|
39
|
|
|
|
|
75
|
|
|
39
|
|
|
|
|
889
|
|
5
|
39
|
|
|
39
|
|
2400
|
use Carp "croak"; |
|
39
|
|
|
|
|
70
|
|
|
39
|
|
|
|
|
3164
|
|
6
|
39
|
|
|
39
|
|
19367
|
use Wiki::Toolkit; |
|
39
|
|
|
|
|
108
|
|
|
39
|
|
|
|
|
1268
|
|
7
|
39
|
|
|
39
|
|
18295
|
use Wiki::Toolkit::TestConfig; |
|
39
|
|
|
|
|
145
|
|
|
39
|
|
|
|
|
1306
|
|
8
|
39
|
|
|
39
|
|
58523
|
use DBI; |
|
39
|
|
|
|
|
647696
|
|
|
39
|
|
|
|
|
2738
|
|
9
|
|
|
|
|
|
|
|
10
|
39
|
|
|
39
|
|
378
|
use vars qw( $VERSION @wiki_info ); |
|
39
|
|
|
|
|
76
|
|
|
39
|
|
|
|
|
29892
|
|
11
|
|
|
|
|
|
|
$VERSION = '0.05'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Wiki::Toolkit::TestLib - Utilities for writing Wiki::Toolkit tests. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 DESCRIPTION |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
When 'perl Makefile.PL' is run on a Wiki::Toolkit distribution, |
20
|
|
|
|
|
|
|
information will be gathered about test databases etc that can be used |
21
|
|
|
|
|
|
|
for running tests. Wiki::Toolkit::TestLib gives convenient access to this |
22
|
|
|
|
|
|
|
information. |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use strict; |
27
|
|
|
|
|
|
|
use Wiki::Toolkit::TestLib; |
28
|
|
|
|
|
|
|
use Test::More; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my $iterator = Wiki::Toolkit::TestLib->new_wiki_maker; |
31
|
|
|
|
|
|
|
plan tests => ( $iterator->number * 6 ); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
while ( my $wiki = $iterator->new_wiki ) { |
34
|
|
|
|
|
|
|
# put some test data in |
35
|
|
|
|
|
|
|
# run six tests |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Each time you call C<< ->next >> on your iterator, you will get a |
39
|
|
|
|
|
|
|
fresh blank wiki object. The iterator will iterate over all configured |
40
|
|
|
|
|
|
|
search and storage backends. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
The Lucy search backend will be configured to index three metadata fields: |
43
|
|
|
|
|
|
|
address, category, and locale. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=cut |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my %configured = %Wiki::Toolkit::TestConfig::config; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
my %datastore_info; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
foreach my $dbtype (qw( MySQL Pg SQLite )) { |
52
|
|
|
|
|
|
|
if ( $configured{$dbtype}{dbname} ) { |
53
|
|
|
|
|
|
|
my %config = %{ $configured{$dbtype} }; |
54
|
|
|
|
|
|
|
my $store_class = "Wiki::Toolkit::Store::$dbtype"; |
55
|
|
|
|
|
|
|
my $setup_class = "Wiki::Toolkit::Setup::$dbtype"; |
56
|
|
|
|
|
|
|
eval "require $store_class"; |
57
|
|
|
|
|
|
|
if ( $@ ) { |
58
|
|
|
|
|
|
|
warn "Couldn't require $store_class: $@\n"; |
59
|
|
|
|
|
|
|
warn "Will skip $dbtype tests.\n"; |
60
|
|
|
|
|
|
|
next; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
my $dsn = $store_class->_dsn( @config{ qw( dbname dbhost dbport ) } ); |
63
|
|
|
|
|
|
|
my $err; |
64
|
|
|
|
|
|
|
if ( $err = _test_dsn( $dsn, $config{dbuser}, $config{dbpass} ) ) { |
65
|
|
|
|
|
|
|
warn "connecting to test $dbtype database failed: $err\n"; |
66
|
|
|
|
|
|
|
warn "will skip $dbtype tests\n"; |
67
|
|
|
|
|
|
|
next; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
$datastore_info{$dbtype} = { |
70
|
|
|
|
|
|
|
class => $store_class, |
71
|
|
|
|
|
|
|
setup_class => $setup_class, |
72
|
|
|
|
|
|
|
params => { |
73
|
|
|
|
|
|
|
dbname => $config{dbname}, |
74
|
|
|
|
|
|
|
dbuser => $config{dbuser}, |
75
|
|
|
|
|
|
|
dbpass => $config{dbpass}, |
76
|
|
|
|
|
|
|
dbhost => $config{dbhost}, |
77
|
|
|
|
|
|
|
}, |
78
|
|
|
|
|
|
|
dsn => $dsn |
79
|
|
|
|
|
|
|
}; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
my %dbixfts_info; |
84
|
|
|
|
|
|
|
# DBIxFTS only works with MySQL. |
85
|
|
|
|
|
|
|
if ( $configured{dbixfts} && $configured{MySQL}{dbname} ) { |
86
|
|
|
|
|
|
|
my %config = %{ $configured{MySQL} }; |
87
|
|
|
|
|
|
|
$dbixfts_info{MySQL} = { |
88
|
|
|
|
|
|
|
db_params => { |
89
|
|
|
|
|
|
|
dbname => $config{dbname}, |
90
|
|
|
|
|
|
|
dbuser => $config{dbuser}, |
91
|
|
|
|
|
|
|
dbpass => $config{dbpass}, |
92
|
|
|
|
|
|
|
dbhost => $config{dbhost}, |
93
|
|
|
|
|
|
|
}, |
94
|
|
|
|
|
|
|
}; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
my %sii_info; |
98
|
|
|
|
|
|
|
# Test the MySQL SII backend, if we can. |
99
|
|
|
|
|
|
|
if ( $configured{search_invertedindex} && $configured{MySQL}{dbname} ) { |
100
|
|
|
|
|
|
|
my %config = %{ $configured{MySQL} }; |
101
|
|
|
|
|
|
|
$sii_info{MySQL} = { |
102
|
|
|
|
|
|
|
db_class => "Search::InvertedIndex::DB::Mysql", |
103
|
|
|
|
|
|
|
db_params => { |
104
|
|
|
|
|
|
|
-db_name => $config{dbname}, |
105
|
|
|
|
|
|
|
-username => $config{dbuser}, |
106
|
|
|
|
|
|
|
-password => $config{dbpass}, |
107
|
|
|
|
|
|
|
-hostname => $config{dbhost} || "", |
108
|
|
|
|
|
|
|
-table_name => 'siindex', |
109
|
|
|
|
|
|
|
-lock_mode => 'EX', |
110
|
|
|
|
|
|
|
}, |
111
|
|
|
|
|
|
|
}; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Test the Pg SII backend, if we can. It's not in the main S::II package. |
115
|
|
|
|
|
|
|
eval { require Search::InvertedIndex::DB::Pg; }; |
116
|
|
|
|
|
|
|
my $sii_pg = $@ ? 0 : 1; |
117
|
|
|
|
|
|
|
if ( $configured{search_invertedindex} |
118
|
|
|
|
|
|
|
&& $configured{Pg}{dbname} |
119
|
|
|
|
|
|
|
&& $sii_pg |
120
|
|
|
|
|
|
|
) { |
121
|
|
|
|
|
|
|
my %config = %{ $configured{Pg} }; |
122
|
|
|
|
|
|
|
$sii_info{Pg} = { |
123
|
|
|
|
|
|
|
db_class => "Search::InvertedIndex::DB::Pg", |
124
|
|
|
|
|
|
|
db_params => { |
125
|
|
|
|
|
|
|
-db_name => $config{dbname}, |
126
|
|
|
|
|
|
|
-username => $config{dbuser}, |
127
|
|
|
|
|
|
|
-password => $config{dbpass}, |
128
|
|
|
|
|
|
|
-hostname => $config{dbhost}, |
129
|
|
|
|
|
|
|
-table_name => 'siindex', |
130
|
|
|
|
|
|
|
-lock_mode => 'EX', |
131
|
|
|
|
|
|
|
}, |
132
|
|
|
|
|
|
|
}; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# Also test the default DB_File backend, if we have S::II installed at all. |
136
|
|
|
|
|
|
|
if ( $configured{search_invertedindex} ) { |
137
|
|
|
|
|
|
|
$sii_info{DB_File} = { |
138
|
|
|
|
|
|
|
db_class => "Search::InvertedIndex::DB::DB_File_SplitHash", |
139
|
|
|
|
|
|
|
db_params => { |
140
|
|
|
|
|
|
|
-map_name => 't/sii-db-file-test.db', |
141
|
|
|
|
|
|
|
-lock_mode => 'EX', |
142
|
|
|
|
|
|
|
}, |
143
|
|
|
|
|
|
|
}; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
my ( $plucene_path, $lucy_path ); |
147
|
|
|
|
|
|
|
# Test with Plucene and Lucy if possible. |
148
|
|
|
|
|
|
|
if ( $configured{plucene} ) { |
149
|
|
|
|
|
|
|
$plucene_path = "t/plucene"; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
if ( $configured{lucy} ) { |
152
|
|
|
|
|
|
|
$lucy_path = "t/lucy"; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# @wiki_info describes which searches work with which stores. |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# Database-specific searchers. |
158
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{MySQL}, |
159
|
|
|
|
|
|
|
dbixfts_info => $dbixfts_info{MySQL} } |
160
|
|
|
|
|
|
|
if ( $datastore_info{MySQL} and $dbixfts_info{MySQL} ); |
161
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{MySQL}, |
162
|
|
|
|
|
|
|
sii_info => $sii_info{MySQL} } |
163
|
|
|
|
|
|
|
if ( $datastore_info{MySQL} and $sii_info{MySQL} ); |
164
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{Pg}, |
165
|
|
|
|
|
|
|
sii_info => $sii_info{Pg} } |
166
|
|
|
|
|
|
|
if ( $datastore_info{Pg} and $sii_info{Pg} ); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# All stores are compatible with the default S::II search, and with Plucene, |
169
|
|
|
|
|
|
|
# and with Lucy, and with no search. |
170
|
|
|
|
|
|
|
foreach my $dbtype ( qw( MySQL Pg SQLite ) ) { |
171
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{$dbtype}, |
172
|
|
|
|
|
|
|
sii_info => $sii_info{DB_File} } |
173
|
|
|
|
|
|
|
if ( $datastore_info{$dbtype} and $sii_info{DB_File} ); |
174
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{$dbtype}, |
175
|
|
|
|
|
|
|
plucene_path => $plucene_path } |
176
|
|
|
|
|
|
|
if ( $datastore_info{$dbtype} and $plucene_path ); |
177
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{$dbtype}, |
178
|
|
|
|
|
|
|
lucy_path => $lucy_path } |
179
|
|
|
|
|
|
|
if ( $datastore_info{$dbtype} and $lucy_path ); |
180
|
|
|
|
|
|
|
push @wiki_info, { datastore_info => $datastore_info{$dbtype} } |
181
|
|
|
|
|
|
|
if $datastore_info{$dbtype}; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head1 METHODS |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=over 4 |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=item B |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
my $iterator = Wiki::Toolkit::TestLib->new_wiki_maker; |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=cut |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub new_wiki_maker { |
195
|
2
|
|
|
2
|
1
|
171
|
my $class = shift; |
196
|
2
|
|
|
|
|
6
|
my $count = 0; |
197
|
2
|
|
|
|
|
5
|
my $iterator = \$count; |
198
|
2
|
|
|
|
|
6
|
bless $iterator, $class; |
199
|
2
|
|
|
|
|
5
|
return $iterator; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item B |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
use Test::More; |
205
|
|
|
|
|
|
|
my $iterator = Wiki::Toolkit::TestLib->new_wiki_maker; |
206
|
|
|
|
|
|
|
plan tests => ( $iterator->number * 6 ); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Returns the number of new wikis that your iterator will be able to give you. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub number { |
213
|
1
|
|
|
1
|
1
|
11
|
return scalar @wiki_info; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=item B |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
my $wiki = $iterator->new_wiki; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Returns a fresh blank wiki object, or false if you've used up all the |
221
|
|
|
|
|
|
|
configured search and storage backends. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=cut |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub new_wiki { |
226
|
1
|
|
|
1
|
1
|
253
|
my $self = shift; |
227
|
1
|
50
|
|
|
|
9
|
return undef if $$self > $#wiki_info; |
228
|
0
|
|
|
|
|
0
|
my $details = $wiki_info[$$self]; |
229
|
0
|
|
|
|
|
0
|
my %wiki_config; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# Set up and clear datastore. |
232
|
0
|
|
|
|
|
0
|
my %datastore_info = %{ $details->{datastore_info } }; |
|
0
|
|
|
|
|
0
|
|
233
|
0
|
|
|
|
|
0
|
my $setup_class = $datastore_info{setup_class}; |
234
|
0
|
|
|
|
|
0
|
eval "require $setup_class"; |
235
|
|
|
|
|
|
|
{ |
236
|
39
|
|
|
39
|
|
345
|
no strict "refs"; |
|
39
|
|
|
|
|
100
|
|
|
39
|
|
|
|
|
32926
|
|
|
0
|
|
|
|
|
0
|
|
237
|
0
|
|
|
|
|
0
|
&{"$setup_class\:\:cleardb"}( $datastore_info{params} ); |
|
0
|
|
|
|
|
0
|
|
238
|
0
|
|
|
|
|
0
|
&{"$setup_class\:\:setup"}( $datastore_info{params} ); |
|
0
|
|
|
|
|
0
|
|
239
|
|
|
|
|
|
|
} |
240
|
0
|
|
|
|
|
0
|
my $class = $datastore_info{class}; |
241
|
0
|
|
|
|
|
0
|
eval "require $class"; |
242
|
0
|
|
|
|
|
0
|
$wiki_config{store} = $class->new( %{ $datastore_info{params} } ); |
|
0
|
|
|
|
|
0
|
|
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# Set up and clear search object (if required). |
245
|
0
|
0
|
|
|
|
0
|
if ( $details->{dbixfts_info} ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
246
|
0
|
|
|
|
|
0
|
my %fts_info = %{ $details->{dbixfts_info} }; |
|
0
|
|
|
|
|
0
|
|
247
|
0
|
|
|
|
|
0
|
require Wiki::Toolkit::Store::MySQL; |
248
|
0
|
|
|
|
|
0
|
my %dbconfig = %{ $fts_info{db_params} }; |
|
0
|
|
|
|
|
0
|
|
249
|
|
|
|
|
|
|
my $dsn = Wiki::Toolkit::Store::MySQL->_dsn( $dbconfig{dbname}, |
250
|
0
|
|
|
|
|
0
|
$dbconfig{dbhost} ); |
251
|
|
|
|
|
|
|
my $dbh = DBI->connect( $dsn, $dbconfig{dbuser}, $dbconfig{dbpass}, |
252
|
0
|
0
|
|
|
|
0
|
{ PrintError => 0, RaiseError => 1, AutoCommit => 1 } ) |
253
|
|
|
|
|
|
|
or croak "Can't connect to $dbconfig{dbname} using $dsn: " . DBI->errstr; |
254
|
0
|
|
|
|
|
0
|
require Wiki::Toolkit::Setup::DBIxFTSMySQL; |
255
|
|
|
|
|
|
|
Wiki::Toolkit::Setup::DBIxFTSMySQL::setup( |
256
|
0
|
|
|
|
|
0
|
@dbconfig{ qw( dbname dbuser dbpass dbhost ) } |
257
|
|
|
|
|
|
|
); |
258
|
0
|
|
|
|
|
0
|
require Wiki::Toolkit::Search::DBIxFTS; |
259
|
0
|
|
|
|
|
0
|
$wiki_config{search} = Wiki::Toolkit::Search::DBIxFTS->new( dbh => $dbh ); |
260
|
|
|
|
|
|
|
} elsif ( $details->{sii_info} ) { |
261
|
0
|
|
|
|
|
0
|
my %sii_info = %{ $details->{sii_info} }; |
|
0
|
|
|
|
|
0
|
|
262
|
0
|
|
|
|
|
0
|
my $db_class = $sii_info{db_class}; |
263
|
0
|
|
|
|
|
0
|
eval "use $db_class"; |
264
|
0
|
|
|
|
|
0
|
my %db_params = %{ $sii_info{db_params} }; |
|
0
|
|
|
|
|
0
|
|
265
|
0
|
|
|
|
|
0
|
my $indexdb = $db_class->new( %db_params ); |
266
|
0
|
|
|
|
|
0
|
require Wiki::Toolkit::Setup::SII; |
267
|
0
|
|
|
|
|
0
|
Wiki::Toolkit::Setup::SII::setup( indexdb => $indexdb ); |
268
|
0
|
|
|
|
|
0
|
$wiki_config{search} = Wiki::Toolkit::Search::SII->new(indexdb =>$indexdb); |
269
|
|
|
|
|
|
|
} elsif ( $details->{plucene_path} ) { |
270
|
0
|
|
|
|
|
0
|
require Wiki::Toolkit::Search::Plucene; |
271
|
0
|
|
|
|
|
0
|
my $dir = $details->{plucene_path}; |
272
|
0
|
|
|
|
|
0
|
unlink <$dir/*>; # don't die if false since there may be no files |
273
|
0
|
0
|
|
|
|
0
|
if ( -d $dir ) { |
274
|
0
|
0
|
|
|
|
0
|
rmdir $dir or die $!; |
275
|
|
|
|
|
|
|
} |
276
|
0
|
0
|
|
|
|
0
|
mkdir $dir or die $!; |
277
|
0
|
|
|
|
|
0
|
$wiki_config{search} = Wiki::Toolkit::Search::Plucene->new( path => $dir ); |
278
|
|
|
|
|
|
|
} elsif ( $details->{lucy_path} ) { |
279
|
0
|
|
|
|
|
0
|
require Wiki::Toolkit::Search::Lucy; |
280
|
0
|
|
|
|
|
0
|
require File::Path; |
281
|
0
|
|
|
|
|
0
|
my $dir = $details->{lucy_path}; |
282
|
0
|
|
|
|
|
0
|
File::Path::rmtree( $dir, 0, 1 ); # 0 = verbose, 1 = safe |
283
|
0
|
0
|
|
|
|
0
|
mkdir $dir or die $!; |
284
|
0
|
|
|
|
|
0
|
$wiki_config{search} = Wiki::Toolkit::Search::Lucy->new( |
285
|
|
|
|
|
|
|
path => $dir, |
286
|
|
|
|
|
|
|
metadata_fields => [ "address", "category", "locale" ] ); |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# Make a wiki. |
290
|
0
|
|
|
|
|
0
|
my $wiki = Wiki::Toolkit->new( %wiki_config ); |
291
|
0
|
|
|
|
|
0
|
$$self++; |
292
|
0
|
|
|
|
|
0
|
return $wiki; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=item B |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
my @configured_databases = $iterator->configured_databases; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Returns the @configured_databases array detailing configured test databases. |
300
|
|
|
|
|
|
|
Useful for very low-level testing only. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=cut |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub configured_databases { |
305
|
1
|
|
|
1
|
1
|
4
|
my @configured_databases; |
306
|
1
|
|
|
|
|
4
|
foreach my $dbtype (qw( MySQL Pg SQLite )) { |
307
|
|
|
|
|
|
|
push @configured_databases, $datastore_info{$dbtype} |
308
|
3
|
50
|
|
|
|
9
|
if $datastore_info{$dbtype}; |
309
|
|
|
|
|
|
|
} |
310
|
1
|
|
|
|
|
3
|
return @configured_databases; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub _test_dsn { |
314
|
0
|
|
|
0
|
|
|
my ( $dsn, $dbuser, $dbpass ) = @_; |
315
|
0
|
|
|
|
|
|
my $dbh = eval { |
316
|
0
|
|
|
|
|
|
DBI->connect($dsn, $dbuser, $dbpass, {RaiseError => 1}); |
317
|
|
|
|
|
|
|
}; |
318
|
0
|
|
|
|
|
|
return $@; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=back |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head1 SEE ALSO |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
L |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head1 AUTHOR |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Kake Pugh (kake@earth.li). |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 COPYRIGHT |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Copyright (C) 2003-2004 Kake Pugh. All Rights Reserved. |
334
|
|
|
|
|
|
|
Copyright (C) 2008 the Wiki::Toolkit team. All Rights Reserved. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
This module is free software; you can redistribute it and/or modify it |
337
|
|
|
|
|
|
|
under the same terms as Perl itself. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=head1 CAVEATS |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
If you have the L backend configured (see |
342
|
|
|
|
|
|
|
L) then your tests will raise warnings like |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
(in cleanup) Search::InvertedIndex::DB::Mysql::lock() - |
345
|
|
|
|
|
|
|
testdb is not open. Can't lock. |
346
|
|
|
|
|
|
|
at /usr/local/share/perl/5.6.1/Search/InvertedIndex.pm line 1348 |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
or |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
(in cleanup) Can't call method "sync" on an undefined value |
351
|
|
|
|
|
|
|
at /usr/local/share/perl/5.6.1/Tie/DB_File/SplitHash.pm line 331 |
352
|
|
|
|
|
|
|
during global destruction. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
in unexpected places. I don't know whether this is a bug in me or in |
355
|
|
|
|
|
|
|
L. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=cut |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
1; |