1package Plucene::TestCase; 2 3=head1 NAME 4 5Plucene::TestCase - Handy functions when testing Plucene 6 7=head1 SYNOPSIS 8 9 use Test::More tests => 10; 10 use Plucene::TestCase; 11 12 new_index { 13 add_document( foo => "bar" ); 14 }; 15 16 re_index { 17 add_document( foo => "baz" ); 18 } 19 20 with_reader { 21 $READER->whatever; 22 } 23 24 my $hits = search("foo:ba*"); 25 26=head1 EXPORTS 27 28=cut 29 30use strict; 31use warnings; 32 33use base 'Exporter'; 34 35use Plucene::Index::Reader; 36use Plucene::Index::Writer; 37use Plucene::Document; 38use Plucene::Document::Field; 39use Plucene::Analysis::SimpleAnalyzer; 40use Plucene::QueryParser; 41use Plucene::Search::IndexSearcher; 42 43our (@EXPORT, $DIR, $DEBUG, $WRITER, $READER, $ANALYZER); 44@EXPORT = qw($DIR $WRITER $READER $ANALYZER new_index re_index 45 with_reader add_document search); 46 47$ANALYZER = "Plucene::Analysis::SimpleAnalyzer"; 48 49=over 3 50 51=item C<$DIR> 52 53A directory which is created for the purposes of this test, in which the 54index will be placed. It will normally be cleaned up at the end of the 55test, unless C<$Plucene::TestCase::DEBUG> is set to allow you to peruse 56the entrails. 57 58=cut 59 60use File::Temp qw(tempdir); 61$DIR = tempdir(CLEANUP => !$DEBUG); 62 63=item C<$WRITER> 64 65A variable holding the current C<Index::Writer> object, if there is one. 66 67=item C<$READER> 68 69A variable holding the current C<Index::Reader> object, if there is one. 70 71=item C<$ANALYZER> 72 73A variable holding the class name of the desired C<Analysis::Analyzer> 74class. 75 76=item new_index BLOCK (Analyzer) 77 78Create a new index, and do the following stuff in the block before 79closing the index writer. C<$WRITER> is set for the duration of the 80block. 81 82The optional parameter should be the class name of the analyzer to use; 83if not specified, the value from C<$ANALYZER>, which in turn defaults to 84C<Plucene::Analysis::SimpleAnalyzer>, will be used. 85 86=cut 87 88sub new_index(&;$) { 89 my ($block, $analyzer) = @_; 90 $analyzer ||= $ANALYZER; 91 92 # UNIVERSAL::require loads UNIVERSAL->import, which won't do. 93 eval "require $analyzer"; 94 die "Couldn't require $analyzer" if $@; 95 $WRITER = Plucene::Index::Writer->new($DIR, $analyzer->new, 1); 96 $block->(); 97 undef $WRITER; 98} 99 100=item re_index BLOCK (Analyzer) 101 102Same as C<new_index>, but doesn't create a new index, rather re-uses an 103old one. 104 105=cut 106 107sub re_index(&;$) { 108 my ($block, $analyzer) = @_; 109 $analyzer ||= $ANALYZER; 110 eval "require $analyzer"; 111 die "Couldn't require $analyzer" if $@; 112 $WRITER = Plucene::Index::Writer->new($DIR, $analyzer->new, 0); 113 $block->(); 114 undef $WRITER; 115} 116 117=item add_document( field1 => value1, ...) 118 119Add a new document to the index, with the given fields and values 120 121=cut 122 123sub add_document { 124 my @args = @_; 125 my $doc = Plucene::Document->new; 126 while (my ($k, $v) = splice(@args, 0, 2)) { 127 $doc->add(Plucene::Document::Field->Text($k, $v)); 128 } 129 $WRITER->add_document($doc); 130} 131 132=item with_reader BLOCK 133 134Opens an index reader in C<$READER> and runs the block. 135 136=cut 137 138sub with_reader (&) { 139 $READER = Plucene::Index::Reader->open($DIR); 140 shift->(); 141 $READER->close; 142 undef $READER; 143} 144 145=item search 146 147Searches for the query given. If any fields are not specified, they will 148be assumed to be the default C<text>. Returns a C<Plucene::Search::Hits> 149object. The value of C<$ANALYZER> will be used to construct an analyzer 150for the query string. 151 152=cut 153 154sub search { 155 eval "require $ANALYZER"; 156 my $parser = Plucene::QueryParser->new({ 157 analyzer => $ANALYZER->new(), 158 default => "text" 159 }); 160 Plucene::Search::IndexSearcher->new($DIR)->search($parser->parse(shift)); 161} 162 1631; 164