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