31 #include <google/protobuf/inlined_string_field.h>
40 #include <google/protobuf/stubs/logging.h>
41 #include <google/protobuf/stubs/common.h>
42 #include <google/protobuf/io/coded_stream.h>
43 #include <google/protobuf/io/zero_copy_stream_impl.h>
44 #include <google/protobuf/arenastring.h>
45 #include <gtest/gtest.h>
46 #include <google/protobuf/stubs/strutil.h>
52 using internal::ArenaStringPtr;
53 using internal::InlinedStringField;
59 const uint32 kMask = ~0x00000001
u;
60 const uint32 kMask1 = ~0x00000004
u;
61 const uint32 kMask2 = ~0x00000020
u;
63 TEST(InlinedStringFieldTest, SetOnHeap) {
64 InlinedStringField
field;
65 uint32 donating_states = 0;
68 &donating_states, kMask);
71 nullptr,
false, &donating_states, kMask);
75 TEST(InlinedStringFieldTest, SetRvalueOnHeap) {
76 InlinedStringField
field;
77 uint32 donating_states = 0;
78 std::string string_moved =
"Moved long long long long string 1";
79 field.Set(
nullptr,
std::move(string_moved),
nullptr,
false, &donating_states,
85 TEST(InlinedStringFieldTest, UnsafeMutablePointerThenRelease) {
86 InlinedStringField
field;
93 *mut =
"Test long long long long value";
97 EXPECT_EQ(
"Test long long long long value", *released);
108 TEST(InlinedStringFieldTest, ArenaSetThenMutable) {
110 auto* field_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
114 true, &donating_states, kMask1);
116 field_arena->Set(&kDefaultValue,
"Test long long long long value", &
arena,
117 (donating_states & ~kMask1) != 0,
118 &donating_states, kMask1);
120 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
124 const std::string* old_string = &field_arena->Get();
125 const char* old_data = old_string->data();
129 (donating_states & ~kMask1) != 0, &donating_states, kMask1);
131 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
136 *mut =
"Test an even longer long long long long value";
149 TEST(InlinedStringFieldTest, ArenaRelease) {
151 auto* field_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
155 true, &donating_states, kMask1);
157 &kDefaultValue, &
arena, (donating_states & ~kMask1) != 0);
160 EXPECT_NE(released, &field_arena->Get());
161 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
168 (donating_states & ~kMask1) != 0u, &donating_states, kMask1);
169 *mut =
"Test long long long long value";
171 field_arena->Release(&kDefaultValue, &
arena,
172 (donating_states & ~kMask1) != 0);
173 EXPECT_EQ(
"Test long long long long value", *released2);
175 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
182 TEST(InlinedStringFieldTest, SetRvalueArena) {
184 auto* field1_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
185 auto* field2_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
189 std::string string_moved =
"Moved long long long long string 1";
191 &donating_states, kMask1);
192 EXPECT_EQ(
"Moved long long long long string 1", field1_arena->Get());
193 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
198 &donating_states, kMask);
199 EXPECT_EQ(
"string 2 on heap", field2_arena->Get());
200 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
206 TEST(InlinedStringFieldTest, SetAllocated) {
207 InlinedStringField
field;
209 auto* field1_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
210 auto* field2_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
215 field.Set(&kDefaultValue,
WrapString(
"String on heap"),
nullptr,
false,
216 &donating_states, kMask);
217 auto* allocated =
new std::string(
"Allocated string on heap");
218 field.SetAllocatedNoArena(&kDefaultValue, allocated);
222 field1_arena->Set(&kDefaultValue,
WrapString(
"String 1 on arena"), &
arena,
223 true, &donating_states, kMask1);
225 (donating_states & ~kMask1) != 0, &donating_states,
226 kMask1) =
"Mutated string 1 is now on heap long long";
228 allocated =
new std::string(
"Allocated string on heap long long long");
229 field1_arena->SetAllocated(&kDefaultValue, allocated, &
arena,
230 (donating_states & ~kMask1) != 0, &donating_states,
232 EXPECT_EQ(
"Allocated string on heap long long long", field1_arena->Get());
233 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
238 field2_arena->Set(&kDefaultValue,
WrapString(
"String 2 on arena long long"),
239 &
arena,
true, &donating_states,
241 allocated =
new std::string(
"Allocated string on heap long long long 2");
242 field2_arena->SetAllocated(&kDefaultValue, allocated, &
arena,
true,
243 &donating_states, kMask2);
244 EXPECT_EQ(
"Allocated string on heap long long long 2", field2_arena->Get());
245 #if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
251 TEST(InlinedStringFieldTest,
Swap) {
253 InlinedStringField field1;
254 InlinedStringField field2;
255 uint32 donating_states = 0;
257 auto* field1_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
258 auto* field2_arena = Arena::CreateMessage<InlinedStringField>(&
arena);
259 uint32 donating_states_1 = ~0
u;
260 uint32 donating_states_2 = ~0
u;
263 const std::string& string1_heap =
"String 1 on heap";
264 const std::string& string2_heap =
"String 2 on heap long long long long";
265 const std::string& string1_arena =
"String 1 on arena";
266 const std::string& string2_arena =
"String 2 on arena long long long long";
267 field1.SetNoArena(&kDefaultValue, string1_heap);
268 field2.SetNoArena(&kDefaultValue, string2_heap);
269 field1_arena->Set(&kDefaultValue, string1_arena, &
arena,
true,
270 &donating_states_1, kMask1);
271 field2_arena->Set(&kDefaultValue, string2_arena, &
arena,
true,
272 &donating_states_2, kMask1);
274 field1.Swap(&field2, &kDefaultValue,
nullptr,
false,
false, &donating_states,
275 &donating_states_2, kMask);
276 field1_arena->Swap(field2_arena, &kDefaultValue, &
arena,
true,
true,
277 &donating_states_1, &donating_states_2, kMask1);
280 EXPECT_EQ(field1_arena->Get(), string2_arena);
281 EXPECT_EQ(field2_arena->Get(), string1_arena);