fzy
terminal fuzzy finder picker
git clone https://9o.is/git/fzy.git
test_choices.c
(3957B)
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 #define ASSERT_SIZE_T_EQ(a,b) ASSERT_EQ_FMT((size_t)(a), (b), "%zu")
12
13 static options_t default_options;
14 static choices_t choices;
15
16 static void setup(void *udata) {
17 (void)udata;
18
19 options_init(&default_options);
20 choices_init(&choices, &default_options);
21 }
22
23 static void teardown(void *udata) {
24 (void)udata;
25 choices_destroy(&choices);
26 }
27
28 TEST test_choices_empty() {
29 ASSERT_SIZE_T_EQ(0, choices.size);
30 ASSERT_SIZE_T_EQ(0, choices.available);
31 ASSERT_SIZE_T_EQ(0, choices.selection);
32
33 choices_prev(&choices);
34 ASSERT_SIZE_T_EQ(0, choices.selection);
35
36 choices_next(&choices);
37 ASSERT_SIZE_T_EQ(0, choices.selection);
38
39 PASS();
40 }
41
42 TEST test_choices_1() {
43 choices_add(&choices, "tags");
44
45 choices_search(&choices, "");
46 ASSERT_SIZE_T_EQ(1, choices.available);
47 ASSERT_SIZE_T_EQ(0, choices.selection);
48
49 choices_search(&choices, "t");
50 ASSERT_SIZE_T_EQ(1, choices.available);
51 ASSERT_SIZE_T_EQ(0, choices.selection);
52
53 choices_prev(&choices);
54 ASSERT_SIZE_T_EQ(0, choices.selection);
55
56 choices_next(&choices);
57 ASSERT_SIZE_T_EQ(0, choices.selection);
58
59 ASSERT(!strcmp(choices_get(&choices, 0), "tags"));
60 ASSERT_EQ(NULL, choices_get(&choices, 1));
61
62 PASS();
63 }
64
65 TEST test_choices_2() {
66 choices_add(&choices, "tags");
67 choices_add(&choices, "test");
68
69 /* Empty search */
70 choices_search(&choices, "");
71 ASSERT_SIZE_T_EQ(0, choices.selection);
72 ASSERT_SIZE_T_EQ(2, choices.available);
73
74 choices_next(&choices);
75 ASSERT_SIZE_T_EQ(1, choices.selection);
76 choices_next(&choices);
77 ASSERT_SIZE_T_EQ(0, choices.selection);
78
79 choices_prev(&choices);
80 ASSERT_SIZE_T_EQ(1, choices.selection);
81 choices_prev(&choices);
82 ASSERT_SIZE_T_EQ(0, choices.selection);
83
84 /* Filtered search */
85 choices_search(&choices, "te");
86 ASSERT_SIZE_T_EQ(1, choices.available);
87 ASSERT_SIZE_T_EQ(0, choices.selection);
88 ASSERT_STR_EQ("test", choices_get(&choices, 0));
89
90 choices_next(&choices);
91 ASSERT_SIZE_T_EQ(0, choices.selection);
92
93 choices_prev(&choices);
94 ASSERT_SIZE_T_EQ(0, choices.selection);
95
96 /* No results */
97 choices_search(&choices, "foobar");
98 ASSERT_SIZE_T_EQ(0, choices.available);
99 ASSERT_SIZE_T_EQ(0, choices.selection);
100
101 /* Different order due to scoring */
102 choices_search(&choices, "ts");
103 ASSERT_SIZE_T_EQ(2, choices.available);
104 ASSERT_SIZE_T_EQ(0, choices.selection);
105 ASSERT_STR_EQ("test", choices_get(&choices, 0));
106 ASSERT_STR_EQ("tags", choices_get(&choices, 1));
107
108 PASS();
109 }
110
111 TEST test_choices_without_search() {
112 /* Before a search is run, it should return no results */
113
114 ASSERT_SIZE_T_EQ(0, choices.available);
115 ASSERT_SIZE_T_EQ(0, choices.selection);
116 ASSERT_SIZE_T_EQ(0, choices.size);
117 ASSERT_EQ(NULL, choices_get(&choices, 0));
118
119 choices_add(&choices, "test");
120
121 ASSERT_SIZE_T_EQ(0, choices.available);
122 ASSERT_SIZE_T_EQ(0, choices.selection);
123 ASSERT_SIZE_T_EQ(1, choices.size);
124 ASSERT_EQ(NULL, choices_get(&choices, 0));
125
126 PASS();
127 }
128
129 /* Regression test for segfault */
130 TEST test_choices_unicode() {
131 choices_add(&choices, "Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf");
132 choices_search(&choices, "e");
133
134 PASS();
135 }
136
137 TEST test_choices_large_input() {
138 const int N = 100000;
139 char *strings[100000];
140
141 for(int i = 0; i < N; i++) {
142 asprintf(&strings[i], "%i", i);
143 choices_add(&choices, strings[i]);
144 }
145
146 choices_search(&choices, "12");
147
148 /* Must match `seq 0 99999 | grep '.*1.*2.*' | wc -l` */
149 ASSERT_SIZE_T_EQ(8146, choices.available);
150
151 ASSERT_STR_EQ("12", choices_get(&choices, 0));
152
153 for(int i = 0; i < N; i++) {
154 free(strings[i]);
155 }
156
157 PASS();
158 }
159
160 SUITE(choices_suite) {
161 SET_SETUP(setup, NULL);
162 SET_TEARDOWN(teardown, NULL);
163
164 RUN_TEST(test_choices_empty);
165 RUN_TEST(test_choices_1);
166 RUN_TEST(test_choices_2);
167 RUN_TEST(test_choices_without_search);
168 RUN_TEST(test_choices_unicode);
169 RUN_TEST(test_choices_large_input);
170 }