esc
Externally Scriptable Editor
git clone git://mccd.space/esc
| Log | Files | Refs | README |
test_strbuf.c (3689B)
1 #include "../strbuf.h"
2 #include "test_harness.h"
3 #include <stdlib.h>
4 #include <string.h>
5
6 /* ---- suite_init_free ---------------------------------------------------- */
7
8 static void suite_init_free(void) {
9 RUN_SUITE(suite_init_free);
10
11 /* default cap (0 -> 1024) */
12 StrBuf sb;
13 strbuf_init(&sb, 0);
14 ASSERT_NOT_NULL(sb.data);
15 ASSERT_EQ_INT((int)sb.len, 0);
16 ASSERT(sb.cap >= 1024);
17 strbuf_free(&sb);
18 ASSERT_NULL(sb.data);
19 ASSERT_EQ_INT((int)sb.len, 0);
20
21 /* explicit small cap */
22 strbuf_init(&sb, 4);
23 ASSERT_NOT_NULL(sb.data);
24 ASSERT_EQ_INT((int)sb.cap, 4);
25 strbuf_free(&sb);
26 ASSERT_NULL(sb.data);
27 }
28
29 /* ---- suite_insert -------------------------------------------------------- */
30
31 static void suite_insert(void) {
32 RUN_SUITE(suite_insert);
33
34 StrBuf sb;
35 strbuf_init(&sb, 64);
36
37 /* insert at position 0 into empty buffer */
38 ASSERT(strbuf_insert(&sb, 0, "hello", 5));
39 ASSERT_EQ_INT((int)sb.len, 5);
40 ASSERT_EQ_STR(sb.data, "hello");
41
42 /* append at end */
43 ASSERT(strbuf_insert(&sb, 5, " world", 6));
44 ASSERT_EQ_INT((int)sb.len, 11);
45 ASSERT_EQ_STR(sb.data, "hello world");
46
47 /* insert in middle */
48 ASSERT(strbuf_insert(&sb, 5, ",", 1));
49 ASSERT_EQ_INT((int)sb.len, 12);
50 ASSERT_EQ_STR(sb.data, "hello, world");
51
52 /* pos > len clamps to end */
53 ASSERT(strbuf_insert(&sb, 9999, "!", 1));
54 ASSERT_EQ_INT((int)sb.len, 13);
55 ASSERT_EQ_STR(sb.data, "hello, world!");
56
57 /* empty insert (text_len == 0) is a no-op */
58 ASSERT(strbuf_insert(&sb, 0, "", 0));
59 ASSERT_EQ_INT((int)sb.len, 13);
60
61 strbuf_free(&sb);
62 }
63
64 /* ---- suite_delete -------------------------------------------------------- */
65
66 static void suite_delete(void) {
67 RUN_SUITE(suite_delete);
68
69 StrBuf sb;
70 strbuf_init(&sb, 64);
71 strbuf_insert(&sb, 0, "hello, world!", 13);
72
73 /* delete from middle */
74 strbuf_delete(&sb, 5, 7); /* remove ", world" */
75 ASSERT_EQ_INT((int)sb.len, 6);
76 ASSERT_EQ_STR(sb.data, "hello!");
77
78 /* pos >= len is a no-op */
79 strbuf_delete(&sb, 6, 1);
80 ASSERT_EQ_INT((int)sb.len, 6);
81
82 /* delete past end clamps */
83 strbuf_delete(&sb, 3, 100);
84 ASSERT_EQ_INT((int)sb.len, 3);
85 ASSERT_EQ_STR(sb.data, "hel");
86
87 /* delete at pos 0 */
88 strbuf_delete(&sb, 0, 2);
89 ASSERT_EQ_INT((int)sb.len, 1);
90 ASSERT_EQ_STR(sb.data, "l");
91
92 strbuf_free(&sb);
93 }
94
95 /* ---- suite_multibyte ----------------------------------------------------- */
96
97 static void suite_multibyte(void) {
98 RUN_SUITE(suite_multibyte);
99
100 /* "café" in UTF-8: c=1, a=1, f=1, é=2 bytes -> 5 bytes total */
101 StrBuf sb;
102 strbuf_init(&sb, 64);
103 strbuf_insert(&sb, 0, "caf\xc3\xa9", 5);
104 ASSERT_EQ_INT((int)sb.len, 5);
105 /* Verify individual bytes are preserved */
106 ASSERT((unsigned char)sb.data[0] == 'c');
107 ASSERT((unsigned char)sb.data[1] == 'a');
108 ASSERT((unsigned char)sb.data[2] == 'f');
109 ASSERT((unsigned char)sb.data[3] == 0xc3);
110 ASSERT((unsigned char)sb.data[4] == 0xa9);
111
112 strbuf_free(&sb);
113 }
114
115 /* ---- suite_capacity_growth ----------------------------------------------- */
116
117 static void suite_capacity_growth(void) {
118 RUN_SUITE(suite_capacity_growth);
119
120 StrBuf sb;
121 strbuf_init(&sb, 4);
122 ASSERT_EQ_INT((int)sb.cap, 4);
123
124 /* Insert 200 bytes worth of 'x' characters one chunk at a time */
125 char chunk[20];
126 memset(chunk, 'x', sizeof(chunk));
127 for (int i = 0; i < 10; i++) {
128 ASSERT(strbuf_insert(&sb, sb.len, chunk, sizeof(chunk)));
129 }
130
131 ASSERT_EQ_INT((int)sb.len, 200);
132 ASSERT(sb.cap >= 200);
133
134 /* Verify all data is intact */
135 for (int i = 0; i < 200; i++) {
136 ASSERT(sb.data[i] == 'x');
137 }
138
139 strbuf_free(&sb);
140 }
141
142 /* ---- main ---------------------------------------------------------------- */
143
144 int main(void) {
145 suite_init_free();
146 suite_insert();
147 suite_delete();
148 suite_multibyte();
149 suite_capacity_growth();
150 REPORT_AND_EXIT();
151 }