| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Wiki::Toolkit::TestLib; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 39 |  |  | 39 |  | 93032 | use 5.006; #by perlver | 
|  | 39 |  |  |  |  | 337 |  | 
| 4 | 39 |  |  | 39 |  | 213 | use strict; | 
|  | 39 |  |  |  |  | 71 |  | 
|  | 39 |  |  |  |  | 3112 |  | 
| 5 | 39 |  |  | 39 |  | 196 | use Carp "croak"; | 
|  | 39 |  |  |  |  | 76 |  | 
|  | 39 |  |  |  |  | 3125 |  | 
| 6 | 39 |  |  | 39 |  | 19760 | use Wiki::Toolkit; | 
|  | 39 |  |  |  |  | 104 |  | 
|  | 39 |  |  |  |  | 1265 |  | 
| 7 | 39 |  |  | 39 |  | 18571 | use Wiki::Toolkit::TestConfig; | 
|  | 39 |  |  |  |  | 147 |  | 
|  | 39 |  |  |  |  | 1288 |  | 
| 8 | 39 |  |  | 39 |  | 58591 | use DBI; | 
|  | 39 |  |  |  |  | 658730 |  | 
|  | 39 |  |  |  |  | 2545 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 39 |  |  | 39 |  | 356 | use vars qw( $VERSION @wiki_info ); | 
|  | 39 |  |  |  |  | 98 |  | 
|  | 39 |  |  |  |  | 30791 |  | 
| 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 | 186 | 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 | 328 | my $self = shift; | 
| 227 | 1 | 50 |  |  |  | 11 | 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 |  | 333 | no strict "refs"; | 
|  | 39 |  |  |  |  | 85 |  | 
|  | 39 |  |  |  |  | 33110 |  | 
|  | 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 | 6 | my @configured_databases; | 
| 306 | 1 |  |  |  |  | 4 | foreach my $dbtype (qw( MySQL Pg SQLite )) { | 
| 307 |  |  |  |  |  |  | push @configured_databases, $datastore_info{$dbtype} | 
| 308 | 3 | 50 |  |  |  | 8 | if $datastore_info{$dbtype}; | 
| 309 |  |  |  |  |  |  | } | 
| 310 | 1 |  |  |  |  | 5 | 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; |