1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2025-01-04     Meco Man     the first version
9  */
10 
11 #include <rtklibc.h>
12 #include "utest.h"
13 
TC_rt_sscanf_char(void)14 static void TC_rt_sscanf_char(void)
15 {
16     const char str[] = "A B";
17     char a, b;
18     rt_sscanf(str, "%c %c", &a, &b);
19     uassert_true(a == 'A' && b == 'B');
20     /* Move to the next character after space for the second %c */
21     rt_sscanf(str + 2, "%c", &b);
22     uassert_true(b == 'B');
23 }
24 
TC_rt_sscanf_basic_int(void)25 static void TC_rt_sscanf_basic_int(void)
26 {
27     const char str[] = "12345";
28     int value;
29     int result = rt_sscanf(str, "%d", &value);
30     uassert_int_equal(result, 1);
31     uassert_int_equal(value, 12345);
32 }
33 
TC_rt_sscanf_basic_float(void)34 static void TC_rt_sscanf_basic_float(void)
35 {
36     const char str[] = "123.45";
37     float value;
38     int result = rt_sscanf(str, "%f", &value);
39     uassert_int_equal(result, 1);
40     uassert_float_equal(value, 123.45);
41 }
42 
TC_rt_sscanf_basic_string(void)43 static void TC_rt_sscanf_basic_string(void)
44 {
45     const char str[] = "Hello, World!";
46     char buffer[20];
47     int result = rt_sscanf(str, "%s", buffer);
48     uassert_int_equal(result, 1);
49     uassert_str_equal(buffer, "Hello,");
50 }
51 
TC_rt_sscanf_string_with_space(void)52 static void TC_rt_sscanf_string_with_space(void)
53 {
54     const char str[] = "Hello   World";
55     char a[20];
56     rt_sscanf(str, "%*s %s", a);
57     uassert_str_equal(a, "World");
58 }
59 
TC_rt_sscanf_basic_char(void)60 static void TC_rt_sscanf_basic_char(void)
61 {
62     const char str[] = "A";
63     char value;
64     int result = rt_sscanf(str, "%c", &value);
65     uassert_int_equal(result, 1);
66     uassert_int_equal(value, 'A');
67 }
68 
TC_rt_sscanf_hex_1(void)69 static void TC_rt_sscanf_hex_1(void)
70 {
71     const char str[] = "0x1A3F";
72     int value;
73     int result = rt_sscanf(str, "%x", &value);
74     uassert_int_equal(result, 1);
75     uassert_int_equal(value, 0x1A3F);
76 }
77 
TC_rt_sscanf_hex_2(void)78 static void TC_rt_sscanf_hex_2(void)
79 {
80     const char str[] = "0x1A 0XFF";
81     int a, b;
82     rt_sscanf(str, "%x %x", &a, &b);
83     uassert_true(a == 0x1A && b == 0XFF);
84 }
85 
TC_rt_sscanf_oct_1(void)86 static void TC_rt_sscanf_oct_1(void)
87 {
88     const char str[] = "0755";
89     int value;
90     int result = rt_sscanf(str, "%o", &value);
91     uassert_int_equal(result, 1);
92     uassert_int_equal(value, 0755);
93 }
94 
TC_rt_sscanf_oct_2(void)95 static void TC_rt_sscanf_oct_2(void)
96 {
97     const char str[] = "012 077";
98     int a, b;
99     rt_sscanf(str, "%o %o", &a, &b);
100     uassert_true(a == 012 && b == 077);
101 }
102 
TC_rt_sscanf_multiple_args(void)103 static void TC_rt_sscanf_multiple_args(void)
104 {
105     const char str[] = "123 Hello";
106     int int_value;
107     char str_value[20];
108     int result = rt_sscanf(str, "%d %s", &int_value, str_value);
109     uassert_int_equal(result, 2);
110     uassert_int_equal(int_value, 123);
111     uassert_str_equal(str_value, "Hello");
112 }
113 
TC_rt_sscanf_pointer(void)114 static void TC_rt_sscanf_pointer(void)
115 {
116     const char str[] = "0x12345678";
117     void *ptr;
118     int result = rt_sscanf(str, "%p", &ptr);
119     uassert_int_equal(result, 1);
120     uassert_ptr_equal(ptr, (void *)0x12345678);
121 }
122 
TC_rt_sscanf_width_specifier(void)123 static void TC_rt_sscanf_width_specifier(void)
124 {
125     const char str[] = "123456789";
126     int value;
127     int result = rt_sscanf(str, "%4d", &value);
128     uassert_int_equal(result, 1);
129     uassert_int_equal(value, 1234);
130 }
131 
TC_rt_sscanf_suppression(void)132 static void TC_rt_sscanf_suppression(void)
133 {
134     const char str[] = "123 456";
135     int second_value;
136     int result = rt_sscanf(str, "%*d %d", &second_value);
137     uassert_int_equal(result, 1);
138     uassert_int_equal(second_value, 456);
139 }
140 
TC_rt_sscanf_match_set(void)141 static void TC_rt_sscanf_match_set(void)
142 {
143     const char str[] = "abc123";
144     char buffer[10] = {0};
145     int result = rt_sscanf(str, "%[a-z]", buffer);
146     uassert_int_equal(result, 1);
147     uassert_str_equal(buffer, "abc");
148 }
149 
TC_rt_sscanf_match_set_negated(void)150 static void TC_rt_sscanf_match_set_negated(void)
151 {
152     const char str[] = "abc123";
153     char buffer[10];
154     int result = rt_sscanf(str, "%[^0-9]", buffer);
155     uassert_int_equal(result, 1);
156     uassert_str_equal(buffer, "abc");
157 }
158 
TC_rt_sscanf_match_set_range(void)159 static void TC_rt_sscanf_match_set_range(void)
160 {
161     const char str[] = "a-zA-Z";
162     char buffer[10];
163     int result = rt_sscanf(str, "%[a-z-A-Z]", buffer);
164     uassert_int_equal(result, 1);
165     uassert_str_equal(buffer, "a-zA-Z");
166 }
167 
TC_rt_sscanf_whitespace_skip(void)168 static void TC_rt_sscanf_whitespace_skip(void)
169 {
170     const char str[] = "   12345";
171     int value;
172     int result = rt_sscanf(str, "%d", &value);
173     uassert_int_equal(result, 1);
174     uassert_int_equal(value, 12345);
175 }
176 
TC_rt_sscanf_unsigned_int(void)177 static void TC_rt_sscanf_unsigned_int(void)
178 {
179     const char str[] = "4294967295";
180     unsigned int value;
181     int result = rt_sscanf(str, "%u", &value);
182     uassert_int_equal(result, 1);
183     uassert_int_equal(value, 4294967295U);
184 }
185 
TC_rt_sscanf_long_long_int(void)186 static void TC_rt_sscanf_long_long_int(void)
187 {
188     const char str[] = "9223372036854775807";
189     long long value;
190     int result = rt_sscanf(str, "%lld", &value);
191     uassert_int_equal(result, 1);
192     uassert_int_equal(value, 9223372036854775807LL);
193 }
194 
TC_rt_sscanf_short_int(void)195 static void TC_rt_sscanf_short_int(void)
196 {
197     const char str[] = "32767";
198     short value;
199     int result = rt_sscanf(str, "%hd", &value);
200     uassert_int_equal(result, 1);
201     uassert_int_equal(value, 32767);
202 }
203 
TC_rt_sscanf_null_string(void)204 static void TC_rt_sscanf_null_string(void)
205 {
206     const char str[] = "";
207     int value;
208     int result = rt_sscanf(str, "%d", &value);
209     uassert_int_equal(result, -1);
210 }
211 
212 /* https://github.com/RT-Thread/rt-thread/issues/9853 */
TC_rt_sscanf_issue_9853(void)213 static void TC_rt_sscanf_issue_9853(void)
214 {
215     int device_socket = 255;
216     int bfsz = 255;
217     const char str[] = "+MIPURC: \"rtcp\",0,240,HTTP/1.1 200 OK";
218     rt_sscanf(str, "+MIPURC:%*[^,],%d,%d", &device_socket, (int *)&bfsz);
219     uassert_int_equal(device_socket, 0);
220     uassert_int_equal(bfsz, 240);
221 }
222 
utest_do_tc(void)223 static void utest_do_tc(void)
224 {
225     UTEST_UNIT_RUN(TC_rt_sscanf_char);
226     UTEST_UNIT_RUN(TC_rt_sscanf_basic_int);
227     UTEST_UNIT_RUN(TC_rt_sscanf_basic_float);
228     UTEST_UNIT_RUN(TC_rt_sscanf_basic_string);
229     UTEST_UNIT_RUN(TC_rt_sscanf_string_with_space);
230     UTEST_UNIT_RUN(TC_rt_sscanf_basic_char);
231     UTEST_UNIT_RUN(TC_rt_sscanf_hex_1);
232     UTEST_UNIT_RUN(TC_rt_sscanf_hex_2);
233     UTEST_UNIT_RUN(TC_rt_sscanf_oct_1);
234     UTEST_UNIT_RUN(TC_rt_sscanf_oct_2);
235     UTEST_UNIT_RUN(TC_rt_sscanf_multiple_args);
236     UTEST_UNIT_RUN(TC_rt_sscanf_pointer);
237     UTEST_UNIT_RUN(TC_rt_sscanf_width_specifier);
238     UTEST_UNIT_RUN(TC_rt_sscanf_suppression);
239     UTEST_UNIT_RUN(TC_rt_sscanf_match_set);
240     UTEST_UNIT_RUN(TC_rt_sscanf_match_set_negated);
241     UTEST_UNIT_RUN(TC_rt_sscanf_match_set_range);
242     UTEST_UNIT_RUN(TC_rt_sscanf_whitespace_skip);
243     UTEST_UNIT_RUN(TC_rt_sscanf_unsigned_int);
244     UTEST_UNIT_RUN(TC_rt_sscanf_long_long_int);
245     UTEST_UNIT_RUN(TC_rt_sscanf_short_int);
246     UTEST_UNIT_RUN(TC_rt_sscanf_null_string);
247     UTEST_UNIT_RUN(TC_rt_sscanf_issue_9853);
248 }
249 
250 UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_sscanf", RT_NULL, RT_NULL, 1000);
251