mhs-xapian 1.0.18a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. data/.gitignore +3 -0
  2. data/AUTHORS +1 -0
  3. data/COPYING +340 -0
  4. data/ChangeLog +5876 -0
  5. data/HACKING +101 -0
  6. data/INSTALL +293 -0
  7. data/Makefile +722 -0
  8. data/Makefile.am +26 -0
  9. data/Makefile.in +722 -0
  10. data/NEWS +2110 -0
  11. data/README +59 -0
  12. data/Rakefile +51 -0
  13. data/TODO +47 -0
  14. data/aclocal.m4 +7675 -0
  15. data/config.guess +1501 -0
  16. data/config.h +56 -0
  17. data/config.h.in +55 -0
  18. data/config.status +1298 -0
  19. data/config.sub +1705 -0
  20. data/configure +18536 -0
  21. data/configure.ac +944 -0
  22. data/csharp/.deps/xapian_wrap.Plo +1 -0
  23. data/csharp/AssemblyInfo.cs +40 -0
  24. data/csharp/AssemblyInfo.cs.in +40 -0
  25. data/csharp/Auto.cs +46 -0
  26. data/csharp/BM25Weight.cs +107 -0
  27. data/csharp/BoolWeight.cs +103 -0
  28. data/csharp/Database.cs +275 -0
  29. data/csharp/DateValueRangeProcessor.cs +61 -0
  30. data/csharp/Document.cs +177 -0
  31. data/csharp/ESet.cs +94 -0
  32. data/csharp/ESetIterator.cs +117 -0
  33. data/csharp/Enquire.cs +274 -0
  34. data/csharp/ExpandDecider.cs +76 -0
  35. data/csharp/Flint.cs +58 -0
  36. data/csharp/InMemory.cs +46 -0
  37. data/csharp/MSet.cs +193 -0
  38. data/csharp/MSetIterator.cs +141 -0
  39. data/csharp/Makefile +868 -0
  40. data/csharp/Makefile.am +106 -0
  41. data/csharp/Makefile.in +868 -0
  42. data/csharp/MatchDecider.cs +76 -0
  43. data/csharp/MultiValueSorter.cs +63 -0
  44. data/csharp/NumberValueRangeProcessor.cs +61 -0
  45. data/csharp/PositionIterator.cs +101 -0
  46. data/csharp/PostingIterator.cs +125 -0
  47. data/csharp/Quartz.cs +58 -0
  48. data/csharp/Query.cs +150 -0
  49. data/csharp/QueryParser.cs +174 -0
  50. data/csharp/RSet.cs +102 -0
  51. data/csharp/Remote.cs +100 -0
  52. data/csharp/SWIGTYPE_p_std__string.cs +30 -0
  53. data/csharp/SWIGTYPE_p_std__vectorTXapian__Query_t.cs +30 -0
  54. data/csharp/SWIGTYPE_p_std__vectorTstd__string_t.cs +30 -0
  55. data/csharp/SimpleStopper.cs +64 -0
  56. data/csharp/SmokeTest.cs +178 -0
  57. data/csharp/Sorter.cs +76 -0
  58. data/csharp/Stem.cs +66 -0
  59. data/csharp/Stopper.cs +91 -0
  60. data/csharp/StringValueRangeProcessor.cs +53 -0
  61. data/csharp/TermGenerator.cs +152 -0
  62. data/csharp/TermIterator.cs +125 -0
  63. data/csharp/TradWeight.cs +107 -0
  64. data/csharp/ValueIterator.cs +102 -0
  65. data/csharp/ValueRangeProcessor.cs +76 -0
  66. data/csharp/Version.cs +60 -0
  67. data/csharp/Weight.cs +93 -0
  68. data/csharp/WritableDatabase.cs +153 -0
  69. data/csharp/Xapian.cs +65 -0
  70. data/csharp/XapianPINVOKE.cs +1527 -0
  71. data/csharp/docs/Makefile +450 -0
  72. data/csharp/docs/Makefile.am +16 -0
  73. data/csharp/docs/Makefile.in +450 -0
  74. data/csharp/docs/examples/SimpleExpand.cs +109 -0
  75. data/csharp/docs/examples/SimpleIndex.cs +71 -0
  76. data/csharp/docs/examples/SimpleSearch.cs +78 -0
  77. data/csharp/docs/index.html +211 -0
  78. data/csharp/util.i +233 -0
  79. data/csharp/xapian_wrap.cc +10338 -0
  80. data/csharp/xapian_wrap.h +93 -0
  81. data/depcomp +632 -0
  82. data/extconf.rb +20 -0
  83. data/generic/except.i +80 -0
  84. data/generic/generic.mk +48 -0
  85. data/install-sh +520 -0
  86. data/java-swig/.deps/xapian_wrap.Plo +1 -0
  87. data/java-swig/Auto.java +35 -0
  88. data/java-swig/BM25Weight.java +81 -0
  89. data/java-swig/BoolWeight.java +77 -0
  90. data/java-swig/Database.java +195 -0
  91. data/java-swig/DateValueRangeProcessor.java +51 -0
  92. data/java-swig/Document.java +135 -0
  93. data/java-swig/ESet.java +71 -0
  94. data/java-swig/ESetIterator.java +71 -0
  95. data/java-swig/Enquire.java +246 -0
  96. data/java-swig/ExpandDecider.java +59 -0
  97. data/java-swig/Flint.java +43 -0
  98. data/java-swig/InMemory.java +35 -0
  99. data/java-swig/MSet.java +143 -0
  100. data/java-swig/MSetIterator.java +87 -0
  101. data/java-swig/Makefile +781 -0
  102. data/java-swig/Makefile.am +132 -0
  103. data/java-swig/Makefile.in +781 -0
  104. data/java-swig/MatchDecider.java +59 -0
  105. data/java-swig/MultiValueSorter.java +51 -0
  106. data/java-swig/NumberValueRangeProcessor.java +51 -0
  107. data/java-swig/PositionIterator.java +63 -0
  108. data/java-swig/PostingIterator.java +83 -0
  109. data/java-swig/Quartz.java +43 -0
  110. data/java-swig/Query.java +189 -0
  111. data/java-swig/QueryParser.java +214 -0
  112. data/java-swig/RSet.java +79 -0
  113. data/java-swig/Remote.java +71 -0
  114. data/java-swig/SWIGTYPE_p_std__string.java +25 -0
  115. data/java-swig/SimpleStopper.java +51 -0
  116. data/java-swig/SmokeTest.java +161 -0
  117. data/java-swig/Sorter.java +59 -0
  118. data/java-swig/Stem.java +51 -0
  119. data/java-swig/Stopper.java +63 -0
  120. data/java-swig/StringValueRangeProcessor.java +43 -0
  121. data/java-swig/TermGenerator.java +158 -0
  122. data/java-swig/TermIterator.java +83 -0
  123. data/java-swig/TradWeight.java +81 -0
  124. data/java-swig/ValueIterator.java +67 -0
  125. data/java-swig/ValueRangeProcessor.java +59 -0
  126. data/java-swig/Version.java +47 -0
  127. data/java-swig/Weight.java +68 -0
  128. data/java-swig/WritableDatabase.java +123 -0
  129. data/java-swig/Xapian.java +39 -0
  130. data/java-swig/XapianConstants.java +15 -0
  131. data/java-swig/XapianJNI.java +508 -0
  132. data/java-swig/run-java-test +6 -0
  133. data/java-swig/xapian_wrap.cc +12594 -0
  134. data/java-swig/xapian_wrap.h +91 -0
  135. data/java/Makefile +660 -0
  136. data/java/Makefile.am +35 -0
  137. data/java/Makefile.in +660 -0
  138. data/java/README +76 -0
  139. data/java/SmokeTest.java +148 -0
  140. data/java/native/.deps/Database.Plo +1 -0
  141. data/java/native/.deps/Document.Plo +1 -0
  142. data/java/native/.deps/ESet.Plo +1 -0
  143. data/java/native/.deps/ESetIterator.Plo +1 -0
  144. data/java/native/.deps/Enquire.Plo +1 -0
  145. data/java/native/.deps/MSet.Plo +1 -0
  146. data/java/native/.deps/MSetIterator.Plo +1 -0
  147. data/java/native/.deps/PositionIterator.Plo +1 -0
  148. data/java/native/.deps/Query.Plo +1 -0
  149. data/java/native/.deps/RSet.Plo +1 -0
  150. data/java/native/.deps/Stem.Plo +1 -0
  151. data/java/native/.deps/TermIterator.Plo +1 -0
  152. data/java/native/.deps/WritableDatabase.Plo +1 -0
  153. data/java/native/.deps/org_xapian_XapianJNI.Plo +1 -0
  154. data/java/native/.deps/utils.Plo +1 -0
  155. data/java/native/Database.cc +222 -0
  156. data/java/native/Document.cc +173 -0
  157. data/java/native/ESet.cc +79 -0
  158. data/java/native/ESetIterator.cc +82 -0
  159. data/java/native/Enquire.cc +271 -0
  160. data/java/native/MSet.cc +169 -0
  161. data/java/native/MSetIterator.cc +107 -0
  162. data/java/native/Makefile +594 -0
  163. data/java/native/Makefile.am +51 -0
  164. data/java/native/Makefile.in +594 -0
  165. data/java/native/PositionIterator.cc +64 -0
  166. data/java/native/Query.cc +180 -0
  167. data/java/native/RSet.cc +98 -0
  168. data/java/native/Stem.cc +75 -0
  169. data/java/native/TermIterator.cc +107 -0
  170. data/java/native/WritableDatabase.cc +118 -0
  171. data/java/native/XapianObjectHolder.h +115 -0
  172. data/java/native/org_xapian_XapianJNI.cc +78 -0
  173. data/java/native/org_xapian_XapianJNI.h +1369 -0
  174. data/java/native/utils.cc +51 -0
  175. data/java/native/xapian_jni.h +116 -0
  176. data/java/org/xapian/Database.java +148 -0
  177. data/java/org/xapian/Document.java +135 -0
  178. data/java/org/xapian/ESet.java +66 -0
  179. data/java/org/xapian/ESetIterator.java +97 -0
  180. data/java/org/xapian/Enquire.java +136 -0
  181. data/java/org/xapian/ExpandDecider.java +30 -0
  182. data/java/org/xapian/MSet.java +104 -0
  183. data/java/org/xapian/MSetIterator.java +132 -0
  184. data/java/org/xapian/Makefile +580 -0
  185. data/java/org/xapian/Makefile.am +38 -0
  186. data/java/org/xapian/Makefile.in +580 -0
  187. data/java/org/xapian/MatchDecider.java +30 -0
  188. data/java/org/xapian/PositionIterator.java +89 -0
  189. data/java/org/xapian/Query.java +190 -0
  190. data/java/org/xapian/RSet.java +89 -0
  191. data/java/org/xapian/Stem.java +80 -0
  192. data/java/org/xapian/TermIterator.java +142 -0
  193. data/java/org/xapian/WritableDatabase.java +92 -0
  194. data/java/org/xapian/Xapian.java +114 -0
  195. data/java/org/xapian/XapianJNI.java +444 -0
  196. data/java/org/xapian/errors/AssertionError.java +40 -0
  197. data/java/org/xapian/errors/DatabaseCorruptError.java +40 -0
  198. data/java/org/xapian/errors/DatabaseError.java +40 -0
  199. data/java/org/xapian/errors/DatabaseLockError.java +40 -0
  200. data/java/org/xapian/errors/DatabaseModifiedError.java +40 -0
  201. data/java/org/xapian/errors/DatabaseOpeningError.java +40 -0
  202. data/java/org/xapian/errors/DocNotFoundError.java +40 -0
  203. data/java/org/xapian/errors/FeatureUnavailableError.java +40 -0
  204. data/java/org/xapian/errors/InternalError.java +40 -0
  205. data/java/org/xapian/errors/InvalidArgumentError.java +40 -0
  206. data/java/org/xapian/errors/InvalidOperationError.java +40 -0
  207. data/java/org/xapian/errors/LogicError.java +40 -0
  208. data/java/org/xapian/errors/Makefile +416 -0
  209. data/java/org/xapian/errors/Makefile.am +32 -0
  210. data/java/org/xapian/errors/Makefile.in +416 -0
  211. data/java/org/xapian/errors/NetworkError.java +40 -0
  212. data/java/org/xapian/errors/NetworkTimeoutError.java +40 -0
  213. data/java/org/xapian/errors/RangeError.java +40 -0
  214. data/java/org/xapian/errors/RuntimeError.java +40 -0
  215. data/java/org/xapian/errors/UnimplementedError.java +40 -0
  216. data/java/org/xapian/errors/XapianError.java +40 -0
  217. data/java/org/xapian/errors/XapianRuntimeError.java +49 -0
  218. data/java/org/xapian/examples/Makefile +391 -0
  219. data/java/org/xapian/examples/Makefile.am +8 -0
  220. data/java/org/xapian/examples/Makefile.in +391 -0
  221. data/java/org/xapian/examples/SimpleIndex.java +68 -0
  222. data/java/org/xapian/examples/SimpleSearch.java +71 -0
  223. data/java/run-java-test +6 -0
  224. data/libtool +7618 -0
  225. data/ltmain.sh +6956 -0
  226. data/mhs-xapian.gemspec +368 -0
  227. data/missing +378 -0
  228. data/php/.deps/xapian_wrap.Plo +1 -0
  229. data/php/Makefile +871 -0
  230. data/php/Makefile.am +82 -0
  231. data/php/Makefile.in +871 -0
  232. data/php/docs/Makefile +453 -0
  233. data/php/docs/Makefile.am +19 -0
  234. data/php/docs/Makefile.in +453 -0
  235. data/php/docs/examples/simpleexpand.php4 +108 -0
  236. data/php/docs/examples/simpleexpand.php5 +104 -0
  237. data/php/docs/examples/simpleindex.php4 +76 -0
  238. data/php/docs/examples/simpleindex.php5 +73 -0
  239. data/php/docs/examples/simplesearch.php4 +75 -0
  240. data/php/docs/examples/simplesearch.php5 +72 -0
  241. data/php/docs/index.html +313 -0
  242. data/php/except.i +98 -0
  243. data/php/php4/php_xapian.h +323 -0
  244. data/php/php4/xapian.php +32 -0
  245. data/php/php4/xapian_wrap.cc +27656 -0
  246. data/php/php5/php_xapian.h +319 -0
  247. data/php/php5/xapian.php +1566 -0
  248. data/php/php5/xapian_wrap.cc +24330 -0
  249. data/php/smoketest.php +246 -0
  250. data/php/smoketest4.php +84 -0
  251. data/php/smoketest5.php +79 -0
  252. data/php/util.i +187 -0
  253. data/python/.deps/xapian_wrap.Plo +1 -0
  254. data/python/Makefile +891 -0
  255. data/python/Makefile.am +105 -0
  256. data/python/Makefile.in +891 -0
  257. data/python/doccomments.i +5134 -0
  258. data/python/docs/Makefile +448 -0
  259. data/python/docs/Makefile.am +14 -0
  260. data/python/docs/Makefile.in +448 -0
  261. data/python/docs/examples/simpleexpand.py +98 -0
  262. data/python/docs/examples/simpleindex.py +65 -0
  263. data/python/docs/examples/simplematchdecider.py +78 -0
  264. data/python/docs/examples/simplesearch.py +65 -0
  265. data/python/docs/index.html +420 -0
  266. data/python/except.i +290 -0
  267. data/python/extra.i +1048 -0
  268. data/python/extracomments.i +28 -0
  269. data/python/generate-python-exceptions +189 -0
  270. data/python/generate-python-exceptions.in +189 -0
  271. data/python/modern/xapian.py +5662 -0
  272. data/python/modern/xapian_wrap.cc +35170 -0
  273. data/python/modern/xapian_wrap.h +244 -0
  274. data/python/pythontest.py +1110 -0
  275. data/python/smoketest.py +328 -0
  276. data/python/testsuite.py +382 -0
  277. data/python/util.i +517 -0
  278. data/ruby/.deps/xapian_wrap.Plo +494 -0
  279. data/ruby/.libs/_xapian.bundle +0 -0
  280. data/ruby/.libs/_xapian.bundle.dSYM/Contents/Info.plist +25 -0
  281. data/ruby/.libs/_xapian.bundle.dSYM/Contents/Resources/DWARF/_xapian.bundle +0 -0
  282. data/ruby/.libs/_xapian.la +35 -0
  283. data/ruby/.libs/_xapian.lai +35 -0
  284. data/ruby/Makefile +854 -0
  285. data/ruby/Makefile.am +62 -0
  286. data/ruby/Makefile.in +854 -0
  287. data/ruby/_xapian.la +35 -0
  288. data/ruby/docs/Makefile +487 -0
  289. data/ruby/docs/Makefile.am +50 -0
  290. data/ruby/docs/Makefile.in +487 -0
  291. data/ruby/docs/examples/simpleexpand.rb +98 -0
  292. data/ruby/docs/examples/simpleindex.rb +60 -0
  293. data/ruby/docs/examples/simplematchdecider.rb +74 -0
  294. data/ruby/docs/examples/simplesearch.rb +63 -0
  295. data/ruby/docs/index.html +197 -0
  296. data/ruby/smoketest.rb +211 -0
  297. data/ruby/util.i +232 -0
  298. data/ruby/xapian.rb +280 -0
  299. data/ruby/xapian_wrap.cc +25837 -0
  300. data/ruby/xapian_wrap.h +65 -0
  301. data/ruby/xapian_wrap.lo +12 -0
  302. data/skiptest +2 -0
  303. data/stamp-h1 +1 -0
  304. data/tcl8/.deps/xapian_wrap.Plo +1 -0
  305. data/tcl8/Makefile +835 -0
  306. data/tcl8/Makefile.am +49 -0
  307. data/tcl8/Makefile.in +835 -0
  308. data/tcl8/docs/Makefile +448 -0
  309. data/tcl8/docs/Makefile.am +14 -0
  310. data/tcl8/docs/Makefile.in +448 -0
  311. data/tcl8/docs/examples/simpleexpand.tcl +104 -0
  312. data/tcl8/docs/examples/simpleindex.tcl +68 -0
  313. data/tcl8/docs/examples/simplesearch.tcl +66 -0
  314. data/tcl8/docs/index.html +208 -0
  315. data/tcl8/except.i +48 -0
  316. data/tcl8/pkgIndex.tcl +1 -0
  317. data/tcl8/pkgIndex.tcl.in +1 -0
  318. data/tcl8/run-tcl-test +15 -0
  319. data/tcl8/runtest.tcl +29 -0
  320. data/tcl8/smoketest.tcl +155 -0
  321. data/tcl8/util.i +76 -0
  322. data/tcl8/xapian_wrap.cc +20900 -0
  323. data/xapian-bindings.spec +206 -0
  324. data/xapian-bindings.spec.in +206 -0
  325. data/xapian-version.h +1 -0
  326. data/xapian-version.h.in +1 -0
  327. data/xapian.i +939 -0
  328. metadata +395 -0
@@ -0,0 +1,328 @@
1
+ # Simple test to ensure that we can load the xapian module and exercise basic
2
+ # functionality successfully.
3
+ #
4
+ # Copyright (C) 2004,2005,2006,2007 Olly Betts
5
+ # Copyright (C) 2007 Lemur Consulting Ltd
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as
9
+ # published by the Free Software Foundation; either version 2 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20
+ # USA
21
+
22
+ import sys
23
+ import xapian
24
+
25
+ from testsuite import *
26
+
27
+ def test_all():
28
+ # Test the version number reporting functions give plausible results.
29
+ v = "%d.%d.%d" % (xapian.major_version(),
30
+ xapian.minor_version(),
31
+ xapian.revision())
32
+ v2 = xapian.version_string()
33
+ expect(v2, v, "Unexpected version output")
34
+
35
+ stem = xapian.Stem("english")
36
+ expect(stem.get_description(), "Xapian::Stem(english)", "Unexpected stem.get_description()")
37
+
38
+ doc = xapian.Document()
39
+ doc.set_data("a\0b")
40
+ if doc.get_data() == "a":
41
+ raise TestFail("get_data+set_data truncates at a zero byte")
42
+ expect(doc.get_data(), "a\0b", "get_data+set_data doesn't transparently handle a zero byte")
43
+ doc.set_data("is there anybody out there?")
44
+ doc.add_term("XYzzy")
45
+ doc.add_posting(stem("is"), 1)
46
+ doc.add_posting(stem("there"), 2)
47
+ doc.add_posting(stem("anybody"), 3)
48
+ doc.add_posting(stem("out"), 4)
49
+ doc.add_posting(stem("there"), 5)
50
+
51
+ db = xapian.inmemory_open()
52
+ db.add_document(doc)
53
+ expect(db.get_doccount(), 1, "Unexpected db.get_doccount()")
54
+ terms = ["smoke", "test", "terms"]
55
+ expect_query(xapian.Query(xapian.Query.OP_OR, terms),
56
+ "(smoke OR test OR terms)")
57
+ query1 = xapian.Query(xapian.Query.OP_PHRASE, ("smoke", "test", "tuple"))
58
+ query2 = xapian.Query(xapian.Query.OP_XOR, (xapian.Query("smoke"), query1, "string"))
59
+ expect_query(query1, "(smoke PHRASE 3 test PHRASE 3 tuple)")
60
+ expect_query(query2, "(smoke XOR (smoke PHRASE 3 test PHRASE 3 tuple) XOR string)")
61
+ subqs = ["a", "b"]
62
+ expect_query(xapian.Query(xapian.Query.OP_OR, subqs), "(a OR b)")
63
+ expect_query(xapian.Query(xapian.Query.OP_VALUE_RANGE, 0, '1', '4'),
64
+ "VALUE_RANGE 0 1 4")
65
+
66
+ # Feature test for Query.__iter__
67
+ term_count = 0
68
+ for term in query2:
69
+ term_count += 1
70
+ expect(term_count, 4, "Unexpected number of terms in query2")
71
+
72
+ enq = xapian.Enquire(db)
73
+ enq.set_query(xapian.Query(xapian.Query.OP_OR, "there", "is"))
74
+ mset = enq.get_mset(0, 10)
75
+ expect(mset.size(), 1, "Unexpected mset.size()")
76
+
77
+ # Feature test for Enquire.matching_terms(docid)
78
+ term_count = 0
79
+ for term in enq.matching_terms(mset.get_hit(0)):
80
+ term_count += 1
81
+ expect(term_count, 2, "Unexpected number of matching terms")
82
+
83
+ # Feature test for MSet.__iter__
84
+ msize = 0
85
+ for match in mset:
86
+ msize += 1
87
+ expect(msize, mset.size(), "Unexpected number of entries in mset")
88
+
89
+ terms = " ".join(enq.matching_terms(mset.get_hit(0)))
90
+ expect(terms, "is there", "Unexpected terms")
91
+
92
+ # Feature test for ESet.__iter__
93
+ rset = xapian.RSet()
94
+ rset.add_document(1)
95
+ eset = enq.get_eset(10, rset)
96
+ term_count = 0
97
+ for term in eset:
98
+ term_count += 1
99
+ expect(term_count, 3, "Unexpected number of expand terms")
100
+
101
+ # Feature test for Database.__iter__
102
+ term_count = 0
103
+ for term in db:
104
+ term_count += 1
105
+ expect(term_count, 5, "Unexpected number of terms in db")
106
+
107
+ # Feature test for Database.allterms
108
+ term_count = 0
109
+ for term in db.allterms():
110
+ term_count += 1
111
+ expect(term_count, 5, "Unexpected number of terms in db.allterms")
112
+
113
+ # Feature test for Database.postlist
114
+ count = 0
115
+ for posting in db.postlist("there"):
116
+ count += 1
117
+ expect(count, 1, "Unexpected number of entries in db.postlist('there')")
118
+
119
+ # Feature test for Database.postlist with empty term (alldocspostlist)
120
+ count = 0
121
+ for posting in db.postlist(""):
122
+ count += 1
123
+ expect(count, 1, "Unexpected number of entries in db.postlist('')")
124
+
125
+ # Feature test for Database.termlist
126
+ count = 0
127
+ for term in db.termlist(1):
128
+ count += 1
129
+ expect(count, 5, "Unexpected number of entries in db.termlist(1)")
130
+
131
+ # Feature test for Database.positionlist
132
+ count = 0
133
+ for term in db.positionlist(1, "there"):
134
+ count += 1
135
+ expect(count, 2, "Unexpected number of entries in db.positionlist(1, 'there')")
136
+
137
+ # Feature test for Document.termlist
138
+ count = 0
139
+ for term in doc.termlist():
140
+ count += 1
141
+ expect(count, 5, "Unexpected number of entries in doc.termlist()")
142
+
143
+ # Feature test for TermIter.skip_to
144
+ term = doc.termlist()
145
+ term.skip_to('n')
146
+ while True:
147
+ try:
148
+ x = term.next()
149
+ except StopIteration:
150
+ break
151
+ if x.term < 'n':
152
+ raise TestFail("TermIter.skip_to didn't skip term '%s'" % x.term)
153
+
154
+ # Feature test for Document.values
155
+ count = 0
156
+ for term in doc.values():
157
+ count += 1
158
+ expect(count, 0, "Unexpected number of entries in doc.values")
159
+
160
+ # Check exception handling for Xapian::DocNotFoundError
161
+ expect_exception(xapian.DocNotFoundError, "Docid 3 not found", db.get_document, 3)
162
+
163
+ # Check value of OP_ELITE_SET
164
+ expect(xapian.Query.OP_ELITE_SET, 10, "Unexpected value for OP_ELITE_SET")
165
+
166
+ # Feature test for MatchDecider
167
+ doc = xapian.Document()
168
+ doc.set_data("Two")
169
+ doc.add_posting(stem("out"), 1)
170
+ doc.add_posting(stem("outside"), 1)
171
+ doc.add_posting(stem("source"), 2)
172
+ doc.add_value(0, "yes")
173
+ db.add_document(doc)
174
+
175
+ class testmatchdecider(xapian.MatchDecider):
176
+ def __call__(self, doc):
177
+ return doc.get_value(0) == "yes"
178
+
179
+ query = xapian.Query(stem("out"))
180
+ enquire = xapian.Enquire(db)
181
+ enquire.set_query(query)
182
+ mset = enquire.get_mset(0, 10, None, testmatchdecider())
183
+ expect(mset.size(), 1, "Unexpected number of documents returned by match decider")
184
+ expect(mset.get_docid(0), 2, "MatchDecider mset has wrong docid in")
185
+
186
+ # Feature test for ExpandDecider
187
+ class testexpanddecider(xapian.ExpandDecider):
188
+ def __call__(self, term):
189
+ return (not term.startswith('a'))
190
+
191
+ enquire = xapian.Enquire(db)
192
+ rset = xapian.RSet()
193
+ rset.add_document(1)
194
+ eset = enquire.get_eset(10, rset, xapian.Enquire.USE_EXACT_TERMFREQ, 1.0, testexpanddecider())
195
+ eset_terms = [term[xapian.ESET_TNAME] for term in eset.items]
196
+ expect(len(eset_terms), eset.size(), "Unexpected number of terms returned by expand")
197
+ if filter(lambda t: t.startswith('a'), eset_terms):
198
+ raise TestFail("ExpandDecider was not used")
199
+
200
+ # Check QueryParser parsing error.
201
+ qp = xapian.QueryParser()
202
+ expect_exception(xapian.QueryParserError, "Syntax: <expression> AND <expression>", qp.parse_query, "test AND")
203
+
204
+ # Check QueryParser pure NOT option
205
+ qp = xapian.QueryParser()
206
+ expect_query(qp.parse_query("NOT test", qp.FLAG_BOOLEAN + qp.FLAG_PURE_NOT),
207
+ "(<alldocuments> AND_NOT test:(pos=1))")
208
+
209
+ # Check QueryParser partial option
210
+ qp = xapian.QueryParser()
211
+ qp.set_database(db)
212
+ qp.set_default_op(xapian.Query.OP_AND)
213
+ qp.set_stemming_strategy(qp.STEM_SOME)
214
+ qp.set_stemmer(xapian.Stem('en'))
215
+ expect_query(qp.parse_query("foo o", qp.FLAG_PARTIAL),
216
+ "(Zfoo:(pos=1) AND (out:(pos=2) OR outsid:(pos=2) OR Zo:(pos=2)))")
217
+
218
+ expect_query(qp.parse_query("foo outside", qp.FLAG_PARTIAL),
219
+ "(Zfoo:(pos=1) AND Zoutsid:(pos=2))")
220
+
221
+ # Test supplying unicode strings
222
+ expect_query(xapian.Query(xapian.Query.OP_OR, (u'foo', u'bar')),
223
+ '(foo OR bar)')
224
+ expect_query(xapian.Query(xapian.Query.OP_OR, ('foo', u'bar\xa3')),
225
+ '(foo OR bar\xc2\xa3)')
226
+ expect_query(xapian.Query(xapian.Query.OP_OR, ('foo', 'bar\xc2\xa3')),
227
+ '(foo OR bar\xc2\xa3)')
228
+ expect_query(xapian.Query(xapian.Query.OP_OR, u'foo', u'bar'),
229
+ '(foo OR bar)')
230
+
231
+ expect_query(qp.parse_query(u"NOT t\xe9st", qp.FLAG_BOOLEAN + qp.FLAG_PURE_NOT),
232
+ "(<alldocuments> AND_NOT Zt\xc3\xa9st:(pos=1))")
233
+
234
+ doc = xapian.Document()
235
+ doc.set_data(u"Unicode with an acc\xe9nt")
236
+ doc.add_posting(stem(u"out\xe9r"), 1)
237
+ expect(doc.get_data(), u"Unicode with an acc\xe9nt".encode('utf-8'))
238
+ term = doc.termlist().next().term
239
+ expect(term, u"out\xe9r".encode('utf-8'))
240
+
241
+ # Check simple stopper
242
+ stop = xapian.SimpleStopper()
243
+ qp.set_stopper(stop)
244
+ expect(stop('a'), False)
245
+ expect_query(qp.parse_query(u"foo bar a", qp.FLAG_BOOLEAN),
246
+ "(Zfoo:(pos=1) AND Zbar:(pos=2) AND Za:(pos=3))")
247
+
248
+ stop.add('a')
249
+ expect(stop('a'), True)
250
+ expect_query(qp.parse_query(u"foo bar a", qp.FLAG_BOOLEAN),
251
+ "(Zfoo:(pos=1) AND Zbar:(pos=2))")
252
+
253
+ # Feature test for custom Stopper
254
+ class my_b_stopper(xapian.Stopper):
255
+ def __call__(self, term):
256
+ return term == "b"
257
+
258
+ def get_description(self):
259
+ return u"my_b_stopper"
260
+
261
+ stop = my_b_stopper()
262
+ expect(stop.get_description(), u"my_b_stopper")
263
+ qp.set_stopper(stop)
264
+ expect(stop('a'), False)
265
+ expect_query(qp.parse_query(u"foo bar a", qp.FLAG_BOOLEAN),
266
+ "(Zfoo:(pos=1) AND Zbar:(pos=2) AND Za:(pos=3))")
267
+
268
+ expect(stop('b'), True)
269
+ expect_query(qp.parse_query(u"foo bar b", qp.FLAG_BOOLEAN),
270
+ "(Zfoo:(pos=1) AND Zbar:(pos=2))")
271
+
272
+ # Test TermGenerator
273
+ termgen = xapian.TermGenerator()
274
+ doc = xapian.Document()
275
+ termgen.set_document(doc)
276
+ termgen.index_text('foo bar baz foo')
277
+ expect([(item.term, item.wdf, [pos for pos in item.positer]) for item in doc.termlist()], [('bar', 1, [2]), ('baz', 1, [3]), ('foo', 2, [1, 4])])
278
+
279
+
280
+ # Check DateValueRangeProcessor works
281
+ context("checking that DateValueRangeProcessor works")
282
+ qp = xapian.QueryParser()
283
+ vrpdate = xapian.DateValueRangeProcessor(1, 1, 1960)
284
+ qp.add_valuerangeprocessor(vrpdate)
285
+ query = qp.parse_query('12/03/99..12/04/01')
286
+ expect(str(query), 'Xapian::Query(VALUE_RANGE 1 19991203 20011204)')
287
+
288
+ # Regression test for bug#193, fixed in 1.0.3.
289
+ context("running regression test for bug#193")
290
+ vrp = xapian.NumberValueRangeProcessor(0, '$', True)
291
+ a = '$10'
292
+ b = '20'
293
+ slot, a, b = vrp(a, b)
294
+ expect(slot, 0)
295
+ expect(xapian.sortable_unserialise(a), 10)
296
+ expect(xapian.sortable_unserialise(b), 20)
297
+
298
+ # Regression tests copied from PHP (probably always worked in python, but
299
+ # let's check...)
300
+ context("running regression tests for issues which were found in PHP")
301
+
302
+ # PHP overload resolution involving boolean types failed.
303
+ enq.set_sort_by_value(1, True)
304
+
305
+ # Regression test - fixed in 0.9.10.1.
306
+ oqparser = xapian.QueryParser()
307
+ oquery = oqparser.parse_query("I like tea")
308
+
309
+ # Regression test for bug#192 - fixed in 1.0.3.
310
+ enq.set_cutoff(100)
311
+
312
+ # Test setting and getting metadata
313
+ expect(db.get_metadata('Foo'), '')
314
+ db.set_metadata('Foo', 'Foo')
315
+ expect(db.get_metadata('Foo'), 'Foo')
316
+ expect_exception(xapian.InvalidArgumentError, "Empty metadata keys are invalid", db.get_metadata, '')
317
+ expect_exception(xapian.InvalidArgumentError, "Empty metadata keys are invalid", db.set_metadata, '', 'Foo')
318
+ expect_exception(xapian.InvalidArgumentError, "Empty metadata keys are invalid", db.get_metadata, '')
319
+
320
+ # Test OP_SCALE_WEIGHT and corresponding constructor
321
+ expect_query(xapian.Query(xapian.Query.OP_SCALE_WEIGHT, xapian.Query('foo'), 5),
322
+ "5 * foo")
323
+
324
+ # Run all tests (ie, callables with names starting "test_").
325
+ if not runtests(globals()):
326
+ sys.exit(1)
327
+
328
+ # vim:syntax=python:set expandtab:
@@ -0,0 +1,382 @@
1
+ # Utility functions for running tests and reporting the results.
2
+ #
3
+ # Copyright (C) 2007 Lemur Consulting Ltd
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.
14
+ #
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
19
+
20
+ import os as _os
21
+ import os.path as _path
22
+ import sys as _sys
23
+ import traceback as _traceback
24
+ import xapian as _xapian
25
+
26
+ class TestFail(Exception):
27
+ pass
28
+
29
+ class TestRunner(object):
30
+ def __init__(self):
31
+ """Initialise the TestRunner.
32
+
33
+ """
34
+
35
+ self._out = OutProxy(_sys.stdout)
36
+
37
+ # _verbose is an integer, higher meaning more verbose
38
+ self._verbose = _os.environ.get('VERBOSE', '').lower()
39
+ if self._verbose in ('', '0', 'no', 'off', 'false'):
40
+ self._verbose = 0
41
+ else:
42
+ try:
43
+ self._verbose = int(self._verbose)
44
+ except:
45
+ self._verbose = 1
46
+
47
+ # context is a description of what the test is currently checking
48
+ self._context = None
49
+
50
+ def context(self, context):
51
+ """Set the context.
52
+
53
+ This should be a string describing what a test is checking, and will be
54
+ displayed if the test fails.
55
+
56
+ A test may change the context several times - each call will override
57
+ subsequent calls.
58
+
59
+ Set the context to None to remove display of a specific context message.
60
+ This is performed automatically at the start of each test.
61
+
62
+ """
63
+ self._context = context
64
+ if context is not None and self._verbose > 1:
65
+ self._out.start_line()
66
+ self._out.write("Context: %s\n" % context)
67
+ self._out.flush()
68
+
69
+ def expect(self, got, expected, message="Expected equality"):
70
+ """Function used to check for a particular expected value.
71
+
72
+ """
73
+ if self._verbose > 2:
74
+ self._out.start_line()
75
+ self._out.write("Checking for %r: expecting %r ... " % (message, expected))
76
+ self._out.flush()
77
+ if got != expected:
78
+ if self._verbose > 2:
79
+ self._out.write_colour(" #red#failed##")
80
+ self._out.write(": got %r\n" % got)
81
+ self._out.flush()
82
+ raise TestFail("%s: got %r, expected %r" % (message, got, expected))
83
+ if self._verbose > 2:
84
+ self._out.write_colour(" #green#ok##\n")
85
+ self._out.flush()
86
+
87
+ def expect_query(self, query, expected):
88
+ """Check that the description of a query is as expected.
89
+
90
+ """
91
+ expected = 'Xapian::Query(' + expected + ')'
92
+ desc = query.get_description()
93
+ if self._verbose > 2:
94
+ self._out.start_line()
95
+ self._out.write("Checking query.get_description(): expecting %r ... " % expected)
96
+ self._out.flush()
97
+ if desc != expected:
98
+ if self._verbose > 2:
99
+ self._out.write_colour(" #red#failed##")
100
+ self._out.write(": got %r\n" % desc)
101
+ self._out.flush()
102
+ raise TestFail("Unexpected query.get_description(): got %r, expected %r" % (desc, expected))
103
+ if self._verbose > 2:
104
+ self._out.write_colour(" #green#ok##\n")
105
+ self._out.flush()
106
+
107
+ def expect_exception(self, expectedclass, expectedmsg, callable, *args):
108
+ if self._verbose > 2:
109
+ self._out.start_line()
110
+ self._out.write("Checking for exception: %s(%r) ... " % (str(expectedclass), expectedmsg))
111
+ self._out.flush()
112
+ try:
113
+ callable(*args)
114
+ if self._verbose > 2:
115
+ self._out.write_colour(" #red#failed##: no exception occurred\n")
116
+ self._out.flush()
117
+ raise TestFail("Expected %s(%r) exception" % (str(expectedclass), expectedmsg))
118
+ except expectedclass, e:
119
+ if str(e) != expectedmsg:
120
+ if self._verbose > 2:
121
+ self._out.write_colour(" #red#failed##")
122
+ self._out.write(": exception string not as expected: got '%s'\n" % str(e))
123
+ self._out.flush()
124
+ raise TestFail("Exception string not as expected: got '%s', expected '%s'" % (str(e), expectedmsg))
125
+ if e.__class__ != expectedclass:
126
+ if self._verbose > 2:
127
+ self._out.write_colour(" #red#failed##")
128
+ self._out.write(": didn't get right exception class: got '%s'\n" % str(e.__class__))
129
+ self._out.flush()
130
+ raise TestFail("Didn't get right exception class: got '%s', expected '%s'" % (str(e.__class__), str(expectedclass)))
131
+ if self._verbose > 2:
132
+ self._out.write_colour(" #green#ok##\n")
133
+ self._out.flush()
134
+
135
+ def report_failure(self, name, msg, show_traceback=True):
136
+ "Report a test failure, with some useful context."
137
+
138
+ orig_tb = _traceback.extract_tb(_sys.exc_info()[2])
139
+ tb = orig_tb
140
+
141
+ # Move up the traceback until we get to the line in the test
142
+ # function which caused the failure.
143
+ while tb[-1][2] != 'test_' + name:
144
+ tb = tb[:-1]
145
+
146
+ # Display the context in the text function.
147
+ filepath, linenum, functionname, text = tb[-1]
148
+ filename = _os.path.basename(filepath)
149
+
150
+ self._out.ensure_space()
151
+ self._out.write_colour("#red#FAILED##\n")
152
+ if self._verbose > 0:
153
+ if self._context is None:
154
+ context = ''
155
+ else:
156
+ context = ", when %s" % self._context
157
+ firstline = "%s:%d" % (filename, linenum)
158
+ self._out.write("\n%s:%s%s\n" % (firstline, msg, context))
159
+
160
+ # Display sourcecode lines
161
+ lines = open(filepath).readlines()
162
+ startline = max(linenum - 3, 0)
163
+ endline = min(linenum + 2, len(lines))
164
+ for num in xrange(startline, endline):
165
+ if num + 1 == linenum:
166
+ self._out.write('->')
167
+ else:
168
+ self._out.write(' ')
169
+ self._out.write("%4d %s\n" % (num + 1, lines[num].rstrip()))
170
+
171
+ # Display the traceback
172
+ if show_traceback:
173
+ self._out.write("Traceback (most recent call last):\n")
174
+ for line in _traceback.format_list(orig_tb):
175
+ self._out.write(line.rstrip() + '\n')
176
+ self._out.write('\n')
177
+
178
+ # Display some information about the xapian version and platform
179
+ self._out.write("Xapian version: %s\n" % _xapian.version_string())
180
+ try:
181
+ import platform
182
+ platdesc = "%s %s (%s)" % platform.system_alias(platform.system(),
183
+ platform.release(),
184
+ platform.version())
185
+ self._out.write("Platform: %s\n" % platdesc)
186
+ except:
187
+ pass
188
+ self._out.write('\nWhen reporting this problem, please quote all the preceding lines from\n"%s" onwards.\n\n' % firstline)
189
+
190
+ self._out.flush()
191
+
192
+ def runtest(self, name, test_fn):
193
+ """Run a single test.
194
+
195
+ """
196
+ startline = "Running test: %s..." % name
197
+ self._out.write(startline)
198
+ self._out.flush()
199
+ try:
200
+ test_fn()
201
+ if self._verbose > 0 or self._out.plain:
202
+ self._out.ensure_space()
203
+ self._out.write_colour("#green#ok##\n")
204
+ else:
205
+ self._out.clear_line()
206
+ self._out.flush()
207
+ return True
208
+ except TestFail, e:
209
+ self.report_failure(name, str(e), show_traceback=False)
210
+ except _xapian.Error, e:
211
+ self.report_failure(name, "%s: %s" % (str(e.__class__), str(e)))
212
+ except Exception, e:
213
+ self.report_failure(name, "%s: %s" % (str(e.__class__), str(e)))
214
+ return False
215
+
216
+ def runtests(self, namedict, runonly=None):
217
+ """Run a set of tests.
218
+
219
+ Takes a dictionary of name-value pairs and runs all the values which are
220
+ callables, for which the name begins with "test_".
221
+
222
+ Typical usage is to pass "locals()" as the parameter, to run all callables
223
+ with names starting "test_" in local scope.
224
+
225
+ If runonly is supplied, and non-empty, only those tests which appear in
226
+ runonly will be run.
227
+
228
+ """
229
+ tests = []
230
+ if isinstance(namedict, dict):
231
+ for name in namedict:
232
+ if name.startswith('test_'):
233
+ fn = namedict[name]
234
+ name = name[5:]
235
+ if callable(fn):
236
+ tests.append((name, fn))
237
+ tests.sort()
238
+ else:
239
+ tests = namedict
240
+
241
+ if runonly is not None and len(runonly) != 0:
242
+ oldtests = tests
243
+ tests = []
244
+ for name, fn in oldtests:
245
+ if name in runonly:
246
+ tests.append((name, fn))
247
+
248
+ passed, failed = 0, 0
249
+ for name, fn in tests:
250
+ self.context(None)
251
+ if self.runtest(name, fn):
252
+ passed += 1
253
+ else:
254
+ failed += 1
255
+ if failed:
256
+ if self._verbose == 0:
257
+ self._out.write('Re-run with the VERBOSE environment variable set to "1" to see details.\n')
258
+ self._out.write_colour("#green#%d## tests passed, #red#%d## tests failed\n" % (passed, failed))
259
+ return False
260
+ else:
261
+ self._out.write_colour("#green#%d## tests passed, no failures\n" % passed)
262
+ return True
263
+
264
+ class OutProxy(object):
265
+ """Proxy output class to make formatting easier.
266
+
267
+ Allows colourisation, and keeps track of whether we're mid-line or not.
268
+
269
+ """
270
+
271
+ def __init__(self, out):
272
+ self._out = out
273
+ self._line_pos = 0 # Position on current line
274
+ self._had_space = True # True iff we're preceded by whitespace (including newline)
275
+ self.plain = not self._allow_control_sequences()
276
+ self._colours = self.get_colour_strings()
277
+
278
+ def _allow_control_sequences(self):
279
+ "Return True if output device allows control sequences."
280
+ mode = _os.environ.get("XAPIAN_TESTSUITE_OUTPUT", '').lower()
281
+ if mode in ('', 'auto'):
282
+ if _sys.platform == 'win32':
283
+ return False
284
+ elif not hasattr(self._out, "isatty"):
285
+ return False
286
+ else:
287
+ return self._out.isatty()
288
+ elif mode == 'plain':
289
+ return False
290
+ return True
291
+
292
+ def get_colour_strings(self):
293
+ """Return a mapping of colour names to colour output sequences.
294
+
295
+ """
296
+ colours = {
297
+ 'red': "\x1b[1m\x1b[31m",
298
+ 'green': "\x1b[1m\x1b[32m",
299
+ 'yellow': "\x1b[1m\x1b[33m",
300
+ '': "\x1b[0m",
301
+ }
302
+ if self.plain:
303
+ for key in colours:
304
+ colours[key] = ''
305
+ return colours
306
+
307
+ def _colourise(self, msg):
308
+ """Apply colours to a message.
309
+
310
+ #colourname# will change the text colour, ## will change the colour back.
311
+
312
+ """
313
+ for colour, val in self._colours.iteritems():
314
+ msg = msg.replace('#%s#' % colour, val)
315
+ return msg
316
+
317
+ def clear_line(self):
318
+ """Clear the current line of output, if possible.
319
+
320
+ Otherwise, just move to the start of the next line.
321
+
322
+ """
323
+ if self._line_pos == 0:
324
+ return
325
+ if self.plain:
326
+ self.write('\n')
327
+ else:
328
+ self.write("\r" + " " * self._line_pos + "\r")
329
+
330
+ def start_line(self):
331
+ """Ensure that we're at the start of a line.
332
+
333
+ """
334
+ if self._line_pos != 0:
335
+ self.write('\n')
336
+
337
+ def ensure_space(self):
338
+ """Ensure that we're preceded by whitespace.
339
+
340
+ """
341
+ if not self._had_space:
342
+ self.write(' ')
343
+
344
+ def write(self, msg):
345
+ """Write the message to the output stream.
346
+
347
+ """
348
+ if len(msg) == 0:
349
+ return
350
+
351
+ # Adjust the line position counted
352
+ nlpos = max(msg.rfind('\n'), msg.rfind('\r'))
353
+ if nlpos >= 0:
354
+ subline = msg[nlpos + 1:]
355
+ self._line_pos = len(subline) # Note - doesn't cope with tabs.
356
+ else:
357
+ self._line_pos += len(msg) # Note - doesn't cope with tabs.
358
+
359
+ # Record whether we ended with whitespace
360
+ self._had_space = msg[-1].isspace()
361
+
362
+ self._out.write(msg)
363
+
364
+ def write_colour(self, msg):
365
+ """Write a message, first substituting markup for colours.
366
+
367
+ """
368
+ self.write(self._colourise(msg))
369
+
370
+ def flush(self):
371
+ self._out.flush()
372
+
373
+
374
+ _runner = TestRunner()
375
+ context = _runner.context
376
+ expect = _runner.expect
377
+ expect_query = _runner.expect_query
378
+ expect_exception = _runner.expect_exception
379
+ runtests = _runner.runtests
380
+
381
+ __all__ = ('context', 'expect', 'expect_query', 'expect_exception', 'runtests')
382
+