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