src/server/test/strreplace.c

changeset 634
9728d3a2ac97
equal deleted inserted replaced
633:392ec9026b07 634:9728d3a2ac97
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2025 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "strreplace.h"
30 #include "../util/strreplace.h"
31 #include <cx/mempool.h>
32
33 CX_TEST(test_string_template_compile) {
34 CxMempool *mp = cxMempoolCreate(100, CX_MEMPOOL_TYPE_ADVANCED);
35 const CxAllocator *a = mp->allocator;
36
37 StringTemplate *tpl = NULL;
38 StringTemplateSegment *s0 = NULL;
39 StringTemplateSegment *s1 = NULL;
40 StringTemplateSegment *s2 = NULL;
41 StringTemplateSegment *s3 = NULL;
42 CX_TEST_DO {
43 // single segment tests
44
45 tpl = string_template_compile(a, cx_str(""));
46 CX_TEST_ASSERT(tpl); // empty str
47 CX_TEST_ASSERT(!tpl->segments);
48 string_template_free(tpl);
49
50 tpl = string_template_compile(a, cx_str("static"));
51 CX_TEST_ASSERT(tpl); // static
52 CX_TEST_ASSERT(tpl->segments);
53 CX_TEST_ASSERT(!tpl->segments->next);
54 CX_TEST_ASSERT(!cx_strcmp(tpl->segments->str, "static"));
55 CX_TEST_ASSERT(tpl->segments->type == STRING_SEGMENT_STR);
56 string_template_free(tpl);
57
58 tpl = string_template_compile(a, cx_str("$$"));
59 CX_TEST_ASSERT(tpl); // $
60 CX_TEST_ASSERT(tpl->segments);
61 CX_TEST_ASSERT(!tpl->segments->next);
62 CX_TEST_ASSERT(!cx_strcmp(tpl->segments->str, "$"));
63 CX_TEST_ASSERT(tpl->segments->type == STRING_SEGMENT_STR);
64 string_template_free(tpl);
65
66 tpl = string_template_compile(a, cx_str("$var"));
67 CX_TEST_ASSERT(tpl); // var
68 CX_TEST_ASSERT(tpl->segments);
69 CX_TEST_ASSERT(!tpl->segments->next);
70 CX_TEST_ASSERT(!cx_strcmp(tpl->segments->str, "var"));
71 CX_TEST_ASSERT(tpl->segments->type == STRING_SEGMENT_VAR_PLACEHOLDER);
72 string_template_free(tpl);
73
74 tpl = string_template_compile(a, cx_str("$12"));
75 CX_TEST_ASSERT(tpl); // 12
76 CX_TEST_ASSERT(tpl->segments);
77 CX_TEST_ASSERT(!tpl->segments->next);
78 CX_TEST_ASSERT(!cx_strcmp(tpl->segments->str, "12"));
79 CX_TEST_ASSERT(tpl->segments->type == STRING_SEGMENT_NUM_PLACEHOLDER);
80 CX_TEST_ASSERT(tpl->segments->num == 12);
81 string_template_free(tpl);
82
83 // double segment tests
84 tpl = string_template_compile(a, cx_str("test $var"));
85 CX_TEST_ASSERT(tpl);
86 s0 = tpl->segments;
87 CX_TEST_ASSERT(s0);
88 s1 = s0->next;
89 CX_TEST_ASSERT(s1);
90 CX_TEST_ASSERT(!cx_strcmp(s0->str, "test "));
91 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_STR);
92 CX_TEST_ASSERT(!cx_strcmp(s1->str, "var"));
93 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_VAR_PLACEHOLDER);
94 CX_TEST_ASSERT(s1->next == NULL);
95 string_template_free(tpl);
96
97 tpl = string_template_compile(a, cx_str("test ${var}"));
98 CX_TEST_ASSERT(tpl);
99 s0 = tpl->segments;
100 CX_TEST_ASSERT(s0);
101 s1 = s0->next;
102 CX_TEST_ASSERT(s1);
103 CX_TEST_ASSERT(!cx_strcmp(s0->str, "test "));
104 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_STR);
105 CX_TEST_ASSERT(!cx_strcmp(s1->str, "var"));
106 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_VAR_PLACEHOLDER);
107 CX_TEST_ASSERT(s1->next == NULL);
108 string_template_free(tpl);
109
110 tpl = string_template_compile(a, cx_str("$var test"));
111 CX_TEST_ASSERT(tpl);
112 s0 = tpl->segments;
113 CX_TEST_ASSERT(s0);
114 s1 = s0->next;
115 CX_TEST_ASSERT(s1);
116 CX_TEST_ASSERT(!cx_strcmp(s0->str, "var"));
117 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_VAR_PLACEHOLDER);
118 CX_TEST_ASSERT(!cx_strcmp(s1->str, " test"));
119 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_STR);
120 CX_TEST_ASSERT(s1->next == NULL);
121 string_template_free(tpl);
122
123 tpl = string_template_compile(a, cx_str("$13 test"));
124 CX_TEST_ASSERT(tpl);
125 s0 = tpl->segments;
126 CX_TEST_ASSERT(s0);
127 s1 = s0->next;
128 CX_TEST_ASSERT(s1);
129 CX_TEST_ASSERT(!cx_strcmp(s0->str, "13"));
130 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_NUM_PLACEHOLDER);
131 CX_TEST_ASSERT(!cx_strcmp(s1->str, " test"));
132 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_STR);
133 CX_TEST_ASSERT(s1->next == NULL);
134 string_template_free(tpl);
135
136 // multi segment tests
137 tpl = string_template_compile(a, cx_str("test$var1$var2"));
138 CX_TEST_ASSERT(tpl);
139 s0 = tpl->segments;
140 CX_TEST_ASSERT(s0);
141 s1 = s0->next;
142 CX_TEST_ASSERT(s1);
143 s2 = s1->next;
144 CX_TEST_ASSERT(2);
145 CX_TEST_ASSERT(!cx_strcmp(s0->str, "test"));
146 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_STR);
147 CX_TEST_ASSERT(!cx_strcmp(s1->str, "var1"));
148 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_VAR_PLACEHOLDER);
149 CX_TEST_ASSERT(!cx_strcmp(s2->str, "var2"));
150 CX_TEST_ASSERT(s2->type == STRING_SEGMENT_VAR_PLACEHOLDER);
151 CX_TEST_ASSERT(s2->next == NULL);
152 string_template_free(tpl);
153
154 tpl = string_template_compile(a, cx_str("test/$1/$2"));
155 CX_TEST_ASSERT(tpl);
156 s0 = tpl->segments;
157 CX_TEST_ASSERT(s0);
158 s1 = s0->next;
159 CX_TEST_ASSERT(s1);
160 s2 = s1->next;
161 CX_TEST_ASSERT(2);
162 s3 = s2->next;
163 CX_TEST_ASSERT(s3);
164 CX_TEST_ASSERT(!cx_strcmp(s0->str, "test/"));
165 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_STR);
166 CX_TEST_ASSERT(!cx_strcmp(s1->str, "1"));
167 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_NUM_PLACEHOLDER);
168 CX_TEST_ASSERT(!cx_strcmp(s2->str, "/"));
169 CX_TEST_ASSERT(s2->type == STRING_SEGMENT_STR);
170 CX_TEST_ASSERT(!cx_strcmp(s3->str, "2"));
171 CX_TEST_ASSERT(s3->type == STRING_SEGMENT_NUM_PLACEHOLDER);
172 CX_TEST_ASSERT(s3->next == NULL);
173 string_template_free(tpl);
174
175 tpl = string_template_compile(a, cx_str("ab$$cd/${1}/${2}"));
176 CX_TEST_ASSERT(tpl);
177 s0 = tpl->segments;
178 CX_TEST_ASSERT(s0);
179 s1 = s0->next;
180 CX_TEST_ASSERT(s1);
181 s2 = s1->next;
182 CX_TEST_ASSERT(2);
183 s3 = s2->next;
184 CX_TEST_ASSERT(s3);
185 CX_TEST_ASSERT(!cx_strcmp(s0->str, "ab$cd/"));
186 CX_TEST_ASSERT(s0->type == STRING_SEGMENT_STR);
187 CX_TEST_ASSERT(!cx_strcmp(s1->str, "1"));
188 CX_TEST_ASSERT(s1->type == STRING_SEGMENT_NUM_PLACEHOLDER);
189 CX_TEST_ASSERT(!cx_strcmp(s2->str, "/"));
190 CX_TEST_ASSERT(s2->type == STRING_SEGMENT_STR);
191 CX_TEST_ASSERT(!cx_strcmp(s3->str, "2"));
192 CX_TEST_ASSERT(s3->type == STRING_SEGMENT_NUM_PLACEHOLDER);
193 CX_TEST_ASSERT(s3->next == NULL);
194 string_template_free(tpl);
195 }
196
197 cxMempoolFree(mp);
198 }
199
200 CX_TEST(test_string_template_compile_error) {
201 // TODO
202 }
203
204 static cxmutstr get_var(const CxAllocator *a, StringTemplateSegment *seg, void *userdata, WSBool *free_str) {
205 cxmutstr var_value = cx_strcat_a(a, 3, cx_str("var("), seg->str, cx_str(")"));
206 *free_str = TRUE;
207 return var_value;
208 }
209
210 CX_TEST(test_string_template_write_to) {
211 CxMempool *mp = cxMempoolCreate(100, CX_MEMPOOL_TYPE_ADVANCED);
212 const CxAllocator *a = mp->allocator;
213
214 CxBuffer buf;
215 cxBufferInit(&buf, NULL, 1024, a, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
216 StringTemplate *tpl = NULL;
217 CX_TEST_DO {
218 tpl = string_template_compile(a, cx_str("hello world"));
219 ssize_t r = string_template_write_to(tpl, a, get_var, NULL, &buf, (cx_write_func)cxBufferWrite);
220 CX_TEST_ASSERT(r > 0);
221 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf.space, buf.pos), cx_str("hello world")));
222 buf.pos = 0;
223 string_template_free(tpl);
224
225 tpl = string_template_compile(a, cx_str("insert $var here"));
226 r = string_template_write_to(tpl, a, get_var, NULL, &buf, (cx_write_func)cxBufferWrite);
227 CX_TEST_ASSERT(r > 0);
228 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf.space, buf.pos), cx_str("insert var(var) here")));
229 buf.pos = 0;
230 string_template_free(tpl);
231
232 tpl = string_template_compile(a, cx_str("$1$2$3$4$5"));
233 r = string_template_write_to(tpl, a, get_var, NULL, &buf, (cx_write_func)cxBufferWrite);
234 CX_TEST_ASSERT(r > 0);
235 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf.space, buf.pos), cx_str("var(1)var(2)var(3)var(4)var(5)")));
236 buf.pos = 0;
237 string_template_free(tpl);
238
239 tpl = string_template_compile(a, cx_str("$$escape$$$myvar$$end"));
240 r = string_template_write_to(tpl, a, get_var, NULL, &buf, (cx_write_func)cxBufferWrite);
241 CX_TEST_ASSERT(r > 0);
242 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf.space, buf.pos), cx_str("$escape$var(myvar)$end")));
243 buf.pos = 0;
244 string_template_free(tpl);
245
246 tpl = string_template_compile(a, cx_str("$$$$${test}"));
247 r = string_template_write_to(tpl, a, get_var, NULL, &buf, (cx_write_func)cxBufferWrite);
248 CX_TEST_ASSERT(r > 0);
249 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf.space, buf.pos), cx_str("$$var(test)")));
250 buf.pos = 0;
251 string_template_free(tpl);
252
253 tpl = string_template_compile(a, cx_str("${123}end"));
254 r = string_template_write_to(tpl, a, get_var, NULL, &buf, (cx_write_func)cxBufferWrite);
255 CX_TEST_ASSERT(r > 0);
256 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf.space, buf.pos), cx_str("var(123)end")));
257 buf.pos = 0;
258 string_template_free(tpl);
259 }
260 cxBufferDestroy(&buf);
261 cxMempoolFree(mp);
262 }
263
264 CX_TEST(test_string_template_build_string) {
265 CxMempool *mp = cxMempoolCreate(100, CX_MEMPOOL_TYPE_ADVANCED);
266 const CxAllocator *a = mp->allocator;
267
268 StringTemplate *tpl = NULL;
269 CX_TEST_DO {
270 tpl = string_template_compile(a, cx_str("insert $var here"));
271 cxmutstr str = string_template_build_string(tpl, a, get_var, NULL);
272 CX_TEST_ASSERT(str.ptr);
273 CX_TEST_ASSERT(!cx_strcmp(str, cx_str("insert var(var) here")));
274 string_template_free(tpl);
275 }
276
277 cxMempoolFree(mp);
278 }

mercurial