esc

Externally Scriptable Editor

git clone git://mccd.space/esc

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 }