Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
test-dat-pat.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
2 /*
3  Copyright (C) 2011-2012 Brazil
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License version 2.1 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <dat.h>
20 #include <pat.h>
21 
22 #include <gcutter.h>
23 #include <glib/gstdio.h>
24 #include <cppcutter.h>
25 
26 #include <grn-assertions.h>
27 
28 #include <algorithm>
29 #include <cstdio>
30 #include <cstdlib>
31 #include <ctime>
32 #include <set>
33 #include <string>
34 #include <vector>
35 
36 namespace
37 {
38  void create_key(std::string *key, std::size_t min_length,
39  std::size_t max_length)
40  {
41  key->resize(min_length + (std::rand() % (max_length - min_length + 1)));
42  for (std::size_t i = 0; i < key->size(); ++i) {
43  (*key)[i] = '0' + (std::rand() % 10);
44  }
45  }
46 
47  void create_keys(std::vector<std::string> *keys, std::size_t num_keys,
48  std::size_t min_length, std::size_t max_length)
49  {
50  std::string key;
51  std::set<std::string> keyset;
52  while (keyset.size() < num_keys) {
53  create_key(&key, min_length, max_length);
54  keyset.insert(key);
55  }
56  std::vector<std::string>(keyset.begin(), keyset.end()).swap(*keys);
57  std::random_shuffle(keys->begin(), keys->end());
58  }
59 }
60 
61 namespace test_dat_pat
62 {
63  const gchar *base_dir = NULL;
65 
66  void cut_setup(void)
67  {
68  std::srand(static_cast<unsigned int>(std::time(NULL)));
69 
70  base_dir = grn_test_get_tmp_dir();
71  cut_remove_path(base_dir, NULL);
72  g_mkdir_with_parents(base_dir, 0755);
73 
74  grn_ctx_init(&ctx, 0);
75  }
76 
77  void cut_teardown(void)
78  {
79  grn_ctx_fin(&ctx);
80 
81  if (base_dir) {
82  cut_remove_path(base_dir, NULL);
83  }
84  }
85 
86  void generate_pat_path(const char *filename, char *path)
87  {
88  std::sprintf(path, "%s/%s.pat", base_dir, filename);
89  }
90 
91  void generate_dat_path(const char *filename, char *path)
92  {
93  std::sprintf(path, "%s/%s.dat", base_dir, filename);
94  }
95 
96  grn_pat *create_pat(const char *filename,
97  const std::vector<std::string> &keys)
98  {
99  char pat_path[PATH_MAX];
100  generate_pat_path(filename, pat_path);
101  grn_pat * const pat =
102  grn_pat_create(&ctx, pat_path, 1024, 0, GRN_OBJ_KEY_VAR_SIZE);
103  cppcut_assert_not_null(pat);
104 
105  for (std::size_t i = 0; i < keys.size(); ++i) {
106  grn_pat_add(&ctx, pat, keys[i].c_str(), keys[i].length(), NULL, NULL);
107  }
108  return pat;
109  }
110 
111  grn_dat *create_dat(const char *filename,
112  const std::vector<std::string> &keys)
113  {
114  char dat_path[PATH_MAX];
115  generate_dat_path(filename, dat_path);
116  grn_dat * const dat =
117  grn_dat_create(&ctx, dat_path, 1024, 0, GRN_OBJ_KEY_VAR_SIZE);
118  cppcut_assert_not_null(dat);
119 
120  for (std::size_t i = 0; i < keys.size(); ++i) {
121  grn_dat_add(&ctx, dat, keys[i].c_str(), keys[i].length(), NULL, NULL);
122  }
123  return dat;
124  }
125 
126  void test_open(void)
127  {
128  const char * const filename = "test_open";
129 
130  char pat_path[PATH_MAX];
131  char dat_path[PATH_MAX];
132 
133  generate_pat_path(filename, pat_path);
134  generate_dat_path(filename, dat_path);
135 
136  cut_assert_not_exist_path(pat_path);
137  cut_assert_not_exist_path(dat_path);
138 
139  grn_pat *pat = grn_pat_open(&ctx, pat_path);
140  grn_dat *dat = grn_dat_open(&ctx, dat_path);
141 
142  cppcut_assert_null(pat);
143  cppcut_assert_null(dat);
144 
145  std::vector<std::string> keys;
146  create_keys(&keys, 1000, 3, 5);
147  pat = create_pat(filename, keys);
148  dat = create_dat(filename, keys);
149 
152 
153  cut_assert_exist_path(pat_path);
154  cut_assert_exist_path(dat_path);
155 
156  pat = grn_pat_open(&ctx, pat_path);
157  dat = grn_dat_open(&ctx, dat_path);
158 
159  cppcut_assert_not_null(pat);
160  cppcut_assert_not_null(dat);
161 
164  }
165 
166  void test_remove(void)
167  {
168  const char * const filename = "test_remove";
169 
170  std::vector<std::string> keys;
171  grn_pat * const pat = create_pat(filename, keys);
172  grn_dat * const dat = create_dat(filename, keys);
173 
176 
177  char pat_path[PATH_MAX];
178  char dat_path[PATH_MAX];
179 
180  generate_pat_path(filename, pat_path);
181  generate_dat_path(filename, dat_path);
182 
183  grn_test_assert(grn_pat_remove(&ctx, pat_path));
184  grn_test_assert(grn_dat_remove(&ctx, dat_path));
185 
186  cut_assert_not_exist_path(pat_path);
187  cut_assert_not_exist_path(dat_path);
188 
190  grn_pat_remove(&ctx, pat_path));
192  grn_dat_remove(&ctx, dat_path));
193 
194  }
195 
196  void test_get(void)
197  {
198  const char * const filename = "test_get";
199 
200  std::vector<std::string> keys;
201  create_keys(&keys, 1000, 3, 5);
202  grn_pat * const pat = create_pat(filename, keys);
203  grn_dat * const dat = create_dat(filename, keys);
204 
205  std::string key;
206  for (int i = 0; i < 1000; ++i) {
207  create_key(&key, 3, 5);
208 
209  const grn_id pat_id =
210  grn_pat_get(&ctx, pat, key.c_str(), key.length(), NULL);
211  const grn_id dat_id =
212  grn_dat_get(&ctx, dat, key.c_str(), key.length(), NULL);
213  cppcut_assert_equal(pat_id, dat_id);
214  if (pat_id != GRN_ID_NIL) {
215  char pat_key[1024];
216  const int pat_length =
217  grn_pat_get_key(&ctx, pat, pat_id, pat_key, sizeof(pat_key));
218  char dat_key[1024];
219  const int dat_length =
220  grn_dat_get_key(&ctx, dat, dat_id, dat_key, sizeof(dat_key));
221  cut_assert_equal_memory(pat_key, pat_length, dat_key, dat_length);
222  }
223  }
224 
227  }
228 
229  void test_add(void)
230  {
231  const char * const filename = "test_add";
232 
233  std::vector<std::string> keys;
234  create_keys(&keys, 1000, 3, 5);
235  grn_pat * const pat = create_pat(filename, keys);
236  grn_dat * const dat = create_dat(filename, keys);
237 
238  std::string key;
239  for (int i = 0; i < 1000; ++i) {
240  create_key(&key, 3, 5);
241  int pat_added = -1;
242  const grn_id pat_id =
243  grn_pat_add(&ctx, pat, key.c_str(), key.length(), NULL, &pat_added);
244  int dat_added = -2;
245  const grn_id dat_id =
246  grn_dat_add(&ctx, dat, key.c_str(), key.length(), NULL, &dat_added);
247  cppcut_assert_equal(pat_id, dat_id);
248  cppcut_assert_equal(pat_added, dat_added);
249 
250  cppcut_assert_equal(grn_pat_size(&ctx, pat),
251  grn_dat_size(&ctx, dat));
252  cppcut_assert_equal(grn_pat_curr_id(&ctx, pat),
253  grn_dat_curr_id(&ctx, dat));
254  }
255 
258  }
259 
260  void test_delete_by_id(void)
261  {
262  const char * const filename = "test_delete_by_id";
263 
265  grn_pat_delete_by_id(&ctx, NULL, 1, NULL));
267  grn_dat_delete_by_id(&ctx, NULL, 1, NULL));
268 
269  std::vector<std::string> keys;
270  create_keys(&keys, 1000, 3, 5);
271  grn_pat * const pat = create_pat(filename, keys);
272  grn_dat * const dat = create_dat(filename, keys);
273 
275  grn_pat_delete_by_id(&ctx, pat, GRN_ID_NIL, NULL));
277  grn_dat_delete_by_id(&ctx, dat, GRN_ID_NIL, NULL));
278 
279  for (std::size_t i = 0; i < keys.size(); i += 2) {
280  const grn_id key_id = static_cast<grn_id>(i + 1);
282  grn_pat_delete_by_id(&ctx, pat, key_id, NULL));
284  grn_dat_delete_by_id(&ctx, dat, key_id, NULL));
285  }
286 
288  grn_pat_delete_by_id(&ctx, pat, 1, NULL));
290  grn_dat_delete_by_id(&ctx, dat, 1, NULL));
291 
292  for (std::size_t i = 0; i < keys.size(); ++i) {
293  const grn_id key_id = static_cast<grn_id>(i + 1);
294  const grn_rc rc = (i & 1) ? GRN_SUCCESS : GRN_INVALID_ARGUMENT;
296  grn_pat_delete_by_id(&ctx, pat, key_id, NULL));
298  grn_dat_delete_by_id(&ctx, dat, key_id, NULL));
299  }
300 
303  }
304 
305  void test_delete(void)
306  {
307  const char * const filename = "test_delete";
308 
310  grn_pat_delete(&ctx, NULL, "XYZ", 3, NULL));
312  grn_dat_delete(&ctx, NULL, "XYZ", 3, NULL));
313 
314  std::vector<std::string> keys;
315  create_keys(&keys, 1000, 3, 5);
316  grn_pat * const pat = create_pat(filename, keys);
317  grn_dat * const dat = create_dat(filename, keys);
318 
320  grn_pat_delete(&ctx, pat, NULL, 1, NULL));
322  grn_dat_delete(&ctx, dat, NULL, 1, NULL));
323 
325  grn_pat_delete(&ctx, pat, "XYZ", 0, NULL));
327  grn_dat_delete(&ctx, dat, "XYZ", 0, NULL));
328 
329  for (std::size_t i = 0; i < keys.size(); i += 2) {
330  const char * const ptr = keys[i].c_str();
331  const uint32_t length = static_cast<uint32_t>(keys[i].length());
333  grn_pat_delete(&ctx, pat, ptr, length, NULL));
335  grn_dat_delete(&ctx, dat, ptr, length, NULL));
336  }
337 
338  for (std::size_t i = 0; i < keys.size(); ++i) {
339  const char * const ptr = keys[i].c_str();
340  const uint32_t length = static_cast<uint32_t>(keys[i].length());
341  const grn_rc rc = (i & 1) ? GRN_SUCCESS : GRN_INVALID_ARGUMENT;
343  grn_pat_delete(&ctx, pat, ptr, length, NULL));
345  grn_dat_delete(&ctx, dat, ptr, length, NULL));
346  }
347 
350  }
351 
352  void test_scan(void)
353  {
354  const char * const filename = "test_scan";
355 
356  std::vector<std::string> keys;
357  create_keys(&keys, 1000, 3, 5);
358  grn_pat * const pat = create_pat(filename, keys);
359  grn_dat * const dat = create_dat(filename, keys);
360 
361  std::string query;
362  for (int i = 0; i < 1000; ++i) {
363  create_key(&query, 8, 16);
364 
365  grn_pat_scan_hit pat_hits[4];
366  const char *pat_rest;
367  const int pat_num_hits =
368  grn_pat_scan(&ctx, pat, query.c_str(), query.length(),
369  pat_hits, 4, &pat_rest);
370 
371  grn_dat_scan_hit dat_hits[4];
372  const char *dat_rest;
373  const int dat_num_hits =
374  grn_dat_scan(&ctx, dat, query.c_str(), query.length(),
375  dat_hits, 4, &dat_rest);
376 
377  cppcut_assert_equal(pat_num_hits, dat_num_hits);
378  for (int j = 0; j < pat_num_hits; ++j) {
379  cppcut_assert_equal(pat_hits[j].id, dat_hits[j].id);
380  cppcut_assert_equal(pat_hits[j].offset, dat_hits[j].offset);
381  cppcut_assert_equal(pat_hits[j].length, dat_hits[j].length);
382  }
383  cppcut_assert_equal(pat_rest, dat_rest);
384  }
385 
388  }
389 
390  void test_lcp_search(void)
391  {
392  const char * const filename = "test_lcp_search";
393 
394  std::vector<std::string> keys;
395  create_keys(&keys, 1000, 3, 5);
396  grn_pat * const pat = create_pat(filename, keys);
397  grn_dat * const dat = create_dat(filename, keys);
398 
399  std::string query;
400  for (int i = 0; i < 1000; ++i) {
401  create_key(&query, 3, 6);
402 
403  const grn_id pat_id =
404  grn_pat_lcp_search(&ctx, pat, query.c_str(), query.length());
405  const grn_id dat_id =
406  grn_dat_lcp_search(&ctx, dat, query.c_str(), query.length());
407  cppcut_assert_equal(pat_id, dat_id);
408  }
409 
412  }
413 
414  void test_id_cursor(void)
415  {
416  const char * const filename = "test_id_cursor";
417 
418  std::vector<std::string> keys;
419  create_keys(&keys, 1000, 3, 5);
420  grn_pat * const pat = create_pat(filename, keys);
421  grn_dat * const dat = create_dat(filename, keys);
422 
423  std::string key;
424  for (int i = 0; i < 1000; ++i) {
425  grn_id min_id = static_cast<grn_id>(std::rand() % (keys.size() + 1));
426  grn_id max_id = static_cast<grn_id>(std::rand() % (keys.size() + 1));
427  if (!min_id) {
428  min_id = GRN_ID_NIL;
429  }
430  if (!max_id) {
431  max_id = GRN_ID_NIL;
432  }
433  if ((min_id != GRN_ID_NIL) && (max_id != GRN_ID_NIL) &&
434  (min_id > max_id)) {
435  std::swap(min_id, max_id);
436  }
437 
438  const char * const min_key =
439  (min_id != GRN_ID_NIL) ? keys[min_id - 1].c_str() : NULL;
440  const int min_length =
441  min_key ? static_cast<int>(keys[min_id - 1].length()) : 0;
442  const char * const max_key =
443  (max_id != GRN_ID_NIL) ? keys[max_id - 1].c_str() : NULL;
444  const int max_length =
445  max_key ? static_cast<int>(keys[max_id - 1].length()) : 0;
446 
447  const int temp = std::rand();
448  const int offset = temp & 0x0F;
449  const int limit = ((temp & 0xF0) == 0xF0) ? -1 : ((temp & 0xF0) >> 4);
450  const int flags = GRN_CURSOR_BY_ID |
451  (((temp & 0x100) == 0x100) ? GRN_CURSOR_LT : GRN_CURSOR_LE) |
452  (((temp & 0x200) == 0x200) ? GRN_CURSOR_GT : GRN_CURSOR_GE) |
453  (((temp & 0x400) == 0x400) ?
455 
456  grn_pat_cursor * const pat_cursor = grn_pat_cursor_open(
457  &ctx, pat, min_key, min_length, max_key, max_length,
458  offset, limit, flags);
459  cppcut_assert_not_null(pat_cursor);
460 
461  grn_dat_cursor * const dat_cursor = grn_dat_cursor_open(
462  &ctx, dat, min_key, min_length, max_key, max_length,
463  offset, limit, flags);
464  cppcut_assert_not_null(dat_cursor);
465 
466  grn_id pat_id;
467  grn_id dat_id;
468  do {
469  pat_id = grn_pat_cursor_next(&ctx, pat_cursor);
470  dat_id = grn_dat_cursor_next(&ctx, dat_cursor);
471  cppcut_assert_equal(pat_id, dat_id);
472  } while (pat_id != GRN_ID_NIL);
473 
474  grn_pat_cursor_close(&ctx, pat_cursor);
475  grn_dat_cursor_close(&ctx, dat_cursor);
476  }
477 
480  }
481 
482  void test_key_cursor(void)
483  {
484  const char * const filename = "test_key_cursor";
485 
486  std::vector<std::string> keys;
487  create_keys(&keys, 1000, 3, 5);
488  grn_pat * const pat = create_pat(filename, keys);
489  grn_dat * const dat = create_dat(filename, keys);
490 
491  std::string min_str;
492  std::string max_str;
493  for (int i = 0; i < 1000; ++i) {
494  create_key(&min_str, 3, 5);
495  create_key(&max_str, 3, 5);
496  if (min_str > max_str) {
497  min_str.swap(max_str);
498  }
499 
500  const int temp = std::rand();
501  const int offset = temp & 0x0F;
502  const int limit = ((temp & 0xF0) == 0xF0) ? -1 : ((temp & 0xF0) >> 4);
503  const int flags = GRN_CURSOR_BY_KEY |
504  (((temp & 0x100) == 0x100) ? GRN_CURSOR_LT : GRN_CURSOR_LE) |
505  (((temp & 0x200) == 0x200) ? GRN_CURSOR_GT : GRN_CURSOR_GE) |
506  (((temp & 0x400) == 0x400) ?
508 
509  const bool disables_min = !(rand() % 32);
510  const bool disables_max = !(rand() % 32);
511 
512  grn_pat_cursor * const pat_cursor =
513  grn_pat_cursor_open(&ctx, pat, disables_min ? NULL : min_str.c_str(),
514  disables_min ? 0 : min_str.length(),
515  disables_max ? NULL : max_str.c_str(),
516  disables_max ? 0 : max_str.length(),
517  offset, limit, flags);
518  cppcut_assert_not_null(pat_cursor);
519 
520  grn_dat_cursor * const dat_cursor =
521  grn_dat_cursor_open(&ctx, dat, disables_min ? NULL : min_str.c_str(),
522  disables_min ? 0 : min_str.length(),
523  disables_max ? NULL : max_str.c_str(),
524  disables_max ? 0 : max_str.length(),
525  offset, limit, flags);
526  cppcut_assert_not_null(dat_cursor);
527 
528  grn_id pat_id;
529  grn_id dat_id;
530  do {
531  pat_id = grn_pat_cursor_next(&ctx, pat_cursor);
532  dat_id = grn_dat_cursor_next(&ctx, dat_cursor);
533  cppcut_assert_equal(pat_id, dat_id);
534  } while (pat_id != GRN_ID_NIL);
535 
536  grn_pat_cursor_close(&ctx, pat_cursor);
537  grn_dat_cursor_close(&ctx, dat_cursor);
538  }
539 
542  }
543 
545  {
546  const char * const filename = "test_prefix_cursor";
547 
548  std::vector<std::string> keys;
549  create_keys(&keys, 1000, 3, 5);
550  grn_pat * const pat = create_pat(filename, keys);
551  grn_dat * const dat = create_dat(filename, keys);
552 
553  std::string max_str;
554  for (int i = 0; i < 1000; ++i) {
555  create_key(&max_str, 3, 5);
556 
557  const int temp = std::rand();
558  const int offset = temp & 0x03;
559  const int limit = ((temp & 0xF0) == 0xF0) ? -1 : ((temp & 0xF0) >> 4);
560  const int flags = GRN_CURSOR_PREFIX |
561  (((temp & 0x100) == 0x100) ? GRN_CURSOR_LT : GRN_CURSOR_LE) |
562  (((temp & 0x200) == 0x200) ? GRN_CURSOR_GT : GRN_CURSOR_GE) |
563  (((temp & 0x400) == 0x400) ?
565 
566  const int min_length = std::rand() % (max_str.length() + 1);
567 
568  grn_pat_cursor * const pat_cursor =
569  grn_pat_cursor_open(&ctx, pat, NULL, min_length, max_str.c_str(),
570  max_str.length(), offset, limit, flags);
571  cppcut_assert_not_null(pat_cursor);
572 
573  grn_dat_cursor * const dat_cursor =
574  grn_dat_cursor_open(&ctx, dat, NULL, min_length, max_str.c_str(),
575  max_str.length(), offset, limit, flags);
576  cppcut_assert_not_null(dat_cursor);
577 
578  grn_id pat_id;
579  grn_id dat_id;
580  do {
581  pat_id = grn_pat_cursor_next(&ctx, pat_cursor);
582  dat_id = grn_dat_cursor_next(&ctx, dat_cursor);
583  cppcut_assert_equal(pat_id, dat_id);
584  } while (pat_id != GRN_ID_NIL);
585 
586  grn_pat_cursor_close(&ctx, pat_cursor);
587  grn_dat_cursor_close(&ctx, dat_cursor);
588  }
589 
592  }
593 
595  {
596  const char * const filename = "test_predictive_cursor";
597 
598  std::vector<std::string> keys;
599  create_keys(&keys, 1000, 3, 5);
600  grn_pat * const pat = create_pat(filename, keys);
601  grn_dat * const dat = create_dat(filename, keys);
602 
603  std::string min_str;
604  for (int i = 0; i < 1000; ++i) {
605  create_key(&min_str, 3, 5);
606 
607  const int temp = std::rand();
608  const int offset = temp & 0x0F;
609  const int limit = ((temp & 0xF0) == 0xF0) ? -1 : ((temp & 0xF0) >> 4);
610  const int flags = GRN_CURSOR_PREFIX |
611  (((temp & 0x100) == 0x100) ? GRN_CURSOR_LT : GRN_CURSOR_LE) |
612  (((temp & 0x200) == 0x200) ? GRN_CURSOR_GT : GRN_CURSOR_GE) |
613  (((temp & 0x400) == 0x400) ?
615 
616  grn_pat_cursor * const pat_cursor =
617  grn_pat_cursor_open(&ctx, pat, min_str.c_str(), min_str.length(),
618  NULL, 0, offset, limit, flags);
619  cppcut_assert_not_null(pat_cursor);
620 
621  grn_dat_cursor *dat_cursor =
622  grn_dat_cursor_open(&ctx, dat, min_str.c_str(), min_str.length(),
623  NULL, 0, offset, limit, flags);
624  cppcut_assert_not_null(dat_cursor);
625 
626  grn_id pat_id;
627  grn_id dat_id;
628  do {
629  pat_id = grn_pat_cursor_next(&ctx, pat_cursor);
630  dat_id = grn_dat_cursor_next(&ctx, dat_cursor);
631  cppcut_assert_equal(pat_id, dat_id);
632  } while (pat_id != GRN_ID_NIL);
633 
634  grn_pat_cursor_close(&ctx, pat_cursor);
635  grn_dat_cursor_close(&ctx, dat_cursor);
636  }
637 
640  }
641 
642  void test_truncate(void)
643  {
644  const char * const filename = "test_truncate";
645 
646  std::vector<std::string> keys;
647  create_keys(&keys, 1000, 3, 5);
648  grn_pat * const pat = create_pat(filename, keys);
649  grn_dat * const dat = create_dat(filename, keys);
650 
653 
654  cppcut_assert_equal(static_cast<unsigned int>(0), grn_pat_size(&ctx, pat));
655  cppcut_assert_equal(static_cast<unsigned int>(0), grn_dat_size(&ctx, dat));
656 
657  for (std::size_t i = 0; i < keys.size(); ++i) {
658  const char * const ptr = keys[i].c_str();
659  const uint32_t length = static_cast<uint32_t>(keys[i].length());
660  cppcut_assert_equal(static_cast<grn_id>(GRN_ID_NIL),
661  grn_pat_get(&ctx, pat, ptr, length, NULL));
662  cppcut_assert_equal(static_cast<grn_id>(GRN_ID_NIL),
663  grn_dat_get(&ctx, dat, ptr, length, NULL));
664  }
665 
668  }
669 }