xref: /aosp_15_r20/external/grpc-grpc/test/core/slice/slice_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include "src/core/lib/slice/slice.h"
20 
21 #include <inttypes.h>
22 #include <string.h>
23 
24 #include <algorithm>
25 #include <functional>
26 #include <memory>
27 #include <random>
28 #include <string>
29 #include <vector>
30 
31 #include "absl/strings/string_view.h"
32 #include "gtest/gtest.h"
33 
34 #include <grpc/slice.h>
35 #include <grpc/support/log.h>
36 #include <grpc/support/port_platform.h>
37 
38 #include "src/core/lib/gprpp/memory.h"
39 #include "src/core/lib/gprpp/no_destruct.h"
40 #include "src/core/lib/slice/slice_internal.h"
41 #include "src/core/lib/slice/slice_refcount.h"
42 #include "test/core/util/build.h"
43 
TEST(GrpcSliceTest,MallocReturnsSomethingSensible)44 TEST(GrpcSliceTest, MallocReturnsSomethingSensible) {
45   // Calls grpc_slice_create for various lengths and verifies the internals for
46   // consistency.
47   size_t length;
48   size_t i;
49   grpc_slice slice;
50 
51   for (length = 0; length <= 1024; length++) {
52     slice = grpc_slice_malloc(length);
53     // If there is a length, slice.data must be non-NULL. If length is zero
54     // we don't care.
55     if (length > GRPC_SLICE_INLINED_SIZE) {
56       EXPECT_NE(slice.data.refcounted.bytes, nullptr);
57     }
58     // Returned slice length must be what was requested.
59     EXPECT_EQ(GRPC_SLICE_LENGTH(slice), length);
60     // We must be able to write to every byte of the data
61     for (i = 0; i < length; i++) {
62       GRPC_SLICE_START_PTR(slice)[i] = static_cast<uint8_t>(i);
63     }
64     // And finally we must succeed in destroying the slice
65     grpc_slice_unref(slice);
66   }
67 }
68 
do_nothing(void *)69 static void do_nothing(void* /*ignored*/) {}
70 
TEST(GrpcSliceTest,SliceNewReturnsSomethingSensible)71 TEST(GrpcSliceTest, SliceNewReturnsSomethingSensible) {
72   uint8_t x;
73 
74   grpc_slice slice = grpc_slice_new(&x, 1, do_nothing);
75   EXPECT_NE(slice.refcount, nullptr);
76   EXPECT_EQ(slice.data.refcounted.bytes, &x);
77   EXPECT_EQ(slice.data.refcounted.length, 1);
78   grpc_slice_unref(slice);
79 }
80 
81 // destroy function that sets a mark to indicate it was called.
set_mark(void * p)82 static void set_mark(void* p) { *(static_cast<int*>(p)) = 1; }
83 
TEST(GrpcSliceTest,SliceNewWithUserData)84 TEST(GrpcSliceTest, SliceNewWithUserData) {
85   int marker = 0;
86   uint8_t buf[2];
87   grpc_slice slice;
88 
89   buf[0] = 0;
90   buf[1] = 1;
91   slice = grpc_slice_new_with_user_data(buf, 2, set_mark, &marker);
92   EXPECT_EQ(marker, 0);
93   EXPECT_EQ(GRPC_SLICE_LENGTH(slice), 2);
94   EXPECT_EQ(GRPC_SLICE_START_PTR(slice)[0], 0);
95   EXPECT_EQ(GRPC_SLICE_START_PTR(slice)[1], 1);
96 
97   // unref should cause destroy function to run.
98   grpc_slice_unref(slice);
99   EXPECT_EQ(marker, 1);
100 }
101 
102 static int do_nothing_with_len_1_calls = 0;
103 
do_nothing_with_len_1(void *,size_t len)104 static void do_nothing_with_len_1(void* /*ignored*/, size_t len) {
105   EXPECT_EQ(len, 1);
106   do_nothing_with_len_1_calls++;
107 }
108 
TEST(GrpcSliceTest,SliceNewWithLenReturnsSomethingSensible)109 TEST(GrpcSliceTest, SliceNewWithLenReturnsSomethingSensible) {
110   uint8_t x;
111   int num_refs = 5;  // To test adding/removing an arbitrary number of refs
112   int i;
113 
114   grpc_slice slice = grpc_slice_new_with_len(&x, 1, do_nothing_with_len_1);
115   EXPECT_NE(slice.refcount,
116             nullptr);  // ref count is initialized to 1 at this point
117   EXPECT_EQ(slice.data.refcounted.bytes, &x);
118   EXPECT_EQ(slice.data.refcounted.length, 1);
119   EXPECT_EQ(do_nothing_with_len_1_calls, 0);
120 
121   // Add an arbitrary number of refs to the slice and remoe the refs. This is to
122   // make sure that that the destroy callback (i.e do_nothing_with_len_1()) is
123   // not called until the last unref operation
124   for (i = 0; i < num_refs; i++) {
125     grpc_slice_ref(slice);
126   }
127   for (i = 0; i < num_refs; i++) {
128     grpc_slice_unref(slice);
129   }
130   EXPECT_EQ(do_nothing_with_len_1_calls, 0);  // Shouldn't be called yet
131 
132   // last unref
133   grpc_slice_unref(slice);
134   EXPECT_EQ(do_nothing_with_len_1_calls, 1);
135 }
136 
137 class GrpcSliceSizedTest : public ::testing::TestWithParam<size_t> {};
138 
TEST_P(GrpcSliceSizedTest,SliceSubWorks)139 TEST_P(GrpcSliceSizedTest, SliceSubWorks) {
140   const auto length = GetParam();
141 
142   grpc_slice slice;
143   grpc_slice sub;
144   unsigned i, j, k;
145 
146   // Create a slice in which each byte is equal to the distance from it to the
147   // beginning of the slice.
148   slice = grpc_slice_malloc(length);
149   for (i = 0; i < length; i++) {
150     GRPC_SLICE_START_PTR(slice)[i] = static_cast<uint8_t>(i);
151   }
152 
153   // Ensure that for all subsets length is correct and that we start on the
154   // correct byte. Additionally check that no copies were made.
155   for (i = 0; i < length; i++) {
156     for (j = i; j < length; j++) {
157       sub = grpc_slice_sub(slice, i, j);
158       EXPECT_EQ(GRPC_SLICE_LENGTH(sub), j - i);
159       for (k = 0; k < j - i; k++) {
160         EXPECT_EQ(GRPC_SLICE_START_PTR(sub)[k], (uint8_t)(i + k));
161       }
162       grpc_slice_unref(sub);
163     }
164   }
165   grpc_slice_unref(slice);
166 }
167 
check_head_tail(grpc_slice slice,grpc_slice head,grpc_slice tail)168 static void check_head_tail(grpc_slice slice, grpc_slice head,
169                             grpc_slice tail) {
170   EXPECT_EQ(GRPC_SLICE_LENGTH(slice),
171             GRPC_SLICE_LENGTH(head) + GRPC_SLICE_LENGTH(tail));
172   EXPECT_EQ(0, memcmp(GRPC_SLICE_START_PTR(slice), GRPC_SLICE_START_PTR(head),
173                       GRPC_SLICE_LENGTH(head)));
174   EXPECT_EQ(0, memcmp(GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(head),
175                       GRPC_SLICE_START_PTR(tail), GRPC_SLICE_LENGTH(tail)));
176 }
177 
TEST_P(GrpcSliceSizedTest,SliceSplitHeadWorks)178 TEST_P(GrpcSliceSizedTest, SliceSplitHeadWorks) {
179   const auto length = GetParam();
180 
181   grpc_slice slice;
182   grpc_slice head, tail;
183   size_t i;
184 
185   gpr_log(GPR_INFO, "length=%" PRIuPTR, length);
186 
187   // Create a slice in which each byte is equal to the distance from it to the
188   // beginning of the slice.
189   slice = grpc_slice_malloc(length);
190   for (i = 0; i < length; i++) {
191     GRPC_SLICE_START_PTR(slice)[i] = static_cast<uint8_t>(i);
192   }
193 
194   // Ensure that for all subsets length is correct and that we start on the
195   // correct byte. Additionally check that no copies were made.
196   for (i = 0; i < length; i++) {
197     tail = grpc_slice_ref(slice);
198     head = grpc_slice_split_head(&tail, i);
199     check_head_tail(slice, head, tail);
200     grpc_slice_unref(tail);
201     grpc_slice_unref(head);
202   }
203 
204   grpc_slice_unref(slice);
205 }
206 
TEST_P(GrpcSliceSizedTest,SliceSplitTailWorks)207 TEST_P(GrpcSliceSizedTest, SliceSplitTailWorks) {
208   const auto length = GetParam();
209 
210   grpc_slice slice;
211   grpc_slice head, tail;
212   size_t i;
213 
214   gpr_log(GPR_INFO, "length=%" PRIuPTR, length);
215 
216   // Create a slice in which each byte is equal to the distance from it to the
217   // beginning of the slice.
218   slice = grpc_slice_malloc(length);
219   for (i = 0; i < length; i++) {
220     GRPC_SLICE_START_PTR(slice)[i] = static_cast<uint8_t>(i);
221   }
222 
223   // Ensure that for all subsets length is correct and that we start on the
224   // correct byte. Additionally check that no copies were made.
225   for (i = 0; i < length; i++) {
226     head = grpc_slice_ref(slice);
227     tail = grpc_slice_split_tail(&head, i);
228     check_head_tail(slice, head, tail);
229     grpc_slice_unref(tail);
230     grpc_slice_unref(head);
231   }
232 
233   grpc_slice_unref(slice);
234 }
235 
236 INSTANTIATE_TEST_SUITE_P(GrpcSliceSizedTest, GrpcSliceSizedTest,
__anoncf142c440102null237                          ::testing::ValuesIn([] {
238                            std::vector<size_t> out;
239                            for (size_t i = 0; i < 128; i++) {
240                              out.push_back(i);
241                            }
242                            return out;
243                          }()),
__anoncf142c440202(const testing::TestParamInfo<size_t>& info) 244                          [](const testing::TestParamInfo<size_t>& info) {
245                            return std::to_string(info.param);
246                          });
247 
TEST(GrpcSliceTest,SliceFromCopiedString)248 TEST(GrpcSliceTest, SliceFromCopiedString) {
249   static const char* text = "HELLO WORLD!";
250   grpc_slice slice;
251 
252   slice = grpc_slice_from_copied_string(text);
253   EXPECT_EQ(strlen(text), GRPC_SLICE_LENGTH(slice));
254   EXPECT_EQ(
255       0, memcmp(text, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)));
256   grpc_slice_unref(slice);
257 }
258 
TEST(GrpcSliceTest,MovedStringSlice)259 TEST(GrpcSliceTest, MovedStringSlice) {
260   // Small string should be inlined.
261   constexpr char kSmallStr[] = "hello12345";
262   char* small_ptr = strdup(kSmallStr);
263   grpc_slice small =
264       grpc_slice_from_moved_string(grpc_core::UniquePtr<char>(small_ptr));
265   EXPECT_EQ(GRPC_SLICE_LENGTH(small), strlen(kSmallStr));
266   EXPECT_NE(GRPC_SLICE_START_PTR(small), reinterpret_cast<uint8_t*>(small_ptr));
267   grpc_slice_unref(small);
268 
269   // Large string should be move the reference.
270   constexpr char kSLargeStr[] = "hello123456789123456789123456789";
271   char* large_ptr = strdup(kSLargeStr);
272   grpc_slice large =
273       grpc_slice_from_moved_string(grpc_core::UniquePtr<char>(large_ptr));
274   EXPECT_EQ(GRPC_SLICE_LENGTH(large), strlen(kSLargeStr));
275   EXPECT_EQ(GRPC_SLICE_START_PTR(large), reinterpret_cast<uint8_t*>(large_ptr));
276   grpc_slice_unref(large);
277 
278   // Moved buffer must respect the provided length not the actual length of the
279   // string.
280   large_ptr = strdup(kSLargeStr);
281   small = grpc_slice_from_moved_buffer(grpc_core::UniquePtr<char>(large_ptr),
282                                        strlen(kSmallStr));
283   EXPECT_EQ(GRPC_SLICE_LENGTH(small), strlen(kSmallStr));
284   EXPECT_NE(GRPC_SLICE_START_PTR(small), reinterpret_cast<uint8_t*>(large_ptr));
285   grpc_slice_unref(small);
286 }
287 
TEST(GrpcSliceTest,StringViewFromSlice)288 TEST(GrpcSliceTest, StringViewFromSlice) {
289   constexpr char kStr[] = "foo";
290   absl::string_view sv(
291       grpc_core::StringViewFromSlice(grpc_slice_from_static_string(kStr)));
292   EXPECT_EQ(sv, kStr);
293 }
294 
295 namespace grpc_core {
296 namespace {
297 
TEST(SliceTest,FromSmallCopiedString)298 TEST(SliceTest, FromSmallCopiedString) {
299   Slice slice = Slice::FromCopiedString("hello");
300   EXPECT_EQ(slice[0], 'h');
301   EXPECT_EQ(slice[1], 'e');
302   EXPECT_EQ(slice[2], 'l');
303   EXPECT_EQ(slice[3], 'l');
304   EXPECT_EQ(slice[4], 'o');
305   EXPECT_EQ(slice.size(), 5);
306   EXPECT_EQ(slice.length(), 5);
307   EXPECT_EQ(slice.as_string_view(), "hello");
308   EXPECT_EQ(0, memcmp(slice.data(), "hello", 5));
309 }
310 
311 class SliceSizedTest : public ::testing::TestWithParam<size_t> {};
312 
RandomString(size_t length)313 std::string RandomString(size_t length) {
314   std::string str;
315   std::random_device r;
316   for (size_t i = 0; i < length; ++i) {
317     str.push_back(static_cast<char>(r()));
318   }
319   return str;
320 }
321 
TEST_P(SliceSizedTest,FromCopiedString)322 TEST_P(SliceSizedTest, FromCopiedString) {
323   const std::string str = RandomString(GetParam());
324   Slice slice = Slice::FromCopiedString(str);
325 
326   EXPECT_EQ(slice.size(), str.size());
327   EXPECT_EQ(slice.length(), str.size());
328   EXPECT_EQ(slice.as_string_view(), str);
329   EXPECT_EQ(0, memcmp(slice.data(), str.data(), str.size()));
330   for (size_t i = 0; i < str.size(); ++i) {
331     EXPECT_EQ(slice[i], uint8_t(str[i]));
332   }
333 
334   EXPECT_TRUE(slice.is_equivalent(slice.Ref()));
335   EXPECT_TRUE(slice.is_equivalent(slice.AsOwned()));
336   EXPECT_TRUE(slice.is_equivalent(slice.Ref().TakeOwned()));
337 }
338 
339 INSTANTIATE_TEST_SUITE_P(SliceSizedTest, SliceSizedTest,
__anoncf142c440402null340                          ::testing::ValuesIn([] {
341                            std::vector<size_t> out;
342                            size_t i = 1;
343                            size_t j = 1;
344                            while (i < 1024 * 1024) {
345                              out.push_back(j);
346                              size_t n = i + j;
347                              i = j;
348                              j = n;
349                            }
350                            return out;
351                          }()),
__anoncf142c440502(const ::testing::TestParamInfo<size_t>& info) 352                          [](const ::testing::TestParamInfo<size_t>& info) {
353                            return std::to_string(info.param);
354                          });
355 
356 class TakeUniquelyOwnedTest
357     : public ::testing::TestWithParam<std::function<Slice()>> {};
358 
TEST_P(TakeUniquelyOwnedTest,TakeUniquelyOwned)359 TEST_P(TakeUniquelyOwnedTest, TakeUniquelyOwned) {
360   auto owned = GetParam()().TakeUniquelyOwned();
361   auto* refcount = owned.c_slice().refcount;
362   if (refcount != nullptr && refcount != grpc_slice_refcount::NoopRefcount()) {
363     EXPECT_TRUE(refcount->IsUnique());
364   }
365 }
366 
367 INSTANTIATE_TEST_SUITE_P(
368     TakeUniquelyOwnedTest, TakeUniquelyOwnedTest,
369     ::testing::Values(
__anoncf142c440602() 370         []() {
371           static const NoDestruct<std::string> big('a', 1024);
372           return Slice::FromStaticBuffer(big->data(), big->size());
373         },
__anoncf142c440702() 374         []() {
375           static const NoDestruct<std::string> big('a', 1024);
376           return Slice::FromCopiedBuffer(big->data(), big->size());
377         },
__anoncf142c440802() 378         []() {
379           static const NoDestruct<std::string> big('a', 1024);
380           static const NoDestruct<Slice> big_slice(
381               Slice::FromCopiedBuffer(big->data(), big->size()));
382           return big_slice->Ref();
383         },
__anoncf142c440902() 384         []() { return Slice::FromStaticString("hello"); }));
385 
SumSlice(const Slice & slice)386 size_t SumSlice(const Slice& slice) {
387   size_t x = 0;
388   for (size_t i = 0; i < slice.size(); ++i) {
389     x += slice[i];
390   }
391   return x;
392 }
393 
TEST(SliceTest,ExternalAsOwned)394 TEST(SliceTest, ExternalAsOwned) {
395   auto external_string = std::make_unique<std::string>(RandomString(1024));
396   Slice slice = Slice::FromExternalString(*external_string);
397   const auto initial_sum = SumSlice(slice);
398   Slice owned = slice.AsOwned();
399   EXPECT_EQ(initial_sum, SumSlice(owned));
400   external_string.reset();
401   // In ASAN (where we can be sure that it'll crash), go ahead and read the
402   // bytes we just deleted.
403   if (BuiltUnderAsan()) {
404     ASSERT_DEATH({ gpr_log(GPR_DEBUG, "%" PRIdPTR, SumSlice(slice)); }, "");
405   }
406   EXPECT_EQ(initial_sum, SumSlice(owned));
407 }
408 
TEST(SliceTest,ExternalTakeOwned)409 TEST(SliceTest, ExternalTakeOwned) {
410   std::unique_ptr<std::string> external_string(
411       new std::string(RandomString(1024)));
412   SumSlice(Slice::FromExternalString(*external_string).TakeOwned());
413 }
414 
TEST(SliceTest,StaticSlice)415 TEST(SliceTest, StaticSlice) {
416   static const char* hello = "hello";
417   StaticSlice slice = StaticSlice::FromStaticString(hello);
418   EXPECT_EQ(slice[0], 'h');
419   EXPECT_EQ(slice[1], 'e');
420   EXPECT_EQ(slice[2], 'l');
421   EXPECT_EQ(slice[3], 'l');
422   EXPECT_EQ(slice[4], 'o');
423   EXPECT_EQ(slice.size(), 5);
424   EXPECT_EQ(slice.length(), 5);
425   EXPECT_EQ(slice.as_string_view(), "hello");
426   EXPECT_EQ(0, memcmp(slice.data(), "hello", 5));
427   EXPECT_EQ(reinterpret_cast<const uint8_t*>(hello), slice.data());
428 }
429 
TEST(SliceTest,SliceEquality)430 TEST(SliceTest, SliceEquality) {
431   auto a = Slice::FromCopiedString(
432       "hello world 123456789123456789123456789123456789123456789");
433   auto b = Slice::FromCopiedString(
434       "hello world 123456789123456789123456789123456789123456789");
435   auto c = Slice::FromCopiedString(
436       "this is not the same as the other two strings!!!!!!!!!!!!");
437   EXPECT_FALSE(a.is_equivalent(b));
438   EXPECT_FALSE(b.is_equivalent(a));
439   EXPECT_EQ(a, b);
440   EXPECT_NE(a, c);
441   EXPECT_NE(b, c);
442   EXPECT_EQ(a, "hello world 123456789123456789123456789123456789123456789");
443   EXPECT_NE(a, "pfoooey");
444   EXPECT_EQ(c, "this is not the same as the other two strings!!!!!!!!!!!!");
445   EXPECT_EQ("hello world 123456789123456789123456789123456789123456789", a);
446   EXPECT_NE("pfoooey", a);
447   EXPECT_EQ("this is not the same as the other two strings!!!!!!!!!!!!", c);
448 }
449 
TEST(SliceTest,LetsGetMutable)450 TEST(SliceTest, LetsGetMutable) {
451   auto slice = MutableSlice::FromCopiedString("hello");
452   EXPECT_EQ(slice[0], 'h');
453   EXPECT_EQ(slice[1], 'e');
454   EXPECT_EQ(slice[2], 'l');
455   EXPECT_EQ(slice[3], 'l');
456   EXPECT_EQ(slice[4], 'o');
457   EXPECT_EQ(slice.size(), 5);
458   EXPECT_EQ(slice.length(), 5);
459   EXPECT_EQ(slice.as_string_view(), "hello");
460   EXPECT_EQ(0, memcmp(slice.data(), "hello", 5));
461   slice[2] = 'm';
462   EXPECT_EQ(slice.as_string_view(), "hemlo");
463   for (auto& c : slice) c++;
464   EXPECT_EQ(slice.as_string_view(), "ifnmp");
465 }
466 
TEST(SliceTest,SliceCastWorks)467 TEST(SliceTest, SliceCastWorks) {
468   using ::grpc_event_engine::experimental::internal::SliceCast;
469   Slice test = Slice::FromCopiedString("hello world!");
470   const grpc_slice& slice = SliceCast<grpc_slice>(test);
471   EXPECT_EQ(&slice, &test.c_slice());
472   const Slice& other = SliceCast<Slice>(slice);
473   EXPECT_EQ(&other, &test);
474 }
475 
476 }  // namespace
477 }  // namespace grpc_core
478 
main(int argc,char ** argv)479 int main(int argc, char** argv) {
480   ::testing::InitGoogleTest(&argc, argv);
481   return RUN_ALL_TESTS();
482 }
483