summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--test/fzytest.c348
-rw-r--r--test/test_choices.c180
-rw-r--r--test/test_match.c168
-rw-r--r--test/test_properties.c7
5 files changed, 359 insertions, 346 deletions
diff --git a/Makefile b/Makefile
index 24b7b29..f3afc81 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ INSTALL_DATA=${INSTALL} -m 644
LIBS=-lpthread
OBJECTS=src/fzy.o src/match.o src/tty.o src/choices.o src/options.o src/tty_interface.o
THEFTDEPS = deps/theft/theft.o deps/theft/theft_bloom.o deps/theft/theft_mt.o deps/theft/theft_hash.o
-TESTOBJECTS=test/fzytest.c test/test_properties.c src/match.o src/choices.o src/options.o $(THEFTDEPS)
+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)
all: fzy
diff --git a/test/fzytest.c b/test/fzytest.c
index 01bcacf..097a4ae 100644
--- a/test/fzytest.c
+++ b/test/fzytest.c
@@ -1,353 +1,17 @@
-#define _GNU_SOURCE
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../config.h"
-#include "match.h"
-#include "choices.h"
-#include "options.h"
-
#include "greatest/greatest.h"
-static options_t default_options;
-
-TEST test_match() {
- ASSERT(has_match("a", "a"));
- ASSERT(has_match("a", "ab"));
- ASSERT(has_match("a", "ba"));
- ASSERT(has_match("abc", "a|b|c"));
-
- /* non-match */
- ASSERT(!has_match("a", ""));
- ASSERT(!has_match("a", "b"));
- ASSERT(!has_match("ass", "tags"));
-
- /* match when query is empty */
- ASSERT(has_match("", ""));
- ASSERT(has_match("", "a"));
-
- PASS();
-}
-
-TEST test_relative_scores() {
- /* App/Models/Order is better than App/MOdels/zRder */
- ASSERT(match("amor", "app/models/order") > match("amor", "app/models/zrder"));
-
- /* App/MOdels/foo is better than App/M/fOo */
- ASSERT(match("amo", "app/m/foo") < match("amo", "app/models/foo"));
-
- /* GEMFIle.Lock < GEMFILe */
- ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
-
- /* GEMFIle.Lock < GEMFILe */
- ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
-
- /* Prefer shorter matches */
- ASSERT(match("abce", "abcdef") > match("abce", "abc de"));
-
- /* Prefer shorter candidates */
- ASSERT(match("test", "tests") > match("test", "testing"));
-
- /* Scores first letter highly */
- ASSERT(match("test", "testing") > match("test", "/testing"));
-
- /* Prefer shorter matches */
- ASSERT(match("abc", " a b c ") > match("abc", " a b c "));
- ASSERT(match("abc", " a b c ") > match("abc", " a b c "));
-
- PASS();
-}
-
-TEST test_exact_scores() {
- /* Exact match is SCORE_MAX */
- ASSERT_EQ(SCORE_MAX, match("abc", "abc"));
- ASSERT_EQ(SCORE_MAX, match("aBc", "abC"));
-
- /* Empty query always results in SCORE_MIN */
- ASSERT_EQ(SCORE_MIN, match("", ""));
- ASSERT_EQ(SCORE_MIN, match("", "a"));
- ASSERT_EQ(SCORE_MIN, match("", "bb"));
-
- /* Gaps */
- ASSERT_EQ(SCORE_GAP_LEADING, match("a", "*a"));
- ASSERT_EQ(SCORE_GAP_LEADING*2, match("a", "*ba"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING, match("a", "**a*"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING*2, match("a", "**a**"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CONSECUTIVE + SCORE_GAP_TRAILING*2, match("aa", "**aa**"));
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_GAP_TRAILING + SCORE_GAP_TRAILING, match("aa", "**a*a**"));
-
- /* Consecutive */
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE, match("aa", "*aa"));
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE*2, match("aaa", "*aaa"));
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_CONSECUTIVE, match("aaa", "*a*aa"));
-
- /* Slash */
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_SLASH, match("a", "/a"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH, match("a", "*/a"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH + SCORE_MATCH_CONSECUTIVE, match("aa", "a/aa"));
-
- /* Capital */
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CAPITAL, match("a", "bA"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL, match("a", "baA"));
- ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL + SCORE_MATCH_CONSECUTIVE, match("aa", "baAa"));
-
- /* Dot */
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_DOT, match("a", ".a"));
- ASSERT_EQ(SCORE_GAP_LEADING*3 + SCORE_MATCH_DOT, match("a", "*a.a"));
- ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_DOT, match("a", "*a.a"));
-
- PASS();
-}
-
-TEST test_positions_1() {
- size_t positions[3];
- match_positions("amo", "app/models/foo", positions);
- ASSERT_EQ(0, positions[0]);
- ASSERT_EQ(4, positions[1]);
- ASSERT_EQ(5, positions[2]);
-
- PASS();
-}
-
-TEST test_positions_2() {
- /*
- * We should prefer matching the 'o' in order, since it's the beginning
- * of a word.
- */
- size_t positions[4];
- match_positions("amor", "app/models/order", positions);
- ASSERT_EQ(0, positions[0]);
- ASSERT_EQ(4, positions[1]);
- ASSERT_EQ(11, positions[2]);
-
- PASS();
-}
-
-TEST test_positions_3() {
- size_t positions[2];
- match_positions("as", "tags", positions);
- ASSERT_EQ(1, positions[0]);
- ASSERT_EQ(3, positions[1]);
-
- PASS();
-}
-
-TEST test_positions_4() {
- size_t positions[2];
- match_positions("as", "examples.txt", positions);
- ASSERT_EQ(2, positions[0]);
- ASSERT_EQ(7, positions[1]);
-
- PASS();
-}
-
-TEST test_positions_5() {
- size_t positions[3];
- match_positions("abc", "a/a/b/c/c", positions);
- ASSERT_EQ(2, positions[0]);
- ASSERT_EQ(4, positions[1]);
- ASSERT_EQ(6, positions[2]);
-
- PASS();
-}
-
-TEST test_positions_exact() {
- size_t positions[3];
- match_positions("foo", "foo", positions);
- ASSERT_EQ(0, positions[0]);
- ASSERT_EQ(1, positions[1]);
- ASSERT_EQ(2, positions[2]);
-
- PASS();
-}
-
-TEST test_choices_empty() {
- choices_t choices;
- choices_init(&choices, &default_options);
- ASSERT_EQ(0, choices.size);
- ASSERT_EQ(0, choices.available);
- ASSERT_EQ(0, choices.selection);
-
- choices_prev(&choices);
- ASSERT_EQ(0, choices.selection);
-
- choices_next(&choices);
- ASSERT_EQ(0, choices.selection);
-
- choices_destroy(&choices);
-
- PASS();
-}
-
-TEST test_choices_1() {
- choices_t choices;
- choices_init(&choices, &default_options);
- choices_add(&choices, "tags");
-
- choices_search(&choices, "");
- ASSERT_EQ(1, choices.available);
- ASSERT_EQ(0, choices.selection);
-
- choices_search(&choices, "t");
- ASSERT_EQ(1, choices.available);
- ASSERT_EQ(0, choices.selection);
-
- choices_prev(&choices);
- ASSERT_EQ(0, choices.selection);
-
- choices_next(&choices);
- ASSERT_EQ(0, choices.selection);
-
- ASSERT(!strcmp(choices_get(&choices, 0), "tags"));
- ASSERT_EQ(NULL, choices_get(&choices, 1));
-
- choices_destroy(&choices);
-
- PASS();
-}
-
-TEST test_choices_2() {
- choices_t choices;
- choices_init(&choices, &default_options);
- choices_add(&choices, "tags");
- choices_add(&choices, "test");
-
- /* Empty search */
- choices_search(&choices, "");
- ASSERT_EQ(0, choices.selection);
- ASSERT_EQ(2, choices.available);
-
- choices_next(&choices);
- ASSERT_EQ(1, choices.selection);
- choices_next(&choices);
- ASSERT_EQ(0, choices.selection);
-
- choices_prev(&choices);
- ASSERT_EQ(1, choices.selection);
- choices_prev(&choices);
- ASSERT_EQ(0, choices.selection);
-
- /* Filtered search */
- choices_search(&choices, "te");
- ASSERT_EQ(1, choices.available);
- ASSERT_EQ(0, choices.selection);
- ASSERT_STR_EQ("test", choices_get(&choices, 0));
-
- choices_next(&choices);
- ASSERT_EQ(0, choices.selection);
-
- choices_prev(&choices);
- ASSERT_EQ(0, choices.selection);
-
- /* No results */
- choices_search(&choices, "foobar");
- ASSERT_EQ(0, choices.available);
- ASSERT_EQ(0, choices.selection);
-
- /* Different order due to scoring */
- choices_search(&choices, "ts");
- ASSERT_EQ(2, choices.available);
- ASSERT_EQ(0, choices.selection);
- ASSERT_STR_EQ("test", choices_get(&choices, 0));
- ASSERT_STR_EQ("tags", choices_get(&choices, 1));
-
- choices_destroy(&choices);
-
- PASS();
-}
-
-TEST test_choices_without_search() {
- /* Before a search is run, it should return no results */
-
- choices_t choices;
- choices_init(&choices, &default_options);
-
- ASSERT_EQ(0, choices.available);
- ASSERT_EQ(0, choices.selection);
- ASSERT_EQ(0, choices.size);
- ASSERT_EQ(NULL, choices_get(&choices, 0));
-
- choices_add(&choices, "test");
-
- ASSERT_EQ(0, choices.available);
- ASSERT_EQ(0, choices.selection);
- ASSERT_EQ(1, choices.size);
- ASSERT_EQ(NULL, choices_get(&choices, 0));
-
- choices_destroy(&choices);
-
- PASS();
-}
-
-/* Regression test for segfault */
-TEST test_choices_unicode() {
- choices_t choices;
- choices_init(&choices, &default_options);
-
- choices_add(&choices, "Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf");
- choices_search(&choices, "e");
-
- choices_destroy(&choices);
- PASS();
-}
-
-TEST test_choices_large_input() {
- choices_t choices;
- choices_init(&choices, &default_options);
-
- int N = 100000;
- char *strings[N];
-
- for(int i = 0; i < N; i++) {
- asprintf(&strings[i], "%i", i);
- choices_add(&choices, strings[i]);
- }
-
- choices_search(&choices, "12");
-
- /* Must match `seq 0 99999 | grep '.*1.*2.*' | wc -l` */
- ASSERT_EQ(8146, choices.available);
-
- ASSERT_STR_EQ("12", choices_get(&choices, 0));
-
- for(int i = 0; i < N; i++) {
- free(strings[i]);
- }
-
- choices_destroy(&choices);
-
- PASS();
-}
-
-SUITE(properties);
+SUITE(match_suite);
+SUITE(choices_suite);
+SUITE(properties_suite);
GREATEST_MAIN_DEFS();
int main(int argc, char *argv[]) {
GREATEST_MAIN_BEGIN();
- options_init(&default_options);
-
- RUN_TEST(test_match);
- RUN_TEST(test_relative_scores);
- RUN_TEST(test_exact_scores);
- RUN_TEST(test_positions_1);
- RUN_TEST(test_positions_2);
- RUN_TEST(test_positions_3);
- RUN_TEST(test_positions_4);
- RUN_TEST(test_positions_5);
- RUN_TEST(test_positions_exact);
-
- RUN_TEST(test_choices_empty);
- RUN_TEST(test_choices_1);
- RUN_TEST(test_choices_2);
- RUN_TEST(test_choices_without_search);
- RUN_TEST(test_choices_unicode);
- RUN_TEST(test_choices_large_input);
-
- RUN_SUITE(properties);
+ RUN_SUITE(match_suite);
+ RUN_SUITE(choices_suite);
+ RUN_SUITE(properties_suite);
GREATEST_MAIN_END();
}
diff --git a/test/test_choices.c b/test/test_choices.c
new file mode 100644
index 0000000..c6a8d64
--- /dev/null
+++ b/test/test_choices.c
@@ -0,0 +1,180 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+
+#include "../config.h"
+#include "options.h"
+#include "choices.h"
+
+#include "greatest/greatest.h"
+
+static options_t default_options;
+
+TEST test_choices_empty() {
+ choices_t choices;
+ choices_init(&choices, &default_options);
+ ASSERT_EQ(0, choices.size);
+ ASSERT_EQ(0, choices.available);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_prev(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_next(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_destroy(&choices);
+
+ PASS();
+}
+
+TEST test_choices_1() {
+ choices_t choices;
+ choices_init(&choices, &default_options);
+ choices_add(&choices, "tags");
+
+ choices_search(&choices, "");
+ ASSERT_EQ(1, choices.available);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_search(&choices, "t");
+ ASSERT_EQ(1, choices.available);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_prev(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_next(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ ASSERT(!strcmp(choices_get(&choices, 0), "tags"));
+ ASSERT_EQ(NULL, choices_get(&choices, 1));
+
+ choices_destroy(&choices);
+
+ PASS();
+}
+
+TEST test_choices_2() {
+ choices_t choices;
+ choices_init(&choices, &default_options);
+ choices_add(&choices, "tags");
+ choices_add(&choices, "test");
+
+ /* Empty search */
+ choices_search(&choices, "");
+ ASSERT_EQ(0, choices.selection);
+ ASSERT_EQ(2, choices.available);
+
+ choices_next(&choices);
+ ASSERT_EQ(1, choices.selection);
+ choices_next(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_prev(&choices);
+ ASSERT_EQ(1, choices.selection);
+ choices_prev(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ /* Filtered search */
+ choices_search(&choices, "te");
+ ASSERT_EQ(1, choices.available);
+ ASSERT_EQ(0, choices.selection);
+ ASSERT_STR_EQ("test", choices_get(&choices, 0));
+
+ choices_next(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ choices_prev(&choices);
+ ASSERT_EQ(0, choices.selection);
+
+ /* No results */
+ choices_search(&choices, "foobar");
+ ASSERT_EQ(0, choices.available);
+ ASSERT_EQ(0, choices.selection);
+
+ /* Different order due to scoring */
+ choices_search(&choices, "ts");
+ ASSERT_EQ(2, choices.available);
+ ASSERT_EQ(0, choices.selection);
+ ASSERT_STR_EQ("test", choices_get(&choices, 0));
+ ASSERT_STR_EQ("tags", choices_get(&choices, 1));
+
+ choices_destroy(&choices);
+
+ PASS();
+}
+
+TEST test_choices_without_search() {
+ /* Before a search is run, it should return no results */
+
+ choices_t choices;
+ choices_init(&choices, &default_options);
+
+ ASSERT_EQ(0, choices.available);
+ ASSERT_EQ(0, choices.selection);
+ ASSERT_EQ(0, choices.size);
+ ASSERT_EQ(NULL, choices_get(&choices, 0));
+
+ choices_add(&choices, "test");
+
+ ASSERT_EQ(0, choices.available);
+ ASSERT_EQ(0, choices.selection);
+ ASSERT_EQ(1, choices.size);
+ ASSERT_EQ(NULL, choices_get(&choices, 0));
+
+ choices_destroy(&choices);
+
+ PASS();
+}
+
+/* Regression test for segfault */
+TEST test_choices_unicode() {
+ choices_t choices;
+ choices_init(&choices, &default_options);
+
+ choices_add(&choices, "Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf");
+ choices_search(&choices, "e");
+
+ choices_destroy(&choices);
+ PASS();
+}
+
+TEST test_choices_large_input() {
+ choices_t choices;
+ choices_init(&choices, &default_options);
+
+ int N = 100000;
+ char *strings[N];
+
+ for(int i = 0; i < N; i++) {
+ asprintf(&strings[i], "%i", i);
+ choices_add(&choices, strings[i]);
+ }
+
+ choices_search(&choices, "12");
+
+ /* Must match `seq 0 99999 | grep '.*1.*2.*' | wc -l` */
+ ASSERT_EQ(8146, choices.available);
+
+ ASSERT_STR_EQ("12", choices_get(&choices, 0));
+
+ for(int i = 0; i < N; i++) {
+ free(strings[i]);
+ }
+
+ choices_destroy(&choices);
+
+ PASS();
+}
+
+SUITE(choices_suite) {
+ options_init(&default_options);
+
+ RUN_TEST(test_choices_empty);
+ RUN_TEST(test_choices_1);
+ RUN_TEST(test_choices_2);
+ RUN_TEST(test_choices_without_search);
+ RUN_TEST(test_choices_unicode);
+ RUN_TEST(test_choices_large_input);
+}
diff --git a/test/test_match.c b/test/test_match.c
new file mode 100644
index 0000000..38c1d20
--- /dev/null
+++ b/test/test_match.c
@@ -0,0 +1,168 @@
+#include <stdlib.h>
+
+#include "../config.h"
+#include "match.h"
+
+#include "greatest/greatest.h"
+
+TEST test_match() {
+ ASSERT(has_match("a", "a"));
+ ASSERT(has_match("a", "ab"));
+ ASSERT(has_match("a", "ba"));
+ ASSERT(has_match("abc", "a|b|c"));
+
+ /* non-match */
+ ASSERT(!has_match("a", ""));
+ ASSERT(!has_match("a", "b"));
+ ASSERT(!has_match("ass", "tags"));
+
+ /* match when query is empty */
+ ASSERT(has_match("", ""));
+ ASSERT(has_match("", "a"));
+
+ PASS();
+}
+
+TEST test_relative_scores() {
+ /* App/Models/Order is better than App/MOdels/zRder */
+ ASSERT(match("amor", "app/models/order") > match("amor", "app/models/zrder"));
+
+ /* App/MOdels/foo is better than App/M/fOo */
+ ASSERT(match("amo", "app/m/foo") < match("amo", "app/models/foo"));
+
+ /* GEMFIle.Lock < GEMFILe */
+ ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
+
+ /* GEMFIle.Lock < GEMFILe */
+ ASSERT(match("gemfil", "Gemfile.lock") < match("gemfil", "Gemfile"));
+
+ /* Prefer shorter matches */
+ ASSERT(match("abce", "abcdef") > match("abce", "abc de"));
+
+ /* Prefer shorter candidates */
+ ASSERT(match("test", "tests") > match("test", "testing"));
+
+ /* Scores first letter highly */
+ ASSERT(match("test", "testing") > match("test", "/testing"));
+
+ /* Prefer shorter matches */
+ ASSERT(match("abc", " a b c ") > match("abc", " a b c "));
+ ASSERT(match("abc", " a b c ") > match("abc", " a b c "));
+
+ PASS();
+}
+
+TEST test_exact_scores() {
+ /* Exact match is SCORE_MAX */
+ ASSERT_EQ(SCORE_MAX, match("abc", "abc"));
+ ASSERT_EQ(SCORE_MAX, match("aBc", "abC"));
+
+ /* Empty query always results in SCORE_MIN */
+ ASSERT_EQ(SCORE_MIN, match("", ""));
+ ASSERT_EQ(SCORE_MIN, match("", "a"));
+ ASSERT_EQ(SCORE_MIN, match("", "bb"));
+
+ /* Gaps */
+ ASSERT_EQ(SCORE_GAP_LEADING, match("a", "*a"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2, match("a", "*ba"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING, match("a", "**a*"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_GAP_TRAILING*2, match("a", "**a**"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CONSECUTIVE + SCORE_GAP_TRAILING*2, match("aa", "**aa**"));
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_GAP_TRAILING + SCORE_GAP_TRAILING, match("aa", "**a*a**"));
+
+ /* Consecutive */
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE, match("aa", "*aa"));
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CONSECUTIVE*2, match("aaa", "*aaa"));
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_CONSECUTIVE, match("aaa", "*a*aa"));
+
+ /* Slash */
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_SLASH, match("a", "/a"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH, match("a", "*/a"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_SLASH + SCORE_MATCH_CONSECUTIVE, match("aa", "a/aa"));
+
+ /* Capital */
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_CAPITAL, match("a", "bA"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL, match("a", "baA"));
+ ASSERT_EQ(SCORE_GAP_LEADING*2 + SCORE_MATCH_CAPITAL + SCORE_MATCH_CONSECUTIVE, match("aa", "baAa"));
+
+ /* Dot */
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_MATCH_DOT, match("a", ".a"));
+ ASSERT_EQ(SCORE_GAP_LEADING*3 + SCORE_MATCH_DOT, match("a", "*a.a"));
+ ASSERT_EQ(SCORE_GAP_LEADING + SCORE_GAP_INNER + SCORE_MATCH_DOT, match("a", "*a.a"));
+
+ PASS();
+}
+
+TEST test_positions_1() {
+ size_t positions[3];
+ match_positions("amo", "app/models/foo", positions);
+ ASSERT_EQ(0, positions[0]);
+ ASSERT_EQ(4, positions[1]);
+ ASSERT_EQ(5, positions[2]);
+
+ PASS();
+}
+
+TEST test_positions_2() {
+ /*
+ * We should prefer matching the 'o' in order, since it's the beginning
+ * of a word.
+ */
+ size_t positions[4];
+ match_positions("amor", "app/models/order", positions);
+ ASSERT_EQ(0, positions[0]);
+ ASSERT_EQ(4, positions[1]);
+ ASSERT_EQ(11, positions[2]);
+
+ PASS();
+}
+
+TEST test_positions_3() {
+ size_t positions[2];
+ match_positions("as", "tags", positions);
+ ASSERT_EQ(1, positions[0]);
+ ASSERT_EQ(3, positions[1]);
+
+ PASS();
+}
+
+TEST test_positions_4() {
+ size_t positions[2];
+ match_positions("as", "examples.txt", positions);
+ ASSERT_EQ(2, positions[0]);
+ ASSERT_EQ(7, positions[1]);
+
+ PASS();
+}
+
+TEST test_positions_5() {
+ size_t positions[3];
+ match_positions("abc", "a/a/b/c/c", positions);
+ ASSERT_EQ(2, positions[0]);
+ ASSERT_EQ(4, positions[1]);
+ ASSERT_EQ(6, positions[2]);
+
+ PASS();
+}
+
+TEST test_positions_exact() {
+ size_t positions[3];
+ match_positions("foo", "foo", positions);
+ ASSERT_EQ(0, positions[0]);
+ ASSERT_EQ(1, positions[1]);
+ ASSERT_EQ(2, positions[2]);
+
+ PASS();
+}
+
+SUITE(match_suite) {
+ RUN_TEST(test_match);
+ RUN_TEST(test_relative_scores);
+ RUN_TEST(test_exact_scores);
+ RUN_TEST(test_positions_1);
+ RUN_TEST(test_positions_2);
+ RUN_TEST(test_positions_3);
+ RUN_TEST(test_positions_4);
+ RUN_TEST(test_positions_5);
+ RUN_TEST(test_positions_exact);
+}
diff --git a/test/test_properties.c b/test/test_properties.c
index 1fcdf80..7a9ca5e 100644
--- a/test/test_properties.c
+++ b/test/test_properties.c
@@ -53,13 +53,14 @@ static void string_print_cb(FILE *f, void *instance, void *env) {
}
static uint64_t string_hash_cb(void *instance, void *env) {
+ (void)env;
char *str = (char *)instance;
int size = strlen(str);
- (void)env;
- return theft_hash_onepass(str, size);
+ return theft_hash_onepass((uint8_t *)str, size);
}
static void *string_shrink_cb(void *instance, uint32_t tactic, void *env) {
+ (void)env;
char *str = (char *)instance;
int n = strlen(str);
@@ -157,7 +158,7 @@ TEST positions_should_match_characters_in_string() {
PASS();
}
-SUITE(properties) {
+SUITE(properties_suite) {
RUN_TEST(should_return_results_if_there_is_a_match);
RUN_TEST(positions_should_match_characters_in_string);
}