Browse code

Add tests and split matching into match.c

John Hawthorn authored on 12/07/2014 22:07:22
Showing 6 changed files

... ...
@@ -1,2 +1,3 @@
1 1
 fzy
2
+testscore
2 3
 *.o
... ...
@@ -1,10 +1,15 @@
1
-LIBS=
2 1
 CFLAGS+=-Wall -Wextra -g
3
-TARGET=fzy
4
-OBJECTS=fzy.o
5 2
 
6
-$(TARGET): $(OBJECTS)
7
-	$(CC) $(CCFLAGS) -o $@ $^ $(LIBS)
3
+all: fzy testscore
4
+
5
+testscore: testscore.o match.o
6
+	$(CC) $(CCFLAGS) -o $@ $^
7
+
8
+test: testscore
9
+	ruby test.rb
10
+
11
+fzy: fzy.o match.o
12
+	$(CC) $(CCFLAGS) -o $@ $^
8 13
 
9 14
 clean:
10
-	$(RM) $(TARGET) *.o
15
+	$(RM) fzy testscore *.o
... ...
@@ -7,15 +7,8 @@
7 7
 #include <fcntl.h>
8 8
 #include <ctype.h>
9 9
 
10
-double match(const char *needle, const char *haystack){
11
-	while(*needle){
12
-		if(!*haystack)
13
-			return 0.0;
14
-		while(tolower(*needle) == tolower(*haystack++))
15
-			needle++;
16
-	}
17
-	return 1.0;
18
-}
10
+/* from match.c */
11
+double match(const char *needle, const char *haystack);
19 12
 
20 13
 #define INITIAL_CAPACITY 1
21 14
 int choices_capacity = 0;
22 15
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+#include <ctype.h>
2
+
3
+double match(const char *needle, const char *haystack){
4
+	while(*needle){
5
+		if(!*haystack)
6
+			return 0.0;
7
+		while(*haystack && tolower(*needle) == tolower(*haystack++)){
8
+			needle++;
9
+		}
10
+	}
11
+	return 1.0;
12
+}
0 13
new file mode 100644
... ...
@@ -0,0 +1,41 @@
1
+require "minitest/autorun"
2
+
3
+# Largely borrowed from selecta
4
+describe "score" do
5
+  def score(candidate, query)
6
+    # FIXME: should escape this properly
7
+    `./testscore '#{query}' '#{candidate}'`.to_f
8
+  end
9
+
10
+  it "scores 1 when the query is empty" do
11
+    assert_equal 1, score("a", "")
12
+  end
13
+
14
+  it "scores 0 when the choice is empty" do
15
+    assert_equal 0, score("", "a")
16
+  end
17
+
18
+  it "scores 1 when exact match" do
19
+    assert_equal 1, score("a", "a")
20
+  end
21
+
22
+  it "scores 0 when the query is longer than the choice" do
23
+    assert_equal 0, score("short", "longer")
24
+  end
25
+
26
+  it "scores 0 when the query doesn't match at all" do
27
+    assert_equal 0, score("a", "b")
28
+  end
29
+
30
+  it "scores 0 when only a prefix of the query matches" do
31
+    assert_equal 0, score("ab", "ac")
32
+  end
33
+
34
+  it "scores greater than 0 when it matches" do
35
+    assert_operator 0, :<, score("a", "a")
36
+    assert_operator 0, :<, score("ab", "a")
37
+    assert_operator 0, :<, score("ba", "a")
38
+    assert_operator 0, :<, score("bab", "a")
39
+    assert_operator 0, :<, score("babababab", "aaaa")
40
+  end
41
+end
0 42
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+#include <stdlib.h>
2
+#include <stdio.h>
3
+
4
+/* from match.c */
5
+double match(const char *needle, const char *haystack);
6
+
7
+void usage(const char *argv0){
8
+	fprintf(stderr, "USAGE: %s QUERY CANDIDATE\n", argv0);
9
+}
10
+
11
+int main(int argc, char *argv[]){
12
+	if(argc != 3){
13
+		usage(argv[0]);
14
+	}
15
+
16
+	double result = match(argv[1], argv[2]);
17
+	printf("%f\n", result);
18
+
19
+	return 0;
20
+}