Branch data Line data Source code
1 : : #include "test_libmem_all.h"
2 : : #include <wchar.h>
3 : :
4 : : /**
5 : : * @brief Capture noisy typed formatted-string frame-error cases
6 : : *
7 : : * These cases intentionally exercise report() paths. match_function_output()
8 : : * keeps the expected diagnostics out of the common test output
9 : : *
10 : : * @return Return describing success or failure
11 : : */
12 : 1 : static Return capture_libmem_formatted_string_frame_errors(void)
13 : : {
14 : 1 : INITTEST;
15 : :
16 : : /* Frame error: a data-mode destination is rejected by the narrow formatter */
17 : : {
18 : 1 : m_create(char,not_a_string);
19 : 1 : ASSERT(not_a_string->is_string == false);
20 : 1 : ASSERT(FAILURE == m_formatted_string(not_a_string,"anything"));
21 : 1 : ASSERT(not_a_string->is_string == false);
22 : 1 : call(m_del(not_a_string));
23 : : }
24 : :
25 : : /* Frame error: a narrow format may only write a char descriptor.
26 : : uint16_t remains unsupported even when it is a string descriptor */
27 : : {
28 : 1 : m_create(uint16_t,unsupported_width,MEMORY_STRING);
29 : 1 : ASSERT(unsupported_width->is_string == true);
30 : 1 : ASSERT(unsupported_width->single_element_size == sizeof(uint16_t));
31 : 1 : ASSERT(unsupported_width->single_element_size != sizeof(char));
32 : 1 : ASSERT(FAILURE == m_formatted_string(unsupported_width,"anything"));
33 : 1 : call(m_del(unsupported_width));
34 : : }
35 : :
36 : : /* Frame error: macro dispatch follows the format type, so a narrow
37 : : format cannot silently write into a wide-character descriptor */
38 : : {
39 : 1 : m_create(wchar_t,wrong_format_width,MEMORY_STRING);
40 : 1 : ASSERT(wrong_format_width->single_element_size == sizeof(wchar_t));
41 : 1 : ASSERT(FAILURE == m_formatted_string(wrong_format_width,"anything"));
42 : 1 : call(m_del(wrong_format_width));
43 : : }
44 : :
45 : : /* Frame error: a typed NULL narrow format is not a formatting request,
46 : : and rejecting it must leave already rendered text untouched */
47 : : {
48 : 1 : m_create(char,null_narrow_format,MEMORY_STRING);
49 : :
50 : 1 : ASSERT(SUCCESS == m_formatted_string(null_narrow_format,"seed"));
51 : : /* Use a typed NULL pointer so the public macro selects the narrow
52 : : formatter and the runtime contract is exercised */
53 : 1 : ASSERT(FAILURE == m_formatted_string(null_narrow_format,(const char *)NULL));
54 : 1 : ASSERT(strcmp(m_text(null_narrow_format),"seed") == 0);
55 : 1 : ASSERT(null_narrow_format->string_length == strlen("seed"));
56 : 1 : call(m_del(null_narrow_format));
57 : : }
58 : :
59 : : /* Frame error: the wide formatter rejects a typed NULL format by the
60 : : same public contract and also preserves the existing text */
61 : : {
62 : 1 : m_create(wchar_t,null_wide_format,MEMORY_STRING);
63 : 1 : const wchar_t *null_format = NULL;
64 : :
65 : 1 : ASSERT(SUCCESS == m_formatted_string(null_wide_format,L"seed"));
66 : 1 : ASSERT(FAILURE == m_formatted_string(null_wide_format,null_format));
67 : 1 : ASSERT(wcscmp((const wchar_t *)null_wide_format->data,L"seed") == 0);
68 : 1 : ASSERT(null_wide_format->string_length == wcslen(L"seed"));
69 : 1 : call(m_del(null_wide_format));
70 : : }
71 : :
72 : 1 : deliver(status);
73 : : }
74 : :
75 : : /**
76 : : * @brief Verify typed formatted-string dispatch for char and wchar_t descriptors
77 : : * @details Exercises the public m_formatted_string macro for both supported
78 : : * element widths. The
79 : : * coverage includes:
80 : : * - byte (char) destinations: basic formatting with mixed
81 : : * conversions, replacement of an existing payload with both
82 : : * shorter and longer rendered text, an empty rendered result
83 : : * that keeps the descriptor in string mode, and direct use of
84 : : * the narrow typed helper
85 : : * - wide (wchar_t) destinations: basic formatting plus a long
86 : : * format that intentionally exceeds the iterative-growth
87 : : * starting capacity so the doubling loop in the wide path is
88 : : * actually exercised
89 : : * - frame-error rejections: non-string destination, mismatched
90 : : * descriptor width, and typed NULL narrow and wide formats
91 : : *
92 : : * @return Return enum indicating success or failure of the test
93 : : * @retval SUCCESS if test passed
94 : : * @retval FAILURE if test failed
95 : : */
96 : 1 : Return test_libmem_0070(void)
97 : : {
98 : 1 : INITTEST;
99 : :
100 : : /* 1. Byte: basic format with mixed conversions writes the expected text */
101 : : {
102 : 1 : m_create(char,byte_basic,MEMORY_STRING);
103 : 1 : ASSERT(SUCCESS == m_formatted_string(byte_basic,"Hello %s %d!","world",42));
104 : 1 : ASSERT(byte_basic->is_string == true);
105 : 1 : ASSERT(byte_basic->single_element_size == sizeof(char));
106 : 1 : ASSERT(byte_basic->string_length == strlen("Hello world 42!"));
107 : 1 : ASSERT(strcmp(m_text(byte_basic),"Hello world 42!") == 0);
108 : 1 : call(m_del(byte_basic));
109 : : }
110 : :
111 : : /* 2. Byte: each call fully replaces the previous content (longer then shorter) */
112 : : {
113 : 1 : m_create(char,byte_replace,MEMORY_STRING);
114 : 1 : ASSERT(SUCCESS == m_formatted_string(byte_replace,"first"));
115 : 1 : ASSERT(strcmp(m_text(byte_replace),"first") == 0);
116 : :
117 : 1 : ASSERT(SUCCESS == m_formatted_string(byte_replace,"second %d goes here",100));
118 : 1 : ASSERT(strcmp(m_text(byte_replace),"second 100 goes here") == 0);
119 : 1 : ASSERT(byte_replace->string_length == strlen("second 100 goes here"));
120 : :
121 : 1 : ASSERT(SUCCESS == m_formatted_string(byte_replace,"x"));
122 : 1 : ASSERT(strcmp(m_text(byte_replace),"x") == 0);
123 : 1 : ASSERT(byte_replace->string_length == 1U);
124 : :
125 : 1 : call(m_del(byte_replace));
126 : : }
127 : :
128 : : /* 3. Byte: an empty rendered result still leaves a valid empty string */
129 : : {
130 : 1 : m_create(char,byte_empty,MEMORY_STRING);
131 : 1 : ASSERT(SUCCESS == m_formatted_string(byte_empty,"%s",""));
132 : 1 : ASSERT(byte_empty->is_string == true);
133 : 1 : ASSERT(byte_empty->string_length == 0U);
134 : 1 : ASSERT(m_text(byte_empty)[0] == '\0');
135 : 1 : call(m_del(byte_empty));
136 : : }
137 : :
138 : : /* 4. Byte: another narrow formatted call exposes the same public contract */
139 : : {
140 : 1 : m_create(char,byte_direct,MEMORY_STRING);
141 : :
142 : 1 : ASSERT(SUCCESS == m_formatted_string(byte_direct,"%s-%u","item",3U));
143 : 1 : ASSERT(strcmp(m_text(byte_direct),"item-3") == 0);
144 : 1 : ASSERT(byte_direct->string_length == strlen("item-3"));
145 : :
146 : 1 : call(m_del(byte_direct));
147 : : }
148 : :
149 : : /* 5. Wide: basic format with mixed conversions writes the expected wide text */
150 : : {
151 : 1 : m_create(wchar_t,wide_basic,MEMORY_STRING);
152 : 1 : ASSERT(SUCCESS == m_formatted_string(wide_basic,L"Wide %ls %d",L"text",7));
153 : 1 : ASSERT(wide_basic->is_string == true);
154 : 1 : ASSERT(wide_basic->single_element_size == sizeof(wchar_t));
155 : 1 : ASSERT(wide_basic->string_length == wcslen(L"Wide text 7"));
156 : 1 : ASSERT(wcscmp((const wchar_t *)wide_basic->data,L"Wide text 7") == 0);
157 : 1 : call(m_del(wide_basic));
158 : : }
159 : :
160 : : /* 6. Wide: long format exercises the iterative-growth path past the
161 : : initial 128-element capacity guess inside the wide branch */
162 : : {
163 : 1 : m_create(wchar_t,wide_long,MEMORY_STRING);
164 : :
165 : : /* This source is intentionally longer than 128 wchar_t elements so the
166 : : initial speculative render fails and the doubling loop runs */
167 : 1 : const wchar_t *long_source =
168 : : L"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
169 : : L"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
170 : : L"Ut enim ad minim veniam, quis nostrud exercitation ullamco.";
171 : :
172 : 1 : ASSERT(wcslen(long_source) > 128U);
173 : 1 : ASSERT(SUCCESS == m_formatted_string(wide_long,L"%ls",long_source));
174 : 1 : ASSERT(wide_long->is_string == true);
175 : 1 : ASSERT(wide_long->string_length == wcslen(long_source));
176 : 1 : ASSERT(wcscmp((const wchar_t *)wide_long->data,long_source) == 0);
177 : 1 : call(m_del(wide_long));
178 : : }
179 : :
180 : : /* Expected stderr layout for frame errors rejected by typed formatters.
181 : : Source line numbers and errno wording are intentionally flexible because
182 : : they are build- and platform-dependent */
183 : : static const char expected_stderr_pattern_libmem_0070[] =
184 : : "\\A"
185 : : "ERROR: src/mem_formatted_string\\.c:mem_formatted_string_char:\\d+ Memory management; Destination must be a string descriptor Errno: [^\\n]+ \\(errno: [0-9]+\\)\n"
186 : : "ERROR: src/mem_formatted_string\\.c:mem_formatted_string_char:\\d+ Memory management; Narrow formatted destination requires char elements Errno: [^\\n]+ \\(errno: [0-9]+\\)\n"
187 : : "ERROR: src/mem_formatted_string\\.c:mem_formatted_string_char:\\d+ Memory management; Narrow formatted destination requires char elements Errno: [^\\n]+ \\(errno: [0-9]+\\)\n"
188 : : "ERROR: src/mem_formatted_string\\.c:mem_formatted_string_char:\\d+ Memory management; Format string must be non-NULL Errno: [^\\n]+ \\(errno: [0-9]+\\)\n"
189 : : "ERROR: src/mem_formatted_string\\.c:mem_formatted_string_wchar:\\d+ Memory management; Format string must be non-NULL Errno: [^\\n]+ \\(errno: [0-9]+\\)\n"
190 : : "\\Z";
191 : :
192 : 1 : ASSERT(SUCCESS == match_function_output(NULL,expected_stderr_pattern_libmem_0070,capture_libmem_formatted_string_frame_errors));
193 : :
194 : 1 : RETURN_STATUS;
195 : : }
|