#include "malunal/microtest.h" #include "malunal/types/strview.h" /* ------------------------------------------------------------------------- * Construction: strview() / strview_from_cstr() * ---------------------------------------------------------------------- */ MICROTEST(strview_construct, from_data_and_length) { malunal_cstr_t data = "hello world"; strview_t view = strview(data, 5); MICROTEST_EXPECT_EQ(view.beg, data); MICROTEST_EXPECT_EQ(view.end, data + 5); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)5); } MICROTEST(strview_construct, zero_length) { malunal_cstr_t data = "hello"; strview_t view = strview(data, 0); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)0); MICROTEST_EXPECT_EQ(view.beg, view.end); } MICROTEST(strview_construct, from_cstr_matches_strlen) { malunal_cstr_t data = "hello world"; strview_t view = strview_from_cstr(data); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)strlen(data)); MICROTEST_EXPECT_TRUE(memcmp(view.beg, data, strview_length(&view)) == 0); } MICROTEST(strview_construct, from_cstr_empty) { strview_t view = strview_from_cstr(""); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)0); } MICROTEST(strview_construct, from_cstr_matches_manual_construction) { malunal_cstr_t data = "matching"; strview_t fromcstr = strview_from_cstr(data); strview_t manual = strview(data, (malunal_size_t)strlen(data)); MICROTEST_EXPECT_TRUE(strview_equals(&fromcstr, &manual)); } /* ------------------------------------------------------------------------- * strview_length() * ---------------------------------------------------------------------- */ MICROTEST(strview_length, reports_correct_length) { strview_t view = strview_from_cstr("0123456789"); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)10); } MICROTEST(strview_length, null_self_returns_zero) { MICROTEST_EXPECT_EQ(strview_length(null), (malunal_size_t)0); } /* ------------------------------------------------------------------------- * strview_ltrim() * ---------------------------------------------------------------------- */ MICROTEST(strview_ltrim, moves_start_forward) { strview_t view = strview_from_cstr("hello world"); strview_ltrim(&view, 6); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)5); MICROTEST_EXPECT_TRUE(memcmp(view.beg, "world", 5) == 0); } MICROTEST(strview_ltrim, zero_count_is_noop) { strview_t view = strview_from_cstr("unchanged"); strview_t original = view; strview_ltrim(&view, 0); MICROTEST_EXPECT_TRUE(strview_equals(&view, &original)); } MICROTEST(strview_ltrim, full_length_yields_empty_view) { strview_t view = strview_from_cstr("hello"); strview_ltrim(&view, strview_length(&view)); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)0); } /* ------------------------------------------------------------------------- * strview_rtrim() * ---------------------------------------------------------------------- */ MICROTEST(strview_rtrim, moves_end_backward) { strview_t view = strview_from_cstr("hello world"); strview_rtrim(&view, 6); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)5); MICROTEST_EXPECT_TRUE(memcmp(view.beg, "hello", 5) == 0); } MICROTEST(strview_rtrim, zero_count_is_noop) { strview_t view = strview_from_cstr("unchanged"); strview_t original = view; strview_rtrim(&view, 0); MICROTEST_EXPECT_TRUE(strview_equals(&view, &original)); } MICROTEST(strview_rtrim, full_length_yields_empty_view) { strview_t view = strview_from_cstr("hello"); strview_rtrim(&view, strview_length(&view)); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)0); } MICROTEST(strview_rtrim, combined_with_ltrim_isolates_middle) { strview_t view = strview_from_cstr(" trimmed "); strview_ltrim(&view, 2); strview_rtrim(&view, 2); MICROTEST_EXPECT_EQ(strview_length(&view), (malunal_size_t)7); MICROTEST_EXPECT_TRUE(memcmp(view.beg, "trimmed", 7) == 0); } /* ------------------------------------------------------------------------- * strview_subview() * ---------------------------------------------------------------------- */ MICROTEST(strview_subview, middle_slice) { strview_t view = strview_from_cstr("hello world"); strview_t sub = strview_subview(&view, 6, 5); MICROTEST_EXPECT_EQ(strview_length(&sub), (malunal_size_t)5); MICROTEST_EXPECT_TRUE(memcmp(sub.beg, "world", 5) == 0); } MICROTEST(strview_subview, from_start) { strview_t view = strview_from_cstr("hello world"); strview_t sub = strview_subview(&view, 0, 5); MICROTEST_EXPECT_TRUE(memcmp(sub.beg, "hello", 5) == 0); } MICROTEST(strview_subview, zero_count_is_empty) { strview_t view = strview_from_cstr("hello world"); strview_t sub = strview_subview(&view, 3, 0); MICROTEST_EXPECT_EQ(strview_length(&sub), (malunal_size_t)0); } MICROTEST(strview_subview, out_of_bounds_start_fails) { /* Per the header remarks, an invalid subview yields null data and zero * length rather than reading past the end of the source view. */ strview_t view = strview_from_cstr("hello"); strview_t sub = strview_subview(&view, 100, 1); MICROTEST_EXPECT_EQ(strview_length(&sub), (malunal_size_t)0); MICROTEST_EXPECT_NULL(sub.beg); } MICROTEST(strview_subview, count_exceeding_bounds_fails) { strview_t view = strview_from_cstr("hello"); strview_t sub = strview_subview(&view, 3, 10); MICROTEST_EXPECT_EQ(strview_length(&sub), (malunal_size_t)0); MICROTEST_EXPECT_NULL(sub.beg); } MICROTEST(strview_subview, null_self_fails) { strview_t sub = strview_subview(null, 0, 1); MICROTEST_EXPECT_EQ(strview_length(&sub), (malunal_size_t)0); MICROTEST_EXPECT_NULL(sub.beg); } /* ------------------------------------------------------------------------- * strview_equals() * ---------------------------------------------------------------------- */ MICROTEST(strview_equals, identical_content_is_equal) { strview_t a = strview_from_cstr("identical"); strview_t b = strview_from_cstr("identical"); MICROTEST_EXPECT_TRUE(strview_equals(&a, &b)); } MICROTEST(strview_equals, different_content_is_not_equal) { strview_t a = strview_from_cstr("hello"); strview_t b = strview_from_cstr("world"); MICROTEST_EXPECT_FALSE(strview_equals(&a, &b)); } MICROTEST(strview_equals, different_lengths_are_not_equal) { strview_t a = strview_from_cstr("hello"); strview_t b = strview_from_cstr("hello!"); MICROTEST_EXPECT_FALSE(strview_equals(&a, &b)); } MICROTEST(strview_equals, empty_views_are_equal) { strview_t a = strview_from_cstr(""); strview_t b = strview_from_cstr(""); MICROTEST_EXPECT_TRUE(strview_equals(&a, &b)); } MICROTEST(strview_equals, is_reflexive) { strview_t a = strview_from_cstr("self"); MICROTEST_EXPECT_TRUE(strview_equals(&a, &a)); } /* ------------------------------------------------------------------------- * strview_compare() * ---------------------------------------------------------------------- */ MICROTEST(strview_compare, equal_views_compare_zero) { strview_t a = strview_from_cstr("apple"); strview_t b = strview_from_cstr("apple"); MICROTEST_EXPECT_EQ(strview_compare(&a, &b), 0); } MICROTEST(strview_compare, lesser_view_compares_negative) { strview_t a = strview_from_cstr("apple"); strview_t b = strview_from_cstr("banana"); MICROTEST_EXPECT_LT(strview_compare(&a, &b), 0); } MICROTEST(strview_compare, greater_view_compares_positive) { strview_t a = strview_from_cstr("banana"); strview_t b = strview_from_cstr("apple"); MICROTEST_EXPECT_GT(strview_compare(&a, &b), 0); } MICROTEST(strview_compare, shorter_prefix_compares_negative) { strview_t a = strview_from_cstr("app"); strview_t b = strview_from_cstr("apple"); MICROTEST_EXPECT_LT(strview_compare(&a, &b), 0); } /* ------------------------------------------------------------------------- * strview_starts_with() * ---------------------------------------------------------------------- */ MICROTEST(strview_starts_with, true_when_prefix_matches) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_TRUE(strview_starts_with(&self, &other)); } MICROTEST(strview_starts_with, false_when_prefix_differs) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("world"); MICROTEST_EXPECT_FALSE(strview_starts_with(&self, &other)); } MICROTEST(strview_starts_with, false_when_other_longer_than_self) { strview_t self = strview_from_cstr("hi"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_FALSE(strview_starts_with(&self, &other)); } MICROTEST(strview_starts_with, true_for_empty_other) { strview_t self = strview_from_cstr("hello"); strview_t other = strview_from_cstr(""); MICROTEST_EXPECT_TRUE(strview_starts_with(&self, &other)); } MICROTEST(strview_starts_with, true_when_equal) { strview_t self = strview_from_cstr("hello"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_TRUE(strview_starts_with(&self, &other)); } /* ------------------------------------------------------------------------- * strview_ends_with() * ---------------------------------------------------------------------- */ MICROTEST(strview_ends_with, true_when_suffix_matches) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("world"); MICROTEST_EXPECT_TRUE(strview_ends_with(&self, &other)); } MICROTEST(strview_ends_with, false_when_suffix_differs) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_FALSE(strview_ends_with(&self, &other)); } MICROTEST(strview_ends_with, false_when_other_longer_than_self) { strview_t self = strview_from_cstr("hi"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_FALSE(strview_ends_with(&self, &other)); } MICROTEST(strview_ends_with, true_for_empty_other) { strview_t self = strview_from_cstr("hello"); strview_t other = strview_from_cstr(""); MICROTEST_EXPECT_TRUE(strview_ends_with(&self, &other)); } MICROTEST(strview_ends_with, true_when_equal) { strview_t self = strview_from_cstr("hello"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_TRUE(strview_ends_with(&self, &other)); } /* ------------------------------------------------------------------------- * strview_contains() * ---------------------------------------------------------------------- */ MICROTEST(strview_contains, true_when_substring_present) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("lo wo"); MICROTEST_EXPECT_TRUE(strview_contains(&self, &other)); } MICROTEST(strview_contains, false_when_substring_absent) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("xyz"); MICROTEST_EXPECT_FALSE(strview_contains(&self, &other)); } MICROTEST(strview_contains, true_for_prefix) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_TRUE(strview_contains(&self, &other)); } MICROTEST(strview_contains, true_for_suffix) { strview_t self = strview_from_cstr("hello world"); strview_t other = strview_from_cstr("world"); MICROTEST_EXPECT_TRUE(strview_contains(&self, &other)); } MICROTEST(strview_contains, true_for_empty_other) { strview_t self = strview_from_cstr("hello"); strview_t other = strview_from_cstr(""); MICROTEST_EXPECT_TRUE(strview_contains(&self, &other)); } MICROTEST(strview_contains, false_when_other_longer_than_self) { strview_t self = strview_from_cstr("hi"); strview_t other = strview_from_cstr("hello"); MICROTEST_EXPECT_FALSE(strview_contains(&self, &other)); } /* ------------------------------------------------------------------------- * STRVIEW_NPOS * ---------------------------------------------------------------------- */ MICROTEST(strview_npos, is_max_size_value) { MICROTEST_EXPECT_EQ(STRVIEW_NPOS, (malunal_size_t)-1); }