[omega] Compute date spans in days
[xapian.git] / xapian-bindings / perl / t / parser.t
blobb5be7aadcdf66faa82782ab7677c45c2061c0287
1 use 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'
5 #########################
7 # Make warnings fatal
8 use warnings;
9 BEGIN {$SIG{__WARN__} = sub { die "Terminating test due to warning: $_[0]" } };
11 use Test::More;
12 use Devel::Peek;
13 BEGIN { plan tests => 76 };
14 use Xapian qw(:standard);
15 ok(1); # If we made it this far, we're ok.
17 #########################
19 # Insert your test code below, the Test module is use()ed here so read
20 # its man page ( perldoc Test ) for help writing this test script.
22 sub mset_expect_order (\@@) {
23     my ($m, @a) = @_;
24     my @m = map { $_->get_docid() } @{$m};
25     is( scalar @m, scalar @a );
26     for my $j (0 .. (scalar @a - 1)) {
27         is( $m[$j], $a[$j] );
28     }
31 # first create database dir, if it doesn't exist;
32 my $db_dir = 'testdb';
34 my $database;
35 ok( $database = Xapian::Database->new( $db_dir ) );
37 my $qp = new Xapian::QueryParser( $database );
38 $qp = new Xapian::QueryParser();
40 $qp->set_stemmer( Xapian::Stem->new('english') );
41 $qp->set_stemming_strategy( STEM_ALL );
42 $qp->set_default_op( OP_AND );
44 my $query;
45 ok( $query = $qp->parse_query( 'one or two', FLAG_BOOLEAN|FLAG_BOOLEAN_ANY_CASE|FLAG_SPELLING_CORRECTION ) );
46 ok( not $qp->get_corrected_query_string());
47 is( $query->get_description(), 'Query((one@1 OR two@2))' );
49 ok( $query = $qp->parse_query( 'one OR (two AND three)' ) );
50 is( $query->get_description(), 'Query((one@1 OR (two@2 AND three@3)))' );
52 ok( my $enq = $database->enquire( $query ) );
55   is( $qp->set_stopper(sub { $_[0] eq 'bad' }), undef );
56   is( $qp->parse_query("bad news")->get_description(), 'Query(news@2)' );
60   my @stopwords = qw(a the in on and);
61   my $stopper;
62   ok( $stopper = new Xapian::SimpleStopper(@stopwords) );
63   foreach (@stopwords) {
64     ok( $stopper->stop_word($_) );
65   }
66   foreach (qw(one two three four five)) {
67     ok( !$stopper->stop_word($_) );
68   }
69   is( $qp->set_stopper($stopper), undef );
71 ok( $qp->parse_query("one two many") );
73 $qp = new Xapian::QueryParser();
74 my $rp;
75 ok( $rp = new Xapian::RangeProcessor(1) );
76 $qp->add_rangeprocessor($rp);
77 $qp->add_boolean_prefix("test", "XTEST");
79 my $pair;
80 foreach $pair (
81     [ 'a..b', 'VALUE_RANGE 1 a b' ],
82     [ '$50..100', 'VALUE_RANGE 1 $50 100' ],
83     [ '$50..$99', 'VALUE_RANGE 1 $50 $99' ],
84     [ '$50..$100', '' ],
85     [ '02/03/1979..10/12/1980', 'VALUE_RANGE 1 02/03/1979 10/12/1980' ],
86     [ 'a..b hello', '(hello@1 FILTER VALUE_RANGE 1 a b)' ],
87     [ 'hello a..b', '(hello@1 FILTER VALUE_RANGE 1 a b)' ],
88     [ 'hello a..b world', '((hello@1 OR world@2) FILTER VALUE_RANGE 1 a b)' ],
89     [ 'hello a..b test:foo', '(hello@1 FILTER (VALUE_RANGE 1 a b AND XTESTfoo))' ],
90     [ '-5..7', 'VALUE_RANGE 1 -5 7' ],
91     [ 'hello -5..7', '(hello@1 FILTER VALUE_RANGE 1 -5 7)' ],
92     [ '-5..7 hello', '(hello@1 FILTER VALUE_RANGE 1 -5 7)' ],
93     [ '"time flies" 09:00..12:30', '((time@1 PHRASE 2 flies@2) FILTER VALUE_RANGE 1 09:00 12:30)' ]
94     ) {
95     my ($str, $res) = @{$pair};
96     my $query = $qp->parse_query($str);
97     is( $query->get_description(), "Query($res)" );
100 $qp = new Xapian::QueryParser();
102 my $rp1 = new Xapian::DateRangeProcessor(1);
103 my $rp2 = new Xapian::NumberRangeProcessor(2);
104 my $rp3 = new Xapian::RangeProcessor(3);
105 my $rp4 = new Xapian::NumberRangeProcessor(4, '$', Xapian::RP_REPEATED);
106 my $rp5 = new Xapian::NumberRangeProcessor(5, 'kg', Xapian::RP_REPEATED|Xapian::RP_SUFFIX);
107 my $rp6 = new Xapian::RangeProcessor(6, 'country:');
108 my $rp7 = new Xapian::RangeProcessor(7, ':name', Xapian::RP_SUFFIX);
109 $qp->add_rangeprocessor( $rp1 );
110 $qp->add_rangeprocessor( $rp2 );
111 $qp->add_rangeprocessor( $rp4 );
112 $qp->add_rangeprocessor( $rp5 );
113 $qp->add_rangeprocessor( $rp6 );
114 $qp->add_rangeprocessor( $rp7 );
115 $qp->add_rangeprocessor( $rp3 );
117 $qp->add_boolean_prefix("test", "XTEST");
119 foreach $pair (
120     [ 'a..b', 'VALUE_RANGE 3 a b' ],
121     [ '1..12', "VALUE_RANGE 2 \\xa0 \\xae" ],
122     [ '20070201..20070228', 'VALUE_RANGE 1 20070201 20070228' ],
123     [ '$10..20', "VALUE_RANGE 4 \\xad \\xb1" ],
124     [ '$10..$20', "VALUE_RANGE 4 \\xad \\xb1" ],
125     [ '12..42kg', "VALUE_RANGE 5 \\xae \\xb5\@" ],
126     [ '12kg..42kg', "VALUE_RANGE 5 \\xae \\xb5\@" ],
127     [ '12kg..42', 'VALUE_RANGE 3 12kg 42' ],
128     [ '10..$20', '' ],
129     [ '1999-03-12..2020-12-30', 'VALUE_RANGE 1 19990312 20201230' ],
130     [ '1999/03/12..2020/12/30', 'VALUE_RANGE 1 19990312 20201230' ],
131     [ '1999.03.12..2020.12.30', 'VALUE_RANGE 1 19990312 20201230' ],
132     [ '12/03/99..12/04/01', 'VALUE_RANGE 1 19990312 20010412' ],
133     [ '03-12-99..04-14-01', 'VALUE_RANGE 1 19990312 20010414' ],
134     [ '(test:a..test:b hello)', '(hello@1 FILTER VALUE_RANGE 3 test:a test:b)' ],
135     [ 'country:chile..denmark', 'VALUE_RANGE 6 chile denmark' ],
136     [ 'albert..xeni:name', 'VALUE_RANGE 7 albert xeni' ],
137     ) {
138     my ($str, $res) = @{$pair};
139     my $query = $qp->parse_query($str);
140     is( $query->get_description(), "Query($res)" );
143 $qp = new Xapian::QueryParser();
144 $qp->add_rangeprocessor( sub { Xapian::Query->new("spam") } );
145 foreach $pair (
146     [ '123..345', '0 * spam' ],
147     ) {
148     my ($str, $res) = @{$pair};
149     my $query = $qp->parse_query($str);
150     is( $query->get_description(), "Query($res)" );
153 $qp = new Xapian::QueryParser();
155   my $rpdate = new Xapian::DateRangeProcessor(1, Xapian::RP_DATE_PREFER_MDY, 1960);
156   $qp->add_rangeprocessor( $rpdate );
159 foreach $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     is( $query->get_description(), "Query($res)" );
169 $qp = new Xapian::QueryParser();
170 $qp->add_prefix("foo", sub {return new Xapian::Query('foo')});
171 is( $qp->parse_query("foo:test")->get_description(), 'Query(foo)' );
173 # Regression test for Search::Xapian bug fixed in 1.0.5.0.  In 1.0.0.0-1.0.4.0
174 # we tried to catch const char * not Xapian::Error, so std::terminate got
175 # called.
176 $qp = Xapian::QueryParser->new;
177 eval {
178     $qp->parse_query('other* AND', FLAG_BOOLEAN|FLAG_WILDCARD);
180 ok($@);
181 is(ref($@), "Xapian::QueryParserError", "correct class for exception");
182 ok($@->isa('Xapian::Error'));
183 is($@->get_msg, "Syntax: <expression> AND <expression>", "get_msg works");
185 # Check FLAG_DEFAULT is wrapped (new in 1.0.11.0).
186 ok( $qp->parse_query('hello world', FLAG_DEFAULT|FLAG_BOOLEAN_ANY_CASE) );
188 # Test OP_WILDCARD with limits.
189 my ($q, @matches);
190 ok( $enq = Xapian::Enquire->new($database) );
192 $qp->set_max_expansion(1, Xapian::WILDCARD_LIMIT_FIRST);
193 ok( $q = $qp->parse_query('t*', FLAG_WILDCARD) );
194 $enq->set_query($q);
195 @matches = $enq->matches(0, 10);
196 mset_expect_order(@matches, (1, 2));
198 $qp->set_max_expansion(1, Xapian::WILDCARD_LIMIT_MOST_FREQUENT);
199 ok( $q = $qp->parse_query('t*', FLAG_WILDCARD) );
200 $enq->set_query($q);
201 @matches = $enq->matches(0, 10);
202 mset_expect_order(@matches, (1, 2));
204 $qp->set_max_expansion(1, Xapian::WILDCARD_LIMIT_ERROR);
205 ok( $q = $qp->parse_query('t*', FLAG_WILDCARD) );
206 $enq->set_query($q);
207 eval {
208     @matches = $enq->matches(0, 10);
210 ok( $@ );
211 is(ref($@), "Xapian::WildcardError", "correct class for exception");