Home | History | Annotate | Download | only in iomgr
      1 /*
      2  *
      3  * Copyright 2017 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/iomgr/error.h"
     20 
     21 #include <grpc/grpc.h>
     22 #include <grpc/support/alloc.h>
     23 #include <grpc/support/log.h>
     24 
     25 #include <string.h>
     26 
     27 #include "test/core/util/test_config.h"
     28 
     29 static void test_set_get_int() {
     30   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test");
     31   GPR_ASSERT(error);
     32   intptr_t i = 0;
     33   GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i));
     34   GPR_ASSERT(i);  // line set will never be 0
     35   GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
     36   GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_SIZE, &i));
     37 
     38   intptr_t errnumber = 314;
     39   error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errnumber);
     40   GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
     41   GPR_ASSERT(i == errnumber);
     42 
     43   intptr_t http = 2;
     44   error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, http);
     45   GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
     46   GPR_ASSERT(i == http);
     47 
     48   GRPC_ERROR_UNREF(error);
     49 }
     50 
     51 static void test_set_get_str() {
     52   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test");
     53 
     54   grpc_slice str;
     55   GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
     56   GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR, &str));
     57 
     58   GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_FILE, &str));
     59   GPR_ASSERT(strstr((char*)GRPC_SLICE_START_PTR(str),
     60                     "error_test.c"));  // __FILE__ expands differently on
     61                                        // Windows. All should at least
     62                                        // contain error_test.c
     63 
     64   GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str));
     65   GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "Test",
     66                       GRPC_SLICE_LENGTH(str)));
     67 
     68   error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
     69                              grpc_slice_from_static_string("longer message"));
     70   GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
     71   GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "longer message",
     72                       GRPC_SLICE_LENGTH(str)));
     73 
     74   GRPC_ERROR_UNREF(error);
     75 }
     76 
     77 static void test_copy_and_unref() {
     78   // error1 has one ref
     79   grpc_error* error1 = grpc_error_set_str(
     80       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"), GRPC_ERROR_STR_GRPC_MESSAGE,
     81       grpc_slice_from_static_string("message"));
     82   grpc_slice str;
     83   GPR_ASSERT(grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
     84   GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message",
     85                       GRPC_SLICE_LENGTH(str)));
     86 
     87   // error 1 has two refs
     88   GRPC_ERROR_REF(error1);
     89   // this gives error3 a ref to the new error, and decrements error1 to one ref
     90   grpc_error* error3 = grpc_error_set_str(
     91       error1, GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("syscall"));
     92   GPR_ASSERT(error3 != error1);  // should not be the same because of extra ref
     93   GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str));
     94   GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message",
     95                       GRPC_SLICE_LENGTH(str)));
     96 
     97   // error 1 should not have a syscall but 3 should
     98   GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL, &str));
     99   GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL, &str));
    100   GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "syscall",
    101                       GRPC_SLICE_LENGTH(str)));
    102 
    103   GRPC_ERROR_UNREF(error1);
    104   GRPC_ERROR_UNREF(error3);
    105 }
    106 
    107 static void test_create_referencing() {
    108   grpc_error* child = grpc_error_set_str(
    109       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"),
    110       GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message"));
    111   grpc_error* parent =
    112       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", &child, 1);
    113   GPR_ASSERT(parent);
    114 
    115   GRPC_ERROR_UNREF(child);
    116   GRPC_ERROR_UNREF(parent);
    117 }
    118 
    119 static void test_create_referencing_many() {
    120   grpc_error* children[3];
    121   children[0] = grpc_error_set_str(
    122       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"),
    123       GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message"));
    124   children[1] =
    125       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child2"),
    126                          GRPC_ERROR_INT_HTTP2_ERROR, 5);
    127   children[2] = grpc_error_set_str(
    128       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"),
    129       GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message 3"));
    130 
    131   grpc_error* parent =
    132       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 3);
    133   GPR_ASSERT(parent);
    134 
    135   for (size_t i = 0; i < 3; ++i) {
    136     GRPC_ERROR_UNREF(children[i]);
    137   }
    138   GRPC_ERROR_UNREF(parent);
    139 }
    140 
    141 static void print_error_string() {
    142   grpc_error* error =
    143       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
    144                          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED);
    145   error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666);
    146   error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
    147                              grpc_slice_from_static_string("message"));
    148   // gpr_log(GPR_DEBUG, "%s", grpc_error_string(error));
    149   GRPC_ERROR_UNREF(error);
    150 }
    151 
    152 static void print_error_string_reference() {
    153   grpc_error* children[2];
    154   children[0] = grpc_error_set_str(
    155       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("1"),
    156                          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED),
    157       GRPC_ERROR_STR_GRPC_MESSAGE,
    158       grpc_slice_from_static_string("message for child 1"));
    159   children[1] = grpc_error_set_str(
    160       grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("2sd"),
    161                          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL),
    162       GRPC_ERROR_STR_GRPC_MESSAGE,
    163       grpc_slice_from_static_string("message for child 2"));
    164 
    165   grpc_error* parent =
    166       GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2);
    167 
    168   for (size_t i = 0; i < 2; ++i) {
    169     GRPC_ERROR_UNREF(children[i]);
    170   }
    171   GRPC_ERROR_UNREF(parent);
    172 }
    173 
    174 static void test_os_error() {
    175   int fake_errno = 5;
    176   const char* syscall = "syscall name";
    177   grpc_error* error = GRPC_OS_ERROR(fake_errno, syscall);
    178 
    179   intptr_t i = 0;
    180   GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
    181   GPR_ASSERT(i == fake_errno);
    182 
    183   grpc_slice str;
    184   GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str));
    185   GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), syscall,
    186                       GRPC_SLICE_LENGTH(str)));
    187   GRPC_ERROR_UNREF(error);
    188 }
    189 
    190 static void test_overflow() {
    191   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow");
    192 
    193   for (size_t i = 0; i < 150; ++i) {
    194     error = grpc_error_add_child(error,
    195                                  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"));
    196   }
    197 
    198   error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 5);
    199   error =
    200       grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
    201                          grpc_slice_from_static_string("message for child 2"));
    202   error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, 5);
    203 
    204   intptr_t i;
    205   GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
    206   GPR_ASSERT(i == 5);
    207   GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i));
    208 
    209   error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 10);
    210   GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
    211   GPR_ASSERT(i == 10);
    212 
    213   GRPC_ERROR_UNREF(error);
    214   ;
    215 }
    216 
    217 int main(int argc, char** argv) {
    218   grpc_test_init(argc, argv);
    219   grpc_init();
    220   test_set_get_int();
    221   test_set_get_str();
    222   test_copy_and_unref();
    223   print_error_string();
    224   print_error_string_reference();
    225   test_os_error();
    226   test_create_referencing();
    227   test_create_referencing_many();
    228   test_overflow();
    229   grpc_shutdown();
    230 
    231   return 0;
    232 }
    233