mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
9.0 KiB
300 lines
9.0 KiB
/* |
|
* |
|
* 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 "src/core/lib/avl/avl.h" |
|
|
|
#include <stdio.h> |
|
#include <string.h> |
|
|
|
#include <grpc/support/alloc.h> |
|
#include <grpc/support/log.h> |
|
|
|
#include "src/core/lib/gpr/useful.h" |
|
#include "test/core/util/test_config.h" |
|
|
|
static int* box(int x) { |
|
int* b = static_cast<int*>(gpr_malloc(sizeof(*b))); |
|
*b = x; |
|
return b; |
|
} |
|
|
|
static long int_compare(void* int1, void* int2, void* unused) { |
|
return (*static_cast<int*>(int1)) - (*static_cast<int*>(int2)); |
|
} |
|
static void* int_copy(void* p, void* unused) { |
|
return box(*static_cast<int*>(p)); |
|
} |
|
|
|
static void destroy(void* p, void* unused) { gpr_free(p); } |
|
|
|
static const grpc_avl_vtable int_int_vtable = {destroy, int_copy, int_compare, |
|
destroy, int_copy}; |
|
|
|
static void check_get(grpc_avl avl, int key, int value) { |
|
int* k = box(key); |
|
GPR_ASSERT(*(int*)grpc_avl_get(avl, k, nullptr) == value); |
|
gpr_free(k); |
|
} |
|
|
|
static void check_negget(grpc_avl avl, int key) { |
|
int* k = box(key); |
|
GPR_ASSERT(grpc_avl_get(avl, k, nullptr) == nullptr); |
|
gpr_free(k); |
|
} |
|
|
|
static grpc_avl remove_int(grpc_avl avl, int key) { |
|
int* k = box(key); |
|
avl = grpc_avl_remove(avl, k, nullptr); |
|
gpr_free(k); |
|
return avl; |
|
} |
|
|
|
static void test_get(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_get"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(1), box(11), nullptr); |
|
avl = grpc_avl_add(avl, box(2), box(22), nullptr); |
|
avl = grpc_avl_add(avl, box(3), box(33), nullptr); |
|
check_get(avl, 1, 11); |
|
check_get(avl, 2, 22); |
|
check_get(avl, 3, 33); |
|
check_negget(avl, 4); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_ll(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_ll"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(5), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(4), box(2), nullptr); |
|
avl = grpc_avl_add(avl, box(3), box(3), nullptr); |
|
GPR_ASSERT(*(int*)avl.root->key == 4); |
|
GPR_ASSERT(*(int*)avl.root->left->key == 3); |
|
GPR_ASSERT(*(int*)avl.root->right->key == 5); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_lr(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_lr"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(5), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(3), box(2), nullptr); |
|
avl = grpc_avl_add(avl, box(4), box(3), nullptr); |
|
GPR_ASSERT(*(int*)avl.root->key == 4); |
|
GPR_ASSERT(*(int*)avl.root->left->key == 3); |
|
GPR_ASSERT(*(int*)avl.root->right->key == 5); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_rr(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_rr"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(3), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(4), box(2), nullptr); |
|
avl = grpc_avl_add(avl, box(5), box(3), nullptr); |
|
GPR_ASSERT(*(int*)avl.root->key == 4); |
|
GPR_ASSERT(*(int*)avl.root->left->key == 3); |
|
GPR_ASSERT(*(int*)avl.root->right->key == 5); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_rl(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_rl"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(3), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(5), box(2), nullptr); |
|
avl = grpc_avl_add(avl, box(4), box(3), nullptr); |
|
GPR_ASSERT(*(int*)avl.root->key == 4); |
|
GPR_ASSERT(*(int*)avl.root->left->key == 3); |
|
GPR_ASSERT(*(int*)avl.root->right->key == 5); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_unbalanced(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_unbalanced"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(5), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(4), box(2), nullptr); |
|
avl = grpc_avl_add(avl, box(3), box(3), nullptr); |
|
avl = grpc_avl_add(avl, box(2), box(4), nullptr); |
|
avl = grpc_avl_add(avl, box(1), box(5), nullptr); |
|
GPR_ASSERT(*(int*)avl.root->key == 4); |
|
GPR_ASSERT(*(int*)avl.root->left->key == 2); |
|
GPR_ASSERT(*(int*)avl.root->left->left->key == 1); |
|
GPR_ASSERT(*(int*)avl.root->left->right->key == 3); |
|
GPR_ASSERT(*(int*)avl.root->right->key == 5); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_replace(void) { |
|
grpc_avl avl; |
|
gpr_log(GPR_DEBUG, "test_replace"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(1), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(1), box(2), nullptr); |
|
check_get(avl, 1, 2); |
|
check_negget(avl, 2); |
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_remove(void) { |
|
grpc_avl avl; |
|
grpc_avl avl3, avl4, avl5, avln; |
|
gpr_log(GPR_DEBUG, "test_remove"); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(3), box(1), nullptr); |
|
avl = grpc_avl_add(avl, box(4), box(2), nullptr); |
|
avl = grpc_avl_add(avl, box(5), box(3), nullptr); |
|
|
|
avl3 = remove_int(grpc_avl_ref(avl, nullptr), 3); |
|
avl4 = remove_int(grpc_avl_ref(avl, nullptr), 4); |
|
avl5 = remove_int(grpc_avl_ref(avl, nullptr), 5); |
|
avln = remove_int(grpc_avl_ref(avl, nullptr), 1); |
|
|
|
grpc_avl_unref(avl, nullptr); |
|
|
|
check_negget(avl3, 3); |
|
check_get(avl3, 4, 2); |
|
check_get(avl3, 5, 3); |
|
grpc_avl_unref(avl3, nullptr); |
|
|
|
check_get(avl4, 3, 1); |
|
check_negget(avl4, 4); |
|
check_get(avl4, 5, 3); |
|
grpc_avl_unref(avl4, nullptr); |
|
|
|
check_get(avl5, 3, 1); |
|
check_get(avl5, 4, 2); |
|
check_negget(avl5, 5); |
|
grpc_avl_unref(avl5, nullptr); |
|
|
|
check_get(avln, 3, 1); |
|
check_get(avln, 4, 2); |
|
check_get(avln, 5, 3); |
|
grpc_avl_unref(avln, nullptr); |
|
} |
|
|
|
static void test_badcase1(void) { |
|
grpc_avl avl; |
|
|
|
gpr_log(GPR_DEBUG, "test_badcase1"); |
|
|
|
avl = grpc_avl_create(&int_int_vtable); |
|
avl = grpc_avl_add(avl, box(88), box(1), nullptr); |
|
avl = remove_int(avl, 643); |
|
avl = remove_int(avl, 983); |
|
avl = grpc_avl_add(avl, box(985), box(4), nullptr); |
|
avl = grpc_avl_add(avl, box(640), box(5), nullptr); |
|
avl = grpc_avl_add(avl, box(41), box(6), nullptr); |
|
avl = grpc_avl_add(avl, box(112), box(7), nullptr); |
|
avl = grpc_avl_add(avl, box(342), box(8), nullptr); |
|
avl = remove_int(avl, 1013); |
|
avl = grpc_avl_add(avl, box(434), box(10), nullptr); |
|
avl = grpc_avl_add(avl, box(520), box(11), nullptr); |
|
avl = grpc_avl_add(avl, box(231), box(12), nullptr); |
|
avl = grpc_avl_add(avl, box(852), box(13), nullptr); |
|
avl = remove_int(avl, 461); |
|
avl = grpc_avl_add(avl, box(108), box(15), nullptr); |
|
avl = grpc_avl_add(avl, box(806), box(16), nullptr); |
|
avl = grpc_avl_add(avl, box(827), box(17), nullptr); |
|
avl = remove_int(avl, 796); |
|
avl = grpc_avl_add(avl, box(340), box(19), nullptr); |
|
avl = grpc_avl_add(avl, box(498), box(20), nullptr); |
|
avl = grpc_avl_add(avl, box(203), box(21), nullptr); |
|
avl = grpc_avl_add(avl, box(751), box(22), nullptr); |
|
avl = grpc_avl_add(avl, box(150), box(23), nullptr); |
|
avl = remove_int(avl, 237); |
|
avl = grpc_avl_add(avl, box(830), box(25), nullptr); |
|
avl = remove_int(avl, 1007); |
|
avl = remove_int(avl, 394); |
|
avl = grpc_avl_add(avl, box(65), box(28), nullptr); |
|
avl = remove_int(avl, 904); |
|
avl = remove_int(avl, 123); |
|
avl = grpc_avl_add(avl, box(238), box(31), nullptr); |
|
avl = grpc_avl_add(avl, box(184), box(32), nullptr); |
|
avl = remove_int(avl, 331); |
|
avl = grpc_avl_add(avl, box(827), box(34), nullptr); |
|
|
|
check_get(avl, 830, 25); |
|
|
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
static void test_stress(int amount_of_stress) { |
|
int added[1024]; |
|
int i, j; |
|
int deletions = 0; |
|
grpc_avl avl; |
|
|
|
unsigned seed = static_cast<unsigned>(time(nullptr)); |
|
|
|
gpr_log(GPR_DEBUG, "test_stress amount=%d seed=%u", amount_of_stress, seed); |
|
|
|
srand(static_cast<unsigned>(time(nullptr))); |
|
avl = grpc_avl_create(&int_int_vtable); |
|
|
|
memset(added, 0, sizeof(added)); |
|
|
|
for (i = 1; deletions < amount_of_stress; i++) { |
|
int idx = rand() % static_cast<int> GPR_ARRAY_SIZE(added); |
|
GPR_ASSERT(i); |
|
if (rand() < RAND_MAX / 2) { |
|
added[idx] = i; |
|
printf("avl = grpc_avl_add(avl, box(%d), box(%d), NULL); /* d=%d */\n", |
|
idx, i, deletions); |
|
avl = grpc_avl_add(avl, box(idx), box(i), nullptr); |
|
} else { |
|
deletions += (added[idx] != 0); |
|
added[idx] = 0; |
|
printf("avl = remove_int(avl, %d); /* d=%d */\n", idx, deletions); |
|
avl = remove_int(avl, idx); |
|
} |
|
for (j = 0; j < static_cast<int> GPR_ARRAY_SIZE(added); j++) { |
|
if (added[j] != 0) { |
|
check_get(avl, j, added[j]); |
|
} else { |
|
check_negget(avl, j); |
|
} |
|
} |
|
} |
|
|
|
grpc_avl_unref(avl, nullptr); |
|
} |
|
|
|
int main(int argc, char* argv[]) { |
|
grpc_test_init(argc, argv); |
|
|
|
test_get(); |
|
test_ll(); |
|
test_lr(); |
|
test_rr(); |
|
test_rl(); |
|
test_unbalanced(); |
|
test_replace(); |
|
test_remove(); |
|
test_badcase1(); |
|
test_stress(10); |
|
|
|
return 0; |
|
}
|
|
|