1use strict;
2# Before `make install' is performed this script should be runnable with
3# `make test'. After `make install' it should work as `perl test.pl'
4
5#########################
6
7use Test;
8use Devel::Leak;
9use Devel::Peek;
10BEGIN { plan tests => 62 };
11use Search::Xapian qw(:standard);
12ok(1); # If we made it this far, we're ok.
13
14#########################
15
16# Insert your test code below, the Test module is use()ed here so read
17# its man page ( perldoc Test ) for help writing this test script.
18
19# Adjust query description from 1.4 to match.
20sub qd {
21    local $_ = (shift @_)->get_description();
22    if (substr($_, 0, 1) eq 'Q') {
23	s/\@([0-9]+)/:(pos=$1)/g;
24	s/\\x([0-9a-f]{2})/chr(hex($1))/ge;
25	s/^Query\(0 \* VALUE_RANGE/Query(VALUE_RANGE/;
26	$_ = "Xapian::$_";
27    }
28    return $_;
29}
30
31# first create database dir, if it doesn't exist;
32my $db_dir = 'testdb';
33
34my $database;
35ok( $database = Search::Xapian::Database->new( $db_dir ) );
36
37my $qp = new Search::Xapian::QueryParser( $database );
38$qp = new Search::Xapian::QueryParser();
39
40$qp->set_stemmer( Search::Xapian::Stem->new('english') );
41$qp->set_stemming_strategy( STEM_ALL );
42$qp->set_default_op( OP_AND );
43
44my $query;
45ok( $query = $qp->parse_query( 'one or two', FLAG_BOOLEAN|FLAG_BOOLEAN_ANY_CASE|FLAG_SPELLING_CORRECTION ) );
46ok( not $qp->get_corrected_query_string());
47ok( qd($query), "Xapian::Query((one:(pos=1) OR two:(pos=2)))" );
48
49ok( $query = $qp->parse_query( 'one OR (two AND three)' ) );
50ok( qd($query), "Xapian::Query((one:(pos=1) OR (two:(pos=2) AND three:(pos=3))))" );
51
52ok( my $enq = $database->enquire( $query ) );
53
54{
55  my @stopwords = qw(a the in on and);
56  my $stopper;
57  ok( $stopper = new Search::Xapian::SimpleStopper(@stopwords) );
58  foreach (@stopwords) {
59    ok( $stopper->stop_word($_) );
60  }
61  foreach (qw(one two three four five)) {
62    ok( !$stopper->stop_word($_) );
63  }
64  ok( $qp->set_stopper($stopper), undef );
65}
66ok( $qp->parse_query("one two many") );
67
68$qp = new Search::Xapian::QueryParser();
69my $vrp;
70ok( $vrp = new Search::Xapian::StringValueRangeProcessor(1) );
71$qp->add_valuerangeprocessor($vrp);
72$qp->add_boolean_prefix("test", "XTEST");
73
74my $handle;
75my $count = Devel::Leak::NoteSV($handle);
76{
77    my $qp2 = new Search::Xapian::QueryParser();
78    $qp2->add_valuerangeprocessor(
79	Search::Xapian::StringValueRangeProcessor->new(1, 'test:', 1));
80    $qp2->set_stopper(Search::Xapian::SimpleStopper->new(qw(a an the)));
81    $qp2->set_stopper(Search::Xapian::SimpleStopper->new(qw(a the)));
82}
83ok( $count == Devel::Leak::CheckSV($handle) );
84
85my $pair;
86foreach $pair (
87    [ 'a..b', 'VALUE_RANGE 1 a b' ],
88    [ '$50..100', 'VALUE_RANGE 1 $50 100' ],
89    [ '$50..$99', 'VALUE_RANGE 1 $50 $99' ],
90    [ '02/03/1979..10/12/1980', 'VALUE_RANGE 1 02/03/1979 10/12/1980' ],
91    [ 'a..b hello', '(hello:(pos=1) FILTER VALUE_RANGE 1 a b)' ],
92    [ 'hello a..b', '(hello:(pos=1) FILTER VALUE_RANGE 1 a b)' ],
93    [ 'hello a..b world', '((hello:(pos=1) OR world:(pos=2)) FILTER VALUE_RANGE 1 a b)' ],
94    [ 'hello a..b test:foo', '(hello:(pos=1) FILTER (VALUE_RANGE 1 a b AND XTESTfoo))' ],
95    [ '-5..7', 'VALUE_RANGE 1 -5 7' ],
96    [ 'hello -5..7', '(hello:(pos=1) FILTER VALUE_RANGE 1 -5 7)' ],
97    [ '-5..7 hello', '(hello:(pos=1) FILTER VALUE_RANGE 1 -5 7)' ],
98    [ '"time flies" 09:00..12:30', '((time:(pos=1) PHRASE 2 flies:(pos=2)) FILTER VALUE_RANGE 1 09:00 12:30)' ]
99    ) {
100    my ($str, $res) = @{$pair};
101    my $query = $qp->parse_query($str);
102    ok( qd($query), "Xapian::Query($res)" );
103}
104
105$qp = new Search::Xapian::QueryParser();
106
107my $vrp1 = new Search::Xapian::DateValueRangeProcessor(1);
108my $vrp2 = new Search::Xapian::NumberValueRangeProcessor(2);
109my $vrp3 = new Search::Xapian::StringValueRangeProcessor(3);
110my $vrp4 = new Search::Xapian::NumberValueRangeProcessor(4, '$');
111my $vrp5 = new Search::Xapian::NumberValueRangeProcessor(5, 'kg', 0);
112my $vrp6 = new Search::Xapian::StringValueRangeProcessor(6, 'country:');
113my $vrp7 = new Search::Xapian::StringValueRangeProcessor(7, ':name', 0);
114$qp->add_valuerangeprocessor( $vrp1 );
115$qp->add_valuerangeprocessor( $vrp2 );
116$qp->add_valuerangeprocessor( $vrp4 );
117$qp->add_valuerangeprocessor( $vrp5 );
118$qp->add_valuerangeprocessor( $vrp6 );
119$qp->add_valuerangeprocessor( $vrp7 );
120$qp->add_valuerangeprocessor( $vrp3 );
121
122$qp->add_boolean_prefix("test", "XTEST");
123foreach $pair (
124    [ 'a..b', 'VALUE_RANGE 3 a b' ],
125    [ '1..12', "VALUE_RANGE 2 \xa0 \xae" ],
126    [ '20070201..20070228', 'VALUE_RANGE 1 20070201 20070228' ],
127    [ '$10..20', "VALUE_RANGE 4 \xad \xb1" ],
128    [ '$10..$20', "VALUE_RANGE 4 \xad \xb1" ],
129    [ '12..42kg', "VALUE_RANGE 5 \xae \xb5@" ],
130    [ '12kg..42kg', "VALUE_RANGE 5 \xae \xb5@" ],
131    [ '12kg..42', 'VALUE_RANGE 3 12kg 42' ],
132    [ '!10..$20', 'VALUE_RANGE 3 !10 $20' ],
133    [ '1999-03-12..2020-12-30', 'VALUE_RANGE 1 19990312 20201230' ],
134    [ '1999/03/12..2020/12/30', 'VALUE_RANGE 1 19990312 20201230' ],
135    [ '1999.03.12..2020.12.30', 'VALUE_RANGE 1 19990312 20201230' ],
136    [ '12/03/99..12/04/01', 'VALUE_RANGE 1 19990312 20010412' ],
137    [ '03-12-99..04-14-01', 'VALUE_RANGE 1 19990312 20010414' ],
138    [ '(test:a..test:b hello)', '(hello:(pos=1) FILTER VALUE_RANGE 3 test:a test:b)' ],
139    [ 'country:chile..denmark', 'VALUE_RANGE 6 chile denmark' ],
140    [ 'albert..xeni:name', 'VALUE_RANGE 7 albert xeni' ],
141    ) {
142    my ($str, $res) = @{$pair};
143    my $query = $qp->parse_query($str);
144    skip(substr($str, 0, 1) eq '!' &&
145	 Search::Xapian::major_version() == 1 &&
146	 Search::Xapian::minor_version() == 2 &&
147	 Search::Xapian::revision() < 21 ?
148	     "Testcase requires xapian-core >= 1.2.21" : 0,
149	qd($query), "Xapian::Query($res)" );
150}
151
152$qp = new Search::Xapian::QueryParser();
153
154{
155  my $vrpdate = new Search::Xapian::DateValueRangeProcessor(1, 1, 1960);
156  $qp->add_valuerangeprocessor( $vrpdate );
157}
158
159foreach $pair (
160    [ '12/03/99..12/04/01', 'VALUE_RANGE 1 19991203 20011204' ],
161    [ '03-12-99..04-14-01', 'VALUE_RANGE 1 19990312 20010414' ],
162    [ '01/30/60..02/02/59', 'VALUE_RANGE 1 19600130 20590202' ],
163    ) {
164    my ($str, $res) = @{$pair};
165    my $query = $qp->parse_query($str);
166    ok( qd($query), "Xapian::Query($res)" );
167}
168
169# Regression test for Search::Xapian bug fixed in 1.0.5.0.  In 1.0.0.0-1.0.4.0
170# we tried to catch const char * not Xapian::Error, so std::terminate got
171# called.
172$qp = Search::Xapian::QueryParser->new;
173eval {
174    $qp->parse_query('other* AND', FLAG_BOOLEAN|FLAG_WILDCARD);
175};
176ok($@);
177ok(ref($@), "Search::Xapian::QueryParserError", "correct class for exception");
178ok($@->isa('Search::Xapian::Error'));
179ok($@->get_msg, "Syntax: <expression> AND <expression>", "get_msg works");
180ok( $@ =~ /^Exception: Syntax: <expression> AND <expression>(?: at \S+ line \d+\.)?$/ );
181
182# Check FLAG_DEFAULT is wrapped (new in 1.0.11.0).
183ok( $qp->parse_query('hello world', FLAG_DEFAULT|FLAG_BOOLEAN_ANY_CASE) );
184
185# Check BAD_VALUENO is wrapped.
186ok( Search::Xapian::BAD_VALUENO != 0 );
187
1881;
189