Browse code

Move test suites into separate files

John Hawthorn authored on 05/04/2017 05:52:53
Showing 5 changed files

... ...
@@ -14,7 +14,7 @@ INSTALL_DATA=${INSTALL} -m 644
14 14
 LIBS=-lpthread
15 15
 OBJECTS=src/fzy.o src/match.o src/tty.o src/choices.o src/options.o src/tty_interface.o
16 16
 THEFTDEPS = deps/theft/theft.o deps/theft/theft_bloom.o deps/theft/theft_mt.o deps/theft/theft_hash.o
17
-TESTOBJECTS=test/fzytest.c test/test_properties.c src/match.o src/choices.o src/options.o $(THEFTDEPS)
17
+TESTOBJECTS=test/fzytest.c test/test_properties.c test/test_choices.c test/test_match.c src/match.o src/choices.o src/options.o $(THEFTDEPS)
18 18
 
19 19
 all: fzy
20 20
 
... ...
@@ -1,353 +1,17 @@
1
-#define _GNU_SOURCE
2
-#include <stdlib.h>
3
-#include <signal.h>
4
-#include <stdio.h>
5
-#include <string.h>
6
-
7
-#include "../config.h"
8
-#include "match.h"
9
-#include "choices.h"
10
-#include "options.h"
11
-
12 1
 #include "greatest/greatest.h"
13 2
 
14
-static options_t default_options;
15
-
16
-TEST test_match() {
17
-	ASSERT(has_match("a", "a"));
18
-	ASSERT(has_match("a", "ab"));
19
-	ASSERT(has_match("a", "ba"));
20
-	ASSERT(has_match("abc", "a|b|c"));
21
-
22
-	/* non-match */
23
-	ASSERT(!has_match("a", ""));
24
-	ASSERT(!has_match("a", "b"));
25
-	ASSERT(!has_match("ass", "tags"));
26
-
27
-	/* match when query is empty */
28
-	ASSERT(has_match("", ""));
29
-	ASSERT(has_match("", "a"));
30
-
31
-	PASS();
32
-}
33
-
34
-TEST test_relative_scores() {
35
-	/* App/Models/Order is better than App/MOdels/zRder  */
36
-	ASSERT(match("amor", "app/models/order") > match("amor", "app/models/zrder"));
37
-
38
-	/* App/MOdels/foo is better than App/M/fOo  */
39
-	ASSERT(match("amo", "app/m/foo") < match("amo", "app/models/foo"));
40
-
41
-	/* GEMFIle.Lock < GEMFILe  */
42
-	ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
43
-
44
-	/* GEMFIle.Lock < GEMFILe  */
45
-	ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
46
-
47
-	/* Prefer shorter matches */
48
-	ASSERT(match("abce", "abcdef") > match("abce", "abc de"));
49
-
50
-	/* Prefer shorter candidates */
51
-	ASSERT(match("test", "tests") > match("test", "testing"));
52
-
53
-	/* Scores first letter highly */
54
-	ASSERT(match("test", "testing") > match("test", "/testing"));
55
-
56
-	/* Prefer shorter matches */
57
-	ASSERT(match("abc", "    a b c ") > match("abc", " a  b  c "));
58
-	ASSERT(match("abc", " a b c    ") > match("abc", " a  b  c "));
59
-
60
-	PASS();
61
-}
62
-
63
-TEST test_exact_scores() {
64
-	/* Exact match is SCORE_MAX */
65
-	ASSERT_EQ(SCORE_MAX, match("abc", "abc"));
66
-	ASSERT_EQ(SCORE_MAX, match("aBc", "abC"));
67
-
68
-	/* Empty query always results in SCORE_MIN */
69
-	ASSERT_EQ(SCORE_MIN, match("", ""));
70
-	ASSERT_EQ(SCORE_MIN, match("", "a"));
71
-	ASSERT_EQ(SCORE_MIN, match("", "bb"));
72
-
73
-	/* Gaps */
74
-	ASSERT_EQ(SCORE_GAP_LEADING, match("a", "*a"));
75
-	ASSERT_EQ(SCORE_GAP_LEADING*2, match("a", "*ba"));
76
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING, match("a", "**a*"));
77
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING*2, match("a", "**a**"));
78
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CONSECUTIVE + SCORE_GAP_TRAILING*2, match("aa", "**aa**"));
79
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_GAP_TRAILING + SCORE_GAP_TRAILING, match("aa", "**a*a**"));
80
-
81
-	/* Consecutive */
82
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE, match("aa", "*aa"));
83
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE*2, match("aaa", "*aaa"));
84
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_CONSECUTIVE, match("aaa", "*a*aa"));
85
-
86
-	/* Slash */
87
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_SLASH, match("a", "/a"));
88
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH, match("a", "*/a"));
89
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH + SCORE_MATCH_CONSECUTIVE, match("aa", "a/aa"));
90
-
91
-	/* Capital */
92
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CAPITAL, match("a", "bA"));
93
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL, match("a", "baA"));
94
-	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL + SCORE_MATCH_CONSECUTIVE, match("aa", "baAa"));
95
-
96
-	/* Dot */
97
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_DOT, match("a", ".a"));
98
-	ASSERT_EQ(SCORE_GAP_LEADING*3 + SCORE_MATCH_DOT, match("a", "*a.a"));
99
-	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_DOT, match("a", "*a.a"));
100
-
101
-	PASS();
102
-}
103
-
104
-TEST test_positions_1() {
105
-	size_t positions[3];
106
-	match_positions("amo", "app/models/foo", positions);
107
-	ASSERT_EQ(0, positions[0]);
108
-	ASSERT_EQ(4, positions[1]);
109
-	ASSERT_EQ(5, positions[2]);
110
-
111
-	PASS();
112
-}
113
-
114
-TEST test_positions_2() {
115
-	/*
116
-	 * We should prefer matching the 'o' in order, since it's the beginning
117
-	 * of a word.
118
-	 */
119
-	size_t positions[4];
120
-	match_positions("amor", "app/models/order", positions);
121
-	ASSERT_EQ(0, positions[0]);
122
-	ASSERT_EQ(4, positions[1]);
123
-	ASSERT_EQ(11, positions[2]);
124
-
125
-	PASS();
126
-}
127
-
128
-TEST test_positions_3() {
129
-	size_t positions[2];
130
-	match_positions("as", "tags", positions);
131
-	ASSERT_EQ(1, positions[0]);
132
-	ASSERT_EQ(3, positions[1]);
133
-
134
-	PASS();
135
-}
136
-
137
-TEST test_positions_4() {
138
-	size_t positions[2];
139
-	match_positions("as", "examples.txt", positions);
140
-	ASSERT_EQ(2, positions[0]);
141
-	ASSERT_EQ(7, positions[1]);
142
-
143
-	PASS();
144
-}
145
-
146
-TEST test_positions_5() {
147
-	size_t positions[3];
148
-	match_positions("abc", "a/a/b/c/c", positions);
149
-	ASSERT_EQ(2, positions[0]);
150
-	ASSERT_EQ(4, positions[1]);
151
-	ASSERT_EQ(6, positions[2]);
152
-
153
-	PASS();
154
-}
155
-
156
-TEST test_positions_exact() {
157
-	size_t positions[3];
158
-	match_positions("foo", "foo", positions);
159
-	ASSERT_EQ(0, positions[0]);
160
-	ASSERT_EQ(1, positions[1]);
161
-	ASSERT_EQ(2, positions[2]);
162
-
163
-	PASS();
164
-}
165
-
166
-TEST test_choices_empty() {
167
-	choices_t choices;
168
-	choices_init(&choices, &default_options);
169
-	ASSERT_EQ(0, choices.size);
170
-	ASSERT_EQ(0, choices.available);
171
-	ASSERT_EQ(0, choices.selection);
172
-
173
-	choices_prev(&choices);
174
-	ASSERT_EQ(0, choices.selection);
175
-
176
-	choices_next(&choices);
177
-	ASSERT_EQ(0, choices.selection);
178
-
179
-	choices_destroy(&choices);
180
-
181
-	PASS();
182
-}
183
-
184
-TEST test_choices_1() {
185
-	choices_t choices;
186
-	choices_init(&choices, &default_options);
187
-	choices_add(&choices, "tags");
188
-
189
-	choices_search(&choices, "");
190
-	ASSERT_EQ(1, choices.available);
191
-	ASSERT_EQ(0, choices.selection);
192
-
193
-	choices_search(&choices, "t");
194
-	ASSERT_EQ(1, choices.available);
195
-	ASSERT_EQ(0, choices.selection);
196
-
197
-	choices_prev(&choices);
198
-	ASSERT_EQ(0, choices.selection);
199
-
200
-	choices_next(&choices);
201
-	ASSERT_EQ(0, choices.selection);
202
-
203
-	ASSERT(!strcmp(choices_get(&choices, 0), "tags"));
204
-	ASSERT_EQ(NULL, choices_get(&choices, 1));
205
-
206
-	choices_destroy(&choices);
207
-
208
-	PASS();
209
-}
210
-
211
-TEST test_choices_2() {
212
-	choices_t choices;
213
-	choices_init(&choices, &default_options);
214
-	choices_add(&choices, "tags");
215
-	choices_add(&choices, "test");
216
-
217
-	/* Empty search */
218
-	choices_search(&choices, "");
219
-	ASSERT_EQ(0, choices.selection);
220
-	ASSERT_EQ(2, choices.available);
221
-
222
-	choices_next(&choices);
223
-	ASSERT_EQ(1, choices.selection);
224
-	choices_next(&choices);
225
-	ASSERT_EQ(0, choices.selection);
226
-
227
-	choices_prev(&choices);
228
-	ASSERT_EQ(1, choices.selection);
229
-	choices_prev(&choices);
230
-	ASSERT_EQ(0, choices.selection);
231
-
232
-	/* Filtered search */
233
-	choices_search(&choices, "te");
234
-	ASSERT_EQ(1, choices.available);
235
-	ASSERT_EQ(0, choices.selection);
236
-	ASSERT_STR_EQ("test", choices_get(&choices, 0));
237
-
238
-	choices_next(&choices);
239
-	ASSERT_EQ(0, choices.selection);
240
-
241
-	choices_prev(&choices);
242
-	ASSERT_EQ(0, choices.selection);
243
-
244
-	/* No results */
245
-	choices_search(&choices, "foobar");
246
-	ASSERT_EQ(0, choices.available);
247
-	ASSERT_EQ(0, choices.selection);
248
-
249
-	/* Different order due to scoring */
250
-	choices_search(&choices, "ts");
251
-	ASSERT_EQ(2, choices.available);
252
-	ASSERT_EQ(0, choices.selection);
253
-	ASSERT_STR_EQ("test", choices_get(&choices, 0));
254
-	ASSERT_STR_EQ("tags", choices_get(&choices, 1));
255
-
256
-	choices_destroy(&choices);
257
-
258
-	PASS();
259
-}
260
-
261
-TEST test_choices_without_search() {
262
-	/* Before a search is run, it should return no results */
263
-
264
-	choices_t choices;
265
-	choices_init(&choices, &default_options);
266
-
267
-	ASSERT_EQ(0, choices.available);
268
-	ASSERT_EQ(0, choices.selection);
269
-	ASSERT_EQ(0, choices.size);
270
-	ASSERT_EQ(NULL, choices_get(&choices, 0));
271
-
272
-	choices_add(&choices, "test");
273
-
274
-	ASSERT_EQ(0, choices.available);
275
-	ASSERT_EQ(0, choices.selection);
276
-	ASSERT_EQ(1, choices.size);
277
-	ASSERT_EQ(NULL, choices_get(&choices, 0));
278
-
279
-	choices_destroy(&choices);
280
-
281
-	PASS();
282
-}
283
-
284
-/* Regression test for segfault */
285
-TEST test_choices_unicode() {
286
-	choices_t choices;
287
-	choices_init(&choices, &default_options);
288
-
289
-	choices_add(&choices, "Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf");
290
-	choices_search(&choices, "e");
291
-
292
-	choices_destroy(&choices);
293
-	PASS();
294
-}
295
-
296
-TEST test_choices_large_input() {
297
-	choices_t choices;
298
-	choices_init(&choices, &default_options);
299
-
300
-	int N = 100000;
301
-	char *strings[N];
302
-
303
-	for(int i = 0; i < N; i++) {
304
-		asprintf(&strings[i], "%i", i);
305
-		choices_add(&choices, strings[i]);
306
-	}
307
-
308
-	choices_search(&choices, "12");
309
-
310
-	/* Must match `seq 0 99999 | grep '.*1.*2.*' | wc -l` */
311
-	ASSERT_EQ(8146, choices.available);
312
-
313
-	ASSERT_STR_EQ("12", choices_get(&choices, 0));
314
-
315
-	for(int i = 0; i < N; i++) {
316
-		free(strings[i]);
317
-	}
318
-
319
-	choices_destroy(&choices);
320
-
321
-	PASS();
322
-}
323
-
324
-SUITE(properties);
3
+SUITE(match_suite);
4
+SUITE(choices_suite);
5
+SUITE(properties_suite);
325 6
 
326 7
 GREATEST_MAIN_DEFS();
327 8
 
328 9
 int main(int argc, char *argv[]) {
329 10
 	GREATEST_MAIN_BEGIN();
330 11
 
331
-	options_init(&default_options);
332
-
333
-	RUN_TEST(test_match);
334
-	RUN_TEST(test_relative_scores);
335
-	RUN_TEST(test_exact_scores);
336
-	RUN_TEST(test_positions_1);
337
-	RUN_TEST(test_positions_2);
338
-	RUN_TEST(test_positions_3);
339
-	RUN_TEST(test_positions_4);
340
-	RUN_TEST(test_positions_5);
341
-	RUN_TEST(test_positions_exact);
342
-
343
-	RUN_TEST(test_choices_empty);
344
-	RUN_TEST(test_choices_1);
345
-	RUN_TEST(test_choices_2);
346
-	RUN_TEST(test_choices_without_search);
347
-	RUN_TEST(test_choices_unicode);
348
-	RUN_TEST(test_choices_large_input);
349
-
350
-	RUN_SUITE(properties);
12
+	RUN_SUITE(match_suite);
13
+	RUN_SUITE(choices_suite);
14
+	RUN_SUITE(properties_suite);
351 15
 
352 16
 	GREATEST_MAIN_END();
353 17
 }
354 18
new file mode 100644
... ...
@@ -0,0 +1,180 @@
1
+#define _GNU_SOURCE
2
+#include <stdlib.h>
3
+#include <string.h>
4
+
5
+#include "../config.h"
6
+#include "options.h"
7
+#include "choices.h"
8
+
9
+#include "greatest/greatest.h"
10
+
11
+static options_t default_options;
12
+
13
+TEST test_choices_empty() {
14
+	choices_t choices;
15
+	choices_init(&choices, &default_options);
16
+	ASSERT_EQ(0, choices.size);
17
+	ASSERT_EQ(0, choices.available);
18
+	ASSERT_EQ(0, choices.selection);
19
+
20
+	choices_prev(&choices);
21
+	ASSERT_EQ(0, choices.selection);
22
+
23
+	choices_next(&choices);
24
+	ASSERT_EQ(0, choices.selection);
25
+
26
+	choices_destroy(&choices);
27
+
28
+	PASS();
29
+}
30
+
31
+TEST test_choices_1() {
32
+	choices_t choices;
33
+	choices_init(&choices, &default_options);
34
+	choices_add(&choices, "tags");
35
+
36
+	choices_search(&choices, "");
37
+	ASSERT_EQ(1, choices.available);
38
+	ASSERT_EQ(0, choices.selection);
39
+
40
+	choices_search(&choices, "t");
41
+	ASSERT_EQ(1, choices.available);
42
+	ASSERT_EQ(0, choices.selection);
43
+
44
+	choices_prev(&choices);
45
+	ASSERT_EQ(0, choices.selection);
46
+
47
+	choices_next(&choices);
48
+	ASSERT_EQ(0, choices.selection);
49
+
50
+	ASSERT(!strcmp(choices_get(&choices, 0), "tags"));
51
+	ASSERT_EQ(NULL, choices_get(&choices, 1));
52
+
53
+	choices_destroy(&choices);
54
+
55
+	PASS();
56
+}
57
+
58
+TEST test_choices_2() {
59
+	choices_t choices;
60
+	choices_init(&choices, &default_options);
61
+	choices_add(&choices, "tags");
62
+	choices_add(&choices, "test");
63
+
64
+	/* Empty search */
65
+	choices_search(&choices, "");
66
+	ASSERT_EQ(0, choices.selection);
67
+	ASSERT_EQ(2, choices.available);
68
+
69
+	choices_next(&choices);
70
+	ASSERT_EQ(1, choices.selection);
71
+	choices_next(&choices);
72
+	ASSERT_EQ(0, choices.selection);
73
+
74
+	choices_prev(&choices);
75
+	ASSERT_EQ(1, choices.selection);
76
+	choices_prev(&choices);
77
+	ASSERT_EQ(0, choices.selection);
78
+
79
+	/* Filtered search */
80
+	choices_search(&choices, "te");
81
+	ASSERT_EQ(1, choices.available);
82
+	ASSERT_EQ(0, choices.selection);
83
+	ASSERT_STR_EQ("test", choices_get(&choices, 0));
84
+
85
+	choices_next(&choices);
86
+	ASSERT_EQ(0, choices.selection);
87
+
88
+	choices_prev(&choices);
89
+	ASSERT_EQ(0, choices.selection);
90
+
91
+	/* No results */
92
+	choices_search(&choices, "foobar");
93
+	ASSERT_EQ(0, choices.available);
94
+	ASSERT_EQ(0, choices.selection);
95
+
96
+	/* Different order due to scoring */
97
+	choices_search(&choices, "ts");
98
+	ASSERT_EQ(2, choices.available);
99
+	ASSERT_EQ(0, choices.selection);
100
+	ASSERT_STR_EQ("test", choices_get(&choices, 0));
101
+	ASSERT_STR_EQ("tags", choices_get(&choices, 1));
102
+
103
+	choices_destroy(&choices);
104
+
105
+	PASS();
106
+}
107
+
108
+TEST test_choices_without_search() {
109
+	/* Before a search is run, it should return no results */
110
+
111
+	choices_t choices;
112
+	choices_init(&choices, &default_options);
113
+
114
+	ASSERT_EQ(0, choices.available);
115
+	ASSERT_EQ(0, choices.selection);
116
+	ASSERT_EQ(0, choices.size);
117
+	ASSERT_EQ(NULL, choices_get(&choices, 0));
118
+
119
+	choices_add(&choices, "test");
120
+
121
+	ASSERT_EQ(0, choices.available);
122
+	ASSERT_EQ(0, choices.selection);
123
+	ASSERT_EQ(1, choices.size);
124
+	ASSERT_EQ(NULL, choices_get(&choices, 0));
125
+
126
+	choices_destroy(&choices);
127
+
128
+	PASS();
129
+}
130
+
131
+/* Regression test for segfault */
132
+TEST test_choices_unicode() {
133
+	choices_t choices;
134
+	choices_init(&choices, &default_options);
135
+
136
+	choices_add(&choices, "Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf");
137
+	choices_search(&choices, "e");
138
+
139
+	choices_destroy(&choices);
140
+	PASS();
141
+}
142
+
143
+TEST test_choices_large_input() {
144
+	choices_t choices;
145
+	choices_init(&choices, &default_options);
146
+
147
+	int N = 100000;
148
+	char *strings[N];
149
+
150
+	for(int i = 0; i < N; i++) {
151
+		asprintf(&strings[i], "%i", i);
152
+		choices_add(&choices, strings[i]);
153
+	}
154
+
155
+	choices_search(&choices, "12");
156
+
157
+	/* Must match `seq 0 99999 | grep '.*1.*2.*' | wc -l` */
158
+	ASSERT_EQ(8146, choices.available);
159
+
160
+	ASSERT_STR_EQ("12", choices_get(&choices, 0));
161
+
162
+	for(int i = 0; i < N; i++) {
163
+		free(strings[i]);
164
+	}
165
+
166
+	choices_destroy(&choices);
167
+
168
+	PASS();
169
+}
170
+
171
+SUITE(choices_suite) {
172
+	options_init(&default_options);
173
+
174
+	RUN_TEST(test_choices_empty);
175
+	RUN_TEST(test_choices_1);
176
+	RUN_TEST(test_choices_2);
177
+	RUN_TEST(test_choices_without_search);
178
+	RUN_TEST(test_choices_unicode);
179
+	RUN_TEST(test_choices_large_input);
180
+}
0 181
new file mode 100644
... ...
@@ -0,0 +1,168 @@
1
+#include <stdlib.h>
2
+
3
+#include "../config.h"
4
+#include "match.h"
5
+
6
+#include "greatest/greatest.h"
7
+
8
+TEST test_match() {
9
+	ASSERT(has_match("a", "a"));
10
+	ASSERT(has_match("a", "ab"));
11
+	ASSERT(has_match("a", "ba"));
12
+	ASSERT(has_match("abc", "a|b|c"));
13
+
14
+	/* non-match */
15
+	ASSERT(!has_match("a", ""));
16
+	ASSERT(!has_match("a", "b"));
17
+	ASSERT(!has_match("ass", "tags"));
18
+
19
+	/* match when query is empty */
20
+	ASSERT(has_match("", ""));
21
+	ASSERT(has_match("", "a"));
22
+
23
+	PASS();
24
+}
25
+
26
+TEST test_relative_scores() {
27
+	/* App/Models/Order is better than App/MOdels/zRder  */
28
+	ASSERT(match("amor", "app/models/order") > match("amor", "app/models/zrder"));
29
+
30
+	/* App/MOdels/foo is better than App/M/fOo  */
31
+	ASSERT(match("amo", "app/m/foo") < match("amo", "app/models/foo"));
32
+
33
+	/* GEMFIle.Lock < GEMFILe  */
34
+	ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
35
+
36
+	/* GEMFIle.Lock < GEMFILe  */
37
+	ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
38
+
39
+	/* Prefer shorter matches */
40
+	ASSERT(match("abce", "abcdef") > match("abce", "abc de"));
41
+
42
+	/* Prefer shorter candidates */
43
+	ASSERT(match("test", "tests") > match("test", "testing"));
44
+
45
+	/* Scores first letter highly */
46
+	ASSERT(match("test", "testing") > match("test", "/testing"));
47
+
48
+	/* Prefer shorter matches */
49
+	ASSERT(match("abc", "    a b c ") > match("abc", " a  b  c "));
50
+	ASSERT(match("abc", " a b c    ") > match("abc", " a  b  c "));
51
+
52
+	PASS();
53
+}
54
+
55
+TEST test_exact_scores() {
56
+	/* Exact match is SCORE_MAX */
57
+	ASSERT_EQ(SCORE_MAX, match("abc", "abc"));
58
+	ASSERT_EQ(SCORE_MAX, match("aBc", "abC"));
59
+
60
+	/* Empty query always results in SCORE_MIN */
61
+	ASSERT_EQ(SCORE_MIN, match("", ""));
62
+	ASSERT_EQ(SCORE_MIN, match("", "a"));
63
+	ASSERT_EQ(SCORE_MIN, match("", "bb"));
64
+
65
+	/* Gaps */
66
+	ASSERT_EQ(SCORE_GAP_LEADING, match("a", "*a"));
67
+	ASSERT_EQ(SCORE_GAP_LEADING*2, match("a", "*ba"));
68
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING, match("a", "**a*"));
69
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING*2, match("a", "**a**"));
70
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CONSECUTIVE + SCORE_GAP_TRAILING*2, match("aa", "**aa**"));
71
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_GAP_TRAILING + SCORE_GAP_TRAILING, match("aa", "**a*a**"));
72
+
73
+	/* Consecutive */
74
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE, match("aa", "*aa"));
75
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE*2, match("aaa", "*aaa"));
76
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_CONSECUTIVE, match("aaa", "*a*aa"));
77
+
78
+	/* Slash */
79
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_SLASH, match("a", "/a"));
80
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH, match("a", "*/a"));
81
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH + SCORE_MATCH_CONSECUTIVE, match("aa", "a/aa"));
82
+
83
+	/* Capital */
84
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CAPITAL, match("a", "bA"));
85
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL, match("a", "baA"));
86
+	ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL + SCORE_MATCH_CONSECUTIVE, match("aa", "baAa"));
87
+
88
+	/* Dot */
89
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_DOT, match("a", ".a"));
90
+	ASSERT_EQ(SCORE_GAP_LEADING*3 + SCORE_MATCH_DOT, match("a", "*a.a"));
91
+	ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_DOT, match("a", "*a.a"));
92
+
93
+	PASS();
94
+}
95
+
96
+TEST test_positions_1() {
97
+	size_t positions[3];
98
+	match_positions("amo", "app/models/foo", positions);
99
+	ASSERT_EQ(0, positions[0]);
100
+	ASSERT_EQ(4, positions[1]);
101
+	ASSERT_EQ(5, positions[2]);
102
+
103
+	PASS();
104
+}
105
+
106
+TEST test_positions_2() {
107
+	/*
108
+	 * We should prefer matching the 'o' in order, since it's the beginning
109
+	 * of a word.
110
+	 */
111
+	size_t positions[4];
112
+	match_positions("amor", "app/models/order", positions);
113
+	ASSERT_EQ(0, positions[0]);
114
+	ASSERT_EQ(4, positions[1]);
115
+	ASSERT_EQ(11, positions[2]);
116
+
117
+	PASS();
118
+}
119
+
120
+TEST test_positions_3() {
121
+	size_t positions[2];
122
+	match_positions("as", "tags", positions);
123
+	ASSERT_EQ(1, positions[0]);
124
+	ASSERT_EQ(3, positions[1]);
125
+
126
+	PASS();
127
+}
128
+
129
+TEST test_positions_4() {
130
+	size_t positions[2];
131
+	match_positions("as", "examples.txt", positions);
132
+	ASSERT_EQ(2, positions[0]);
133
+	ASSERT_EQ(7, positions[1]);
134
+
135
+	PASS();
136
+}
137
+
138
+TEST test_positions_5() {
139
+	size_t positions[3];
140
+	match_positions("abc", "a/a/b/c/c", positions);
141
+	ASSERT_EQ(2, positions[0]);
142
+	ASSERT_EQ(4, positions[1]);
143
+	ASSERT_EQ(6, positions[2]);
144
+
145
+	PASS();
146
+}
147
+
148
+TEST test_positions_exact() {
149
+	size_t positions[3];
150
+	match_positions("foo", "foo", positions);
151
+	ASSERT_EQ(0, positions[0]);
152
+	ASSERT_EQ(1, positions[1]);
153
+	ASSERT_EQ(2, positions[2]);
154
+
155
+	PASS();
156
+}
157
+
158
+SUITE(match_suite) {
159
+	RUN_TEST(test_match);
160
+	RUN_TEST(test_relative_scores);
161
+	RUN_TEST(test_exact_scores);
162
+	RUN_TEST(test_positions_1);
163
+	RUN_TEST(test_positions_2);
164
+	RUN_TEST(test_positions_3);
165
+	RUN_TEST(test_positions_4);
166
+	RUN_TEST(test_positions_5);
167
+	RUN_TEST(test_positions_exact);
168
+}
... ...
@@ -53,13 +53,14 @@ static void string_print_cb(FILE *f, void *instance, void *env) {
53 53
 }
54 54
 
55 55
 static uint64_t string_hash_cb(void *instance, void *env) {
56
+	(void)env;
56 57
 	char *str = (char *)instance;
57 58
 	int size = strlen(str);
58
-	(void)env;
59
-	return theft_hash_onepass(str, size);
59
+	return theft_hash_onepass((uint8_t *)str, size);
60 60
 }
61 61
 
62 62
 static void *string_shrink_cb(void *instance, uint32_t tactic, void *env) {
63
+	(void)env;
63 64
 	char *str = (char *)instance;
64 65
 	int n = strlen(str);
65 66
 
... ...
@@ -157,7 +158,7 @@ TEST positions_should_match_characters_in_string() {
157 158
 	PASS();
158 159
 }
159 160
 
160
-SUITE(properties) {
161
+SUITE(properties_suite) {
161 162
 	RUN_TEST(should_return_results_if_there_is_a_match);
162 163
 	RUN_TEST(positions_should_match_characters_in_string);
163 164
 }