Update for 1.4.20
[xapian.git] / xapian-bindings / java / SmokeTest.java
blob9a194df3136cd6c4ce52e192b4888f2c93b89fc1
1 // Simple test that we can use xapian from java
2 //
3 // Copyright (C) 2005,2006,2007,2008,2011,2016,2017,2019 Olly Betts
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
18 // USA
20 import org.xapian.*;
22 // FIXME: need to sort out throwing wrapped Xapian::Error subclasses
23 //import org.xapian.errors.*;
25 // FIXME: "implements" not "extends" in JNI Java API
26 class MyMatchDecider extends MatchDecider {
27 public boolean accept(Document d) {
28 // NB It's not normally appropriate to call getData() in a MatchDecider
29 // but we do it here to make sure we don't get an empty document.
30 /* try { */
31 return d.getData().length() == 0;
33 } catch (XapianError e) {
34 return true;
40 // FIXME: "implements" not "extends" in JNI Java API
41 class MyExpandDecider extends ExpandDecider {
42 public boolean accept(String s) { return s.charAt(0) != 'a'; }
45 class MyFieldProcessor extends FieldProcessor {
46 public Query apply(String str) {
47 if (str.equals("spam"))
48 return new Query("eggs");
49 return new Query("spam");
53 public class SmokeTest {
54 public static void main(String[] args) throws Exception {
55 TermGenerator termGenerator = new TermGenerator();
56 termGenerator.setFlags(TermGenerator.FLAG_SPELLING);
57 try {
58 // Test the version number reporting functions give plausible
59 // results.
60 String v = "";
61 v += Version.major();
62 v += ".";
63 v += Version.minor();
64 v += ".";
65 v += Version.revision();
66 String v2 = Version.string();
67 if (!v.equals(v2)) {
68 System.err.println("Unexpected version output (" + v + " != " + v2 + ")");
69 System.exit(1);
72 Stem stem = new Stem("english");
73 if (!stem.toString().equals("Xapian::Stem(english)")) {
74 System.err.println("Unexpected stem.toString()");
75 System.exit(1);
77 Document doc = new Document();
78 doc.setData("a\000b");
79 String s = doc.getData();
80 if (s.equals("a")) {
81 System.err.println("getData+setData truncates at a zero byte");
82 System.exit(1);
84 if (!s.equals("a\000b")) {
85 System.err.println("getData+setData doesn't transparently handle a zero byte");
86 System.exit(1);
88 doc.setData("is there anybody out there?");
89 doc.addTerm("XYzzy");
90 // apply was stemWord() in the JNI bindings
91 doc.addPosting(stem.apply("is"), 1);
92 doc.addPosting(stem.apply("there"), 2);
93 doc.addPosting(stem.apply("anybody"), 3);
94 doc.addPosting(stem.apply("out"), 4);
95 doc.addPosting(stem.apply("there"), 5);
96 WritableDatabase db = new WritableDatabase("", Xapian.DB_BACKEND_INMEMORY);
97 db.addDocument(doc);
98 if (db.getDocCount() != 1) {
99 System.err.println("Unexpected db.getDocCount()");
100 System.exit(1);
103 QueryParser qp = new QueryParser();
105 // Test wrapping of null-able grouping parameter.
106 qp.addBooleanPrefix("colour", "XC");
107 qp.addBooleanPrefix("color", "XC");
108 qp.addBooleanPrefix("foo", "XFOO", null);
109 qp.addBooleanPrefix("bar", "XBAR", "XBA*");
110 qp.addBooleanPrefix("baa", "XBAA", "XBA*");
111 DateRangeProcessor rpdate = new DateRangeProcessor(1, Xapian.RP_DATE_PREFER_MDY, 1960);
112 qp.addRangeprocessor(rpdate);
113 qp.addRangeprocessor(rpdate, null);
114 qp.addRangeprocessor(rpdate, "foo");
116 if (!Query.MatchAll.toString().equals("Query(<alldocuments>)")) {
117 System.err.println("Unexpected Query.MatchAll.toString()");
118 System.exit(1);
121 if (!Query.MatchNothing.toString().equals("Query()")) {
122 System.err.println("Unexpected Query.MatchNothing.toString()");
123 System.exit(1);
126 String[] terms = { "smoke", "test", "terms" };
127 Query query = new Query(Query.OP_OR, terms);
128 if (!query.toString().equals("Query((smoke OR test OR terms))")) {
129 System.err.println("Unexpected query.toString()");
130 System.exit(1);
132 Query[] queries = { new Query("smoke"), query, new Query("string") };
133 Query query2 = new Query(Query.OP_XOR, queries);
134 if (!query2.toString().equals("Query((smoke XOR (smoke OR test OR terms) XOR string))")) {
135 System.err.println("Unexpected query2.toString()");
136 System.exit(1);
138 String[] subqs = { "a", "b" };
139 Query query3 = new Query(Query.OP_OR, subqs);
140 if (!query3.toString().equals("Query((a OR b))")) {
141 System.err.println("Unexpected query3.toString()");
142 System.exit(1);
144 Enquire enq = new Enquire(db);
146 // Check Xapian::BAD_VALUENO is wrapped suitably.
147 enq.setCollapseKey(Xapian.BAD_VALUENO);
149 // Test that the non-constant wrapping prior to 1.4.10 still works.
150 enq.setCollapseKey(Xapian.getBAD_VALUENO());
152 enq.setQuery(new Query(Query.OP_OR, "there", "is"));
153 MSet mset = enq.getMSet(0, 10);
154 if (mset.size() != 1) {
155 System.err.println("Unexpected mset.size()");
156 System.exit(1);
158 MSetIterator m_itor = mset.begin();
159 Document m_doc = null;
160 long m_id;
161 while(m_itor.hasNext()) {
162 m_id = m_itor.next();
163 if(m_itor.hasNext()) {
164 m_doc = mset.getDocument(m_id);
168 // Only one doc exists in this mset
169 if(m_doc != null && m_doc.getDocId() != 0) {
170 System.err.println("Unexpected docid");
171 System.exit(1);
174 String term_str = "";
175 TermIterator itor = enq.getMatchingTermsBegin(mset.getElement(0));
176 while (itor.hasNext()) {
177 term_str += itor.next();
178 if (itor.hasNext())
179 term_str += ' ';
181 if (!term_str.equals("is there")) {
182 System.err.println("Unexpected term_str");
183 System.exit(1);
185 /* FIXME:dc: Fails since Xapian::Error is still unmapped
186 boolean ok = false;
187 try {
188 Database db_fail = new Database("NOsuChdaTabASe");
189 // Ignore the return value.
190 db_fail.getDocCount();
191 } catch (DatabaseOpeningError e) {
192 ok = true;
194 if (!ok) {
195 System.err.println("Managed to open non-existent database");
196 System.exit(1);
200 if (Query.OP_ELITE_SET != 10) {
201 System.err.println("OP_ELITE_SET is " + Query.OP_ELITE_SET + " not 10");
202 System.exit(1);
205 RSet rset = new RSet();
206 rset.addDocument(1);
207 ESet eset = enq.getESet(10, rset, new MyExpandDecider());
208 // FIXME: temporary simple check
209 if (0 == eset.size()) {
210 System.err.println("ESet.size() was 0");
211 System.exit(1);
214 int count = 0;
215 for(ESetIterator eit = eset.begin(); eit.hasNext(); ) {
216 // for (int i = 0; i < eset.size(); i++) {
217 if (eit.getTerm().charAt(0) == 'a') {
218 System.err.println("MyExpandDecider wasn't used");
219 System.exit(1);
221 ++count;
222 eit.next();
224 if (count != eset.size()) {
225 System.err.println("ESet.size() mismatched number of terms returned by ESetIterator");
226 System.err.println(count + " " + eset.size());
227 System.exit(1);
231 MSet mset2 = enq.getMSet(0, 10, null, new MyMatchDecider());
232 if (mset2.size() > 0) {
233 System.err.println("MyMatchDecider wasn't used");
234 System.exit(1);
238 if (!enq.getQuery().toString().equals("Query((there OR is))")) {
239 System.err.println("Enquire::getQuery() returned the wrong query: " + enq.getQuery().toString());
240 System.exit(1);
244 qp.addPrefix("food", new MyFieldProcessor());
245 if (!qp.parseQuery("food:spam").toString().equals("Query(eggs)")) {
246 System.err.println("FieldProcessor subclass doesn't work as expected");
247 System.exit(1);
252 // Wrapped functions which take/return byte[] for std::string.
254 // Check that serialisation returns byte[], that
255 // unserialisation takes byte[], and round-tripping works.
256 byte[] res = Xapian.sortableSerialise(1.675);
257 if (Xapian.sortableUnserialise(res) != 1.675) {
258 System.err.println("sortableSerialise() and/or sortableUnserialise() don't work as expected");
259 System.exit(1);
262 // Check that serialisation returns byte[], that
263 // unserialisation takes byte[], and round-tripping works.
264 Query q = new Query("foo");
265 res = q.serialise();
266 Query q_out = Query.unserialise(res);
267 if (!q.toString().equals(q_out.toString())) {
268 System.err.println("Query serialisation doesn't work as expected");
269 System.exit(1);
272 // Check Document.addValue() takes byte[], that getValue()
273 // returns byte[], that serialisation returns byte[], that
274 // unserialisation takes byte[], and round-tripping works.
275 Document d = new Document();
276 d.setData("xyzzy");
277 d.addValue(7, res);
278 byte[] res2 = d.getValue(7);
279 if (!java.util.Arrays.equals(res, res2)) {
280 System.err.println("Document.getValue() returns a different byte[] to the one set with addValue()");
281 System.exit(1);
283 res = d.serialise();
284 Document d_out = Document.unserialise(res);
285 // Make sure the "terms_here" flag is set so the descriptions match.
286 d_out.termListCount();
287 if (!d.toString().equals(d_out.toString())) {
288 System.err.println("Document serialisation doesn't work as expected");
289 System.err.println(d.toString());
290 System.err.println(d_out.toString());
291 System.exit(1);
294 // Check that serialisation returns byte[], that
295 // unserialisation takes byte[], and round-tripping works.
296 LatLongCoord llc = new LatLongCoord(10.5, 45.25);
297 res = llc.serialise();
298 LatLongCoord llc_out = new LatLongCoord();
299 llc_out.unserialise(res);
300 if (!llc.toString().equals(llc_out.toString())) {
301 System.err.println("LatLongCoord serialisation doesn't work as expected");
302 System.exit(1);
305 // Check that serialisation returns byte[], that
306 // unserialisation takes byte[], and round-tripping works.
307 LatLongCoords llcs = new LatLongCoords();
308 llcs.append(llc);
309 res = llcs.serialise();
310 LatLongCoords llcs_out = new LatLongCoords();
311 llcs_out.unserialise(res);
312 if (!llcs.toString().equals(llcs_out.toString())) {
313 System.err.println("LatLongCoords serialisation doesn't work as expected");
314 System.exit(1);
317 // Check `range_limit` mapped to byte[].
318 q = new Query(Query.op.OP_VALUE_GE, 0, res);
319 if (q.toString().length() == 0) {
320 // Mostly just a way to actually use the constructed object.
321 System.err.println("Query description shouldn't be empty");
322 System.exit(1);
325 // Check `range_limit` mapped to byte[].
326 q = new Query(Query.op.OP_VALUE_LE, 1, res);
327 if (q.toString().length() == 0) {
328 // Mostly just a way to actually use the constructed object.
329 System.err.println("Query description shouldn't be empty");
330 System.exit(1);
333 // Check `range_lower` and `range_upper` mapped to byte[].
334 q = new Query(Query.op.OP_VALUE_RANGE, 2, res, res);
335 if (q.toString().length() == 0) {
336 // Mostly just a way to actually use the constructed object.
337 System.err.println("Query description shouldn't be empty");
338 System.exit(1);
341 // Check ValueSetMatchDecider.addValue() and removeValue() take
342 // byte[].
343 ValueSetMatchDecider vsmd = new ValueSetMatchDecider(1, false);
344 vsmd.addValue(res);
345 vsmd.removeValue(res);
347 // Check Database.getValueLowerBound() and getValueUpperBound()
348 // return byte[].
349 byte[] lo = "abba".getBytes();
350 byte[] hi = "xyzzy".getBytes();
352 WritableDatabase wdb = new WritableDatabase("", Xapian.DB_BACKEND_INMEMORY);
353 Document document = new Document();
354 document.addValue(42, hi);
355 wdb.addDocument(document);
356 document.addValue(42, lo);
357 wdb.addDocument(document);
358 db = wdb;
361 if (!java.util.Arrays.equals(db.getValueLowerBound(42), lo)) {
362 System.err.println("Database.getValueLowerBound() doesn't work as expected");
363 System.exit(1);
365 if (!java.util.Arrays.equals(db.getValueUpperBound(42), hi)) {
366 System.err.println("Database.getValueUpperBound() doesn't work as expected");
367 System.exit(1);
370 ValueIterator it = db.valuestreamBegin(42);
371 if (!java.util.Arrays.equals(it.getValue(), hi)) {
372 System.err.println("ValueIterator.getValue() doesn't work as expected");
373 System.exit(1);
376 } catch (Exception e) {
377 System.err.println("Caught unexpected exception " + e.toString());
378 System.exit(1);