#define _GNU_SOURCE #include #include #include "../config.h" #include "options.h" #include "choices.h" #include "greatest/greatest.h" #define ASSERT_SIZE_T_EQ(a,b) ASSERT_EQ_FMT((size_t)(a), (b), "%zu") static options_t default_options; static choices_t choices; static void setup(void *udata) { (void)udata; options_init(&default_options); choices_init(&choices, &default_options); } static void teardown(void *udata) { (void)udata; choices_destroy(&choices); } TEST test_choices_empty() { ASSERT_SIZE_T_EQ(0, choices.size); ASSERT_SIZE_T_EQ(0, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); choices_prev(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); choices_next(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); PASS(); } TEST test_choices_1() { choices_add(&choices, "tags"); choices_search(&choices, ""); ASSERT_SIZE_T_EQ(1, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); choices_search(&choices, "t"); ASSERT_SIZE_T_EQ(1, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); choices_prev(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); choices_next(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); ASSERT(!strcmp(choices_get(&choices, 0), "tags")); ASSERT_EQ(NULL, choices_get(&choices, 1)); PASS(); } TEST test_choices_2() { choices_add(&choices, "tags"); choices_add(&choices, "test"); /* Empty search */ choices_search(&choices, ""); ASSERT_SIZE_T_EQ(0, choices.selection); ASSERT_SIZE_T_EQ(2, choices.available); choices_next(&choices); ASSERT_SIZE_T_EQ(1, choices.selection); choices_next(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); choices_prev(&choices); ASSERT_SIZE_T_EQ(1, choices.selection); choices_prev(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); /* Filtered search */ choices_search(&choices, "te"); ASSERT_SIZE_T_EQ(1, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); ASSERT_STR_EQ("test", choices_get(&choices, 0)); choices_next(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); choices_prev(&choices); ASSERT_SIZE_T_EQ(0, choices.selection); /* No results */ choices_search(&choices, "foobar"); ASSERT_SIZE_T_EQ(0, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); /* Different order due to scoring */ choices_search(&choices, "ts"); ASSERT_SIZE_T_EQ(2, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); ASSERT_STR_EQ("test", choices_get(&choices, 0)); ASSERT_STR_EQ("tags", choices_get(&choices, 1)); PASS(); } TEST test_choices_without_search() { /* Before a search is run, it should return no results */ ASSERT_SIZE_T_EQ(0, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); ASSERT_SIZE_T_EQ(0, choices.size); ASSERT_EQ(NULL, choices_get(&choices, 0)); choices_add(&choices, "test"); ASSERT_SIZE_T_EQ(0, choices.available); ASSERT_SIZE_T_EQ(0, choices.selection); ASSERT_SIZE_T_EQ(1, choices.size); ASSERT_EQ(NULL, choices_get(&choices, 0)); PASS(); } /* Regression test for segfault */ TEST test_choices_unicode() { choices_add(&choices, "Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf"); choices_search(&choices, "e"); PASS(); } TEST test_choices_large_input() { const int N = 100000; char *strings[100000]; 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_SIZE_T_EQ(8146, choices.available); ASSERT_STR_EQ("12", choices_get(&choices, 0)); for(int i = 0; i < N; i++) { free(strings[i]); } PASS(); } SUITE(choices_suite) { SET_SETUP(setup, NULL); SET_TEARDOWN(teardown, NULL); 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); }