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