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