1 /*
2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Copyright (C) 2023 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 * http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33 #include <gtest/gtest.h>
34
35 #include "gbl/print.h"
36
37 // Must be the same value as `PRINT_BUFFER_SIZE` from format.c
38 #define MOCK_PRINT_BUFFER_SIZE 2048
39 static char print_buffer[MOCK_PRINT_BUFFER_SIZE];
40
gbl_print_string(const char * s)41 void gbl_print_string(const char* s) {
42 strncpy(print_buffer, s, MOCK_PRINT_BUFFER_SIZE);
43 }
44
test_gbl_printf(const char * fmt,...)45 void test_gbl_printf(const char* fmt, ...) {
46 va_list args;
47 va_start(args, fmt);
48 gbl_printf(fmt, args);
49 va_end(args);
50 }
51
TEST(PrintfTest,FormatString)52 TEST(PrintfTest, FormatString) {
53 test_gbl_printf("before %s after", "text");
54 ASSERT_STREQ("before text after", print_buffer);
55 }
56
TEST(PrintfTest,FormatInt)57 TEST(PrintfTest, FormatInt) {
58 test_gbl_printf("before %d after", 100);
59 ASSERT_STREQ("before 100 after", print_buffer);
60 }
61
TEST(PrintfTest,FormatChar)62 TEST(PrintfTest, FormatChar) {
63 test_gbl_printf("char value: %c", 'a');
64 ASSERT_STREQ("char value: a", print_buffer);
65 }
66
TEST(PrintfTest,FormatCharAsciiCode)67 TEST(PrintfTest, FormatCharAsciiCode) {
68 test_gbl_printf("char value: %hhd", 'a');
69 ASSERT_STREQ("char value: 97", print_buffer);
70 }
71
TEST(PrintfTest,FormatUnsigned)72 TEST(PrintfTest, FormatUnsigned) {
73 test_gbl_printf("Unsigned value: %u", 123456789U);
74 ASSERT_STREQ("Unsigned value: 123456789", print_buffer);
75 }
76
TEST(PrintfTest,FormatOctal)77 TEST(PrintfTest, FormatOctal) {
78 test_gbl_printf("Octal value: %o", 0777);
79 ASSERT_STREQ("Octal value: 777", print_buffer);
80 }
81
TEST(PrintfTest,FormatHex)82 TEST(PrintfTest, FormatHex) {
83 test_gbl_printf("Hex value: %x", 0xabcdef);
84 ASSERT_STREQ("Hex value: abcdef", print_buffer);
85 }
86
TEST(PrintfTest,FormatEmptyString)87 TEST(PrintfTest, FormatEmptyString) {
88 test_gbl_printf("String: '%s'", "");
89 ASSERT_STREQ("String: ''", print_buffer);
90 }
91
TEST(PrintfTest,FormatMultiple)92 TEST(PrintfTest, FormatMultiple) {
93 test_gbl_printf("Values: %d %u %x %s", -42, 42U, 0x42, "forty-two");
94 ASSERT_STREQ("Values: -42 42 42 forty-two", print_buffer);
95 }
96
TEST(PrintfTest,FormatLongLong)97 TEST(PrintfTest, FormatLongLong) {
98 long long val = 1234567890123LL;
99 test_gbl_printf("Long long: %lld", val);
100 ASSERT_STREQ("Long long: 1234567890123", print_buffer);
101 }
102
TEST(PrintfTest,FormatLLongMin)103 TEST(PrintfTest, FormatLLongMin) {
104 long long val = LLONG_MIN;
105 char expected[64];
106 snprintf(expected, sizeof(expected), "LLONG_MIN: %lld", val);
107 test_gbl_printf("LLONG_MIN: %lld", val);
108 ASSERT_STREQ(expected, print_buffer);
109 }
110
TEST(PrintfTest,FormatULLongMax)111 TEST(PrintfTest, FormatULLongMax) {
112 unsigned long long val = ULLONG_MAX;
113 char expected[64];
114 snprintf(expected, sizeof(expected), "ULLONG_MAX: %llu", val);
115 test_gbl_printf("ULLONG_MAX: %llu", val);
116 ASSERT_STREQ(expected, print_buffer);
117 }
118
TEST(PrintfTest,FormatUnknownSpecifierErrorAppended)119 TEST(PrintfTest, FormatUnknownSpecifierErrorAppended) {
120 test_gbl_printf("Unknown specifier: %q");
121 ASSERT_STREQ(
122 "Unknown specifier: GBL print implementation cannot handle format string "
123 "at symbol: q",
124 print_buffer);
125 }
126
TEST(PrintfTest,FormatPercent)127 TEST(PrintfTest, FormatPercent) {
128 test_gbl_printf("percent: %%");
129 ASSERT_STREQ("percent: %", print_buffer);
130 }
131
TEST(PrintfTest,FormatIntNegative)132 TEST(PrintfTest, FormatIntNegative) {
133 test_gbl_printf("before %d after", -100);
134 ASSERT_STREQ("before -100 after", print_buffer);
135 }
136
TEST(PrintfTest,SkipWidthZeroFlag)137 TEST(PrintfTest, SkipWidthZeroFlag) {
138 test_gbl_printf("before %08d after", 42);
139 ASSERT_STREQ("before 42 after", print_buffer);
140 }
141
TEST(PrintfTest,SkipPrecisionInt)142 TEST(PrintfTest, SkipPrecisionInt) {
143 test_gbl_printf("before %.5d after", 2025);
144 ASSERT_STREQ("before 2025 after", print_buffer);
145 }
146
TEST(PrintfTest,SkipComplexFlagsInt)147 TEST(PrintfTest, SkipComplexFlagsInt) {
148 test_gbl_printf("before %-015.6d after", -999);
149 ASSERT_STREQ("before -999 after", print_buffer);
150 }
151
TEST(PrintfTest,SkipDynamicWidth)152 TEST(PrintfTest, SkipDynamicWidth) {
153 test_gbl_printf("before %*d after", 77);
154 ASSERT_STREQ("before 77 after", print_buffer);
155 }
156
TEST(PrintfTest,SkipDynamicPrecision)157 TEST(PrintfTest, SkipDynamicPrecision) {
158 test_gbl_printf("before %.*d after", 123);
159 ASSERT_STREQ("before 123 after", print_buffer);
160 }
161
TEST(PrintfTest,SkipFlagsString)162 TEST(PrintfTest, SkipFlagsString) {
163 test_gbl_printf("before %-+#5.8s after", "TestMe!");
164 ASSERT_STREQ("before TestMe! after", print_buffer);
165 }
166
TEST(PrintfTest,SkipPlusFlag)167 TEST(PrintfTest, SkipPlusFlag) {
168 test_gbl_printf("before %+d after", 100);
169 ASSERT_STREQ("before 100 after", print_buffer);
170 }
171
TEST(PrintfTest,SkipSpaceFlag)172 TEST(PrintfTest, SkipSpaceFlag) {
173 test_gbl_printf("before % d after", 500);
174 ASSERT_STREQ("before 500 after", print_buffer);
175 }
176
TEST(PrintfTest,LongStringIsTruncated)177 TEST(PrintfTest, LongStringIsTruncated) {
178 char long_string[MOCK_PRINT_BUFFER_SIZE + 100];
179 memset(long_string, 'A', sizeof(long_string) - 1);
180 long_string[sizeof(long_string) - 1] = '\0';
181
182 test_gbl_printf("%s", long_string);
183
184 ASSERT_EQ(strlen(print_buffer), MOCK_PRINT_BUFFER_SIZE - 1);
185 for (int i = 0; i < MOCK_PRINT_BUFFER_SIZE - 1; ++i) {
186 ASSERT_EQ(print_buffer[i], 'A') << "Expected character 'A' at index " << i
187 << ", but got '" << print_buffer[i] << "'";
188 }
189 }
190
TEST(PrintfTest,MultipleMessages)191 TEST(PrintfTest, MultipleMessages) {
192 test_gbl_printf("First message: %s", "first");
193 ASSERT_STREQ("First message: first", print_buffer);
194 test_gbl_printf("Second message: %s", "second");
195 ASSERT_STREQ("Second message: second", print_buffer);
196 }
197