#include "../../unity/unity.h" #include #include #include /* keycmp and the required types/globals are available because this file is included into the same translation unit as join.c. */ /* Prototypes to satisfy some compilers (the function is defined above). */ static int keycmp (struct line const *line1, struct line const *line2, idx_t jf_1, idx_t jf_2); /* Globals from the program under test (defined earlier in the TU). */ extern bool ignore_case; /* static in original file; visible here via inclusion */ extern bool hard_LC_COLLATE; /* static in original file; visible here via inclusion */ static void setup_line_fields(struct line *ln, struct field *fields, idx_t n) { /* Initialize a line with a given array of fields. */ memset(ln, 0, sizeof(*ln)); ln->fields = fields; ln->nfields = n; ln->nfields_allocated = n; /* ln->buf is unused by keycmp. */ } void setUp(void) { /* Default to byte-wise comparisons. */ ignore_case = false; hard_LC_COLLATE = false; } void tearDown(void) { /* Nothing to clean up */ } /* Helper to create a field pointing at a string literal with given length. */ static void make_field(struct field *f, const char *s, idx_t len) { f->beg = (char *)s; f->len = len; } void test_keycmp_both_missing(void) { struct line l1, l2; setup_line_fields(&l1, NULL, 0); setup_line_fields(&l2, NULL, 0); int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_EQUAL_INT(0, r); } void test_keycmp_left_missing_right_present(void) { struct line l1, l2; struct field f2[1]; make_field(&f2[0], "x", (idx_t)1); setup_line_fields(&l1, NULL, 0); setup_line_fields(&l2, f2, 1); int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r < 0); } void test_keycmp_left_present_right_missing(void) { struct line l1, l2; struct field f1[1]; make_field(&f1[0], "x", (idx_t)1); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, NULL, 0); int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r > 0); } void test_keycmp_both_empty_fields(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "", (idx_t)0); make_field(&f2[0], "", (idx_t)0); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_EQUAL_INT(0, r); } void test_keycmp_empty_vs_nonempty(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "", (idx_t)0); make_field(&f2[0], "a", (idx_t)1); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r < 0); } void test_keycmp_memcmp_less(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "abc", (idx_t)3); make_field(&f2[0], "abd", (idx_t)3); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); ignore_case = false; hard_LC_COLLATE = false; int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r < 0); } void test_keycmp_memcmp_greater(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "abd", (idx_t)3); make_field(&f2[0], "abc", (idx_t)3); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); ignore_case = false; hard_LC_COLLATE = false; int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r > 0); } void test_keycmp_len_tiebreak_shorter_less(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "ab", (idx_t)2); make_field(&f2[0], "abc", (idx_t)3); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); ignore_case = false; hard_LC_COLLATE = false; int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r < 0); } void test_keycmp_ignore_case_equal(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "AbC", (idx_t)3); make_field(&f2[0], "aBc", (idx_t)3); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); ignore_case = true; hard_LC_COLLATE = false; int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_EQUAL_INT(0, r); } void test_keycmp_ignore_case_len_tiebreak(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "Ab", (idx_t)2); make_field(&f2[0], "aBc", (idx_t)3); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); ignore_case = true; hard_LC_COLLATE = false; int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_TRUE(r < 0); } void test_keycmp_hard_collate_equal(void) { struct line l1, l2; struct field f1[1], f2[1]; make_field(&f1[0], "abc", (idx_t)3); make_field(&f2[0], "abc", (idx_t)3); setup_line_fields(&l1, f1, 1); setup_line_fields(&l2, f2, 1); ignore_case = false; hard_LC_COLLATE = true; /* Force xmemcoll path; equal strings must compare equal. */ int r = keycmp(&l1, &l2, 0, 0); TEST_ASSERT_EQUAL_INT(0, r); } void test_keycmp_nonzero_join_field(void) { struct line l1, l2; struct field f1[2], f2[2]; make_field(&f1[0], "k1", (idx_t)2); make_field(&f1[1], "x", (idx_t)1); make_field(&f2[0], "k2", (idx_t)2); make_field(&f2[1], "x", (idx_t)1); setup_line_fields(&l1, f1, 2); setup_line_fields(&l2, f2, 2); ignore_case = false; hard_LC_COLLATE = false; /* Compare on field index 1 (second field) which is "x" in both lines. */ int r = keycmp(&l1, &l2, 1, 1); TEST_ASSERT_EQUAL_INT(0, r); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_keycmp_both_missing); RUN_TEST(test_keycmp_left_missing_right_present); RUN_TEST(test_keycmp_left_present_right_missing); RUN_TEST(test_keycmp_both_empty_fields); RUN_TEST(test_keycmp_empty_vs_nonempty); RUN_TEST(test_keycmp_memcmp_less); RUN_TEST(test_keycmp_memcmp_greater); RUN_TEST(test_keycmp_len_tiebreak_shorter_less); RUN_TEST(test_keycmp_ignore_case_equal); RUN_TEST(test_keycmp_ignore_case_len_tiebreak); RUN_TEST(test_keycmp_hard_collate_equal); RUN_TEST(test_keycmp_nonzero_join_field); return UNITY_END(); }