1 /*
2 * Copyright (C) 2008 Aliaksey Kandratsenka
3 *
4 * This program is free software: you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program 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 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see
16 * `http://www.gnu.org/licenses/'.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <memory.h>
21 #include <check.h>
22
23 #include "scorer.h"
24
25 static
26 struct scorer_query qry;
27
28 static
_assert_scores(char * file,int line,int expected_score,char * string,char * pattern,unsigned * expected_match)29 void _assert_scores(char *file, int line, int expected_score, char *string, char *pattern, unsigned *expected_match)
30 {
31 int pat_len = strlen(pattern);
32 int real_score;
33 int i;
34 unsigned match[pat_len];
35
36 qry.pattern = pattern;
37 real_score = score_string(string, &qry, strlen(string), match);
38 if (real_score != expected_score) {
39 _ck_assert_msg(0, file, line, 0, "scoring %s against pattern %s should score 0x%x, not 0x%x",
40 string, pattern, expected_score, real_score,
41 0);
42 return;
43 }
44 if (expected_match)
45 for (i=0;i<pat_len;i++)
46 if (expected_match[i] != match[i])
47 _ck_assert_msg(0, file, line, 0,
48 "match differs in pos %d. Expected %d, got %d",
49 i, expected_match[i], match[i], 0);
50 _ck_assert_msg(1, __FILE__, __LINE__, "cannot happen", 0);
51 }
52
53 #define assert_scores(score, string, pattern, match) _assert_scores(__FILE__, __LINE__, (score), (string), (pattern), (match))
54 #define M(...) ((unsigned[]){__VA_ARGS__})
55
START_TEST(test_empty_string)56 START_TEST(test_empty_string)
57 {
58 int score;
59
60 qry.pattern = "a";
61 score = score_string("", &qry, 0, 0);
62
63 fail_unless(score == -1, NULL);
64 }
65 END_TEST
66
START_TEST(test_capital_pattern_chars_work)67 START_TEST(test_capital_pattern_chars_work)
68 {
69 assert_scores(0x200000, "flexi_record", "FR", M(0,6));
70 }
71 END_TEST
72
START_TEST(test_char_after_delimiter_handling)73 START_TEST(test_char_after_delimiter_handling)
74 {
75 /* char right after delimiter must match start of word */
76 assert_scores(0x200400, "some.owo.word", "s.wo", M(0,4,9,10));
77 assert_scores(0x200400, "some.owoWord", "s.wo", M(0,4,8,9));
78
79 /* char right after delimiter must match start of word */
80 assert_scores(0x200400, "some-owoWord", "s-wo", M(0,SCORER_MATCH_NONE,8,9));
81 }
82 END_TEST
83
START_TEST(test_single_char_matches_work)84 START_TEST(test_single_char_matches_work)
85 {
86 assert_scores(0, "asd", "s", M(1));
87 assert_scores(0, "asd", "d", M(2));
88 assert_scores(0x100000,"asd", "a", 0);
89 assert_scores(0x100000, "asd", "ad", M(0,2));
90 assert_scores(-1, "asd", "q", 0);
91 assert_scores(-1, "asd", "ds", 0);
92 assert_scores(0x400, "asd", "sd", M(1,2));
93 assert_scores(0x100000, "asdaaas", "a", M(0));
94 }
95 END_TEST
96
START_TEST(test_slash_handling)97 START_TEST(test_slash_handling)
98 {
99 qry.right_match = 1;
100 assert_scores(0x100201, "activerecord/lib/active_record", "ar", M(17,24));
101 qry.right_match = 0;
102 assert_scores(0x100000, "base.rb", "b", M(0));
103 /* '/' works */
104 assert_scores(0x200201, "activerecord/lib/octive_record/base.rb", "ar/b", M(0,24,30,31));
105 qry.right_match = 1;
106 assert_scores(0x200201, "activerecord/lib/octive_record/base.rb", "ar/b", M(0,24,30,31));
107 qry.right_match = 0;
108 }
109 END_TEST
110
START_TEST(test_right_match)111 START_TEST(test_right_match)
112 {
113 qry.right_match = 1;
114
115 assert_scores(0, "sabababa", "a", M(7));
116 assert_scores(0, "sabababa", "aa", M(5,7));
117
118 assert_scores(0, "sabababa", "b", M(6));
119 assert_scores(0, "sabababa", "bb", M(4,6));
120
121 qry.right_match = 0;
122
123 assert_scores(0, "sabababa", "a", M(1));
124 assert_scores(0, "sabababa", "aa", M(1,3));
125
126 assert_scores(0, "sabababa", "b", M(2));
127 assert_scores(0, "sabababa", "bb", M(2,4));
128 }
129 END_TEST
130
START_TEST(test_scorer_optimization_bug)131 START_TEST(test_scorer_optimization_bug)
132 {
133 assert_scores(0x0101201, "ClassLoadingImpl.c", "clload", 0);
134 assert_scores(0x0100800, "play", "pla", 0);
135 }
136 END_TEST
137
138 static
setup(void)139 void setup(void)
140 {
141 qry.right_match = 0;
142 }
143
scorer_suite(void)144 Suite *scorer_suite (void)
145 {
146 Suite *s = suite_create ("Scorer");
147
148 #define T(name) \
149 do { \
150 TCase *tc = tcase_create(#name); \
151 tcase_add_test(tc, name); \
152 tcase_add_checked_fixture(tc, setup, 0); \
153 suite_add_tcase(s, tc); \
154 } while (0)
155
156 T(test_char_after_delimiter_handling);
157 T(test_capital_pattern_chars_work);
158 T(test_single_char_matches_work);
159 T(test_slash_handling);
160 T(test_right_match);
161 T(test_empty_string);
162 T(test_scorer_optimization_bug);
163
164 return s;
165 #undef T
166 }
167
main(void)168 int main(void)
169 {
170 int number_failed;
171 Suite *s = scorer_suite();
172 SRunner *sr = srunner_create(s);
173
174 prepare_scorer();
175
176 srunner_run_all(sr, CK_NORMAL);
177
178 number_failed = srunner_ntests_failed(sr);
179 srunner_free (sr);
180
181 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
182 }
183