diff options
author | Craig Tiller <ctiller@google.com> | 2017-11-08 09:42:32 -0800 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2017-11-08 09:42:32 -0800 |
commit | 660d4aa2d281dbfbc6c3a3e3349b3e4b6a444285 (patch) | |
tree | 592cecc1d6670bb12b9af81c19cd3cb98cc0eeef /test/core/slice/slice_test.cc | |
parent | 48d26966646e910f7dd63d428ef831178ca9315e (diff) | |
parent | d9da7387b8057f3bd99a417a5ee905377bce9296 (diff) |
Merge github.com:grpc/grpc into tfix2
Diffstat (limited to 'test/core/slice/slice_test.cc')
-rw-r--r-- | test/core/slice/slice_test.cc | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/test/core/slice/slice_test.cc b/test/core/slice/slice_test.cc new file mode 100644 index 0000000000..aec5636376 --- /dev/null +++ b/test/core/slice/slice_test.cc @@ -0,0 +1,309 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <grpc/slice.h> + +#include <string.h> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> + +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x); + +static void test_slice_malloc_returns_something_sensible(void) { + /* Calls grpc_slice_create for various lengths and verifies the internals for + consistency. */ + size_t length; + size_t i; + grpc_slice slice; + + LOG_TEST_NAME("test_slice_malloc_returns_something_sensible"); + + for (length = 0; length <= 1024; length++) { + slice = grpc_slice_malloc(length); + /* If there is a length, slice.data must be non-NULL. If length is zero + we don't care. */ + if (length > GRPC_SLICE_INLINED_SIZE) { + GPR_ASSERT(slice.data.refcounted.bytes); + } + /* Returned slice length must be what was requested. */ + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == length); + /* If the slice has a refcount, it must be destroyable. */ + if (slice.refcount) { + GPR_ASSERT(slice.refcount->vtable != NULL); + GPR_ASSERT(slice.refcount->vtable->ref != NULL); + GPR_ASSERT(slice.refcount->vtable->unref != NULL); + GPR_ASSERT(slice.refcount->vtable->hash != NULL); + } + /* We must be able to write to every byte of the data */ + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + /* And finally we must succeed in destroying the slice */ + grpc_slice_unref(slice); + } +} + +static void do_nothing(void* ignored) {} + +static void test_slice_new_returns_something_sensible(void) { + uint8_t x; + + grpc_slice slice = grpc_slice_new(&x, 1, do_nothing); + GPR_ASSERT(slice.refcount); + GPR_ASSERT(slice.data.refcounted.bytes == &x); + GPR_ASSERT(slice.data.refcounted.length == 1); + grpc_slice_unref(slice); +} + +/* destroy function that sets a mark to indicate it was called. */ +static void set_mark(void* p) { *((int*)p) = 1; } + +static void test_slice_new_with_user_data(void) { + int marker = 0; + uint8_t buf[2]; + grpc_slice slice; + + buf[0] = 0; + buf[1] = 1; + slice = grpc_slice_new_with_user_data(buf, 2, set_mark, &marker); + GPR_ASSERT(marker == 0); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 2); + GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[0] == 0); + GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[1] == 1); + + /* unref should cause destroy function to run. */ + grpc_slice_unref(slice); + GPR_ASSERT(marker == 1); +} + +static int do_nothing_with_len_1_calls = 0; + +static void do_nothing_with_len_1(void* ignored, size_t len) { + GPR_ASSERT(len == 1); + do_nothing_with_len_1_calls++; +} + +static void test_slice_new_with_len_returns_something_sensible(void) { + uint8_t x; + int num_refs = 5; /* To test adding/removing an arbitrary number of refs */ + int i; + + grpc_slice slice = grpc_slice_new_with_len(&x, 1, do_nothing_with_len_1); + GPR_ASSERT(slice.refcount); /* ref count is initialized to 1 at this point */ + GPR_ASSERT(slice.data.refcounted.bytes == &x); + GPR_ASSERT(slice.data.refcounted.length == 1); + GPR_ASSERT(do_nothing_with_len_1_calls == 0); + + /* Add an arbitrary number of refs to the slice and remoe the refs. This is to + make sure that that the destroy callback (i.e do_nothing_with_len_1()) is + not called until the last unref operation */ + for (i = 0; i < num_refs; i++) { + grpc_slice_ref(slice); + } + for (i = 0; i < num_refs; i++) { + grpc_slice_unref(slice); + } + GPR_ASSERT(do_nothing_with_len_1_calls == 0); /* Shouldn't be called yet */ + + /* last unref */ + grpc_slice_unref(slice); + GPR_ASSERT(do_nothing_with_len_1_calls == 1); +} + +static void test_slice_sub_works(unsigned length) { + grpc_slice slice; + grpc_slice sub; + unsigned i, j, k; + + LOG_TEST_NAME("test_slice_sub_works"); + gpr_log(GPR_INFO, "length=%d", length); + + /* Create a slice in which each byte is equal to the distance from it to the + beginning of the slice. */ + slice = grpc_slice_malloc(length); + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + + /* Ensure that for all subsets length is correct and that we start on the + correct byte. Additionally check that no copies were made. */ + for (i = 0; i < length; i++) { + for (j = i; j < length; j++) { + sub = grpc_slice_sub(slice, i, j); + GPR_ASSERT(GRPC_SLICE_LENGTH(sub) == j - i); + for (k = 0; k < j - i; k++) { + GPR_ASSERT(GRPC_SLICE_START_PTR(sub)[k] == (uint8_t)(i + k)); + } + grpc_slice_unref(sub); + } + } + grpc_slice_unref(slice); +} + +static void check_head_tail(grpc_slice slice, grpc_slice head, + grpc_slice tail) { + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == + GRPC_SLICE_LENGTH(head) + GRPC_SLICE_LENGTH(tail)); + GPR_ASSERT(0 == memcmp(GRPC_SLICE_START_PTR(slice), + GRPC_SLICE_START_PTR(head), GRPC_SLICE_LENGTH(head))); + GPR_ASSERT(0 == memcmp(GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(head), + GRPC_SLICE_START_PTR(tail), GRPC_SLICE_LENGTH(tail))); +} + +static void test_slice_split_head_works(size_t length) { + grpc_slice slice; + grpc_slice head, tail; + size_t i; + + LOG_TEST_NAME("test_slice_split_head_works"); + gpr_log(GPR_INFO, "length=%" PRIuPTR, length); + + /* Create a slice in which each byte is equal to the distance from it to the + beginning of the slice. */ + slice = grpc_slice_malloc(length); + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + + /* Ensure that for all subsets length is correct and that we start on the + correct byte. Additionally check that no copies were made. */ + for (i = 0; i < length; i++) { + tail = grpc_slice_ref(slice); + head = grpc_slice_split_head(&tail, i); + check_head_tail(slice, head, tail); + grpc_slice_unref(tail); + grpc_slice_unref(head); + } + + grpc_slice_unref(slice); +} + +static void test_slice_split_tail_works(size_t length) { + grpc_slice slice; + grpc_slice head, tail; + size_t i; + + LOG_TEST_NAME("test_slice_split_tail_works"); + gpr_log(GPR_INFO, "length=%" PRIuPTR, length); + + /* Create a slice in which each byte is equal to the distance from it to the + beginning of the slice. */ + slice = grpc_slice_malloc(length); + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + + /* Ensure that for all subsets length is correct and that we start on the + correct byte. Additionally check that no copies were made. */ + for (i = 0; i < length; i++) { + head = grpc_slice_ref(slice); + tail = grpc_slice_split_tail(&head, i); + check_head_tail(slice, head, tail); + grpc_slice_unref(tail); + grpc_slice_unref(head); + } + + grpc_slice_unref(slice); +} + +static void test_slice_from_copied_string_works(void) { + static const char* text = "HELLO WORLD!"; + grpc_slice slice; + + LOG_TEST_NAME("test_slice_from_copied_string_works"); + + slice = grpc_slice_from_copied_string(text); + GPR_ASSERT(strlen(text) == GRPC_SLICE_LENGTH(slice)); + GPR_ASSERT( + 0 == memcmp(text, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice))); + grpc_slice_unref(slice); +} + +static void test_slice_interning(void) { + LOG_TEST_NAME("test_slice_interning"); + + grpc_init(); + grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789"); + grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789"); + GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2)); + grpc_slice interned1 = grpc_slice_intern(src1); + grpc_slice interned2 = grpc_slice_intern(src2); + GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) == + GRPC_SLICE_START_PTR(interned2)); + GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1)); + GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2)); + grpc_slice_unref(src1); + grpc_slice_unref(src2); + grpc_slice_unref(interned1); + grpc_slice_unref(interned2); + grpc_shutdown(); +} + +static void test_static_slice_interning(void) { + LOG_TEST_NAME("test_static_slice_interning"); + + // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary + // to intern a static slice + + for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { + GPR_ASSERT(grpc_slice_is_equivalent( + grpc_static_slice_table[i], + grpc_slice_intern(grpc_static_slice_table[i]))); + } +} + +static void test_static_slice_copy_interning(void) { + LOG_TEST_NAME("test_static_slice_copy_interning"); + + grpc_init(); + + for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { + grpc_slice copy = grpc_slice_dup(grpc_static_slice_table[i]); + GPR_ASSERT(grpc_static_slice_table[i].refcount != copy.refcount); + GPR_ASSERT(grpc_static_slice_table[i].refcount == + grpc_slice_intern(copy).refcount); + grpc_slice_unref(copy); + } + + grpc_shutdown(); +} + +int main(int argc, char** argv) { + unsigned length; + grpc_test_init(argc, argv); + test_slice_malloc_returns_something_sensible(); + test_slice_new_returns_something_sensible(); + test_slice_new_with_user_data(); + test_slice_new_with_len_returns_something_sensible(); + for (length = 0; length < 128; length++) { + test_slice_sub_works(length); + test_slice_split_head_works(length); + test_slice_split_tail_works(length); + } + test_slice_from_copied_string_works(); + test_slice_interning(); + test_static_slice_interning(); + test_static_slice_copy_interning(); + return 0; +} |