1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include <cstdint>
9 #include <string>
10
11 #include <gtest/gtest.h>
12 #include "absl/log/absl_check.h"
13 #include "google/protobuf/descriptor.h"
14 #include "google/protobuf/generated_message_bases.h"
15 #include "google/protobuf/repeated_ptr_field.h"
16 #include "google/protobuf/unittest.pb.h"
17
18 // Must be included last.
19 #include "google/protobuf/port_def.inc"
20
21 namespace google {
22 namespace protobuf {
23 namespace compiler {
24 namespace cpp {
25
26 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
27 namespace cpp_unittest {
28
29
30 #if !defined(ABSL_CHECK_MESSAGE_SIZE)
31 #define ABSL_CHECK_MESSAGE_SIZE(t, expected)
32 #endif
33
34 // Mock structures to lock down the size of messages in a platform-independent
35 // way. The commented sizes only apply when build with clang x86_64.
36 struct MockMessageBase {
37 virtual ~MockMessageBase() = default; // 8 bytes vtable
38 void* internal_metadata; // 8 bytes
39 };
40 ABSL_CHECK_MESSAGE_SIZE(MockMessageBase, 16);
41
42 struct MockZeroFieldsBase : public MockMessageBase {
43 int cached_size; // 4 bytes
44 // + 4 bytes padding
45 };
46 ABSL_CHECK_MESSAGE_SIZE(MockZeroFieldsBase, 24);
47
48 struct MockExtensionSet {
49 void* arena; // 8 bytes
50 int16_t capacity; // 4 bytes
51 int16_t size; // 4 bytes
52 void* data; // 8 bytes
53 };
54 ABSL_CHECK_MESSAGE_SIZE(MockExtensionSet, 24);
55
56 struct MockRepeatedPtrField {
57 void* arena; // 8 bytes
58 int current_size; // 4 bytes
59 int total_size; // 4 bytes
60 void* data; // 8 bytes
61 };
62 ABSL_CHECK_MESSAGE_SIZE(MockRepeatedPtrField, 24);
63
64 struct MockRepeatedField {
65 int current_size; // 4 bytes
66 int total_size; // 4 bytes
67 void* data; // 8 bytes
68 };
69 ABSL_CHECK_MESSAGE_SIZE(MockRepeatedField, 16);
70
TEST(GeneratedMessageTest,MockSizes)71 TEST(GeneratedMessageTest, MockSizes) {
72 // Consistency checks -- if these fail, the tests below will definitely fail.
73 ABSL_CHECK_EQ(sizeof(MessageLite), sizeof(MockMessageBase));
74 ABSL_CHECK_EQ(sizeof(Message), sizeof(MockMessageBase));
75 ABSL_CHECK_EQ(sizeof(internal::ZeroFieldsBase), sizeof(MockZeroFieldsBase));
76 ABSL_CHECK_EQ(sizeof(internal::ExtensionSet), sizeof(MockExtensionSet));
77 ABSL_CHECK_EQ(sizeof(RepeatedPtrField<std::string>),
78 sizeof(MockRepeatedPtrField));
79 ABSL_CHECK_EQ(sizeof(RepeatedField<int>), sizeof(MockRepeatedField));
80 }
81
TEST(GeneratedMessageTest,EmptyMessageSize)82 TEST(GeneratedMessageTest, EmptyMessageSize) {
83 EXPECT_EQ(sizeof(protobuf_unittest::TestEmptyMessage),
84 sizeof(MockZeroFieldsBase));
85 }
86
TEST(GeneratedMessageTest,ReservedSize)87 TEST(GeneratedMessageTest, ReservedSize) {
88 EXPECT_EQ(sizeof(protobuf_unittest::TestReservedFields),
89 sizeof(MockZeroFieldsBase));
90 }
91
TEST(GeneratedMessageTest,EmptyMessageWithExtensionsSize)92 TEST(GeneratedMessageTest, EmptyMessageWithExtensionsSize) {
93 struct MockGenerated : public MockMessageBase { // 16 bytes
94 MockExtensionSet extensions; // 24 bytes
95 int cached_size; // 4 bytes
96 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
97 // + 0-4 bytes of padding
98 };
99 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 48);
100 EXPECT_EQ(sizeof(protobuf_unittest::TestEmptyMessageWithExtensions),
101 sizeof(MockGenerated));
102 }
103
TEST(GeneratedMessageTest,RecursiveMessageSize)104 TEST(GeneratedMessageTest, RecursiveMessageSize) {
105 // TODO: remove once synthetic_pdproto lands.
106 #ifndef PROTOBUF_FORCE_SPLIT
107 struct MockGenerated : public MockMessageBase { // 16 bytes
108 int has_bits[1]; // 4 bytes
109 int cached_size; // 4 bytes
110 void* a; // 8 bytes
111 int32_t i; // 4 bytes
112 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
113 // + 0-4 bytes padding
114 };
115 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 40);
116 #else // !PROTOBUF_FORCE_SPLIT
117 struct MockGenerated : public MockMessageBase { // 16 bytes
118 int has_bits[1]; // 4 bytes
119 int cached_size; // 4 bytes
120 void* split; // 8 bytes
121 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
122 // + 0-4 bytes padding
123 };
124 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
125 #endif // PROTOBUF_FORCE_SPLIT
126
127 EXPECT_EQ(sizeof(protobuf_unittest::TestRecursiveMessage),
128 sizeof(MockGenerated));
129 }
130
TEST(GeneratedMessageTest,OneStringSize)131 TEST(GeneratedMessageTest, OneStringSize) {
132 struct MockGenerated : public MockMessageBase { // 16 bytes
133 int has_bits[1]; // 4 bytes
134 int cached_size; // 4 bytes
135 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
136 // + 0-4 bytes padding
137 void* data; // 8 bytes
138 };
139 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
140 EXPECT_EQ(sizeof(protobuf_unittest::OneString), sizeof(MockGenerated));
141 }
142
TEST(GeneratedMessageTest,MoreStringSize)143 TEST(GeneratedMessageTest, MoreStringSize) {
144 // TODO: remove once synthetic_pdproto lands.
145 #ifndef PROTOBUF_FORCE_SPLIT
146 struct MockGenerated : public MockMessageBase { // 16 bytes
147 int cached_size; // 4 bytes
148 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
149 // + 0-4 bytes padding
150 MockRepeatedPtrField data; // 24 bytes
151 };
152 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 48);
153 #else // !PROTOBUF_FORCE_SPLIT
154 struct MockGenerated : public MockMessageBase { // 16 bytes
155 int cached_size; // 4 bytes
156 void* split; // 8 bytes
157 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
158 // + 0-4 bytes padding
159 };
160 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
161 #endif // PROTOBUF_FORCE_SPLIT
162 EXPECT_EQ(sizeof(protobuf_unittest::MoreString), sizeof(MockGenerated));
163 }
164
TEST(GeneratedMessageTest,Int32MessageSize)165 TEST(GeneratedMessageTest, Int32MessageSize) {
166 struct MockGenerated : public MockMessageBase { // 16 bytes
167 int has_bits[1]; // 4 bytes
168 int cached_size; // 4 bytes
169 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
170 // + 0-4 bytes padding
171 int32_t data; // 4 bytes
172 };
173 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
174 EXPECT_EQ(sizeof(protobuf_unittest::Int32Message), sizeof(MockGenerated));
175 }
176
TEST(GeneratedMessageTest,Int64MessageSize)177 TEST(GeneratedMessageTest, Int64MessageSize) {
178 struct MockGenerated : public MockMessageBase { // 16 bytes
179 int has_bits[1]; // 4 bytes
180 int cached_size; // 4 bytes
181 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
182 // + 0-4 bytes padding
183 int64_t data; // 8 bytes
184 };
185 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
186 EXPECT_EQ(sizeof(protobuf_unittest::Int64Message), sizeof(MockGenerated));
187 }
188
TEST(GeneratedMessageTest,BoolMessageSize)189 TEST(GeneratedMessageTest, BoolMessageSize) {
190 struct MockGenerated : public MockMessageBase { // 16 bytes
191 int has_bits[1]; // 4 bytes
192 int cached_size; // 4 bytes
193 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
194 // + 0-4 bytes padding
195 bool data; // 1 byte
196 // + 3 bytes padding
197 };
198 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
199 EXPECT_EQ(sizeof(protobuf_unittest::BoolMessage), sizeof(MockGenerated));
200 }
201
TEST(GeneratedMessageTest,OneofSize)202 TEST(GeneratedMessageTest, OneofSize) {
203 struct MockGenerated : public MockMessageBase { // 16 bytes
204 void* foo; // 8 bytes
205 int cached_size; // 4 bytes
206 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
207 // + 0-4 bytes padding
208 uint32_t oneof_case[1]; // 4 bytes
209 };
210 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
211 EXPECT_EQ(sizeof(protobuf_unittest::TestOneof), sizeof(MockGenerated));
212 }
213
TEST(GeneratedMessageTest,Oneof2Size)214 TEST(GeneratedMessageTest, Oneof2Size) {
215 // TODO: remove once synthetic_pdproto lands.
216 #ifndef PROTOBUF_FORCE_SPLIT
217 struct MockGenerated : public MockMessageBase { // 16 bytes
218 int has_bits[1]; // 4 bytes
219 int cached_size; // 4 bytes
220 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
221 // + 0-4 bytes padding
222 void* baz_string; // 8 bytes
223 int32_t baz_int; // 4 bytes
224 // + 4 bytes padding
225 void* foo; // 8 bytes
226 void* bar; // 8 bytes
227 uint32_t oneof_case[2]; // 8 bytes
228 };
229 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 64);
230 #else // !PROTOBUF_FORCE_SPLIT
231 struct MockGenerated : public MockMessageBase { // 16 bytes
232 int has_bits[1]; // 4 bytes
233 int cached_size; // 4 bytes
234 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
235 // + 0-4 bytes padding
236 void* split; // 8 bytes
237 void* foo; // 8 bytes
238 void* bar; // 8 bytes
239 uint32_t oneof_case[2]; // 8 bytes
240 };
241 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 56);
242 #endif // PROTOBUF_FORCE_SPLIT
243 EXPECT_EQ(sizeof(protobuf_unittest::TestOneof2), sizeof(MockGenerated));
244 }
245
TEST(GeneratedMessageTest,FieldOrderingsSize)246 TEST(GeneratedMessageTest, FieldOrderingsSize) {
247 // TODO: remove once synthetic_pdproto lands.
248 #ifndef PROTOBUF_FORCE_SPLIT
249 struct MockGenerated : public MockMessageBase { // 16 bytes
250 int has_bits[1]; // 4 bytes
251 int cached_size; // 4 bytes
252 MockExtensionSet extensions; // 24 bytes
253 void* my_string; // 8 bytes
254 void* optional_nested_message; // 8 bytes
255 int64_t my_int; // 8 bytes
256 float my_float; // 4 bytes
257 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
258 // + 0-4 bytes padding
259 };
260 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 80);
261 #else // !PROTOBUF_FORCE_SPLIT
262 struct MockGenerated : public MockMessageBase { // 16 bytes
263 int has_bits[1]; // 4 bytes
264 int cached_size; // 4 bytes
265 MockExtensionSet extensions; // 24 bytes
266 void* split; // 8 bytes
267 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
268 // + 0-4 bytes padding
269 };
270 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 56);
271 #endif // PROTOBUF_FORCE_SPLIT
272 EXPECT_EQ(sizeof(protobuf_unittest::TestFieldOrderings), sizeof(MockGenerated));
273 }
274
TEST(GeneratedMessageTest,TestMessageSize)275 TEST(GeneratedMessageTest, TestMessageSize) {
276 // We expect the message to contain (not in this order):
277 // TODO: remove once synthetic_pdproto lands.
278 #ifndef PROTOBUF_FORCE_SPLIT
279 struct MockGenerated : public MockMessageBase { // 16 bytes
280 int has_bits[1]; // 4 bytes
281 int cached_size; // 4 bytes
282 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
283 // + 0-4 bytes padding
284 void* m4; // 8 bytes
285 int64_t m2; // 8 bytes
286 bool m1; // 1 bytes
287 bool m3; // 1 bytes
288 // + 2 bytes padding
289 int m5; // 4 bytes
290 int64_t m6; // 8 bytes
291 };
292 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 56);
293 #else // !PROTOBUF_FORCE_SPLIT
294 struct MockGenerated : public MockMessageBase { // 16 bytes
295 int has_bits[1]; // 4 bytes
296 int cached_size; // 4 bytes
297 void* split; // 8 bytes
298 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
299 // + 0-4 bytes padding
300 };
301 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
302 #endif // PROTOBUF_FORCE_SPLIT
303 EXPECT_EQ(sizeof(protobuf_unittest::TestMessageSize), sizeof(MockGenerated));
304 }
305
TEST(GeneratedMessageTest,PackedTypesSize)306 TEST(GeneratedMessageTest, PackedTypesSize) {
307 // TODO: remove once synthetic_pdproto lands.
308 #ifndef PROTOBUF_FORCE_SPLIT
309 struct MockGenerated : public MockMessageBase { // 16 bytes
310 MockRepeatedField packed_int32; // 16 bytes
311 int packed_int32_cached_byte_size; // 4 bytes + 4 bytes padding
312 MockRepeatedField packed_int64; // 16 bytes
313 int packed_int64_cached_byte_size; // 4 bytes + 4 bytes padding
314 MockRepeatedField packed_uint32; // 16 bytes
315 int packed_uint32_cached_byte_size; // 4 bytes + 4 bytes padding
316 MockRepeatedField packed_uint64; // 16 bytes
317 int packed_uint64_cached_byte_size; // 4 bytes + 4 bytes padding
318 MockRepeatedField packed_sint32; // 16 bytes
319 int packed_sint32_cached_byte_size; // 4 bytes + 4 bytes padding
320 MockRepeatedField packed_sint64; // 16 bytes
321 int packed_sint64_cached_byte_size; // 4 bytes + 4 bytes padding
322 MockRepeatedField packed_fixed32; // 16 bytes
323 MockRepeatedField packed_fixed64; // 16 bytes
324 MockRepeatedField packed_sfixed32; // 16 bytes
325 MockRepeatedField packed_sfixed64; // 16 bytes
326 MockRepeatedField packed_float; // 16 bytes
327 MockRepeatedField packed_double; // 16 bytes
328 MockRepeatedField packed_bool; // 16 bytes
329 MockRepeatedField packed_enum; // 16 bytes
330 int packed_enum_cached_byte_size; // 4 bytes
331 int cached_size; // 4 bytes
332 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
333 // + 0-4 bytes padding
334 };
335 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 16 * 15 + 8 * 6 + 8);
336 #else // !PROTOBUF_FORCE_SPLIT
337 struct MockGenerated : public MockMessageBase { // 16 bytes
338 int cached_size; // 4 bytes + 4 bytes padding
339 void* split; // 8 bytes
340 PROTOBUF_TSAN_DECLARE_MEMBER; // 0-4 bytes
341 // + 0-4 bytes padding
342 };
343 ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
344 #endif // PROTOBUF_FORCE_SPLIT
345 EXPECT_EQ(sizeof(protobuf_unittest::TestPackedTypes), sizeof(MockGenerated));
346 }
347
348 } // namespace cpp_unittest
349 } // namespace cpp
350 } // namespace compiler
351 } // namespace protobuf
352 } // namespace google
353
354 #include "google/protobuf/port_undef.inc"
355