// tests/suite/test_string.el — comprehensive tests for runtime/string.el // // Covers every public function in string.el. Import this file after all // runtime modules and runtime/test.el have been concatenated in. // ── str_eq ──────────────────────────────────────────────────────────────────── fn test_str_eq_basic(_: String) -> String { assert_true(str_eq("hello", "hello"), "identical strings are equal") assert_false(str_eq("hello", "world"), "different strings are not equal") assert_true(str_eq("", ""), "empty strings are equal") assert_false(str_eq("a", ""), "non-empty vs empty is not equal") assert_false(str_eq("", "a"), "empty vs non-empty is not equal") assert_false(str_eq("Hello", "hello"), "comparison is case-sensitive") return "" } fn test_str_eq_symbols(_: String) -> String { assert_true(str_eq("!@#$", "!@#$"), "symbols are equal") assert_true(str_eq(" ", " "), "spaces match") assert_false(str_eq(" a", "a "), "leading vs trailing space differ") assert_false(str_eq("abc", "ab"), "prefix not equal to full string") assert_false(str_eq("ab", "abc"), "shorter not equal to longer") return "" } // ── str_len ─────────────────────────────────────────────────────────────────── fn test_str_len_basic(_: String) -> String { assert_int_eq(str_len(""), 0, "empty string has length 0") assert_int_eq(str_len("a"), 1, "single char has length 1") assert_int_eq(str_len("hello"), 5, "hello has length 5") assert_int_eq(str_len("hello world"), 11, "space counted in length") assert_int_eq(str_len("12345"), 5, "digits counted correctly") assert_int_eq(str_len("!@#$%"), 5, "punctuation counted correctly") return "" } fn test_str_len_longer(_: String) -> String { let s: String = str_repeat("ab", 50) assert_int_eq(str_len(s), 100, "repeated string has correct length") assert_int_eq(str_len("abcdefghij"), 10, "10-char string") return "" } // ── str_concat / + operator ─────────────────────────────────────────────────── fn test_str_concat_basic(_: String) -> String { assert_eq(str_concat("hello", " world"), "hello world", "basic concat") assert_eq(str_concat("", "world"), "world", "empty prefix") assert_eq(str_concat("hello", ""), "hello", "empty suffix") assert_eq(str_concat("", ""), "", "both empty") assert_eq("foo" + "bar", "foobar", "operator + concat") return "" } fn test_str_concat_chaining(_: String) -> String { let a: String = "hello" let b: String = " " let c: String = "world" assert_eq(a + b + c, "hello world", "chained concat") assert_eq(str_concat(str_concat("a", "b"), "c"), "abc", "nested concat") assert_int_eq(str_len(str_concat("abc", "def")), 6, "length after concat") return "" } // ── str_slice ───────────────────────────────────────────────────────────────── fn test_str_slice_basic(_: String) -> String { assert_eq(str_slice("hello world", 0, 5), "hello", "slice from start") assert_eq(str_slice("hello world", 6, 11), "world", "slice from middle") assert_eq(str_slice("hello world", 0, 0), "", "zero-length slice") assert_eq(str_slice("hello", 0, 100), "hello", "end clamped to length") assert_eq(str_slice("hello", 3, 3), "", "start == end is empty") assert_eq(str_slice("hello world", 2, 7), "llo w", "interior slice") return "" } fn test_str_slice_edge(_: String) -> String { assert_eq(str_slice("", 0, 0), "", "empty string slice") assert_eq(str_slice("abc", 1, 2), "b", "single char slice") assert_eq(str_slice("abc", 0, 3), "abc", "full string slice") assert_eq(str_slice("abc", 2, 1), "", "inverted range is empty") assert_eq(str_slice("hello", 5, 5), "", "slice at end is empty") return "" } // ── str_starts_with ─────────────────────────────────────────────────────────── fn test_str_starts_with_basic(_: String) -> String { assert_true(str_starts_with("hello world", "hello"), "prefix present") assert_false(str_starts_with("hello world", "world"), "not a prefix") assert_true(str_starts_with("hello", "hello"), "string is its own prefix") assert_true(str_starts_with("hello", ""), "empty prefix always true") assert_false(str_starts_with("", "a"), "empty string has no non-empty prefix") assert_false(str_starts_with("hi", "hello"), "prefix longer than string") return "" } fn test_str_starts_with_edge(_: String) -> String { assert_true(str_starts_with("abc", "a"), "single-char prefix") assert_false(str_starts_with("abc", "b"), "wrong single-char prefix") assert_true(str_starts_with("", ""), "empty starts with empty") assert_true(str_starts_with("hello world", "hello world"), "full string is prefix") assert_false(str_starts_with("hello", "HELLO"), "case-sensitive prefix") return "" } // ── str_ends_with ───────────────────────────────────────────────────────────── fn test_str_ends_with_basic(_: String) -> String { assert_true(str_ends_with("hello world", "world"), "suffix present") assert_false(str_ends_with("hello world", "hello"), "not a suffix") assert_true(str_ends_with("hello", "hello"), "string is its own suffix") assert_true(str_ends_with("hello", ""), "empty suffix always true") assert_false(str_ends_with("", "a"), "empty string has no non-empty suffix") assert_false(str_ends_with("hi", "world"), "suffix longer than string") return "" } fn test_str_ends_with_edge(_: String) -> String { assert_true(str_ends_with("abc", "c"), "single-char suffix") assert_false(str_ends_with("abc", "b"), "wrong single-char suffix") assert_true(str_ends_with("", ""), "empty ends with empty") assert_false(str_ends_with("hello", "HELLO"), "case-sensitive suffix") assert_true(str_ends_with("file.txt", ".txt"), "common file extension case") return "" } // ── str_contains ───────────────────────────────────────────────────────────── fn test_str_contains_basic(_: String) -> String { assert_true(str_contains("hello world", "world"), "contains at end") assert_true(str_contains("hello world", "hello"), "contains at start") assert_true(str_contains("hello world", "lo wo"), "contains in middle") assert_false(str_contains("hello world", "xyz"), "not contained") assert_true(str_contains("hello", ""), "empty sub always contained") assert_false(str_contains("", "a"), "empty string contains nothing") return "" } fn test_str_contains_edge(_: String) -> String { assert_true(str_contains("hello", "hello"), "string contains itself") assert_false(str_contains("hello", "helloo"), "longer sub not contained") assert_true(str_contains("aaa", "a"), "single char in repeated chars") assert_true(str_contains("aaa", "aa"), "two-char sub in repeated chars") assert_false(str_contains("abc", "ABC"), "case-sensitive") return "" } // ── str_index_of ───────────────────────────────────────────────────────────── fn test_str_index_of_basic(_: String) -> String { assert_int_eq(str_index_of("hello world", "world"), 6, "index of suffix") assert_int_eq(str_index_of("hello world", "hello"), 0, "index of prefix") assert_int_eq(str_index_of("hello world", "o"), 4, "index of first occurrence") assert_int_eq(str_index_of("hello world", "xyz"), -1, "not found returns -1") assert_int_eq(str_index_of("hello", ""), 0, "empty sub returns 0") assert_int_eq(str_index_of("", "a"), -1, "search in empty string") return "" } fn test_str_index_of_duplicates(_: String) -> String { assert_int_eq(str_index_of("aababc", "ab"), 1, "finds first of two occurrences") assert_int_eq(str_index_of("abab", "ab"), 0, "finds first at position 0") assert_int_eq(str_index_of("xabab", "ab"), 1, "finds first after leading char") assert_int_eq(str_index_of("hello hello", "hello"), 0, "finds first hello") assert_int_eq(str_index_of("hello", "hello"), 0, "exact match at 0") return "" } // ── str_last_index_of ───────────────────────────────────────────────────────── fn test_str_last_index_of_basic(_: String) -> String { assert_int_eq(str_last_index_of("hello hello", "hello"), 6, "last occurrence index") assert_int_eq(str_last_index_of("hello", "hello"), 0, "only one occurrence") assert_int_eq(str_last_index_of("hello", "xyz"), -1, "not found returns -1") assert_int_eq(str_last_index_of("aababc", "ab"), 3, "last ab in aababc") assert_int_eq(str_last_index_of("abcabc", "abc"), 3, "last abc") return "" } // ── str_replace ─────────────────────────────────────────────────────────────── fn test_str_replace_basic(_: String) -> String { assert_eq(str_replace("hello world", "world", "there"), "hello there", "basic replace") assert_eq(str_replace("aaa", "a", "b"), "bbb", "replaces all occurrences") assert_eq(str_replace("hello", "xyz", "abc"), "hello", "no match is identity") assert_eq(str_replace("", "a", "b"), "", "empty string unchanged") assert_eq(str_replace("hello", "", "x"), "hello", "empty from is identity") return "" } fn test_str_replace_multiple(_: String) -> String { assert_eq(str_replace("hello hello", "hello", "bye"), "bye bye", "replace multiple") assert_eq(str_replace("aXbXc", "X", "-"), "a-b-c", "single-char delimiter") assert_eq(str_replace("abcabc", "abc", "X"), "XX", "multi-char replaced twice") assert_eq(str_replace("aabbcc", "bb", ""), "aacc", "replace with empty") assert_eq(str_replace("hello", "hello", "world"), "world", "replace whole string") return "" } // ── str_to_upper / str_to_lower ────────────────────────────────────────────── fn test_str_to_upper_basic(_: String) -> String { assert_eq(str_to_upper("hello"), "HELLO", "lowercase to uppercase") assert_eq(str_to_upper("HELLO"), "HELLO", "already uppercase unchanged") assert_eq(str_to_upper("Hello World"), "HELLO WORLD", "mixed case") assert_eq(str_to_upper(""), "", "empty string unchanged") assert_eq(str_to_upper("hello123"), "HELLO123", "digits unchanged") assert_eq(str_to_upper("abc-def"), "ABC-DEF", "punctuation unchanged") return "" } fn test_str_to_lower_basic(_: String) -> String { assert_eq(str_to_lower("HELLO"), "hello", "uppercase to lowercase") assert_eq(str_to_lower("hello"), "hello", "already lowercase unchanged") assert_eq(str_to_lower("Hello World"), "hello world", "mixed case") assert_eq(str_to_lower(""), "", "empty string unchanged") assert_eq(str_to_lower("HELLO123"), "hello123", "digits unchanged") assert_eq(str_to_lower("ABC-DEF"), "abc-def", "punctuation unchanged") return "" } fn test_str_upper_lower_roundtrip(_: String) -> String { let s: String = "Hello, World!" assert_eq(str_to_lower(str_to_upper(s)), "hello, world!", "upper then lower") assert_eq(str_to_upper(str_to_lower(s)), "HELLO, WORLD!", "lower then upper") assert_eq(str_to_upper(str_to_lower("ABC")), "ABC", "ABC roundtrip") return "" } // ── str_trim / str_lstrip / str_rstrip ─────────────────────────────────────── fn test_str_trim_basic(_: String) -> String { assert_eq(str_trim(" hello "), "hello", "trims spaces both sides") assert_eq(str_trim("hello"), "hello", "no whitespace unchanged") assert_eq(str_trim(" "), "", "all-space string becomes empty") assert_eq(str_trim(""), "", "empty string unchanged") assert_eq(str_trim("\t hello \n"), "hello", "trims tabs and newlines") assert_eq(str_trim(" hello world "), "hello world", "internal spaces preserved") return "" } fn test_str_lstrip_rstrip(_: String) -> String { assert_eq(str_lstrip(" hello "), "hello ", "lstrip removes leading spaces") assert_eq(str_rstrip(" hello "), " hello", "rstrip removes trailing spaces") assert_eq(str_lstrip("hello"), "hello", "lstrip no-op on clean string") assert_eq(str_rstrip("hello"), "hello", "rstrip no-op on clean string") assert_eq(str_lstrip(""), "", "lstrip empty string") assert_eq(str_rstrip(""), "", "rstrip empty string") return "" } // ── str_split ───────────────────────────────────────────────────────────────── fn test_str_split_basic(_: String) -> String { let parts: [String] = str_split("a,b,c", ",") assert_int_eq(el_list_len(parts), 3, "split yields 3 parts") assert_eq(el_list_get(parts, 0), "a", "first part is a") assert_eq(el_list_get(parts, 1), "b", "second part is b") assert_eq(el_list_get(parts, 2), "c", "third part is c") return "" } fn test_str_split_edge(_: String) -> String { let single: [String] = str_split("hello", ",") assert_int_eq(el_list_len(single), 1, "no sep found yields 1 part") assert_eq(el_list_get(single, 0), "hello", "single part is the full string") let trailing: [String] = str_split("a,b,", ",") assert_int_eq(el_list_len(trailing), 3, "trailing sep yields empty last element") assert_eq(el_list_get(trailing, 2), "", "last element is empty") let multi: [String] = str_split("one::two::three", "::") assert_int_eq(el_list_len(multi), 3, "multi-char separator works") assert_eq(el_list_get(multi, 1), "two", "middle element correct") return "" } // ── str_join ───────────────────────────────────────────────────────────────── fn test_str_join_basic(_: String) -> String { let parts: [String] = el_list_empty() let parts = el_list_append(parts, "a") let parts = el_list_append(parts, "b") let parts = el_list_append(parts, "c") assert_eq(str_join(parts, ","), "a,b,c", "basic join with comma") assert_eq(str_join(parts, ""), "abc", "join with empty separator") assert_eq(str_join(parts, " | "), "a | b | c", "join with multi-char sep") return "" } fn test_str_join_edge(_: String) -> String { let empty_list: [String] = el_list_empty() assert_eq(str_join(empty_list, ","), "", "joining empty list yields empty") let one: [String] = el_list_empty() let one = el_list_append(one, "solo") assert_eq(str_join(one, ","), "solo", "joining single element yields that element") assert_eq(str_join(one, "---"), "solo", "single element: no sep inserted") let two: [String] = el_list_empty() let two = el_list_append(two, "alpha") let two = el_list_append(two, "beta") assert_eq(str_join(two, ", "), "alpha, beta", "two elements join correctly") return "" } // ── int_to_str / str_to_int ────────────────────────────────────────────────── fn test_int_to_str_basic(_: String) -> String { assert_eq(int_to_str(0), "0", "zero") assert_eq(int_to_str(42), "42", "positive integer") assert_eq(int_to_str(-1), "-1", "negative integer") assert_eq(int_to_str(1000000), "1000000", "large integer") assert_eq(int_to_str(-999), "-999", "negative large") assert_int_eq(str_len(int_to_str(12345)), 5, "correct digit count") return "" } fn test_str_to_int_basic(_: String) -> String { assert_int_eq(str_to_int("0"), 0, "zero") assert_int_eq(str_to_int("42"), 42, "positive integer") assert_int_eq(str_to_int("-1"), -1, "negative integer") assert_int_eq(str_to_int("1000000"), 1000000, "large integer") assert_int_eq(str_to_int("-999"), -999, "negative large") assert_int_eq(str_to_int(int_to_str(12345)), 12345, "roundtrip") return "" } // ── float_to_str / str_to_float ────────────────────────────────────────────── fn test_float_to_str_basic(_: String) -> String { assert_eq(float_to_str(0.0), "0", "zero float to str") assert_eq(float_to_str(1.5), "1.5", "basic float") assert_eq(float_to_str(-3.14), "-3.14", "negative float") assert_true(str_len(float_to_str(1.0)) > 0, "float_to_str produces output") assert_contains(float_to_str(100.0), "100", "100.0 contains 100") return "" } fn test_str_to_float_basic(_: String) -> String { let f: Float = str_to_float("1.5") let s: String = float_to_str(f) assert_eq(s, "1.5", "roundtrip 1.5") let f2: Float = str_to_float("0.0") let s2: String = float_to_str(f2) assert_eq(s2, "0", "roundtrip 0.0") assert_true(str_to_float("3.14") > 3.13, "3.14 > 3.13") assert_true(str_to_float("3.14") < 3.15, "3.14 < 3.15") assert_true(str_to_float("-1.0") < 0.0, "negative float is negative") return "" } // ── str_repeat / str_reverse ───────────────────────────────────────────────── fn test_str_repeat_basic(_: String) -> String { assert_eq(str_repeat("ab", 3), "ababab", "repeat 3 times") assert_eq(str_repeat("x", 1), "x", "repeat once") assert_eq(str_repeat("x", 0), "", "repeat zero times yields empty") assert_eq(str_repeat("", 5), "", "repeating empty string yields empty") assert_eq(str_repeat("-", 4), "----", "single char repeat") assert_int_eq(str_len(str_repeat("abc", 10)), 30, "length is n * len") return "" } fn test_str_reverse_basic(_: String) -> String { assert_eq(str_reverse("hello"), "olleh", "basic reverse") assert_eq(str_reverse("a"), "a", "single char is its own reverse") assert_eq(str_reverse(""), "", "empty string reverses to empty") assert_eq(str_reverse("abcd"), "dcba", "even-length reverse") assert_eq(str_reverse("racecar"), "racecar", "palindrome unchanged") assert_eq(str_reverse("abc"), "cba", "three-char reverse") return "" } // ── str_count ───────────────────────────────────────────────────────────────── fn test_str_count_basic(_: String) -> String { assert_int_eq(str_count("hello world hello", "hello"), 2, "two occurrences") assert_int_eq(str_count("aaa", "a"), 3, "adjacent single chars") assert_int_eq(str_count("aaa", "aa"), 1, "non-overlapping: one match") assert_int_eq(str_count("hello", "xyz"), 0, "no match") assert_int_eq(str_count("", "a"), 0, "empty string has no occurrences") assert_int_eq(str_count("hello", ""), 0, "empty sub returns 0") return "" } // ── str_strip_prefix / str_strip_suffix ────────────────────────────────────── fn test_str_strip_prefix_basic(_: String) -> String { assert_eq(str_strip_prefix("foobar", "foo"), "bar", "strips matching prefix") assert_eq(str_strip_prefix("foobar", "baz"), "foobar", "no-match is identity") assert_eq(str_strip_prefix("hello", ""), "hello", "empty prefix is identity") assert_eq(str_strip_prefix("hello", "hello"), "", "full match yields empty") assert_eq(str_strip_prefix("hello", "HELLO"), "hello", "case-sensitive no-match") return "" } fn test_str_strip_suffix_basic(_: String) -> String { assert_eq(str_strip_suffix("hello.md", ".md"), "hello", "strips matching suffix") assert_eq(str_strip_suffix("hello.md", ".txt"), "hello.md", "no-match is identity") assert_eq(str_strip_suffix("hello", ""), "hello", "empty suffix is identity") assert_eq(str_strip_suffix("hello", "hello"), "", "full match yields empty") assert_eq(str_strip_suffix("hello", "HELLO"), "hello", "case-sensitive no-match") return "" } // ── str_find_chars ──────────────────────────────────────────────────────────── fn test_str_find_chars_basic(_: String) -> String { assert_int_eq(str_find_chars("hello world", " "), 5, "finds space at index 5") assert_int_eq(str_find_chars("hello", "xyz"), -1, "not found returns -1") assert_int_eq(str_find_chars("hello", ""), -1, "empty charset returns -1") assert_int_eq(str_find_chars("hello", "aeiou"), 1, "finds first vowel at index 1") assert_int_eq(str_find_chars("", "a"), -1, "search in empty string returns -1") assert_int_eq(str_find_chars("abc", "c"), 2, "finds last char of string") return "" } // ── str_char_at / str_char_code ─────────────────────────────────────────────── fn test_str_char_at_basic(_: String) -> String { assert_eq(str_char_at("hello", 0), "h", "first char") assert_eq(str_char_at("hello", 4), "o", "last char") assert_eq(str_char_at("hello", 2), "l", "middle char") assert_eq(str_char_at("hello", -1), "", "negative index yields empty") assert_eq(str_char_at("hello", 5), "", "out-of-bounds yields empty") assert_eq(str_char_at("", 0), "", "empty string yields empty") return "" } fn test_str_char_code_basic(_: String) -> String { assert_int_eq(str_char_code("A", 0), 65, "A has code 65") assert_int_eq(str_char_code("a", 0), 97, "a has code 97") assert_int_eq(str_char_code("0", 0), 48, "0 has code 48") assert_int_eq(str_char_code("hello", 0), 104, "h has code 104") assert_int_eq(str_char_code("", 0), 0, "empty string yields 0") assert_int_eq(str_char_code("a", 5), 0, "out-of-bounds yields 0") return "" } // ── str_pad_left / str_pad_right ───────────────────────────────────────────── fn test_str_pad_left_basic(_: String) -> String { assert_eq(str_pad_left("hi", 5, " "), " hi", "pads to width 5") assert_eq(str_pad_left("hi", 2, " "), "hi", "already at width is unchanged") assert_eq(str_pad_left("hi", 1, " "), "hi", "wider than width is unchanged") assert_eq(str_pad_left("5", 3, "0"), "005", "zero-pad a number") assert_int_eq(str_len(str_pad_left("ab", 7, "x")), 7, "padded to exact width") return "" } fn test_str_pad_right_basic(_: String) -> String { assert_eq(str_pad_right("hi", 5, " "), "hi ", "pads to width 5") assert_eq(str_pad_right("hi", 2, " "), "hi", "already at width is unchanged") assert_eq(str_pad_right("hi", 1, " "), "hi", "wider than width is unchanged") assert_int_eq(str_len(str_pad_right("ab", 7, "-")), 7, "padded to exact width") assert_starts_with(str_pad_right("ab", 7, "-"), "ab", "original string at start") return "" } // ── Character classification ────────────────────────────────────────────────── fn test_is_letter_basic(_: String) -> String { assert_true(is_letter("a"), "a is a letter") assert_true(is_letter("Z"), "Z is a letter") assert_true(is_letter("abc"), "abc all letters") assert_false(is_letter("1"), "1 is not a letter") assert_false(is_letter(""), "empty string is not a letter") assert_false(is_letter("a1"), "a1 has non-letter") return "" } fn test_is_digit_basic(_: String) -> String { assert_true(is_digit("0"), "0 is a digit") assert_true(is_digit("9"), "9 is a digit") assert_true(is_digit("123"), "123 all digits") assert_false(is_digit("a"), "a is not a digit") assert_false(is_digit(""), "empty is not a digit") assert_false(is_digit("1a"), "1a has non-digit") return "" } fn test_is_whitespace_basic(_: String) -> String { assert_true(is_whitespace(" "), "space is whitespace") assert_true(is_whitespace(" "), "multiple spaces") assert_false(is_whitespace("a"), "a is not whitespace") assert_false(is_whitespace(""), "empty string is not whitespace") assert_false(is_whitespace(" a"), "mixed is not all whitespace") return "" } // ── str_count_lines / str_count_words ──────────────────────────────────────── fn test_str_count_lines_basic(_: String) -> String { assert_int_eq(str_count_lines(""), 0, "empty string has 0 lines") assert_int_eq(str_count_lines("hello"), 1, "single line no newline") assert_int_eq(str_count_lines("a\nb"), 2, "two lines with newline") assert_int_eq(str_count_lines("a\nb\nc"), 3, "three lines") assert_int_eq(str_count_lines("a\n"), 1, "trailing newline not counted as extra line") return "" } fn test_str_count_words_basic(_: String) -> String { assert_int_eq(str_count_words(""), 0, "empty string has 0 words") assert_int_eq(str_count_words("hello"), 1, "single word") assert_int_eq(str_count_words("hello world"), 2, "two words") assert_int_eq(str_count_words(" hello world "), 2, "extra spaces do not add words") assert_int_eq(str_count_words("one two three four"), 4, "four words") return "" } // ── url_encode / url_decode ────────────────────────────────────────────────── fn test_url_encode_basic(_: String) -> String { assert_eq(url_encode("hello"), "hello", "plain string unchanged") assert_contains(url_encode("hello world"), "%20", "space encoded as %20") assert_true(str_len(url_encode("hello world")) > str_len("hello world"), "encoded is longer") let encoded: String = url_encode("hello world") let decoded: String = url_decode(encoded) assert_eq(decoded, "hello world", "decode reverses encode") return "" } fn test_url_roundtrip(_: String) -> String { let s: String = "name=hello world&value=42" let encoded: String = url_encode(s) let decoded: String = url_decode(encoded) assert_eq(decoded, s, "url encode/decode roundtrip") assert_true(!str_eq(encoded, s), "encoded differs from original") assert_true(str_len(encoded) >= str_len(s), "encoded is at least as long") return "" } // ── bool_to_str ─────────────────────────────────────────────────────────────── fn test_bool_to_str_basic(_: String) -> String { assert_eq(bool_to_str(true), "true", "true becomes 'true'") assert_eq(bool_to_str(false), "false", "false becomes 'false'") assert_true(str_eq(bool_to_str(1 == 1), "true"), "expression true") assert_true(str_eq(bool_to_str(1 == 2), "false"), "expression false") assert_int_eq(str_len(bool_to_str(true)), 4, "true has length 4") return "" } // ── str_to_bytes / bytes_to_str ─────────────────────────────────────────────── fn test_str_to_bytes_basic(_: String) -> String { let b: String = str_to_bytes("hi") assert_true(str_contains(b, "104"), "h has code 104") assert_true(str_contains(b, "105"), "i has code 105") assert_eq(str_to_bytes(""), "[]", "empty string yields empty array") assert_true(str_starts_with(b, "["), "bytes is JSON array") assert_true(str_ends_with(b, "]"), "bytes is JSON array") return "" } fn test_bytes_roundtrip(_: String) -> String { let s: String = "hello" let b: String = str_to_bytes(s) let s2: String = bytes_to_str(b) assert_eq(s2, s, "bytes roundtrip: hello") let s3: String = "ABC" let b3: String = str_to_bytes(s3) let s4: String = bytes_to_str(b3) assert_eq(s4, s3, "bytes roundtrip: ABC") assert_eq(bytes_to_str("[]"), "", "empty bytes yields empty string") return "" }