droonga-engine 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (341) hide show
  1. data/.dir-locals.el +3 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +7 -0
  5. data/Gemfile +66 -0
  6. data/LICENSE.txt +14 -0
  7. data/README.md +17 -0
  8. data/Rakefile +64 -0
  9. data/benchmark/benchmark.rb +123 -0
  10. data/benchmark/utils.rb +246 -0
  11. data/benchmark/watch/benchmark-notify.rb +143 -0
  12. data/benchmark/watch/benchmark-notify.sh +20 -0
  13. data/benchmark/watch/benchmark-publish.rb +120 -0
  14. data/benchmark/watch/benchmark-scan.rb +213 -0
  15. data/bin/droonga-catalog-generate +103 -0
  16. data/bin/droonga-engine +20 -0
  17. data/bin/droonga-engine-service +20 -0
  18. data/doc/text/news.md +106 -0
  19. data/droonga-engine.gemspec +52 -0
  20. data/lib/droonga/adapter.rb +48 -0
  21. data/lib/droonga/adapter_runner.rb +104 -0
  22. data/lib/droonga/catalog/base.rb +41 -0
  23. data/lib/droonga/catalog/collection_volume.rb +106 -0
  24. data/lib/droonga/catalog/dataset.rb +69 -0
  25. data/lib/droonga/catalog/errors.rb +113 -0
  26. data/lib/droonga/catalog/schema.rb +186 -0
  27. data/lib/droonga/catalog/single_volume.rb +28 -0
  28. data/lib/droonga/catalog/slice.rb +41 -0
  29. data/lib/droonga/catalog/version1.rb +427 -0
  30. data/lib/droonga/catalog/version2.rb +96 -0
  31. data/lib/droonga/catalog/version2_validator.rb +63 -0
  32. data/lib/droonga/catalog/volume.rb +33 -0
  33. data/lib/droonga/catalog/volume_collection.rb +56 -0
  34. data/lib/droonga/catalog_generator.rb +156 -0
  35. data/lib/droonga/catalog_loader.rb +56 -0
  36. data/lib/droonga/catalog_observer.rb +83 -0
  37. data/lib/droonga/collector.rb +38 -0
  38. data/lib/droonga/collector_message.rb +71 -0
  39. data/lib/droonga/collector_runner.rb +64 -0
  40. data/lib/droonga/collectors/and.rb +26 -0
  41. data/lib/droonga/collectors/or.rb +26 -0
  42. data/lib/droonga/collectors/sum.rb +26 -0
  43. data/lib/droonga/collectors.rb +18 -0
  44. data/lib/droonga/dispatcher.rb +326 -0
  45. data/lib/droonga/distributed_command_planner.rb +179 -0
  46. data/lib/droonga/distributor.rb +87 -0
  47. data/lib/droonga/engine/command/droonga_engine.rb +441 -0
  48. data/lib/droonga/engine/version.rb +20 -0
  49. data/lib/droonga/engine.rb +80 -0
  50. data/lib/droonga/engine_state.rb +79 -0
  51. data/lib/droonga/error.rb +73 -0
  52. data/lib/droonga/error_messages.rb +33 -0
  53. data/lib/droonga/event_loop.rb +46 -0
  54. data/lib/droonga/farm.rb +58 -0
  55. data/lib/droonga/fluent_message_receiver.rb +191 -0
  56. data/lib/droonga/fluent_message_sender.rb +140 -0
  57. data/lib/droonga/forwarder.rb +119 -0
  58. data/lib/droonga/handler.rb +49 -0
  59. data/lib/droonga/handler_message.rb +61 -0
  60. data/lib/droonga/handler_messenger.rb +119 -0
  61. data/lib/droonga/handler_runner.rb +125 -0
  62. data/lib/droonga/input_message.rb +51 -0
  63. data/lib/droonga/job_protocol.rb +20 -0
  64. data/lib/droonga/job_pusher.rb +179 -0
  65. data/lib/droonga/job_receiver.rb +70 -0
  66. data/lib/droonga/loggable.rb +29 -0
  67. data/lib/droonga/logger.rb +142 -0
  68. data/lib/droonga/message_matcher.rb +109 -0
  69. data/lib/droonga/output_message.rb +55 -0
  70. data/lib/droonga/planner.rb +47 -0
  71. data/lib/droonga/pluggable.rb +31 -0
  72. data/lib/droonga/plugin/metadata/adapter_input_message.rb +39 -0
  73. data/lib/droonga/plugin/metadata/adapter_output_message.rb +39 -0
  74. data/lib/droonga/plugin/metadata/collector_message.rb +39 -0
  75. data/lib/droonga/plugin/metadata/handler_action.rb +39 -0
  76. data/lib/droonga/plugin/metadata/input_message.rb +54 -0
  77. data/lib/droonga/plugin.rb +43 -0
  78. data/lib/droonga/plugin_loader.rb +63 -0
  79. data/lib/droonga/plugin_registry.rb +66 -0
  80. data/lib/droonga/plugins/basic.rb +54 -0
  81. data/lib/droonga/plugins/crud.rb +145 -0
  82. data/lib/droonga/plugins/dump.rb +97 -0
  83. data/lib/droonga/plugins/error.rb +51 -0
  84. data/lib/droonga/plugins/groonga/column_create.rb +123 -0
  85. data/lib/droonga/plugins/groonga/column_list.rb +124 -0
  86. data/lib/droonga/plugins/groonga/column_remove.rb +65 -0
  87. data/lib/droonga/plugins/groonga/column_rename.rb +67 -0
  88. data/lib/droonga/plugins/groonga/delete.rb +117 -0
  89. data/lib/droonga/plugins/groonga/generic_command.rb +105 -0
  90. data/lib/droonga/plugins/groonga/generic_response.rb +43 -0
  91. data/lib/droonga/plugins/groonga/select.rb +236 -0
  92. data/lib/droonga/plugins/groonga/table_create.rb +111 -0
  93. data/lib/droonga/plugins/groonga/table_list.rb +120 -0
  94. data/lib/droonga/plugins/groonga/table_remove.rb +57 -0
  95. data/lib/droonga/plugins/groonga.rb +37 -0
  96. data/lib/droonga/plugins/search/distributed_search_planner.rb +407 -0
  97. data/lib/droonga/plugins/search.rb +146 -0
  98. data/lib/droonga/plugins/watch.rb +178 -0
  99. data/lib/droonga/processor.rb +63 -0
  100. data/lib/droonga/reducer.rb +169 -0
  101. data/lib/droonga/replier.rb +49 -0
  102. data/lib/droonga/schema_applier.rb +167 -0
  103. data/lib/droonga/searcher/mecab_filter.rb +67 -0
  104. data/lib/droonga/searcher.rb +733 -0
  105. data/lib/droonga/server.rb +45 -0
  106. data/lib/droonga/session.rb +99 -0
  107. data/lib/droonga/single_step.rb +68 -0
  108. data/lib/droonga/single_step_definition.rb +54 -0
  109. data/lib/droonga/slice.rb +122 -0
  110. data/lib/droonga/status_code.rb +25 -0
  111. data/lib/droonga/step_runner.rb +64 -0
  112. data/lib/droonga/sweeper.rb +42 -0
  113. data/lib/droonga/test/stub_handler.rb +37 -0
  114. data/lib/droonga/test/stub_handler_message.rb +35 -0
  115. data/lib/droonga/test/stub_handler_messenger.rb +34 -0
  116. data/lib/droonga/test/stub_planner.rb +31 -0
  117. data/lib/droonga/test.rb +21 -0
  118. data/lib/droonga/watch_schema.rb +92 -0
  119. data/lib/droonga/watcher.rb +257 -0
  120. data/lib/droonga/worker.rb +61 -0
  121. data/sample/cluster/catalog.json +42 -0
  122. data/sample/mecab_filter/data.grn +7 -0
  123. data/sample/mecab_filter/ddl.grn +7 -0
  124. data/sample/mecab_filter/search_with_mecab_filter.json +21 -0
  125. data/sample/mecab_filter/search_without_mecab_filter.json +21 -0
  126. data/test/command/config/default/catalog.json +85 -0
  127. data/test/command/config/default/fluentd.conf +11 -0
  128. data/test/command/config/version1/catalog.json +68 -0
  129. data/test/command/config/version1/fluentd.conf +11 -0
  130. data/test/command/fixture/documents.jsons +208 -0
  131. data/test/command/fixture/event.jsons +41 -0
  132. data/test/command/fixture/user-table-array.jsons +38 -0
  133. data/test/command/fixture/user-table.jsons +47 -0
  134. data/test/command/run-test.rb +34 -0
  135. data/test/command/suite/add/dimension/column.catalog.json +28 -0
  136. data/test/command/suite/add/dimension/column.expected +41 -0
  137. data/test/command/suite/add/dimension/column.test +51 -0
  138. data/test/command/suite/add/dimension/integer.catalog.json +19 -0
  139. data/test/command/suite/add/dimension/integer.expected +41 -0
  140. data/test/command/suite/add/dimension/integer.test +51 -0
  141. data/test/command/suite/add/error/invalid-integer.expected +46 -0
  142. data/test/command/suite/add/error/invalid-integer.test +12 -0
  143. data/test/command/suite/add/error/invalid-time.expected +46 -0
  144. data/test/command/suite/add/error/invalid-time.test +12 -0
  145. data/test/command/suite/add/error/missing-key.expected +25 -0
  146. data/test/command/suite/add/error/missing-key.test +16 -0
  147. data/test/command/suite/add/error/missing-table.expected +25 -0
  148. data/test/command/suite/add/error/missing-table.test +16 -0
  149. data/test/command/suite/add/error/unknown-column.expected +46 -0
  150. data/test/command/suite/add/error/unknown-column.test +12 -0
  151. data/test/command/suite/add/error/unknown-table.expected +25 -0
  152. data/test/command/suite/add/error/unknown-table.test +17 -0
  153. data/test/command/suite/add/minimum.expected +6 -0
  154. data/test/command/suite/add/minimum.test +11 -0
  155. data/test/command/suite/add/with-values.expected +6 -0
  156. data/test/command/suite/add/with-values.test +17 -0
  157. data/test/command/suite/add/without-key.expected +6 -0
  158. data/test/command/suite/add/without-key.test +16 -0
  159. data/test/command/suite/groonga/column_create/scalar.expected +26 -0
  160. data/test/command/suite/groonga/column_create/scalar.test +17 -0
  161. data/test/command/suite/groonga/column_create/unknown-table.expected +14 -0
  162. data/test/command/suite/groonga/column_create/unknown-table.test +7 -0
  163. data/test/command/suite/groonga/column_create/vector.expected +26 -0
  164. data/test/command/suite/groonga/column_create/vector.test +18 -0
  165. data/test/command/suite/groonga/column_list/success.expected +86 -0
  166. data/test/command/suite/groonga/column_list/success.test +24 -0
  167. data/test/command/suite/groonga/column_list/unknown-table.expected +13 -0
  168. data/test/command/suite/groonga/column_list/unknown-table.test +7 -0
  169. data/test/command/suite/groonga/column_remove/success.expected +39 -0
  170. data/test/command/suite/groonga/column_remove/success.test +25 -0
  171. data/test/command/suite/groonga/column_remove/unknown-column.expected +27 -0
  172. data/test/command/suite/groonga/column_remove/unknown-column.test +16 -0
  173. data/test/command/suite/groonga/column_remove/unknown-table.expected +14 -0
  174. data/test/command/suite/groonga/column_remove/unknown-table.test +7 -0
  175. data/test/command/suite/groonga/column_rename/success.expected +39 -0
  176. data/test/command/suite/groonga/column_rename/success.test +26 -0
  177. data/test/command/suite/groonga/column_rename/unknown-column.expected +27 -0
  178. data/test/command/suite/groonga/column_rename/unknown-column.test +16 -0
  179. data/test/command/suite/groonga/column_rename/unknown-table.expected +14 -0
  180. data/test/command/suite/groonga/column_rename/unknown-table.test +7 -0
  181. data/test/command/suite/groonga/delete/duplicated-identifiers.expected +27 -0
  182. data/test/command/suite/groonga/delete/duplicated-identifiers.test +17 -0
  183. data/test/command/suite/groonga/delete/filter.expected +19 -0
  184. data/test/command/suite/groonga/delete/filter.test +19 -0
  185. data/test/command/suite/groonga/delete/invalid-filter.expected +14 -0
  186. data/test/command/suite/groonga/delete/invalid-filter.test +9 -0
  187. data/test/command/suite/groonga/delete/no-identifier.expected +27 -0
  188. data/test/command/suite/groonga/delete/no-identifier.test +15 -0
  189. data/test/command/suite/groonga/delete/success.expected +19 -0
  190. data/test/command/suite/groonga/delete/success.test +19 -0
  191. data/test/command/suite/groonga/delete/unknown-table.expected +14 -0
  192. data/test/command/suite/groonga/delete/unknown-table.test +7 -0
  193. data/test/command/suite/groonga/select/minimum.expected +22 -0
  194. data/test/command/suite/groonga/select/minimum.test +8 -0
  195. data/test/command/suite/groonga/table_create/array.expected +14 -0
  196. data/test/command/suite/groonga/table_create/array.test +8 -0
  197. data/test/command/suite/groonga/table_create/hash.expected +13 -0
  198. data/test/command/suite/groonga/table_create/hash.test +8 -0
  199. data/test/command/suite/groonga/table_list/success.expected +71 -0
  200. data/test/command/suite/groonga/table_list/success.test +15 -0
  201. data/test/command/suite/groonga/table_remove/success.expected +13 -0
  202. data/test/command/suite/groonga/table_remove/success.test +8 -0
  203. data/test/command/suite/groonga/table_remove/unknown-table.expected +14 -0
  204. data/test/command/suite/groonga/table_remove/unknown-table.test +7 -0
  205. data/test/command/suite/message/error/missing-dataset.expected +9 -0
  206. data/test/command/suite/message/error/missing-dataset.test +5 -0
  207. data/test/command/suite/message/error/unknown-dataset.expected +9 -0
  208. data/test/command/suite/message/error/unknown-dataset.test +6 -0
  209. data/test/command/suite/message/error/unknown-type.expected +9 -0
  210. data/test/command/suite/message/error/unknown-type.test +6 -0
  211. data/test/command/suite/search/adjusters/multiple.catalog.json +38 -0
  212. data/test/command/suite/search/adjusters/multiple.expected +19 -0
  213. data/test/command/suite/search/adjusters/multiple.test +75 -0
  214. data/test/command/suite/search/adjusters/one.catalog.json +38 -0
  215. data/test/command/suite/search/adjusters/one.expected +19 -0
  216. data/test/command/suite/search/adjusters/one.test +66 -0
  217. data/test/command/suite/search/attributes/array.expected +21 -0
  218. data/test/command/suite/search/attributes/array.test +28 -0
  219. data/test/command/suite/search/attributes/hash.expected +30 -0
  220. data/test/command/suite/search/attributes/hash.test +36 -0
  221. data/test/command/suite/search/complex.expected +48 -0
  222. data/test/command/suite/search/complex.test +23 -0
  223. data/test/command/suite/search/condition/nested.expected +15 -0
  224. data/test/command/suite/search/condition/nested.test +27 -0
  225. data/test/command/suite/search/condition/query/nonexistent_column.catalog.json +37 -0
  226. data/test/command/suite/search/condition/query/nonexistent_column.expected +48 -0
  227. data/test/command/suite/search/condition/query/nonexistent_column.test +33 -0
  228. data/test/command/suite/search/condition/query/syntax_error.catalog.json +36 -0
  229. data/test/command/suite/search/condition/query/syntax_error.expected +48 -0
  230. data/test/command/suite/search/condition/query/syntax_error.test +33 -0
  231. data/test/command/suite/search/condition/query.expected +24 -0
  232. data/test/command/suite/search/condition/query.test +23 -0
  233. data/test/command/suite/search/condition/script.expected +24 -0
  234. data/test/command/suite/search/condition/script.test +26 -0
  235. data/test/command/suite/search/error/cyclic-source.expected +14 -0
  236. data/test/command/suite/search/error/cyclic-source.test +12 -0
  237. data/test/command/suite/search/error/deeply-cyclic-source.expected +17 -0
  238. data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
  239. data/test/command/suite/search/error/missing-source-parameter.expected +13 -0
  240. data/test/command/suite/search/error/missing-source-parameter.test +11 -0
  241. data/test/command/suite/search/error/no-query.expected +9 -0
  242. data/test/command/suite/search/error/no-query.test +7 -0
  243. data/test/command/suite/search/error/unknown-source.expected +52 -0
  244. data/test/command/suite/search/error/unknown-source.test +12 -0
  245. data/test/command/suite/search/group/count.expected +10 -0
  246. data/test/command/suite/search/group/count.test +18 -0
  247. data/test/command/suite/search/group/limit.expected +15 -0
  248. data/test/command/suite/search/group/limit.test +20 -0
  249. data/test/command/suite/search/group/string.expected +32 -0
  250. data/test/command/suite/search/group/string.test +40 -0
  251. data/test/command/suite/search/group/subrecord/with-sort.catalog.json +33 -0
  252. data/test/command/suite/search/group/subrecord/with-sort.expected +30 -0
  253. data/test/command/suite/search/group/subrecord/with-sort.test +81 -0
  254. data/test/command/suite/search/multiple/chained.expected +41 -0
  255. data/test/command/suite/search/multiple/chained.test +39 -0
  256. data/test/command/suite/search/multiple/parallel.expected +35 -0
  257. data/test/command/suite/search/multiple/parallel.test +35 -0
  258. data/test/command/suite/search/output/attributes/invalid.catalog.json +13 -0
  259. data/test/command/suite/search/output/attributes/invalid.expected +44 -0
  260. data/test/command/suite/search/output/attributes/invalid.test +28 -0
  261. data/test/command/suite/search/range/only-output.expected +24 -0
  262. data/test/command/suite/search/range/only-output.test +23 -0
  263. data/test/command/suite/search/range/only-sort.expected +24 -0
  264. data/test/command/suite/search/range/only-sort.test +26 -0
  265. data/test/command/suite/search/range/sort-and-output.expected +21 -0
  266. data/test/command/suite/search/range/sort-and-output.test +27 -0
  267. data/test/command/suite/search/range/too-large-output-offset.expected +12 -0
  268. data/test/command/suite/search/range/too-large-output-offset.test +23 -0
  269. data/test/command/suite/search/range/too-large-sort-offset.expected +12 -0
  270. data/test/command/suite/search/range/too-large-sort-offset.test +26 -0
  271. data/test/command/suite/search/response/elapsed_time.catalog.json +13 -0
  272. data/test/command/suite/search/response/elapsed_time.expected +11 -0
  273. data/test/command/suite/search/response/elapsed_time.test +26 -0
  274. data/test/command/suite/search/response/records/value/time.expected +20 -0
  275. data/test/command/suite/search/response/records/value/time.test +22 -0
  276. data/test/command/suite/search/simple.expected +48 -0
  277. data/test/command/suite/search/simple.test +22 -0
  278. data/test/command/suite/search/sort/default-offset-limit.expected +39 -0
  279. data/test/command/suite/search/sort/default-offset-limit.test +24 -0
  280. data/test/command/suite/search/sort/invisible-column.expected +24 -0
  281. data/test/command/suite/search/sort/invisible-column.test +26 -0
  282. data/test/command/suite/watch/subscribe.expected +6 -0
  283. data/test/command/suite/watch/subscribe.test +9 -0
  284. data/test/command/suite/watch/unsubscribe.expected +6 -0
  285. data/test/command/suite/watch/unsubscribe.test +9 -0
  286. data/test/performance/run-test.rb +56 -0
  287. data/test/performance/watch/catalog.json +33 -0
  288. data/test/performance/watch/feed.json +9 -0
  289. data/test/performance/watch/fluentd.conf +11 -0
  290. data/test/performance/watch/subscribe.json +3 -0
  291. data/test/unit/catalog/test_collection_volume.rb +103 -0
  292. data/test/unit/catalog/test_dataset.rb +104 -0
  293. data/test/unit/catalog/test_schema.rb +226 -0
  294. data/test/unit/catalog/test_single_volume.rb +31 -0
  295. data/test/unit/catalog/test_slice.rb +92 -0
  296. data/test/unit/catalog/test_version1.rb +361 -0
  297. data/test/unit/catalog/test_version2.rb +124 -0
  298. data/test/unit/catalog/test_version2_validator.rb +66 -0
  299. data/test/unit/catalog/test_volume_collection.rb +50 -0
  300. data/test/unit/fixtures/array.grn +18 -0
  301. data/test/unit/fixtures/catalog/version1.json +40 -0
  302. data/test/unit/fixtures/catalog/version2.json +62 -0
  303. data/test/unit/fixtures/document.grn +34 -0
  304. data/test/unit/fixtures/reference/array.grn +11 -0
  305. data/test/unit/fixtures/reference/hash.grn +7 -0
  306. data/test/unit/helper/distributed_search_planner_helper.rb +83 -0
  307. data/test/unit/helper/fixture.rb +28 -0
  308. data/test/unit/helper/plugin_helper.rb +38 -0
  309. data/test/unit/helper/sandbox.rb +86 -0
  310. data/test/unit/helper/stub_worker.rb +27 -0
  311. data/test/unit/helper/watch_helper.rb +23 -0
  312. data/test/unit/helper.rb +28 -0
  313. data/test/unit/plugins/crud/test_add.rb +190 -0
  314. data/test/unit/plugins/groonga/select/test_adapter_input.rb +510 -0
  315. data/test/unit/plugins/groonga/select/test_adapter_output.rb +201 -0
  316. data/test/unit/plugins/groonga/test_column_create.rb +171 -0
  317. data/test/unit/plugins/groonga/test_column_list.rb +170 -0
  318. data/test/unit/plugins/groonga/test_column_remove.rb +98 -0
  319. data/test/unit/plugins/groonga/test_column_rename.rb +105 -0
  320. data/test/unit/plugins/groonga/test_delete.rb +127 -0
  321. data/test/unit/plugins/groonga/test_table_create.rb +147 -0
  322. data/test/unit/plugins/groonga/test_table_list.rb +184 -0
  323. data/test/unit/plugins/groonga/test_table_remove.rb +61 -0
  324. data/test/unit/plugins/search/planner/test_basic.rb +120 -0
  325. data/test/unit/plugins/search/planner/test_group_by.rb +573 -0
  326. data/test/unit/plugins/search/planner/test_output.rb +388 -0
  327. data/test/unit/plugins/search/planner/test_sort_by.rb +938 -0
  328. data/test/unit/plugins/search/test_collector.rb +806 -0
  329. data/test/unit/plugins/search/test_handler.rb +930 -0
  330. data/test/unit/plugins/search/test_planner.rb +174 -0
  331. data/test/unit/plugins/test_basic.rb +510 -0
  332. data/test/unit/plugins/test_groonga.rb +70 -0
  333. data/test/unit/plugins/test_watch.rb +211 -0
  334. data/test/unit/run-test.rb +56 -0
  335. data/test/unit/test_catalog_generator.rb +93 -0
  336. data/test/unit/test_message_matcher.rb +160 -0
  337. data/test/unit/test_schema_applier.rb +59 -0
  338. data/test/unit/test_sweeper.rb +95 -0
  339. data/test/unit/test_watch_schema.rb +57 -0
  340. data/test/unit/test_watcher.rb +336 -0
  341. metadata +759 -0
@@ -0,0 +1,190 @@
1
+ # Copyright (C) 2013-2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/plugins/crud"
17
+
18
+ class CRUDAddHandlerTest < Test::Unit::TestCase
19
+ SUCCESS_RESPONSE_BODY = true
20
+
21
+ def setup
22
+ setup_database
23
+ setup_schema
24
+ setup_handler
25
+ end
26
+
27
+ def teardown
28
+ teardown_handler
29
+ teardown_database
30
+ end
31
+
32
+ private
33
+ def setup_schema
34
+ end
35
+
36
+ def setup_handler
37
+ @worker = StubWorker.new
38
+ @messenger = Droonga::Test::StubHandlerMessenger.new
39
+ @loop = nil
40
+ @handler = Droonga::Plugins::CRUD::Handler.new("name",
41
+ @worker.context,
42
+ @messenger,
43
+ @loop)
44
+ end
45
+
46
+ def teardown_handler
47
+ @handler = nil
48
+ end
49
+
50
+ def process(request)
51
+ message = Droonga::Test::StubHandlerMessage.new(request)
52
+ @handler.handle(message)
53
+ end
54
+
55
+ public
56
+ class HasKeyTest < self
57
+ def setup_schema
58
+ Groonga::Schema.define do |schema|
59
+ schema.create_table("Users",
60
+ :type => :hash,
61
+ :key_type => :short_text) do |table|
62
+ table.short_text("country")
63
+ table.int32("age")
64
+ table.time("birthday")
65
+ end
66
+ end
67
+ end
68
+
69
+ def test_empty_values
70
+ request = {
71
+ "table" => "Users",
72
+ "key" => "mori",
73
+ "values" => {},
74
+ }
75
+ response = process(request)
76
+ assert_equal(SUCCESS_RESPONSE_BODY, response)
77
+ table = @worker.context["Users"]
78
+ assert_equal(["mori"], table.collect(&:key))
79
+ end
80
+
81
+ def test_values
82
+ request = {
83
+ "table" => "Users",
84
+ "key" => "mori",
85
+ "values" => {"country" => "japan"},
86
+ }
87
+ response = process(request)
88
+ assert_equal(SUCCESS_RESPONSE_BODY, response)
89
+ table = @worker.context["Users"]
90
+ assert_equal(["japan"], table.collect(&:country))
91
+ end
92
+
93
+ def test_missing_key_parameter
94
+ request = {
95
+ "table" => "Users",
96
+ "values" => {"country" => "japan"},
97
+ }
98
+ assert_raise(Droonga::Plugins::CRUD::Handler::MissingPrimaryKeyParameter) do
99
+ process(request)
100
+ end
101
+ end
102
+
103
+ def test_invalid_integer_value
104
+ request = {
105
+ "table" => "Users",
106
+ "key" => "mori",
107
+ "values" => {"age" => "secret"},
108
+ }
109
+ assert_raise(Droonga::Plugins::CRUD::Handler::InvalidValue) do
110
+ process(request)
111
+ end
112
+ end
113
+
114
+ def test_invalid_time_value
115
+ request = {
116
+ "table" => "Users",
117
+ "key" => "mori",
118
+ "values" => {"birthday" => "today"},
119
+ }
120
+ assert_raise(Droonga::Plugins::CRUD::Handler::InvalidValue) do
121
+ process(request)
122
+ end
123
+ end
124
+
125
+ def test_unknown_column
126
+ request = {
127
+ "table" => "Users",
128
+ "key" => "mori",
129
+ "values" => {"unknown" => "unknown"},
130
+ }
131
+ assert_raise(Droonga::Plugins::CRUD::Handler::UnknownColumn) do
132
+ process(request)
133
+ end
134
+ end
135
+ end
136
+
137
+ class NoKeyTest < self
138
+ def setup_schema
139
+ Groonga::Schema.define do |schema|
140
+ schema.create_table("Books",
141
+ :type => :array) do |table|
142
+ table.short_text("title")
143
+ end
144
+ end
145
+ end
146
+
147
+ def test_empty_values
148
+ request = {
149
+ "table" => "Books",
150
+ "values" => {},
151
+ }
152
+ response = process(request)
153
+ assert_equal(SUCCESS_RESPONSE_BODY, response)
154
+ table = @worker.context["Books"]
155
+ assert_equal([nil], table.collect(&:title))
156
+ end
157
+
158
+ def test_with_values
159
+ request = {
160
+ "table" => "Books",
161
+ "values" => {"title" => "CSS"},
162
+ }
163
+ response = process(request)
164
+ assert_equal(SUCCESS_RESPONSE_BODY, response)
165
+ table = @worker.context["Books"]
166
+ assert_equal(["CSS"], table.collect(&:title))
167
+ end
168
+ end
169
+
170
+ class FailureTest < self
171
+ def test_missing_table_parameter
172
+ request = {
173
+ "values" => {},
174
+ }
175
+ assert_raise(Droonga::Plugins::CRUD::Handler::MissingTableParameter) do
176
+ process(request)
177
+ end
178
+ end
179
+
180
+ def test_nonexistent_table
181
+ request = {
182
+ "table" => "Nonexistent",
183
+ "values" => {},
184
+ }
185
+ assert_raise(Droonga::Plugins::CRUD::Handler::UnknownTable) do
186
+ process(request)
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,510 @@
1
+ # Copyright (C) 2013-2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/plugins/groonga/select"
17
+
18
+ class GroongaSelectAdapterInputTest < Test::Unit::TestCase
19
+ private
20
+ def convert(select_request)
21
+ converter = Droonga::Plugins::Groonga::Select::RequestConverter.new
22
+ converter.convert(select_request)
23
+ end
24
+
25
+ class OutputColumnsTest < self
26
+ def assert_attributes(expected_attributes, output_columns)
27
+ select_request = {
28
+ "table" => "EmptyTable",
29
+ "output_columns" => output_columns,
30
+ }
31
+
32
+ expected_search_request = {
33
+ "queries" => {
34
+ "EmptyTable_result" => {
35
+ "source" => "EmptyTable",
36
+ "output" => {
37
+ "elements" => [
38
+ "startTime",
39
+ "elapsedTime",
40
+ "count",
41
+ "attributes",
42
+ "records",
43
+ ],
44
+ "attributes" => expected_attributes,
45
+ "offset" => 0,
46
+ "limit" => 10,
47
+ },
48
+ },
49
+ },
50
+ }
51
+ assert_equal(expected_search_request, convert(select_request))
52
+ end
53
+
54
+ def test_multiple_columns
55
+ assert_attributes(["_id", "_key"], "_id,_key")
56
+ end
57
+
58
+ class FunctionTest < self
59
+ def test_single_argument
60
+ assert_attributes(["snippet_html(content)"], "snippet_html(content)")
61
+ end
62
+
63
+ def test_with_columns
64
+ assert_attributes(["_id","_key","snippet_html(content)"], "_id,_key,snippet_html(content)")
65
+ end
66
+ end
67
+ end
68
+
69
+ class MatchColumnsTest < self
70
+ def assert_matchTo(expected_matchTo, match_columns)
71
+ select_request = {
72
+ "table" => "EmptyTable",
73
+ "match_columns" => match_columns,
74
+ "query" => "QueryTest",
75
+ "output_columns" => "_id",
76
+ }
77
+
78
+ expected_search_request = {
79
+ "queries" => {
80
+ "EmptyTable_result" => {
81
+ "source" => "EmptyTable",
82
+ "condition"=> {
83
+ "query" => "QueryTest",
84
+ "matchTo"=> expected_matchTo,
85
+ "defaultOperator"=> "&&",
86
+ "allowPragma"=> false,
87
+ "allowColumn"=> true,
88
+ },
89
+ "output" => {
90
+ "elements" => [
91
+ "startTime",
92
+ "elapsedTime",
93
+ "count",
94
+ "attributes",
95
+ "records",
96
+ ],
97
+ "attributes" => ["_id"],
98
+ "offset" => 0,
99
+ "limit" => 10,
100
+ },
101
+ },
102
+ },
103
+ }
104
+ assert_equal(expected_search_request, convert(select_request))
105
+ end
106
+
107
+ def test_single_column
108
+ assert_matchTo(["_key"], "_key")
109
+ end
110
+
111
+ def test_multiple_columns
112
+ assert_matchTo(["_key", "content"], "_key || content")
113
+ end
114
+ end
115
+
116
+ class FilterTest < self
117
+ def test_filter
118
+ select_request = {
119
+ "table" => "EmptyTable",
120
+ "filter" => "title@'FilterTest'",
121
+ "output_columns" => "_id",
122
+ }
123
+
124
+ expected_search_request = {
125
+ "queries" => {
126
+ "EmptyTable_result" => {
127
+ "source" => "EmptyTable",
128
+ "condition"=> "title@'FilterTest'",
129
+ "output" => {
130
+ "elements" => [
131
+ "startTime",
132
+ "elapsedTime",
133
+ "count",
134
+ "attributes",
135
+ "records",
136
+ ],
137
+ "attributes" => ["_id"],
138
+ "offset" => 0,
139
+ "limit" => 10,
140
+ },
141
+ },
142
+ },
143
+ }
144
+ assert_equal(expected_search_request, convert(select_request))
145
+ end
146
+ end
147
+
148
+ class CombinedConditionsTest < self
149
+ def test_conditions
150
+ select_request = {
151
+ "table" => "EmptyTable",
152
+ "match_columns" => "_key",
153
+ "query" => "QueryTest",
154
+ "filter" => "title@'FilterTest'",
155
+ "output_columns" => "_id",
156
+ }
157
+
158
+ expected_search_request = {
159
+ "queries" => {
160
+ "EmptyTable_result" => {
161
+ "source" => "EmptyTable",
162
+ "condition"=> [
163
+ "&&",
164
+ {
165
+ "query" => "QueryTest",
166
+ "matchTo"=> ["_key"],
167
+ "defaultOperator"=> "&&",
168
+ "allowPragma"=> false,
169
+ "allowColumn"=> true,
170
+ },
171
+ "title@'FilterTest'",
172
+ ],
173
+ "output" => {
174
+ "elements" => [
175
+ "startTime",
176
+ "elapsedTime",
177
+ "count",
178
+ "attributes",
179
+ "records",
180
+ ],
181
+ "attributes" => ["_id"],
182
+ "offset" => 0,
183
+ "limit" => 10,
184
+ },
185
+ },
186
+ },
187
+ }
188
+ assert_equal(expected_search_request, convert(select_request))
189
+ end
190
+ end
191
+
192
+ class OffsetTest < self
193
+ def assert_offset(expected_offset, offset)
194
+ select_request = {
195
+ "table" => "EmptyTable",
196
+ "output_columns" => "_id",
197
+ }
198
+ select_request["offset"] = offset unless offset.nil?
199
+
200
+ expected_search_request = {
201
+ "queries" => {
202
+ "EmptyTable_result" => {
203
+ "source" => "EmptyTable",
204
+ "output" => {
205
+ "elements" => [
206
+ "startTime",
207
+ "elapsedTime",
208
+ "count",
209
+ "attributes",
210
+ "records",
211
+ ],
212
+ "attributes" => ["_id"],
213
+ "offset" => expected_offset,
214
+ "limit" => 10,
215
+ },
216
+ },
217
+ },
218
+ }
219
+ assert_equal(expected_search_request, convert(select_request))
220
+ end
221
+
222
+ def test_zero
223
+ assert_offset(0, "0")
224
+ end
225
+
226
+ def test_large
227
+ assert_offset(100, "100")
228
+ end
229
+
230
+ def test_integer
231
+ assert_offset(100, 100)
232
+ end
233
+
234
+ def test_default
235
+ assert_offset(0, nil)
236
+ end
237
+ end
238
+
239
+ class LimitTest < self
240
+ def assert_limit(expected_limit, limit)
241
+ select_request = {
242
+ "table" => "EmptyTable",
243
+ "output_columns" => "_id",
244
+ }
245
+ select_request["limit"] = limit unless limit.nil?
246
+
247
+ expected_search_request = {
248
+ "queries" => {
249
+ "EmptyTable_result" => {
250
+ "source" => "EmptyTable",
251
+ "output" => {
252
+ "elements" => [
253
+ "startTime",
254
+ "elapsedTime",
255
+ "count",
256
+ "attributes",
257
+ "records",
258
+ ],
259
+ "attributes" => ["_id"],
260
+ "offset" => 0,
261
+ "limit" => expected_limit,
262
+ },
263
+ },
264
+ },
265
+ }
266
+ assert_equal(expected_search_request, convert(select_request))
267
+ end
268
+
269
+ def test_zero
270
+ assert_limit(0, "0")
271
+ end
272
+
273
+ def test_large
274
+ assert_limit(100, "100")
275
+ end
276
+
277
+ def test_negative
278
+ assert_limit(-1, "-1")
279
+ end
280
+
281
+ def test_integer
282
+ assert_limit(100, 100)
283
+ end
284
+
285
+ def test_default
286
+ assert_limit(10, nil)
287
+ end
288
+ end
289
+
290
+ class SortTest < self
291
+ data(
292
+ :only_keys => {
293
+ :input => {
294
+ :keys => "-_id",
295
+ },
296
+ :expected => {
297
+ :keys => ["-_id"],
298
+ :offset => 0,
299
+ :limit => 10,
300
+ },
301
+ },
302
+ :offset => {
303
+ :input => {
304
+ :keys => "-_id",
305
+ :offset => 5,
306
+ },
307
+ :expected => {
308
+ :keys => ["-_id"],
309
+ :offset => 5,
310
+ :limit => 10,
311
+ },
312
+ },
313
+ :limit => {
314
+ :input => {
315
+ :keys => "-_id",
316
+ :limit => 5,
317
+ },
318
+ :expected => {
319
+ :keys => ["-_id"],
320
+ :offset => 0,
321
+ :limit => 5,
322
+ },
323
+ },
324
+ )
325
+ def test_sort(data)
326
+ expected = data[:expected]
327
+ input = data[:input]
328
+ select_request = {
329
+ "table" => "EmptyTable",
330
+ "output_columns" => "_id",
331
+ }
332
+ select_request["sortby"] = input[:keys] unless input[:keys].nil?
333
+ select_request["offset"] = input[:offset] unless input[:offset].nil?
334
+ select_request["limit"] = input[:limit] unless input[:limit].nil?
335
+
336
+ expected_search_request = {
337
+ "queries" => {
338
+ "EmptyTable_result" => {
339
+ "source" => "EmptyTable",
340
+ "sortBy" => {
341
+ "keys" => expected[:keys],
342
+ "offset" => expected[:offset],
343
+ "limit" => expected[:limit],
344
+ },
345
+ "output" => {
346
+ "elements" => [
347
+ "startTime",
348
+ "elapsedTime",
349
+ "count",
350
+ "attributes",
351
+ "records",
352
+ ],
353
+ "attributes" => ["_id"],
354
+ "offset" => 0,
355
+ "limit" => expected[:limit],
356
+ },
357
+ },
358
+ },
359
+ }
360
+ assert_equal(expected_search_request, convert(select_request))
361
+ end
362
+ end
363
+
364
+ class DrilldownTest < self
365
+ def base_request
366
+ {
367
+ "table" => "EmptyTable",
368
+ "output_columns" => "_id",
369
+ "limit" => 1,
370
+ }
371
+ end
372
+
373
+ def base_queries
374
+ {
375
+ "EmptyTable_result" => {
376
+ "source" => "EmptyTable",
377
+ "output" => {
378
+ "elements" => [
379
+ "startTime",
380
+ "elapsedTime",
381
+ "count",
382
+ "attributes",
383
+ "records",
384
+ ],
385
+ "attributes" => ["_id"],
386
+ "offset" => 0,
387
+ "limit" => 1,
388
+ },
389
+ },
390
+ }
391
+ end
392
+
393
+ def test_simple
394
+ select_request = base_request.merge({
395
+ "drilldown" => "a,b",
396
+ "drilldown_output_columns" => "_key,_nsubrecs",
397
+ })
398
+
399
+ expected_output = {
400
+ "elements" => [
401
+ "count",
402
+ "attributes",
403
+ "records",
404
+ ],
405
+ "attributes" => ["_key", "_nsubrecs"],
406
+ "offset" => 0,
407
+ "limit" => 10,
408
+ }
409
+ expected_search_request = {
410
+ "queries" => base_queries.merge({
411
+ "drilldown_result_a" => {
412
+ "source" => "EmptyTable_result",
413
+ "groupBy" => "a",
414
+ "output" => expected_output,
415
+ },
416
+ "drilldown_result_b" => {
417
+ "source" => "EmptyTable_result",
418
+ "groupBy" => "b",
419
+ "output" => expected_output,
420
+ },
421
+ }),
422
+ }
423
+ assert_equal(expected_search_request, convert(select_request))
424
+ end
425
+
426
+ def test_sorted
427
+ select_request = base_request.merge({
428
+ "drilldown" => "a,b",
429
+ "drilldown_output_columns" => "_key,_nsubrecs",
430
+ "drilldown_sortby" => "-_nsubrecs",
431
+ "drilldown_offset" => "1",
432
+ "drilldown_limit" => "2",
433
+ })
434
+
435
+ expected_sort_by = {
436
+ "keys" => ["-_nsubrecs"],
437
+ "offset" => 1,
438
+ "limit" => 2,
439
+ }
440
+ expected_output = {
441
+ "elements" => [
442
+ "count",
443
+ "attributes",
444
+ "records",
445
+ ],
446
+ "attributes" => ["_key", "_nsubrecs"],
447
+ "limit" => 2,
448
+ }
449
+ expected_search_request = {
450
+ "queries" => base_queries.merge({
451
+ "drilldown_result_a" => {
452
+ "source" => "EmptyTable_result",
453
+ "groupBy" => "a",
454
+ "sortBy" => expected_sort_by,
455
+ "output" => expected_output,
456
+ },
457
+ "drilldown_result_b" => {
458
+ "source" => "EmptyTable_result",
459
+ "groupBy" => "b",
460
+ "sortBy" => expected_sort_by,
461
+ "output" => expected_output,
462
+ },
463
+ }),
464
+ }
465
+ assert_equal(expected_search_request, convert(select_request))
466
+ end
467
+
468
+ def test_only_pagination
469
+ select_request = base_request.merge({
470
+ "drilldown" => "a,b",
471
+ "drilldown_output_columns" => "_key,_nsubrecs",
472
+ "drilldown_sortby" => "-_nsubrecs",
473
+ "drilldown_offset" => "1",
474
+ "drilldown_limit" => "2",
475
+ })
476
+
477
+ expected_sort_by = {
478
+ "keys" => ["-_nsubrecs"],
479
+ "offset" => 1,
480
+ "limit" => 2,
481
+ }
482
+ expected_output = {
483
+ "elements" => [
484
+ "count",
485
+ "attributes",
486
+ "records",
487
+ ],
488
+ "attributes" => ["_key", "_nsubrecs"],
489
+ "limit" => 2,
490
+ }
491
+ expected_search_request = {
492
+ "queries" => base_queries.merge({
493
+ "drilldown_result_a" => {
494
+ "source" => "EmptyTable_result",
495
+ "groupBy" => "a",
496
+ "sortBy" => expected_sort_by,
497
+ "output" => expected_output,
498
+ },
499
+ "drilldown_result_b" => {
500
+ "source" => "EmptyTable_result",
501
+ "groupBy" => "b",
502
+ "sortBy" => expected_sort_by,
503
+ "output" => expected_output,
504
+ },
505
+ }),
506
+ }
507
+ assert_equal(expected_search_request, convert(select_request))
508
+ end
509
+ end
510
+ end