Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
test-snip.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
2 /*
3  Copyright (C) 2008-2012 Kouhei Sutou <kou@clear-code.com>
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 <groonga.h>
20 
21 #include <gcutter.h>
22 #include <glib/gstdio.h>
23 
24 #include "../lib/grn-assertions.h"
25 
26 void test_simple_exec(void);
27 void test_simple_exec_euc_jp(void);
28 void test_simple_exec_sjis(void);
29 void test_simple_exec_utf8(void);
32 void data_proper_tag_insertion(void);
33 void test_proper_tag_insertion(gconstpointer data);
35 void test_exec_with_normalize(void);
37 void test_customized_tag(void);
38 void test_multi_conditions(void);
39 void test_invalid_result_index(void);
40 void test_html_mapping(void);
41 void test_html_mapping_escape(void);
42 void test_close_with_null(void);
47 
48 static grn_ctx context;
49 static grn_obj *database;
50 static grn_snip *snip;
51 static gchar *keyword;
52 static gchar *result;
53 
54 static grn_encoding default_encoding;
55 static int default_flags;
56 static unsigned int default_width;
57 static unsigned int default_max_results;
58 static gchar *default_open_tag;
59 static unsigned int default_open_tag_len;
60 static gchar *default_close_tag;
61 static unsigned int default_close_tag_len;
62 static grn_snip_mapping *default_mapping;
63 
64 static const gchar text[] =
65  "Groonga is an embeddable fulltext search engine, which you can use in\n"
66  "conjunction with various scripting languages and databases. Groonga is\n"
67  "an inverted index based engine, & combines the best of n-gram\n"
68  "indexing and word indexing to achieve fast, precise searches. While\n"
69  "groonga codebase is rather compact it is scalable enough to handle large\n"
70  "amounts of data and queries.";
71 static const gchar text_ja_utf8[] =
72  "Groongaは組み込み型の全文検索エンジンです。DBMSやスクリプト言語処理系等に\n"
73  "組み込むことによって、その全文検索機能を強化することができます。n-gram\n"
74  "インデックスと単語インデックスの特徴を兼ね備えた、高速かつ高精度な転置\n"
75  "インデックスタイプのエンジンです。コンパクトな実装ですが、大規模な文書\n"
76  "量と検索要求を処理できるように設計されています。また、純粋なn-gramイン\n"
77  "デックスの作成も可能です。";
78 static gchar *text_ja_euc;
79 static gchar *text_ja_sjis;
80 static const gchar html_text[] =
81  "<div class=\"day\">\n"
82  " <h2 id=\"Requirements\">Requirements</h2>\n"
83  " <div class=\"body\">\n"
84  " <div class=\"section\">\n"
85  " <ul>\n"
86  " <li>OS</li>\n"
87  " <ul>\n"
88  " <li>Linux, FreeBSD, MacOS X</li>\n"
89  " </ul>\n"
90  " <li>Requirements</li>\n"
91  " <ul>\n"
92  " <li>MeCab-0.80 or later "
93  /* */"(for japanese-word indexing. normally not required.)</li>\n"
94  " <li>Ruby 1.8.1 or later (for Ruby binding.)"
95  /* */"<a class=\"external\" href=\"http://www.ruby-lang.org/\">"
96  /* */"http://www.ruby-lang.org/"
97  /* */"</a>"
98  /* */"</li>\n"
99  " </ul>\n"
100  " </ul>\n"
101  " </div><!--section-->\n"
102  " </div><!--body-->\n"
103  "</div><!--day-->\n";
104 
105 static gchar *
106 convert(const gchar *string, const gchar *from, const gchar *to, GError **error)
107 {
108  return g_convert(string, -1, to, from, NULL, NULL, error);
109 }
110 
111 static gchar *
112 utf8_to_euc_jp(const gchar *utf8, GError **error)
113 {
114  return convert(utf8, "utf-8", "eucJP", error);
115 }
116 
117 static gchar *
118 euc_jp_to_utf8(const gchar *euc_jp, GError **error)
119 {
120  return convert(euc_jp, "eucJP", "utf-8", error);
121 }
122 
123 static gchar *
124 utf8_to_sjis(const gchar *utf8, GError **error)
125 {
126  return convert(utf8, "utf-8", "CP932", error);
127 }
128 
129 static gchar *
130 sjis_to_utf8(const gchar *sjis, GError **error)
131 {
132  return convert(sjis, "CP932", "utf-8", error);
133 }
134 
135 static const gchar *
136 take_euc_jp_to_utf8(const gchar *euc_jp)
137 {
138  gchar *utf8;
139  GError *error = NULL;
140 
141  utf8 = euc_jp_to_utf8(euc_jp, &error);
142  cut_assert_g_error(error);
143  return cut_take_string(utf8);
144 }
145 
146 static const gchar *
147 take_sjis_to_utf8(const gchar *sjis)
148 {
149  gchar *utf8;
150  GError *error = NULL;
151 
152  utf8 = sjis_to_utf8(sjis, &error);
153  cut_assert_g_error(error);
154  return cut_take_string(utf8);
155 }
156 
157 #define cut_check_g_error(error) do \
158 { \
159  GError *_error = (error); \
160  if (_error) { \
161  const gchar *message; \
162  message = cut_take_printf("%s: %d: %s", \
163  g_quark_to_string(_error->domain), \
164  _error->code, \
165  _error->message); \
166  g_error_free(_error); \
167  cut_error("%s", message); \
168  } \
169 } while (0)
170 
171 void
173 {
174  GError *error = NULL;
175 
176  text_ja_euc = NULL;
177  text_ja_sjis = NULL;
178 
179  text_ja_euc = utf8_to_euc_jp(text_ja_utf8, &error);
180  cut_check_g_error(error);
181 
182  text_ja_sjis = utf8_to_sjis(text_ja_utf8, &error);
183  cut_check_g_error(error);
184 }
185 
186 void
188 {
189  if (text_ja_euc) {
190  g_free(text_ja_euc);
191  }
192 
193  if (text_ja_sjis) {
194  g_free(text_ja_sjis);
195  }
196 }
197 
198 void
200 {
201  grn_ctx_init(&context, 0);
202  database = grn_db_create(&context, NULL, NULL);
203 
204  snip = NULL;
205  keyword = NULL;
206  result = NULL;
207 
208  default_encoding = GRN_ENC_DEFAULT;
209  default_flags = 0;
210  default_width = 100;
211  default_max_results = 10;
212  default_open_tag = g_strdup("[[");
213  default_open_tag_len = strlen(default_open_tag);
214  default_close_tag = g_strdup("]]");
215  default_close_tag_len = strlen(default_close_tag);
216  default_mapping = NULL;
217 }
218 
219 void
221 {
222  if (snip) {
223  grn_obj_close(&context, (grn_obj *)snip);
224  }
225  if (keyword) {
226  g_free(keyword);
227  }
228  if (result) {
229  g_free(result);
230  }
231 
232  if (default_open_tag) {
233  g_free(default_open_tag);
234  }
235  if (default_close_tag) {
236  g_free(default_close_tag);
237  }
238 
239  grn_obj_close(&context, database);
240  grn_ctx_fin(&context);
241 }
242 
243 static grn_snip *
244 open_snip(void)
245 {
246  if (snip) {
247  grn_obj_close(&context, (grn_obj *)snip);
248  }
249  GRN_CTX_SET_ENCODING(&context, default_encoding);
250  snip = grn_snip_open(&context, default_flags,
251  default_width, default_max_results,
252  default_open_tag, default_open_tag_len,
253  default_close_tag, default_close_tag_len,
254  default_mapping);
255  return snip;
256 }
257 
258 #define cut_assert_open_snip() do \
259 { \
260  open_snip(); \
261  cut_assert(snip); \
262 } while (0)
263 
264 void
266 {
267  unsigned int n_results;
268  unsigned int max_tagged_len;
269  unsigned int result_len;
270  const gchar keyword[] = "Groonga";
271 
273  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
274  NULL, 0, NULL, 0));
275 
276  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
277  &n_results, &max_tagged_len));
278  cut_assert_equal_uint(2, n_results);
279  cut_assert_equal_uint(105, max_tagged_len);
280  result = g_new(gchar, max_tagged_len);
281 
282  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
283  cut_assert_equal_string("[[Groonga]] is an embeddable fulltext search engine, "
284  "which you can use in\n"
285  "conjunction with various scrip",
286  result);
287  cut_assert_equal_uint(104, result_len);
288 
289  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
290  cut_assert_equal_string("ting languages and databases. [[Groonga]] is\n"
291  "an inverted index based engine, & combines "
292  "the best of n-gr",
293  result);
294  cut_assert_equal_uint(104, result_len);
295 }
296 
297 void
299 {
300  GError *error = NULL;
301  unsigned int n_results;
302  unsigned int max_tagged_len;
303  unsigned int result_len;
304 
305  keyword = utf8_to_euc_jp("検索", &error);
306  cut_assert_g_error(error);
307 
308  default_encoding = GRN_ENC_EUC_JP;
309 
311  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
312  NULL, 0, NULL, 0));
313 
314  grn_test_assert(grn_snip_exec(&context, snip,
315  text_ja_euc, strlen(text_ja_euc),
316  &n_results, &max_tagged_len));
317  cut_assert_equal_uint(2, n_results);
318  cut_assert_equal_uint(108, max_tagged_len);
319  result = g_new(gchar, max_tagged_len);
320 
321  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
322  cut_assert_equal_string("型の全文[[検索]]エンジンです。"
323  "DBMSやスクリプト言語処理系等に\n"
324  "組み込むことによって、その全文[[検索]]機能を強",
325  take_euc_jp_to_utf8(result));
326  cut_assert_equal_uint(107, result_len);
327 
328  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
329  cut_assert_equal_string("です。コンパクトな実装ですが、大規模な文書\n"
330  "量と[[検索]]要求を処理できるように設計されて"
331  "います。また、純",
332  take_euc_jp_to_utf8(result));
333  cut_assert_equal_uint(103, result_len);
334 }
335 
336 void
338 {
339  GError *error = NULL;
340  unsigned int n_results;
341  unsigned int max_tagged_len;
342  unsigned int result_len;
343 
344  keyword = utf8_to_sjis("処理", &error);
345  cut_assert_g_error(error);
346 
347  default_encoding = GRN_ENC_SJIS;
348 
350  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
351  NULL, 0, NULL, 0));
352 
353  grn_test_assert(grn_snip_exec(&context, snip,
354  text_ja_sjis, strlen(text_ja_sjis),
355  &n_results, &max_tagged_len));
356  cut_assert_equal_uint(2, n_results);
357  cut_assert_equal_uint(104, max_tagged_len);
358  result = g_new(gchar, max_tagged_len);
359 
360  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
361  cut_assert_equal_string("み型の全文検索エンジンです。"
362  "DBMSやスクリプト言語[[処理]]系等に\n"
363  "組み込むことによって、その全文検索機能を",
364  take_sjis_to_utf8(result));
365  cut_assert_equal_uint(103, result_len);
366 
367  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
368  cut_assert_equal_string("パクトな実装ですが、大規模な文書\n"
369  "量と検索要求を[[処理]]できるように設計"
370  "されています。また、純粋なn-gram",
371  take_sjis_to_utf8(result));
372  cut_assert_equal_uint(103, result_len);
373 }
374 
375 void
377 {
378  unsigned int n_results;
379  unsigned int max_tagged_len;
380  unsigned int result_len;
381  const gchar keyword[] = "エンジン";
382 
383  default_encoding = GRN_ENC_UTF8;
384 
386  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
387  NULL, 0, NULL, 0));
388 
389  grn_test_assert(grn_snip_exec(&context, snip,
390  text_ja_utf8, strlen(text_ja_utf8),
391  &n_results, &max_tagged_len));
392  cut_assert_equal_uint(2, n_results);
393  cut_assert_equal_uint(105, max_tagged_len);
394  result = g_new(gchar, max_tagged_len);
395 
396  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
397  cut_assert_equal_string("Groongaは組み込み型の全文検索[[エンジン]]です。"
398  "DBMSやスクリプト言語処理系",
399  result);
400  cut_assert_equal_uint(102, result_len);
401 
402  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
403  cut_assert_equal_string("度な転置\n"
404  "インデックスタイプの[[エンジン]]です。"
405  "コンパクトな実装ですが、",
406  result);
407  cut_assert_equal_uint(104, result_len);
408 }
409 
410 void
412 {
413  unsigned int n_results;
414  unsigned int max_tagged_len;
415 
417 
418  grn_test_assert(grn_snip_exec(&context, snip, "", 0,
419  &n_results, &max_tagged_len));
420  cut_assert_equal_uint(0, n_results);
421 }
422 
423 void
425 {
426  unsigned int n_results;
427  unsigned int max_tagged_len;
428 
430 
431  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
432  &n_results, &max_tagged_len));
433 
435  grn_snip_exec(&context, NULL, text, strlen(text),
436  &n_results, &max_tagged_len));
438  grn_snip_exec(&context, snip, NULL, strlen(text),
439  &n_results, &max_tagged_len));
441  grn_snip_exec(&context, snip, text, strlen(text),
442  NULL, &max_tagged_len));
444  grn_snip_exec(&context, snip, text, strlen(text),
445  &n_results, NULL));
446 }
447 
448 void
450 {
451  unsigned int n_results;
452  unsigned int max_tagged_len;
453  unsigned int result_len;
454  const gchar text[] = "Ⅶ¨abcde";
455  const gchar keyword[] = "ab";
456 
457  default_encoding = GRN_ENC_UTF8;
458  default_flags = GRN_SNIP_NORMALIZE;
459 
461  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
462  NULL, 0, NULL, 0));
463 
464  grn_test_assert(grn_snip_exec(&context, snip,
465  text, strlen(text),
466  &n_results, &max_tagged_len));
467  cut_assert_equal_uint(1, n_results);
468  cut_assert_equal_uint(15, max_tagged_len);
469  result = g_new(gchar, max_tagged_len);
470 
471  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
472  cut_assert_equal_string("Ⅶ¨[[ab]]cde",
473  result);
474  cut_assert_equal_uint(14, result_len);
475 }
476 
477 void
479 {
480  unsigned int n_results;
481  unsigned int max_tagged_len;
482  unsigned int result_len;
483  const gchar keyword[] = "転置インデックス";
484 
485  default_encoding = GRN_ENC_UTF8;
486 
488  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
489  NULL, 0, NULL, 0));
490 
491  grn_test_assert(grn_snip_exec(&context, snip,
492  text_ja_utf8, strlen(text_ja_utf8),
493  &n_results, &max_tagged_len));
494  cut_assert_equal_uint(0, n_results);
495 
496  grn_obj_close(&context, (grn_obj *)snip);
497  snip = NULL;
498 
499 
500  default_flags = GRN_SNIP_NORMALIZE;
501 
503  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
504  NULL, 0, NULL, 0));
505 
506  grn_test_assert(grn_snip_exec(&context, snip,
507  text_ja_utf8, strlen(text_ja_utf8),
508  &n_results, &max_tagged_len));
509  cut_assert_equal_uint(1, n_results);
510  cut_assert_equal_uint(105, max_tagged_len);
511  result = g_new(gchar, max_tagged_len);
512 
513  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
514  cut_assert_equal_string("備えた、高速かつ高精度な[[転置\n"
515  "インデックス]]タイプのエンジンです。コン",
516  result);
517  cut_assert_equal_uint(104, result_len);
518 }
519 
520 void
522 {
523 #define ADD_DATUM(label, expected, flags) \
524  gcut_add_datum(label, \
525  "expected", G_TYPE_STRING, (expected),\
526  "flags", G_TYPE_INT, (flags), \
527  NULL)
528  const gchar tag_after_space[] =
529  "Groonga is an [[embeddable]] fulltext search engine, which you can use in\n"
530  "conjunction with various scrip";
531  const gchar tag_before_space[] =
532  "Groonga is an[[ embeddable]] fulltext search engine, which you can use in\n"
533  "conjunction with various scrip";
534 
535  ADD_DATUM("no flags", tag_after_space,
536  0);
537  ADD_DATUM("copy_tag", tag_after_space,
539  ADD_DATUM("skip_spaces", tag_after_space,
541  ADD_DATUM("copy_tag and skip_spaces", tag_after_space,
543  ADD_DATUM("normalize", tag_before_space,
545  ADD_DATUM("normalize and copy_tag", tag_before_space,
547  ADD_DATUM("normalize and skip_spaces", tag_after_space,
549  ADD_DATUM("normalize, copy_tag and skip_spaces", tag_after_space,
551 #undef ADD_DATUM
552 }
553 
554 void
555 test_proper_tag_insertion(gconstpointer data)
556 {
557  unsigned int n_results;
558  unsigned int max_tagged_len;
559  const gchar keyword[] = "embeddable";
560  const gchar *expected;
561  gchar *result;
562  unsigned int text_len, keyword_len, result_len, expected_len;
563 
564  default_encoding = GRN_ENC_UTF8;
565  default_flags = gcut_data_get_int(data, "flags");
566 
567  text_len = strlen(text);
568  keyword_len = strlen(keyword);
569  expected = gcut_data_get_string(data, "expected");
570  expected_len = strlen(expected);
571 
573  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, keyword_len,
574  NULL, 0, NULL, 0));
575 
576  grn_test_assert(grn_snip_exec(&context, snip, text, text_len, &n_results,
577  &max_tagged_len));
578  cut_assert_equal_uint(1, n_results);
579  cut_assert_equal_uint(expected_len + 1, max_tagged_len);
580  result = g_new(gchar, max_tagged_len);
581 
582  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
583  cut_assert_equal_string(expected, result);
584  cut_assert_equal_uint(expected_len, result_len);
585 }
586 
587 void
589 {
590  unsigned int n_results;
591  unsigned int max_tagged_len;
592  unsigned int result_len;
593  const gchar keyword[] = "x";
594 
596  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
597  NULL, 0, NULL, 0));
598 
599  grn_test_assert(grn_snip_exec(&context, snip,
600  text, strlen(text),
601  &n_results, &max_tagged_len));
602  cut_assert_equal_uint(2, n_results);
603  cut_assert_equal_uint(113, max_tagged_len);
604  result = g_new(gchar, max_tagged_len);
605 
606  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
607  cut_assert_equal_string("Groonga is an embeddable fullte[[x]]t search "
608  "engine, which you can use in\n"
609  "conjunction with various scrip",
610  result);
611  cut_assert_equal_uint(104, result_len);
612 
613  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
614  cut_assert_equal_string("an inverted inde[[x]] based engine, & "
615  "combines the best of n-gram\n"
616  "inde[[x]]ing and word inde[[x]]ing to achieve ",
617  result);
618  cut_assert_equal_uint(112, result_len);
619 }
620 
621 void
623 {
624  const gchar open_tag[] = "((*";
625  const gchar close_tag[] = "*))";
626  unsigned int n_results;
627  unsigned int max_tagged_len;
628  unsigned int result_len;
629  const gchar keyword[] = "engine";
630 
632  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
633  open_tag, strlen(open_tag),
634  close_tag, strlen(close_tag)));
635 
636  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
637  &n_results, &max_tagged_len));
638  cut_assert_equal_uint(2, n_results);
639  cut_assert_equal_uint(107, max_tagged_len);
640  result = g_new(gchar, max_tagged_len);
641 
642  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
643  cut_assert_equal_string("Groonga is an embeddable fulltext search "
644  "((*engine*)), which you can use in\n"
645  "conjunction with various scrip",
646  result);
647  cut_assert_equal_uint(106, result_len);
648 
649  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
650  cut_assert_equal_string(" databases. Groonga is\n"
651  "an inverted index based ((*engine*)), "
652  "& combines the best of n-gram\n"
653  "indexing and wo",
654  result);
655  cut_assert_equal_uint(106, result_len);
656 }
657 
658 void
660 {
661  const gchar open_tag[] = "((*";
662  const gchar close_tag[] = "*))";
663  unsigned int n_results;
664  unsigned int max_tagged_len;
665  unsigned int result_len;
666  const gchar keyword1[] = "fulltext";
667  const gchar keyword2[] = "groonga";
668 
670  grn_test_assert(grn_snip_add_cond(&context, snip, keyword1, strlen(keyword1),
671  open_tag, strlen(open_tag),
672  close_tag, strlen(close_tag)));
673  grn_test_assert(grn_snip_add_cond(&context, snip, keyword2, strlen(keyword2),
674  NULL, 0, NULL, 0));
675 
676  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
677  &n_results, &max_tagged_len));
678  cut_assert_equal_uint(2, n_results);
679  cut_assert_equal_uint(107, max_tagged_len);
680  result = g_new(gchar, max_tagged_len);
681 
682  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
683  cut_assert_equal_string("Groonga is an embeddable ((*fulltext*)) search "
684  "engine, which you can use in\n"
685  "conjunction with various scrip",
686  result);
687  cut_assert_equal_uint(106, result_len);
688 
689  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
690  cut_assert_equal_string("exing to achieve fast, precise searches. While\n"
691  "[[groonga]] codebase is rather compact it is "
692  "scalable eno",
693  result);
694  cut_assert_equal_uint(104, result_len);
695 }
696 
697 void
699 {
700  unsigned int n_results;
701  unsigned int max_tagged_len;
702  unsigned int result_len;
703  const gchar keyword[] = "index";
704 
706  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
707  NULL, 0, NULL, 0));
708 
709  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
710  &n_results, &max_tagged_len));
711  cut_assert_equal_uint(1, n_results);
712  cut_assert_equal_uint(113, max_tagged_len);
713  result = g_new(gchar, max_tagged_len);
714 
715  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
717  grn_snip_get_result(&context, snip, 1,
718  result, &result_len));
719 }
720 
721 void
723 {
724  const gchar open_tag[] = "<<";
725  unsigned int n_results;
726  unsigned int max_tagged_len;
727  unsigned int result_len;
728  const gchar keyword[] = "indexing";
729 
730  default_mapping = (grn_snip_mapping *)-1;
732  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
733  open_tag, strlen(open_tag), NULL, 0));
734 
735  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
736  &n_results, &max_tagged_len));
737  cut_assert_equal_uint(1, n_results);
738  cut_assert_equal_uint(113, max_tagged_len);
739  result = g_new(gchar, max_tagged_len);
740 
741  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
742  cut_assert_equal_string("ngine, &amp; combines the best of n-gram\n"
743  "<<indexing]] and word <<indexing]] to achieve fast, "
744  "precise searches. W",
745  result);
746  cut_assert_equal_uint(112, result_len);
747 }
748 
749 void
751 {
752  const gchar close_tag[] = ">&>";
753  unsigned int n_results;
754  unsigned int max_tagged_len;
755  unsigned int result_len;
756  const gchar keyword[] = "Ruby";
757  const gchar expected[] =
758  "y not required.)&lt;/li&gt;\n"
759  " &lt;li&gt;[[Ruby>&> 1.8.1 or later "
760  /* */"(for [[Ruby>&> binding.)"
761  /* */"&lt;a class=&quot;external&quot; "
762  /* */"href=";
763 
764  default_mapping = (grn_snip_mapping *)-1;
766  grn_test_assert(grn_snip_add_cond(&context, snip, keyword, strlen(keyword),
767  NULL, 0, close_tag, strlen(close_tag)));
768 
769  grn_test_assert(grn_snip_exec(&context, snip, html_text, strlen(html_text),
770  &n_results, &max_tagged_len));
771  cut_assert_equal_uint(1, n_results);
772  cut_assert_equal_uint(strlen(expected) + 1, max_tagged_len);
773  result = g_new(gchar, max_tagged_len);
774 
775  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
776  cut_assert_equal_string(expected, result);
777  cut_assert_equal_uint(strlen(expected), result_len);
778 }
779 
780 void
782 {
784 }
785 
786 void
788 {
789  default_max_results = -1;
790  cut_assert_null(open_snip());
791 
792  default_max_results = 0;
793  cut_assert_null(open_snip());
794 
795  default_max_results = 16;
796  cut_assert_not_null(open_snip());
797 
798  default_max_results = 17;
799  cut_assert_null(open_snip());
800 }
801 
802 void
804 {
805  const gchar *original_default_open_tag, *original_default_close_tag;
806  unsigned int original_default_open_tag_len, original_default_close_tag_len;
807 
808  default_flags = GRN_SNIP_COPY_TAG;
809 
810  cut_assert_not_null(open_snip());
811 
812  original_default_open_tag = cut_take_string(default_open_tag);
813  original_default_open_tag_len = default_open_tag_len;
814  original_default_close_tag = cut_take_string(default_close_tag);
815  original_default_close_tag_len = default_close_tag_len;
816 
817  default_open_tag = NULL;
818  default_open_tag_len = 0;
819  default_close_tag = NULL;
820  default_close_tag_len = 0;
821  cut_assert_not_null(open_snip());
822 
823  default_open_tag = g_strdup(original_default_open_tag);
824  default_open_tag_len = original_default_open_tag_len;
825  cut_assert_not_null(open_snip());
826  g_free(default_open_tag);
827  default_open_tag = NULL;
828  default_open_tag_len = 0;
829 
830  default_close_tag = g_strdup(original_default_open_tag);
831  default_close_tag_len = original_default_open_tag_len;
832  cut_assert_not_null(open_snip());
833 }
834 
835 void
837 {
838  unsigned int n_conds = 0, max_n_conds = 32U;
839  const gchar keyword[] = "Groonga";
840  unsigned int keyword_len;
841  const gchar open_tag[] = "<<";
842  const gchar close_tag[] = ">>";
843  unsigned int open_tag_len, close_tag_len;
844 
845  keyword_len = strlen(keyword);
846  open_tag_len = strlen(open_tag);
847  close_tag_len = strlen(close_tag);
848 
850 
851  grn_test_assert(grn_snip_add_cond(&context, snip,
852  keyword, keyword_len,
853  open_tag, open_tag_len,
854  close_tag, close_tag_len));
855  n_conds++;
856 
858  grn_snip_add_cond(&context, NULL,
859  keyword, keyword_len,
860  open_tag, open_tag_len,
861  close_tag, close_tag_len));
863  grn_snip_add_cond(&context, snip,
864  NULL, keyword_len,
865  open_tag, open_tag_len,
866  close_tag, close_tag_len));
868  grn_snip_add_cond(&context, snip,
869  keyword, 0,
870  open_tag, open_tag_len,
871  close_tag, close_tag_len));
872 
873  while (n_conds < max_n_conds) {
874  grn_test_assert(grn_snip_add_cond(&context, snip,
875  keyword, keyword_len,
876  open_tag, open_tag_len,
877  close_tag, close_tag_len),
878  cut_message("cond #%d", n_conds));
879  n_conds++;
880  }
881 
883  grn_snip_add_cond(&context, snip,
884  keyword, keyword_len,
885  open_tag, open_tag_len,
886  close_tag, close_tag_len),
887  cut_message("cond #%d", n_conds));
888 }
889 
890 void
892 {
893  const gchar *sub_text;
894 
896 
897  cut_assert_operator_int(strlen(text), >, default_width);
899  grn_snip_add_cond(&context, snip,
900  text, strlen(text),
901  NULL, 0, NULL, 0));
902 
903  sub_text = text + strlen(text) - default_width;
904  grn_test_assert(grn_snip_add_cond(&context, snip,
905  sub_text, strlen(sub_text),
906  NULL, 0, NULL, 0));
907 
908  sub_text--;
910  grn_snip_add_cond(&context, snip,
911  sub_text, strlen(sub_text),
912  NULL, 0, NULL, 0));
913 }
914 
915 void
917 {
918  const gchar keyword[] = "Groonga";
919  unsigned int keyword_len;
920  const gchar open_tag[] = "<<";
921  const gchar close_tag[] = ">>";
922  unsigned int open_tag_len, close_tag_len;
923 
924  keyword_len = strlen(keyword);
925  open_tag_len = strlen(open_tag);
926  close_tag_len = strlen(close_tag);
927 
928  default_flags = GRN_SNIP_COPY_TAG;
929 
931 
932  grn_test_assert(grn_snip_add_cond(&context, snip,
933  keyword, keyword_len,
934  open_tag, open_tag_len,
935  close_tag, close_tag_len));
936  grn_test_assert(grn_snip_add_cond(&context, snip,
937  keyword, keyword_len,
938  open_tag, open_tag_len,
939  NULL, 0));
940  grn_test_assert(grn_snip_add_cond(&context, snip,
941  keyword, keyword_len,
942  NULL, 0,
943  close_tag, close_tag_len));
944  grn_test_assert(grn_snip_add_cond(&context, snip,
945  keyword, keyword_len,
946  NULL, 0,
947  NULL, 0));
948 }