blob: 35deba58013f3be19c06a25f0b9398d45e1661be [file] [log] [blame]
Krzysztof Chruscinskidccfe762021-03-03 10:48:30 +01001/*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +01006
Fabio Baltieridef23012022-07-19 14:16:24 +00007#include <zephyr/ztest.h>
Gerard Marull-Paretasade7ccb2022-05-06 10:44:33 +02008#include <zephyr/sys/cbprintf.h>
9#include <zephyr/linker/utils.h>
Krzysztof Chruscinskidccfe762021-03-03 10:48:30 +010010
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +010011#define CBPRINTF_DEBUG 1
Krzysztof Chruscinskidccfe762021-03-03 10:48:30 +010012
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +010013#ifndef CBPRINTF_PACKAGE_ALIGN_OFFSET
14#define CBPRINTF_PACKAGE_ALIGN_OFFSET 0
15#endif
16
17#define ALIGN_OFFSET (sizeof(void *) * CBPRINTF_PACKAGE_ALIGN_OFFSET)
18
19struct out_buffer {
20 char *buf;
21 size_t idx;
22 size_t size;
23};
24
25static int out(int c, void *dest)
26{
27 int rv = EOF;
28 struct out_buffer *buf = (struct out_buffer *)dest;
29
30 if (buf->idx < buf->size) {
31 buf->buf[buf->idx++] = (char)(unsigned char)c;
32 rv = (int)(unsigned char)c;
33 }
34 return rv;
35}
36
37static char static_buf[512];
38static char runtime_buf[512];
39static char compare_buf[128];
40
41static void dump(const char *desc, uint8_t *package, size_t len)
42{
43 printk("%s package %p:\n", desc, package);
44 for (size_t i = 0; i < len; i++) {
45 printk("%02x ", package[i]);
46 }
47 printk("\n");
48}
49
50static void unpack(const char *desc, struct out_buffer *buf,
51 uint8_t *package, size_t len)
52{
53 cbpprintf((cbprintf_cb)out, buf, package);
54 buf->buf[buf->idx] = 0;
55 zassert_equal(strcmp(buf->buf, compare_buf), 0,
56 "Strings differ\nexp: |%s|\ngot: |%s|\n",
57 compare_buf, buf->buf);
58}
59
60#define TEST_PACKAGING(flags, fmt, ...) do { \
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +010061 int must_runtime = CBPRINTF_MUST_RUNTIME_PACKAGE(flags, fmt, __VA_ARGS__); \
Michał Barnaśdae8efa2022-08-17 17:36:15 +020062 zassert_equal(must_runtime, !Z_C_GENERIC); \
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +010063 snprintfcb(compare_buf, sizeof(compare_buf), fmt, __VA_ARGS__); \
64 printk("-----------------------------------------\n"); \
65 printk("%s\n", compare_buf); \
66 uint8_t *pkg; \
67 struct out_buffer rt_buf = { \
68 .buf = runtime_buf, .idx = 0, .size = sizeof(runtime_buf) \
69 }; \
70 int rc = cbprintf_package(NULL, ALIGN_OFFSET, 0, fmt, __VA_ARGS__); \
71 zassert_true(rc > 0, "cbprintf_package() returned %d", rc); \
72 int len = rc; \
73 /* Aligned so the package is similar to the static one. */ \
74 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) \
75 rt_package[len + ALIGN_OFFSET]; \
76 memset(rt_package, 0, len + ALIGN_OFFSET); \
77 pkg = &rt_package[ALIGN_OFFSET]; \
78 rc = cbprintf_package(pkg, len, 0, fmt, __VA_ARGS__); \
79 zassert_equal(rc, len, "cbprintf_package() returned %d, expected %d", \
80 rc, len); \
81 dump("runtime", pkg, len); \
82 unpack("runtime", &rt_buf, pkg, len); \
83 struct out_buffer st_buf = { \
84 .buf = static_buf, .idx = 0, .size = sizeof(static_buf) \
85 }; \
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +010086 CBPRINTF_STATIC_PACKAGE(NULL, 0, len, ALIGN_OFFSET, flags, fmt, __VA_ARGS__); \
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +010087 zassert_true(len > 0, "CBPRINTF_STATIC_PACKAGE() returned %d", len); \
88 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) \
89 package[len + ALIGN_OFFSET];\
90 int outlen; \
91 pkg = &package[ALIGN_OFFSET]; \
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +010092 CBPRINTF_STATIC_PACKAGE(pkg, len, outlen, ALIGN_OFFSET, flags, fmt, __VA_ARGS__);\
Michał Barnaśdae8efa2022-08-17 17:36:15 +020093 zassert_equal(len, outlen); \
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +010094 dump("static", pkg, len); \
95 unpack("static", &st_buf, pkg, len); \
96} while (0)
97
Tristan Honscheide4d24fc2021-11-15 16:46:45 -070098ZTEST(cbprintf_package, test_cbprintf_package)
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +010099{
100 volatile signed char sc = -11;
101 int i = 100;
102 char c = 'a';
103 static const short s = -300;
104 long li = -1111111111;
105 long long lli = 0x1122334455667788;
106 unsigned char uc = 100;
107 unsigned int ui = 0x12345;
108 unsigned short us = 0x1234;
109 unsigned long ul = 0xaabbaabb;
110 unsigned long long ull = 0xaabbaabbaabb;
111 void *vp = NULL;
112 static const char *str = "test";
113 char *pstr = (char *)str;
114 int rv;
115
Nazar Kazakovf483b1b2022-03-16 21:07:43 +0000116 /* tests to exercise different element alignments */
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100117 TEST_PACKAGING(0, "test long %x %lx %x", 0xb1b2b3b4, li, 0xe4e3e2e1);
118 TEST_PACKAGING(0, "test long long %x %llx %x", 0xb1b2b3b4, lli, 0xe4e3e2e1);
119
120 /* tests with varied elements */
121 TEST_PACKAGING(0, "test %d %hd %hhd", i, s, sc);
122 TEST_PACKAGING(0, "test %ld %llx %hhu %hu %u", li, lli, uc, us, ui);
123 TEST_PACKAGING(0, "test %lu %llu", ul, ull);
124 TEST_PACKAGING(0, "test %c %p", c, vp);
125
126 /* Runtime packaging is still possible when const strings are used. */
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +0100127 TEST_PACKAGING(CBPRINTF_PACKAGE_CONST_CHAR_RO,
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100128 "test %s %s", str, (const char *)pstr);
129
130 /* When flag is set but argument is char * runtime packaging must be used. */
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +0100131 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO,
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100132 "test %s %s", str, pstr);
133 zassert_true(rv != 0, "Unexpected value %d", rv);
134
135 /* When const char * are used but flag is not used then runtime packaging must be used. */
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +0100136 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, "test %s %s", str, (const char *)pstr);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100137 zassert_true(rv != 0, "Unexpected value %d", rv);
138
Krzysztof Chruscinskic917e6c2022-02-22 14:31:26 +0100139 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO,
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100140 "test %s", (char *)str);
141 zassert_true(rv != 0, "Unexpected value %d", rv);
142
143 if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
144 float f = -1.234f;
145 double d = 1.2333;
146
147 TEST_PACKAGING(0, "test double %x %f %x", 0xb1b2b3b4, d, 0xe4e3e2e1);
148 TEST_PACKAGING(0, "test %f %a", (double)f, d);
Krzysztof Chruscinskifd517ff2022-03-08 13:01:45 +0100149#if CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE && !(defined(CONFIG_RISCV) && !defined(CONFIG_64BIT))
150 /* Excluding riscv32 which does not handle long double correctly. */
Ryan McClellandbf1efa82023-07-19 16:51:11 -0700151 long double ld = 1.2333L;
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100152
153 TEST_PACKAGING(0, "test %Lf", ld);
154#endif
155 }
156}
157
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700158ZTEST(cbprintf_package, test_cbprintf_rw_str_indexes)
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100159{
160 int len0, len1, len2;
161 static const char *test_str = "test %d %s";
162 static const char *test_str1 = "lorem ipsum";
163 uint8_t str_idx;
164 char *addr;
165
166 len0 = cbprintf_package(NULL, 0, 0, test_str, 100, test_str1);
167 if (len0 > (int)(4 * sizeof(void *))) {
168 TC_PRINT("Skipping test, platform does not detect RO strings.\n");
169 ztest_test_skip();
170 }
171
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200172 zassert_true(len0 > 0);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100173 len1 = cbprintf_package(NULL, 0, CBPRINTF_PACKAGE_ADD_STRING_IDXS,
174 test_str, 100, test_str1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200175 zassert_true(len1 > 0);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100176
177 CBPRINTF_STATIC_PACKAGE(NULL, 0, len2, 0,
178 CBPRINTF_PACKAGE_ADD_STRING_IDXS,
179 test_str, 100, test_str1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200180 zassert_true(len2 > 0);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100181
182 /* package with string indexes will contain two more bytes holding indexes
183 * of string parameter locations.
184 */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200185 zassert_equal(len0 + 2, len1);
186 zassert_equal(len0 + 2, len2);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100187
188 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package0[len0];
189 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package1[len1];
190 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package2[len2];
191
192 len0 = cbprintf_package(package0, sizeof(package0), 0,
193 test_str, 100, test_str1);
194
195 len1 = cbprintf_package(package1, sizeof(package1) - 1,
196 CBPRINTF_PACKAGE_ADD_STRING_IDXS,
197 test_str, 100, test_str1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200198 zassert_equal(-ENOSPC, len1);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100199
200 CBPRINTF_STATIC_PACKAGE(package2, sizeof(package2) - 1, len2, 0,
201 CBPRINTF_PACKAGE_ADD_STRING_IDXS,
202 test_str, 100, test_str1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200203 zassert_equal(-ENOSPC, len2);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100204
205 len1 = cbprintf_package(package1, sizeof(package1),
206 CBPRINTF_PACKAGE_ADD_STRING_IDXS,
207 test_str, 100, test_str1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200208 zassert_equal(len0 + 2, len1);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100209
210 CBPRINTF_STATIC_PACKAGE(package2, sizeof(package2), len2, 0,
211 CBPRINTF_PACKAGE_ADD_STRING_IDXS,
212 test_str, 100, test_str1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200213 zassert_equal(len0 + 2, len2);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100214
Daniel Leungaff6e8b2022-02-17 13:51:00 -0800215 union cbprintf_package_hdr *desc0 = (union cbprintf_package_hdr *)package0;
216 union cbprintf_package_hdr *desc1 = (union cbprintf_package_hdr *)package1;
217 union cbprintf_package_hdr *desc2 = (union cbprintf_package_hdr *)package2;
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100218
219 /* Compare descriptor content. Second package has one ro string index. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200220 zassert_equal(desc0->desc.ro_str_cnt, 0);
221 zassert_equal(desc1->desc.ro_str_cnt, 2);
222 zassert_equal(desc2->desc.ro_str_cnt, 2);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100223
224 int *p = (int *)package1;
225
226 str_idx = package1[len0];
227 addr = *(char **)&p[str_idx];
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200228 zassert_equal(addr, test_str);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100229
230 str_idx = package2[len0];
231 addr = *(char **)&p[str_idx];
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200232 zassert_equal(addr, test_str);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100233
234 str_idx = package1[len0 + 1];
235 addr = *(char **)&p[str_idx];
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200236 zassert_equal(addr, test_str1);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100237
238 str_idx = package2[len0 + 1];
239 addr = *(char **)&p[str_idx];
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200240 zassert_equal(addr, test_str1);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100241}
242
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700243ZTEST(cbprintf_package, test_cbprintf_fsc_package)
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100244{
245 int len;
246 static const char *test_str = "test %d %s";
247 static const char *test_str1 = "lorem ipsum";
248 char *addr;
249 int fsc_len;
250
251 len = cbprintf_package(NULL, 0, CBPRINTF_PACKAGE_ADD_STRING_IDXS,
252 test_str, 100, test_str1);
253 if (len > (int)(4 * sizeof(void *) + 2)) {
254 TC_PRINT("Skipping test, platform does not detect RO strings.\n");
255 ztest_test_skip();
256 }
257
258 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package[len];
259
260 len = cbprintf_package(package, sizeof(package),
261 CBPRINTF_PACKAGE_ADD_STRING_IDXS,
262 test_str, 100, test_str1);
263
Daniel Leungaff6e8b2022-02-17 13:51:00 -0800264 union cbprintf_package_hdr *desc = (union cbprintf_package_hdr *)package;
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100265
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200266 zassert_equal(desc->desc.ro_str_cnt, 2);
267 zassert_equal(desc->desc.str_cnt, 0);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100268
269 /* Get length of fsc package. */
270 fsc_len = cbprintf_fsc_package(package, len, NULL, 0);
271
272 int exp_len = len + (int)strlen(test_str) + 1 + (int)strlen(test_str1) + 1;
273
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200274 zassert_equal(exp_len, fsc_len);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100275
276 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) fsc_package[fsc_len];
277
278 fsc_len = cbprintf_fsc_package(package, len, fsc_package, sizeof(fsc_package) - 1);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200279 zassert_equal(fsc_len, -ENOSPC);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100280
281 fsc_len = cbprintf_fsc_package(package, len, fsc_package, sizeof(fsc_package));
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200282 zassert_equal((int)sizeof(fsc_package), fsc_len);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100283
284 /* New package has no RO string locations, only copied one. */
Daniel Leungaff6e8b2022-02-17 13:51:00 -0800285 desc = (union cbprintf_package_hdr *)fsc_package;
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200286 zassert_equal(desc->desc.ro_str_cnt, 0);
287 zassert_equal(desc->desc.str_cnt, 2);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100288
289 /* Get pointer to the first string in the package. */
Daniel Leungaff6e8b2022-02-17 13:51:00 -0800290 addr = (char *)&fsc_package[desc->desc.len * sizeof(int) + 1];
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100291
Rubin Gerritsen8799ab12024-06-11 14:39:44 +0200292 zassert_str_equal(test_str, addr);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100293
294 /* Get address of the second string. */
295 addr += strlen(addr) + 2;
Rubin Gerritsen8799ab12024-06-11 14:39:44 +0200296 zassert_str_equal(test_str1, addr);
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +0100297}
Krzysztof Chruscinskidccfe762021-03-03 10:48:30 +0100298
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100299static void check_package(void *package, size_t len, const char *exp_str)
300{
301 char out_str[128];
302
303 strcpy(compare_buf, exp_str);
304
305 struct out_buffer out_buf = {
306 .buf = out_str,
307 .idx = 0,
308 .size = sizeof(out_str)
309 };
310
311 unpack(NULL, &out_buf, (uint8_t *)package, len);
312}
313
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700314ZTEST(cbprintf_package, test_cbprintf_ro_loc)
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100315{
316 static const char *test_str = "test %d";
317 uint32_t flags = CBPRINTF_PACKAGE_ADD_RO_STR_POS;
318
319#define TEST_FMT test_str, 100
320 char exp_str[256];
321
322 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
323
324 int len = cbprintf_package(NULL, 0, flags, TEST_FMT);
325
326 int slen;
327
328 CBPRINTF_STATIC_PACKAGE(NULL, 0, slen, ALIGN_OFFSET, flags, TEST_FMT);
329
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200330 zassert_true(len > 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100331 zassert_equal(len, slen, "Runtime length: %d, static length: %d", len, slen);
332
333 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package[len];
334 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[slen];
335
Daniel Leungaff6e8b2022-02-17 13:51:00 -0800336 /*
337 * Since memcpy() is being done below, it is better to zero out
338 * both arrays as there might a paddings in the package headers
339 * which are not touched by packaging functions, where those bytes
340 * have whatever is in the stack.
341 */
342 memset(package, 0, len);
343 memset(spackage, 0, slen);
344
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100345 len = cbprintf_package(package, sizeof(package), flags, TEST_FMT);
346 CBPRINTF_STATIC_PACKAGE(spackage, sizeof(spackage), slen, ALIGN_OFFSET, flags, TEST_FMT);
347
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200348 zassert_true(len > 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100349 zassert_equal(len, slen, "Runtime length: %d, static length: %d", len, slen);
350
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200351 zassert_equal(memcmp(package, spackage, len), 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100352
353 uint8_t *hdr = package;
354
355 /* Check that only read-only string location array size is non zero */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200356 zassert_equal(hdr[1], 0);
357 zassert_equal(hdr[2], 1);
358 zassert_equal(hdr[3], 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100359
360 int clen;
361
362 /* Calculate size needed for package with appended read-only strings. */
363 clen = cbprintf_package_copy(package, sizeof(package), NULL, 0,
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200364 CBPRINTF_PACKAGE_CONVERT_RO_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100365
366 /* Length will be increased by string length + null terminator. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200367 zassert_equal(clen, len + (int)strlen(test_str) + 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100368
369 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage[clen];
370
371 int clen2 = cbprintf_package_copy(package, sizeof(package), cpackage, sizeof(cpackage),
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200372 CBPRINTF_PACKAGE_CONVERT_RO_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100373
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200374 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100375
376 /* Length will be increased by string length + null terminator. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200377 zassert_equal(clen, len + (int)strlen(test_str) + 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100378
379 uint8_t *chdr = cpackage;
380
381 /* Check that only package after copying has no locations but has
382 * appended string.
383 */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200384 zassert_equal(chdr[1], 1);
385 zassert_equal(chdr[2], 0);
386 zassert_equal(chdr[3], 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100387
388 check_package(package, len, exp_str);
389 check_package(cpackage, clen, exp_str);
390
391#undef TEST_FMT
392}
393
394/* Store read-only string by index when read-write string is appended. This
395 * is supported only by runtime packaging.
396 */
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700397ZTEST(cbprintf_package, test_cbprintf_ro_loc_rw_present)
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100398{
399 static const char *test_str = "test %d %s";
400 char test_str1[] = "test str1";
401 uint32_t flags = CBPRINTF_PACKAGE_ADD_RO_STR_POS;
402
403#define TEST_FMT test_str, 100, test_str1
404 char exp_str[256];
405
406 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
407
408 int len = cbprintf_package(NULL, 0, flags, TEST_FMT);
409
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200410 zassert_true(len > 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100411
412 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package[len];
413
414 len = cbprintf_package(package, sizeof(package), flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200415 zassert_true(len > 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100416
417 uint8_t *hdr = package;
418
419 /* Check that only read-only string location array size is non zero */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200420 zassert_equal(hdr[1], 1);
421 zassert_equal(hdr[2], 1);
422 zassert_equal(hdr[3], 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100423
424 int clen;
425
426 /* Calculate size needed for package with appended read-only strings. */
427 clen = cbprintf_package_copy(package, sizeof(package), NULL, 0,
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200428 CBPRINTF_PACKAGE_CONVERT_RO_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100429
430 /* Length will be increased by string length + null terminator. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200431 zassert_equal(clen, len + (int)strlen(test_str) + 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100432
433 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage[clen];
434
435 int clen2 = cbprintf_package_copy(package, sizeof(package), cpackage, sizeof(cpackage),
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200436 CBPRINTF_PACKAGE_CONVERT_RO_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100437
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200438 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100439
440 /* Length will be increased by string length + null terminator. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200441 zassert_equal(clen, len + (int)strlen(test_str) + 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100442
443 uint8_t *chdr = cpackage;
444
445 /* Check that only package after copying has no locations but has
446 * appended string.
447 */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200448 zassert_equal(chdr[1], 2);
449 zassert_equal(chdr[2], 0);
450 zassert_equal(chdr[3], 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100451
452 check_package(package, clen, exp_str);
453 check_package(cpackage, clen, exp_str);
454
455#undef TEST_FMT
456}
457
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700458ZTEST(cbprintf_package, test_cbprintf_ro_rw_loc)
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100459{
460 /* Strings does not need to be in read-only memory section, flag indicates
461 * that n first strings are read only.
462 */
463 char test_str[] = "test %s %s %d %s";
464 char cstr[] = "const";
465
466 char test_str1[] = "test str1";
467 char test_str2[] = "test str2";
468
469#define TEST_FMT test_str, cstr, test_str1, 100, test_str2
470 char exp_str[256];
471
472 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
473
474 uint32_t flags = CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(1) |
475 CBPRINTF_PACKAGE_ADD_RO_STR_POS |
476 CBPRINTF_PACKAGE_ADD_RW_STR_POS;
477
478 int len = cbprintf_package(NULL, 0, flags, TEST_FMT);
479 int slen;
480
481 CBPRINTF_STATIC_PACKAGE(NULL, 0, slen, ALIGN_OFFSET, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200482 zassert_true(len > 0);
483 zassert_equal(len, slen);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100484
485 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package[len];
486 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[len];
487
488 memset(package, 0, len);
489 memset(spackage, 0, len);
490
491 int len2 = cbprintf_package(package, sizeof(package), flags, TEST_FMT);
492
493 CBPRINTF_STATIC_PACKAGE(spackage, sizeof(spackage), slen, ALIGN_OFFSET, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200494 zassert_equal(len, len2);
495 zassert_equal(slen, len2);
496 zassert_equal(memcmp(package, spackage, len), 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100497
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200498 struct cbprintf_package_desc *hdr = (struct cbprintf_package_desc *)package;
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100499
500 /* Check that expected number of ro and rw locations are present and no
501 * strings appended.
502 */
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200503 zassert_equal(hdr->str_cnt, 0);
504 zassert_equal(hdr->ro_str_cnt, 2);
505 zassert_equal(hdr->rw_str_cnt, 2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100506
507 int clen;
508
509 uint16_t strl[2] = {0};
510
511 /* Calculate size needed for package with appended read-only strings. */
512 clen = cbprintf_package_copy(package, sizeof(package), NULL, 0,
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200513 CBPRINTF_PACKAGE_CONVERT_RO_STR, strl, ARRAY_SIZE(strl));
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100514
515 /* Length will be increased by 2 string lengths + null terminators. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200516 zassert_equal(clen, len + (int)strlen(test_str) + (int)strlen(cstr) + 2);
517 zassert_equal(strl[0], strlen(test_str) + 1);
518 zassert_equal(strl[1], strlen(cstr) + 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100519
520 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage[clen];
521
522 int clen2 = cbprintf_package_copy(package, sizeof(package), cpackage, sizeof(cpackage),
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200523 CBPRINTF_PACKAGE_CONVERT_RO_STR, strl, ARRAY_SIZE(strl));
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100524
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200525 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100526
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200527 struct cbprintf_package_desc *chdr = (struct cbprintf_package_desc *)cpackage;
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100528
529 /* Check that read only strings have been appended. */
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200530 zassert_equal(chdr->str_cnt, 2);
531 zassert_equal(chdr->ro_str_cnt, 0);
532 zassert_equal(chdr->rw_str_cnt, 2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100533
534 check_package(package, len, exp_str);
535 check_package(cpackage, clen, exp_str);
536
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200537 uint32_t cpy_flags = CBPRINTF_PACKAGE_CONVERT_RW_STR |
538 CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR;
Krzysztof Chruscinskia33f7de2022-03-23 07:15:09 +0100539
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100540 /* Calculate size needed for package with appended read-write strings. */
541 clen = cbprintf_package_copy(package, sizeof(package), NULL, 0,
Krzysztof Chruscinskia33f7de2022-03-23 07:15:09 +0100542 cpy_flags, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100543
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200544 /* Length will be increased by 2 string lengths + null terminators - arg indexes. */
545 zassert_equal(clen, len + (int)strlen(test_str1) + (int)strlen(test_str2) + 2 - 2,
546 "exp: %d, got: %d",
547 clen, len + (int)strlen(test_str1) + (int)strlen(test_str2) + 2 - 2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100548
549 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage2[clen];
550
551 clen2 = cbprintf_package_copy(package, sizeof(package), cpackage2, sizeof(cpackage2),
Krzysztof Chruscinskia33f7de2022-03-23 07:15:09 +0100552 cpy_flags, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100553
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200554 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100555
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200556 chdr = (struct cbprintf_package_desc *)cpackage2;
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100557
558 /* Check that read write strings have been appended. */
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200559 zassert_equal(chdr->str_cnt, 2);
560 zassert_equal(chdr->ro_str_cnt, 2);
561 zassert_equal(chdr->rw_str_cnt, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100562
563 check_package(package, len, exp_str);
564 check_package(cpackage2, clen, exp_str);
565
566#undef TEST_FMT
567}
568
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700569ZTEST(cbprintf_package, test_cbprintf_ro_rw_loc_const_char_ptr)
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100570{
571 /* Strings does not need to be in read-only memory section, flag indicates
572 * that n first strings are read only.
573 */
574 char test_str[] = "test %s %s %d %s";
575 static const char cstr[] = "const";
576
577 char test_str1[] = "test str1";
578 static const char test_str2[] = "test str2";
579
580 /* Test skipped for cases where static const data is not located in
581 * read-only section.
582 */
583 if (!linker_is_in_rodata(test_str)) {
584 ztest_test_skip();
585 }
586
587#define TEST_FMT test_str, cstr, test_str1, 100, test_str2
588 char exp_str[256];
589
590 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
591
592
593 /* Use flag which is causing all const char pointers to be considered as
594 * read only strings.
595 */
596 uint32_t flags = CBPRINTF_PACKAGE_CONST_CHAR_RO |
597 CBPRINTF_PACKAGE_ADD_RO_STR_POS |
598 CBPRINTF_PACKAGE_ADD_RW_STR_POS;
599
600 int len = cbprintf_package(NULL, 0, flags, TEST_FMT);
601 int slen;
602
603 CBPRINTF_STATIC_PACKAGE(NULL, 0, slen, ALIGN_OFFSET, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200604 zassert_true(len > 0);
605 zassert_equal(len, slen);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100606
607 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package[len];
608 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[len];
609
610 memset(package, 0, len);
611 memset(spackage, 0, len);
612
613 int len2 = cbprintf_package(package, sizeof(package), flags, TEST_FMT);
614
615 CBPRINTF_STATIC_PACKAGE(spackage, sizeof(spackage), slen, ALIGN_OFFSET, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200616 zassert_equal(len, len2);
617 zassert_equal(slen, len2);
618 zassert_equal(memcmp(package, spackage, len), 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100619
620 uint8_t *hdr = package;
621
622 /* Check that expected number of ro and rw locations are present and no
623 * strings appended.
624 */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200625 zassert_equal(hdr[1], 0);
626 zassert_equal(hdr[2], 3);
627 zassert_equal(hdr[3], 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100628
629 int clen;
630
631 /* Calculate size needed for package with appended read-only strings. */
632 clen = cbprintf_package_copy(package, sizeof(package), NULL, 0,
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200633 CBPRINTF_PACKAGE_CONVERT_RO_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100634
635 /* Length will be increased by 2 string lengths + null terminators. */
636 size_t str_append_len = (int)strlen(test_str) +
637 (int)strlen(cstr) +
638 (int)strlen(test_str2) + 3;
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200639 zassert_equal(clen, len + (int)str_append_len);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100640
641 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage[clen];
642
643 int clen2 = cbprintf_package_copy(package, sizeof(package), cpackage, sizeof(cpackage),
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200644 CBPRINTF_PACKAGE_CONVERT_RO_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100645
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200646 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100647
648 uint8_t *chdr = cpackage;
649
650 /* Check that read only strings have been appended. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200651 zassert_equal(chdr[1], 3);
652 zassert_equal(chdr[2], 0);
653 zassert_equal(chdr[3], 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100654
655 check_package(package, len, exp_str);
656 check_package(cpackage, clen, exp_str);
657
658 /* Calculate size needed for package with appended read-write strings. */
659 clen = cbprintf_package_copy(package, sizeof(package), NULL, 0,
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200660 CBPRINTF_PACKAGE_CONVERT_RW_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100661
662 /* Length will be increased by 1 string length + null terminator. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200663 zassert_equal(clen, len + (int)strlen(test_str1) + 1);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100664
665 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage2[clen];
666
667 clen2 = cbprintf_package_copy(package, sizeof(package), cpackage2, sizeof(cpackage2),
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200668 CBPRINTF_PACKAGE_CONVERT_RW_STR, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100669
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200670 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100671
672 chdr = cpackage2;
673
674 /* Check that read write strings have been appended. */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200675 zassert_equal(chdr[1], 1);
676 zassert_equal(chdr[2], 3);
677 zassert_equal(chdr[3], 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100678
679 check_package(package, len, exp_str);
680 check_package(cpackage2, clen, exp_str);
681#undef TEST_FMT
682}
683
Krzysztof Chruscinski50cc5582022-03-23 07:31:35 +0100684static void cbprintf_rw_loc_const_char_ptr(bool keep_ro_str)
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100685{
686 /* Test requires that static packaging is applied. Runtime packaging
687 * cannot be tricked because it checks pointers against read only
688 * section.
689 */
690 if (Z_C_GENERIC == 0) {
691 ztest_test_skip();
692 }
693
694 int slen, slen2;
695 int clen, clen2;
696 static const char test_str[] = "test %s %d %s";
697 char test_str1[] = "test str1";
698 static const char test_str2[] = "test str2";
699 /* Store indexes of rw strings. */
700 uint32_t flags = CBPRINTF_PACKAGE_ADD_RW_STR_POS;
701 uint8_t *hdr;
702
703 /* Test skipped for cases where static const data is not located in
704 * read-only section.
705 */
706 if (!linker_is_in_rodata(test_str)) {
707 ztest_test_skip();
708 }
709
710#define TEST_FMT test_str, test_str1, 100, test_str2
711 char exp_str[256];
712
713 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
714
715 CBPRINTF_STATIC_PACKAGE(NULL, 0, slen, ALIGN_OFFSET, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200716 zassert_true(slen > 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100717
718 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[slen];
719
720 memset(spackage, 0, slen);
721
722 CBPRINTF_STATIC_PACKAGE(spackage, sizeof(spackage), slen2, ALIGN_OFFSET, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200723 zassert_equal(slen, slen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100724
725 hdr = spackage;
726
727 /* Check that expected number of ro and rw locations are present and no
728 * strings appended.
729 */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200730 zassert_equal(hdr[1], 0);
731 zassert_equal(hdr[2], 0);
732 zassert_equal(hdr[3], 2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100733
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200734 uint32_t copy_flags = CBPRINTF_PACKAGE_CONVERT_RW_STR |
735 (keep_ro_str ? CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR : 0);
Krzysztof Chruscinskia33f7de2022-03-23 07:15:09 +0100736
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100737 /* Calculate size needed for package with appended read-only strings. */
738 clen = cbprintf_package_copy(spackage, sizeof(spackage), NULL, 0,
Krzysztof Chruscinski50cc5582022-03-23 07:31:35 +0100739 copy_flags, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100740
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200741 /* Previous len + string length + null terminator - argument index -
742 * decrease size of ro str location. If it is kept then it is decreased
743 * by 1 (argument index is dropped) if it is discarded then it is decreased
744 * by 2 (argument index + position dropped).
745 */
746 int exp_len = slen + (int)strlen(test_str1) + 1 - 1 - (keep_ro_str ? 1 : 2);
Krzysztof Chruscinski50cc5582022-03-23 07:31:35 +0100747
748 /* Length will be increased by string length + null terminator. */
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200749 zassert_equal(clen, exp_len, "clen:%d exp_len:%d", clen, exp_len);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100750
751 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) cpackage[clen];
752
753 clen2 = cbprintf_package_copy(spackage, sizeof(spackage), cpackage, sizeof(cpackage),
Krzysztof Chruscinski50cc5582022-03-23 07:31:35 +0100754 copy_flags, NULL, 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100755
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200756 zassert_equal(clen, clen2);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100757
758 hdr = cpackage;
759
Krzysztof Chruscinski50cc5582022-03-23 07:31:35 +0100760 /* Check that one string has been appended. Second is detected to be RO */
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200761 zassert_equal(hdr[1], 1);
762 zassert_equal(hdr[2], keep_ro_str ? 1 : 0);
763 zassert_equal(hdr[3], 0);
Krzysztof Chruscinskid45d2612022-03-11 07:49:23 +0100764
765 check_package(spackage, slen, exp_str);
766 test_str1[0] = '\0';
767 check_package(cpackage, clen, exp_str);
768#undef TEST_FMT
769}
770
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700771ZTEST(cbprintf_package, test_cbprintf_rw_loc_const_char_ptr)
Krzysztof Chruscinski50cc5582022-03-23 07:31:35 +0100772{
773 cbprintf_rw_loc_const_char_ptr(true);
774 cbprintf_rw_loc_const_char_ptr(false);
775}
776
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700777ZTEST(cbprintf_package, test_cbprintf_must_runtime_package)
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100778{
779 int rv;
780
781 if (Z_C_GENERIC == 0) {
782 ztest_test_skip();
783 }
784
785 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, "test");
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200786 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100787
788 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, "test %x", 100);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200789 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100790
791 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, "test %x %s", 100, "");
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200792 zassert_equal(rv, 1);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100793
794 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO, "test %x", 100);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200795 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100796
797 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO,
798 "test %x %s", 100, (const char *)"s");
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200799 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100800
801 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO,
802 "test %x %s %s", 100, (char *)"s", (const char *)"foo");
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200803 zassert_equal(rv, 1);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100804
805 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(1),
806 "test %s", (char *)"s");
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200807 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100808
809 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(2),
810 "test %s %s %d", (const char *)"s", (char *)"s", 10);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200811 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100812
813 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(2),
814 "test %s %s %s", (const char *)"s", (char *)"s", "s");
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200815 zassert_equal(rv, 1);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100816
817 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(1) |
818 CBPRINTF_PACKAGE_CONST_CHAR_RO,
819 "test %s %s %d", (char *)"s", (const char *)"s", 10);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200820 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100821
822 /* When RW str positions are stored static packaging can always be used */
823 rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_ADD_RW_STR_POS,
824 "test %s %s %d", (char *)"s", (const char *)"s", 10);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200825 zassert_equal(rv, 0);
Krzysztof Chruscinskid00f9e82022-02-25 13:21:13 +0100826}
827
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200828struct test_cbprintf_covert_ctx {
829 uint8_t buf[256];
830 size_t offset;
831 bool null;
832};
833
834static int convert_cb(const void *buf, size_t len, void *context)
835{
836 struct test_cbprintf_covert_ctx *ctx = (struct test_cbprintf_covert_ctx *)context;
837
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200838 zassert_false(ctx->null);
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200839 if (buf) {
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200840 zassert_false(ctx->null);
841 zassert_true(ctx->offset + len <= sizeof(ctx->buf));
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200842 memcpy(&ctx->buf[ctx->offset], buf, len);
843 ctx->offset += len;
844 return len;
845 }
846
847 /* At the end of conversion callback should be called with null
848 * buffer to indicate the end.
849 */
850 ctx->null = true;
851 return 0;
852}
853
854ZTEST(cbprintf_package, test_cbprintf_package_convert)
855{
856 int slen, clen;
857 static const char test_str[] = "test %s %d %s";
858 char test_str1[] = "test str1";
859 static const char test_str2[] = "test str2";
860 /* Store indexes of rw strings. */
861 uint32_t flags = CBPRINTF_PACKAGE_ADD_RW_STR_POS;
862 struct test_cbprintf_covert_ctx ctx;
863
864#define TEST_FMT test_str, test_str1, 100, test_str2
865 char exp_str[256];
866
867 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
868
869 slen = cbprintf_package(NULL, 0, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200870 zassert_true(slen > 0);
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200871
872 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[slen];
873
874 memset(&ctx, 0, sizeof(ctx));
875 memset(spackage, 0, slen);
876
877 slen = cbprintf_package(spackage, slen, flags, TEST_FMT);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200878 zassert_true(slen > 0);
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200879
Krzysztof Chruscinskibb74b4f2022-08-25 15:51:11 +0200880 uint32_t copy_flags = CBPRINTF_PACKAGE_CONVERT_RW_STR |
881 CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR;
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200882
883 clen = cbprintf_package_convert(spackage, slen, NULL, 0, copy_flags, NULL, 0);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200884 zassert_true(clen > 0);
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200885
886 clen = cbprintf_package_convert(spackage, slen, convert_cb, &ctx, copy_flags, NULL, 0);
Michał Barnaśdae8efa2022-08-17 17:36:15 +0200887 zassert_true(clen > 0);
888 zassert_true(ctx.null);
Krzysztof Chruscinskia7224832022-08-26 14:14:23 +0200889 zassert_equal((int)ctx.offset, clen);
Krzysztof Chruscinski6f5cf302022-05-04 11:57:23 +0200890
891 check_package(ctx.buf, ctx.offset, exp_str);
892#undef TEST_FMT
893
894}
895
Krzysztof Chruścińskif82ffc92024-10-30 12:13:40 +0100896/* Test uses package convert with initial size calculation. Array provided to hold
897 * argument string lengths is shorter than number of string arguments.
898 */
899ZTEST(cbprintf_package, test_cbprintf_package_convert_strl)
900{
901 int slen, clen;
902 char test_str[] = "test %s %d %s %s";
903 char test_str1[] = "test str1";
904 char test_str2[] = "test str 2";
905 char test_str3[] = "test str 3";
906 /* Store indexes of rw strings. */
907 uint32_t flags = CBPRINTF_PACKAGE_ADD_RW_STR_POS;
908 struct test_cbprintf_covert_ctx ctx;
909 uint16_t strl[2];
910
911#define TEST_FMT test_str, test_str1, 100, test_str2, test_str3
912 char exp_str[256];
913
914 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
915
916 slen = cbprintf_package(NULL, 0, flags, TEST_FMT);
917 zassert_true(slen > 0);
918
919 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[slen];
920
921 memset(&ctx, 0, sizeof(ctx));
922 memset(spackage, 0, slen);
923
924 slen = cbprintf_package(spackage, slen, flags, TEST_FMT);
925 zassert_true(slen > 0);
926
927 uint32_t copy_flags = CBPRINTF_PACKAGE_CONVERT_RW_STR |
928 CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR;
929
930 clen = cbprintf_package_convert(spackage, slen, NULL, 0, copy_flags,
931 strl, ARRAY_SIZE(strl));
932 zassert_true(clen > 0);
933 /* Two locations were provided to store string lengths. 3rd string length
934 * will need to be calculated in both conversions.
935 */
936 zassert_equal(strl[0], strlen(test_str1) + 1);
937 zassert_equal(strl[1], strlen(test_str2) + 1);
938
939 clen = cbprintf_package_convert(spackage, slen, convert_cb, &ctx, copy_flags,
940 strl, ARRAY_SIZE(strl));
941 zassert_true(clen > 0);
942 zassert_true(ctx.null);
943 zassert_equal((int)ctx.offset, clen);
944
945 check_package(ctx.buf, ctx.offset, exp_str);
946#undef TEST_FMT
947
948}
949
Krzysztof Chruścińskib46d9612023-12-20 15:51:37 +0100950ZTEST(cbprintf_package, test_cbprintf_package_convert_static)
951{
952 int slen, clen, olen;
953 static const char test_str[] = "test %s";
954 char test_str1[] = "test str1";
955 /* Store indexes of rw strings. */
956 uint32_t flags = CBPRINTF_PACKAGE_ADD_RW_STR_POS |
957 CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(0) |
958 CBPRINTF_PACKAGE_ADD_STRING_IDXS;
959 struct test_cbprintf_covert_ctx ctx;
960
961#define TEST_FMT test_str, test_str1
962 char exp_str[256];
963
964 snprintfcb(exp_str, sizeof(exp_str), TEST_FMT);
965
966 CBPRINTF_STATIC_PACKAGE(NULL, 0, slen, CBPRINTF_PACKAGE_ALIGNMENT, flags, TEST_FMT);
967 zassert_true(slen > 0);
968
969 uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) spackage[slen];
970
971 memset(&ctx, 0, sizeof(ctx));
972 memset(spackage, 0, slen);
973
974 CBPRINTF_STATIC_PACKAGE(spackage, slen, olen, CBPRINTF_PACKAGE_ALIGNMENT, flags, TEST_FMT);
975 zassert_equal(olen, slen);
976
977 uint32_t copy_flags = CBPRINTF_PACKAGE_CONVERT_RW_STR;
978
979 clen = cbprintf_package_convert(spackage, slen, NULL, 0, copy_flags, NULL, 0);
Fabio Baltieri23f37a52024-09-19 16:04:19 +0000980 zassert_true(clen >= 0);
981 zassert_true((size_t)clen == slen + sizeof(test_str1) + 1/*null*/ - 2 /* arg+ro idx gone*/);
Krzysztof Chruścińskib46d9612023-12-20 15:51:37 +0100982
983 clen = cbprintf_package_convert(spackage, slen, convert_cb, &ctx, copy_flags, NULL, 0);
984 zassert_true(clen > 0);
985 zassert_true(ctx.null);
986 zassert_equal((int)ctx.offset, clen);
987
988 check_package(ctx.buf, ctx.offset, exp_str);
989#undef TEST_FMT
990
991}
992
Tristan Honscheide4d24fc2021-11-15 16:46:45 -0700993/**
994 * @brief Log information about variable sizes and alignment.
995 *
996 * @return NULL as we are not supplying any fixture object.
997 */
998static void *print_size_and_alignment_info(void)
Krzysztof Chruscinskidccfe762021-03-03 10:48:30 +0100999{
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +01001000#ifdef __cplusplus
1001 printk("C++\n");
1002#else
1003 printk("sizeof: int=%zu long=%zu ptr=%zu long long=%zu double=%zu long double=%zu\n",
Tristan Honscheide4d24fc2021-11-15 16:46:45 -07001004 sizeof(int), sizeof(long), sizeof(void *), sizeof(long long), sizeof(double),
1005 sizeof(long double));
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +01001006 printk("alignof: int=%zu long=%zu ptr=%zu long long=%zu double=%zu long double=%zu\n",
Tristan Honscheide4d24fc2021-11-15 16:46:45 -07001007 __alignof__(int), __alignof__(long), __alignof__(void *), __alignof__(long long),
1008 __alignof__(double), __alignof__(long double));
Krzysztof Chruscinski7cba9f52022-02-22 15:29:42 +01001009 printk("%s C11 _Generic\n", Z_C_GENERIC ? "With" : "Without");
1010#endif
1011
Tristan Honscheide4d24fc2021-11-15 16:46:45 -07001012 return NULL;
Krzysztof Chruscinskidccfe762021-03-03 10:48:30 +01001013}
Tristan Honscheide4d24fc2021-11-15 16:46:45 -07001014
1015ZTEST_SUITE(cbprintf_package, NULL, print_size_and_alignment_info, NULL, NULL, NULL);