• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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