1 /*
2 * Copyright (c) 2015 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/sys/printk-hooks.h>
9
10 #define BUF_SZ 1024
11
12 static int pos;
13 char pk_console[BUF_SZ];
14
15 int (*_old_char_out)(int);
16
17 #if defined(CONFIG_PICOLIBC)
18
19 #define ZEPHYR_PICOLIBC_VERSION (__PICOLIBC__ * 10000 + \
20 __PICOLIBC_MINOR__ * 100 + \
21 __PICOLIBC_PATCHLEVEL__)
22
23 #ifdef CONFIG_PICOLIBC_IO_MINIMAL
24 /*
25 * If picolibc is >= 1.8.4, then minimal printf is available. Otherwise,
26 * we're going to get the floating point version when the minimal one is
27 * selected.
28 */
29 #if ZEPHYR_PICOLIBC_VERSION >= 10804
30 #define HAS_PICOLIBC_IO_MINIMAL
31 #else
32 #define HAS_PICOLIBC_IO_FLOAT
33 #endif
34 #endif
35
36 #ifdef CONFIG_PICOLIBC_IO_LONG_LONG
37 /*
38 * If picolibc is >= 1.8.5, then long long printf is available. Otherwise,
39 * we're going to get the floating point version when the long long one is
40 * selected.
41 */
42 #if ZEPHYR_PICOLIBC_VERSION >= 10805
43 #define HAS_PICOLIBC_IO_LONG_LONG
44 #else
45 #define HAS_PICOLIBC_IO_FLOAT
46 #endif
47 #endif
48
49 #ifdef CONFIG_PICOLIBC_IO_FLOAT
50 #define HAS_PICOLIBC_IO_FLOAT
51 #endif
52
53 /*
54 * Picolibc long long support is present if Zephyr configuration has
55 * enabled long long or floating point support.
56 */
57
58 char expected_32[] = "22 113 10000 32768 40000 22\n"
59 "p 112 -10000 -32768 -40000 -22\n"
60 #if defined(HAS_PICOLIBC_IO_MINIMAL)
61 "0x1 0x1 0x1 0x1 0x1\n"
62 "0x1 0x1 0x1 0x1\n"
63 "42 42 42 42\n"
64 "-42 -42 -42 -42\n"
65 "42 42 42 42\n"
66 "42 42 42 42\n"
67 "25542abcdef 42\n"
68 #if defined(_WANT_MINIMAL_IO_LONG_LONG)
69 "68719476735 -1 18446744073709551615 ffffffffffffffff\n"
70 #else
71 "-1 -1 4294967295 ffffffff\n"
72 #endif
73 #else
74 "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n"
75 "0x1 0x 1 0x 1 0x 1\n"
76 "42 42 0042 00000042\n"
77 "-42 -42 -042 -0000042\n"
78 "42 42 42 42\n"
79 "42 42 0042 00000042\n"
80 "255 42 abcdef 42\n"
81 #if defined(HAS_PICOLIBC_IO_LONG_LONG) || defined(HAS_PICOLIBC_IO_FLOAT)
82 "68719476735 -1 18446744073709551615 ffffffffffffffff\n"
83 #else
84 "-1 -1 4294967295 ffffffff\n"
85 #endif
86 #endif
87 "0xcafebabe 0xbeef 0x2a\n"
88 ;
89
90 char expected_64[] = "22 113 10000 32768 40000 22\n"
91 "p 112 -10000 -32768 -40000 -22\n"
92 #if defined(HAS_PICOLIBC_IO_MINIMAL)
93 "0x1 0x1 0x1 0x1 0x1\n"
94 "0x1 0x1 0x1 0x1\n"
95 "42 42 42 42\n"
96 "-42 -42 -42 -42\n"
97 "42 42 42 42\n"
98 "42 42 42 42\n"
99 "25542abcdef 42\n"
100 #else
101 "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n"
102 "0x1 0x 1 0x 1 0x 1\n"
103 "42 42 0042 00000042\n"
104 "-42 -42 -042 -0000042\n"
105 "42 42 42 42\n"
106 "42 42 0042 00000042\n"
107 "255 42 abcdef 42\n"
108 #endif
109 "68719476735 -1 18446744073709551615 ffffffffffffffff\n"
110 "0xcafebabe 0xbeef 0x2a\n"
111 ;
112 char *expected = (sizeof(long) == sizeof(long long)) ? expected_64 : expected_32;
113 #else
114 #if defined(CONFIG_CBPRINTF_FULL_INTEGRAL)
115 char *expected = "22 113 10000 32768 40000 22\n"
116 "p 112 -10000 -32768 -40000 -22\n"
117 "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n"
118 "0x1 0x 1 0x 1 0x 1\n"
119 "42 42 0042 00000042\n"
120 "-42 -42 -042 -0000042\n"
121 "42 42 42 42\n"
122 "42 42 0042 00000042\n"
123 "255 42 abcdef 42\n"
124 "68719476735 -1 18446744073709551615 ffffffffffffffff\n"
125 "0xcafebabe 0xbeef 0x2a\n"
126 ;
127 #elif defined(CONFIG_CBPRINTF_COMPLETE)
128 char *expected = "22 113 10000 32768 40000 %llu\n"
129 "p 112 -10000 -32768 -40000 %lld\n"
130 "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n"
131 "0x1 0x 1 0x 1 0x 1\n"
132 "42 42 0042 00000042\n"
133 "-42 -42 -042 -0000042\n"
134 "42 42 42 42\n"
135 "42 42 0042 00000042\n"
136 "255 42 abcdef 42\n"
137 "%lld %lld %llu %llx\n"
138 "0xcafebabe 0xbeef 0x2a\n"
139 ;
140 #elif defined(CONFIG_CBPRINTF_NANO)
141 char *expected = "22 113 10000 32768 40000 22\n"
142 "p 112 -10000 -32768 -40000 -22\n"
143 "0x1 0x01 0x0001 0x00000001 0x0000000000000001\n"
144 "0x1 0x 1 0x 1 0x 1\n"
145 "42 42 0042 00000042\n"
146 "-42 -42 -042 -0000042\n"
147 "42 42 42 42\n"
148 "42 42 0042 00000042\n"
149 "255 42 abcdef 42\n"
150 "ERR -1 ERR ERR\n"
151 "0xcafebabe 0xbeef 0x2a\n"
152 ;
153 #endif
154 #endif
155
156 size_t stv = 22;
157 unsigned char uc = 'q';
158 unsigned short int usi = 10000U;
159 unsigned int ui = 32768U;
160 unsigned long ul = 40000;
161
162 /* FIXME
163 * we know printk doesn't have full support for 64-bit values.
164 * at least show it can print uint64_t values less than 32-bits wide
165 */
166 unsigned long long ull = 22;
167
168 char c = 'p';
169 signed short int ssi = -10000;
170 signed int si = -32768;
171 signed long sl = -40000;
172 signed long long sll = -22;
173
174 uint32_t hex = 0xCAFEBABE;
175
176 void *ptr = (void *)0xBEEF;
177
ram_console_out(int character)178 static int ram_console_out(int character)
179 {
180 pk_console[pos] = (char)character;
181 pos = (pos + 1) % BUF_SZ;
182 return _old_char_out(character);
183 }
184 /**
185 * @addtogroup kernel_common_tests
186 * @{
187 */
188
189 /**
190 * @brief Test printk() functionality
191 *
192 * @see printk(), __printk_get_hook(),
193 * __printk_hook_install(), snprintk()
194 *
195 */
ZTEST(printk,test_printk)196 ZTEST(printk, test_printk)
197 {
198 int count;
199
200 if (IS_ENABLED(CONFIG_LOG_PRINTK)) {
201 ztest_test_skip();
202 }
203
204 _old_char_out = __printk_get_hook();
205 __printk_hook_install(ram_console_out);
206
207 printk("%zu %hhu %hu %u %lu %llu\n", stv, uc, usi, ui, ul, ull);
208 printk("%c %hhd %hd %d %ld %lld\n", c, c, ssi, si, sl, sll);
209 printk("0x%x 0x%02x 0x%04x 0x%08x 0x%016x\n", 1, 1, 1, 1, 1);
210 printk("0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1);
211 printk("%d %02d %04d %08d\n", 42, 42, 42, 42);
212 printk("%d %02d %04d %08d\n", -42, -42, -42, -42);
213 printk("%u %2u %4u %8u\n", 42, 42, 42, 42);
214 printk("%u %02u %04u %08u\n", 42, 42, 42, 42);
215 printk("%-8u%-6d%-4x %8d\n", 0xFF, 42, 0xABCDEF, 42);
216 printk("%lld %lld %llu %llx\n", 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL);
217 printk("0x%x %p %-2p\n", hex, ptr, (char *)42);
218
219 pk_console[pos] = '\0';
220 __printk_hook_install(_old_char_out);
221 printk("expected '%s'\n", expected);
222 zassert_str_equal(pk_console, expected, "printk failed");
223
224 (void)memset(pk_console, 0, sizeof(pk_console));
225 count = 0;
226
227 count += snprintk(pk_console + count, sizeof(pk_console) - count,
228 "%zu %hhu %hu %u %lu %llu\n",
229 stv, uc, usi, ui, ul, ull);
230 count += snprintk(pk_console + count, sizeof(pk_console) - count,
231 "%c %hhd %hd %d %ld %lld\n", c, c, ssi, si, sl, sll);
232 count += snprintk(pk_console + count, sizeof(pk_console) - count,
233 "0x%x 0x%02x 0x%04x 0x%08x 0x%016x\n", 1, 1, 1, 1, 1);
234 count += snprintk(pk_console + count, sizeof(pk_console) - count,
235 "0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1);
236 count += snprintk(pk_console + count, sizeof(pk_console) - count,
237 "%d %02d %04d %08d\n", 42, 42, 42, 42);
238 count += snprintk(pk_console + count, sizeof(pk_console) - count,
239 "%d %02d %04d %08d\n", -42, -42, -42, -42);
240 count += snprintk(pk_console + count, sizeof(pk_console) - count,
241 "%u %2u %4u %8u\n", 42, 42, 42, 42);
242 count += snprintk(pk_console + count, sizeof(pk_console) - count,
243 "%u %02u %04u %08u\n", 42, 42, 42, 42);
244 count += snprintk(pk_console + count, sizeof(pk_console) - count,
245 "%-8u%-6d%-4x %8d\n",
246 0xFF, 42, 0xABCDEF, 42);
247 count += snprintk(pk_console + count, sizeof(pk_console) - count,
248 "%lld %lld %llu %llx\n",
249 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL);
250 count += snprintk(pk_console + count, sizeof(pk_console) - count,
251 "0x%x %p %-2p\n", hex, ptr, (char *)42);
252 pk_console[count] = '\0';
253 zassert_str_equal(pk_console, expected, "snprintk failed");
254 }
255
256 extern void *common_setup(void);
257 ZTEST_SUITE(printk, NULL, common_setup, NULL, NULL, NULL);
258
259 /**
260 * @}
261 */
262