cbase 1.50.0
C/C++ Static Template
Loading...
Searching...
No Matches
test_str_builder.c
1#include "base/str_builder.h"
3#include "memory/mem_arena.h"
4#include "test/test.h"
5#include <string.h>
6
7TEST_CASE(sb_empty_join)
8{
9 MemArena scratch_arena = mem_arena_create(KB(64));
10 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
11 EXPECT_FATAL(scratch_arena.base != NULL);
12
13 StringBuilder sb = {0};
14 String8 result = sb_join(&sb, &scratch);
15
16 EXPECT(result.str == NULL);
17 EXPECT(result.size == 0);
18
19 mem_arena_release(&scratch_arena);
20}
21
22TEST_CASE(sb_single_append)
23{
24 MemArena scratch_arena = mem_arena_create(KB(64));
25 MemArena out_arena = mem_arena_create(KB(64));
26 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
27 MemAllocator out = mem_arena_allocator(&out_arena);
28 EXPECT_FATAL(scratch_arena.base != NULL);
29 EXPECT_FATAL(out_arena.base != NULL);
30
31 StringBuilder sb = {0};
32 sb_append(&sb, &scratch, STR8("Hello"));
33
34 EXPECT(sb.node_count == 1);
35 EXPECT(sb.total_size == 5);
36
37 String8 result = sb_join(&sb, &out);
38 EXPECT(result.size == 5);
39 EXPECT(str8_match(result, STR8("Hello")));
40
41 mem_arena_release(&scratch_arena);
42 mem_arena_release(&out_arena);
43}
44
45TEST_CASE(sb_multiple_append)
46{
47 MemArena scratch_arena = mem_arena_create(KB(64));
48 MemArena out_arena = mem_arena_create(KB(64));
49 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
50 MemAllocator out = mem_arena_allocator(&out_arena);
51 EXPECT_FATAL(scratch_arena.base != NULL);
52 EXPECT_FATAL(out_arena.base != NULL);
53
54 StringBuilder sb = {0};
55 sb_append(&sb, &scratch, STR8("Hello"));
56 sb_append(&sb, &scratch, STR8(", "));
57 sb_append(&sb, &scratch, STR8("World"));
58 sb_append(&sb, &scratch, STR8("!"));
59
60 EXPECT(sb.node_count == 4);
61 EXPECT(sb.total_size == 13);
62
63 String8 result = sb_join(&sb, &out);
64 EXPECT(result.size == 13);
65 EXPECT(str8_match(result, STR8("Hello, World!")));
66
67 mem_arena_release(&scratch_arena);
68 mem_arena_release(&out_arena);
69}
70
72{
73 MemArena scratch_arena = mem_arena_create(KB(64));
74 MemArena out_arena = mem_arena_create(KB(64));
75 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
76 MemAllocator out = mem_arena_allocator(&out_arena);
77 EXPECT_FATAL(scratch_arena.base != NULL);
78 EXPECT_FATAL(out_arena.base != NULL);
79
80 StringBuilder sb = {0};
81 sb_append_cstr(&sb, &scratch, "foo");
82 sb_append_cstr(&sb, &scratch, "bar");
83
84 String8 result = sb_join(&sb, &out);
85 EXPECT(str8_match(result, STR8("foobar")));
86
87 mem_arena_release(&scratch_arena);
88 mem_arena_release(&out_arena);
89}
90
92{
93 MemArena scratch_arena = mem_arena_create(KB(64));
94 MemArena out_arena = mem_arena_create(KB(64));
95 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
96 MemAllocator out = mem_arena_allocator(&out_arena);
97 EXPECT_FATAL(scratch_arena.base != NULL);
98 EXPECT_FATAL(out_arena.base != NULL);
99
100 StringBuilder sb = {0};
101 sb_append(&sb, &scratch, STR8("Value: "));
102 sb_append_fmt(&sb, &scratch, "%d", 42);
103
104 String8 result = sb_join(&sb, &out);
105 EXPECT(str8_match(result, STR8("Value: 42")));
106
107 mem_arena_release(&scratch_arena);
108 mem_arena_release(&out_arena);
109}
110
111TEST_CASE(sb_result_in_separate_alloc)
112{
113 // Verifies that the result lives in out and scratch can be
114 // cleared independently without corrupting the joined string.
115 MemArena scratch_arena = mem_arena_create(KB(64));
116 MemArena out_arena = mem_arena_create(KB(64));
117 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
118 MemAllocator out = mem_arena_allocator(&out_arena);
119 EXPECT_FATAL(scratch_arena.base != NULL);
120 EXPECT_FATAL(out_arena.base != NULL);
121
122 StringBuilder sb = {0};
123 sb_append_fmt(&sb, &scratch, "ping %d", 1);
124 sb_append_fmt(&sb, &scratch, " pong %d", 2);
125
126 String8 result = sb_join(&sb, &out);
127
128 // Clear scratch - result must still be valid since it lives in out.
129 mem_free_all(&scratch);
130
131 EXPECT(str8_match(result, STR8("ping 1 pong 2")));
132
133 mem_arena_release(&scratch_arena);
134 mem_arena_release(&out_arena);
135}
136
137TEST_CASE(sb_reset_and_reuse)
138{
139 MemArena scratch_arena = mem_arena_create(KB(64));
140 MemArena out_arena = mem_arena_create(KB(64));
141 MemAllocator scratch = mem_arena_allocator(&scratch_arena);
142 MemAllocator out = mem_arena_allocator(&out_arena);
143 EXPECT_FATAL(scratch_arena.base != NULL);
144 EXPECT_FATAL(out_arena.base != NULL);
145
146 StringBuilder sb = {0};
147 sb_append(&sb, &scratch, STR8("first"));
148 sb_reset(&sb);
149
150 EXPECT(sb.node_count == 0);
151 EXPECT(sb.total_size == 0);
152 EXPECT(sb.first == NULL);
153
154 sb_append(&sb, &scratch, STR8("second"));
155 String8 result = sb_join(&sb, &out);
156 EXPECT(str8_match(result, STR8("second")));
157
158 mem_arena_release(&scratch_arena);
159 mem_arena_release(&out_arena);
160}
function void mem_free_all(MemAllocator *alloc)
Clears the entire allocator in one shot (e.g. arena reset, pool reset).
void mem_arena_release(MemArena *arena)
Returns all virtual memory back to the operating system.
Definition mem_arena.c:59
struct MemAllocator mem_arena_allocator(MemArena *arena)
Wraps a MemArena in the generic MemAllocator interface.
Definition mem_arena.c:172
MemArena mem_arena_create(usize reserve_size)
Initializes a new virtual memory Arena.
Definition mem_arena.c:48
#define KB(x)
Definition base_types.h:119
static void sb_append_cstr(StringBuilder *sb, MemAllocator *alloc, const char *cstr)
Appends a null-terminated C string to the builder.
static void sb_reset(StringBuilder *sb)
Resets the builder to empty without touching the allocator.
static void sb_append(StringBuilder *sb, MemAllocator *alloc, String8 str)
Appends a String8 slice to the builder.
Definition str_builder.h:75
static String8 sb_join(StringBuilder *sb, MemAllocator *out_alloc)
Materializes all appended segments into a single contiguous String8.
static void sb_append_fmt(StringBuilder *sb, MemAllocator *alloc, const char *fmt,...)
Appends a printf-style formatted string to the builder.
static b32 str8_match(String8 a, String8 b)
Returns 1 if a and b contain identical bytes (case-sensitive).
#define STR8(s)
Wraps a C string literal into a String8 at compile time.
Generic interface for abstracting memory allocators.
High-performance virtual memory Arena Allocator.
Allocator-agnostic StringBuilder for efficient string concatenation.
An abstract allocator interface.
A virtual memory-backed linear allocator.
Definition mem_arena.h:70
u8 * base
Definition mem_arena.h:71
A sized UTF-8 string slice.
usize size
An allocator-agnostic string builder.
Definition str_builder.h:56
String8Node * first
Definition str_builder.h:57
Single-header testing framework with pretty-printed output.
#define EXPECT(cond)
Evaluates a condition. Records and counts the failure if false.
Definition test.h:161
#define TEST_CASE(name)
Declares a test case function.
Definition test.h:205
#define EXPECT_FATAL(cond)
Like EXPECT but aborts immediately on failure.
Definition test.h:175