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) || defined(__IO_MINIMAL_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 /**
186  * @defgroup kernel_printk_tests Printk
187  * @ingroup all_tests
188  * @{
189  * @}
190  *
191  * @addtogroup kernel_printk_tests
192  * @{
193  */
194 
195 /**
196  * @brief Test printk() functionality
197  *
198  * @see printk(), __printk_get_hook(),
199  * __printk_hook_install(), snprintk()
200  *
201  */
ZTEST(printk,test_printk)202 ZTEST(printk, test_printk)
203 {
204 	int count;
205 
206 	if (IS_ENABLED(CONFIG_LOG_PRINTK)) {
207 		ztest_test_skip();
208 	}
209 
210 	_old_char_out = __printk_get_hook();
211 	__printk_hook_install(ram_console_out);
212 
213 	printk("%zu %hhu %hu %u %lu %llu\n", stv, uc, usi, ui, ul, ull);
214 	printk("%c %hhd %hd %d %ld %lld\n", c, c, ssi, si, sl, sll);
215 	printk("0x%x 0x%02x 0x%04x 0x%08x 0x%016x\n", 1, 1, 1, 1, 1);
216 	printk("0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1);
217 	printk("%d %02d %04d %08d\n", 42, 42, 42, 42);
218 	printk("%d %02d %04d %08d\n", -42, -42, -42, -42);
219 	printk("%u %2u %4u %8u\n", 42, 42, 42, 42);
220 	printk("%u %02u %04u %08u\n", 42, 42, 42, 42);
221 	printk("%-8u%-6d%-4x  %8d\n", 0xFF, 42, 0xABCDEF, 42);
222 	printk("%lld %lld %llu %llx\n", 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL);
223 	printk("0x%x %p %-2p\n", hex, ptr, (char *)42);
224 
225 	pk_console[pos] = '\0';
226 	__printk_hook_install(_old_char_out);
227 	printk("expected '%s'\n", expected);
228 	zassert_str_equal(pk_console, expected, "printk failed");
229 
230 	(void)memset(pk_console, 0, sizeof(pk_console));
231 	count = 0;
232 
233 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
234 			  "%zu %hhu %hu %u %lu %llu\n",
235 			  stv, uc, usi, ui, ul, ull);
236 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
237 			  "%c %hhd %hd %d %ld %lld\n", c, c, ssi, si, sl, sll);
238 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
239 			  "0x%x 0x%02x 0x%04x 0x%08x 0x%016x\n", 1, 1, 1, 1, 1);
240 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
241 			  "0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1);
242 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
243 			  "%d %02d %04d %08d\n", 42, 42, 42, 42);
244 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
245 			  "%d %02d %04d %08d\n", -42, -42, -42, -42);
246 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
247 			  "%u %2u %4u %8u\n", 42, 42, 42, 42);
248 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
249 			  "%u %02u %04u %08u\n", 42, 42, 42, 42);
250 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
251 			  "%-8u%-6d%-4x  %8d\n",
252 			  0xFF, 42, 0xABCDEF, 42);
253 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
254 			  "%lld %lld %llu %llx\n",
255 			  0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL);
256 	count += snprintk(pk_console + count, sizeof(pk_console) - count,
257 			  "0x%x %p %-2p\n", hex, ptr, (char *)42);
258 	pk_console[count] = '\0';
259 	zassert_str_equal(pk_console, expected, "snprintk failed");
260 }
261 
262 
263 /**
264  * @}
265  */
266 extern void *common_setup(void);
267 ZTEST_SUITE(printk, NULL, common_setup, NULL, NULL, NULL);
268