Home | History | Annotate | Download | only in slice
      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/b64.h"
     20 
     21 #include <string.h>
     22 
     23 #include <grpc/grpc.h>
     24 #include <grpc/slice.h>
     25 #include <grpc/support/alloc.h>
     26 #include <grpc/support/log.h>
     27 #include "src/core/lib/iomgr/exec_ctx.h"
     28 #include "src/core/lib/slice/slice_internal.h"
     29 #include "test/core/util/test_config.h"
     30 
     31 static int buffers_are_equal(const unsigned char* buf1,
     32                              const unsigned char* buf2, size_t size) {
     33   size_t i;
     34   for (i = 0; i < size; i++) {
     35     if (buf1[i] != buf2[i]) {
     36       gpr_log(GPR_ERROR, "buf1 and buf2 differ: buf1[%d] = %x vs buf2[%d] = %x",
     37               static_cast<int>(i), buf1[i], static_cast<int>(i), buf2[i]);
     38       return 0;
     39     }
     40   }
     41   return 1;
     42 }
     43 
     44 static void test_simple_encode_decode_b64(int url_safe, int multiline) {
     45   const char* hello = "hello";
     46   char* hello_b64 =
     47       grpc_base64_encode(hello, strlen(hello), url_safe, multiline);
     48   grpc_core::ExecCtx exec_ctx;
     49   grpc_slice hello_slice = grpc_base64_decode(hello_b64, url_safe);
     50   GPR_ASSERT(GRPC_SLICE_LENGTH(hello_slice) == strlen(hello));
     51   GPR_ASSERT(strncmp((const char*)GRPC_SLICE_START_PTR(hello_slice), hello,
     52                      GRPC_SLICE_LENGTH(hello_slice)) == 0);
     53 
     54   grpc_slice_unref_internal(hello_slice);
     55 
     56   gpr_free(hello_b64);
     57 }
     58 
     59 static void test_full_range_encode_decode_b64(int url_safe, int multiline) {
     60   unsigned char orig[256];
     61   size_t i;
     62   char* b64;
     63   grpc_slice orig_decoded;
     64   for (i = 0; i < sizeof(orig); i++) orig[i] = static_cast<uint8_t>(i);
     65 
     66   /* Try all the different paddings. */
     67   for (i = 0; i < 3; i++) {
     68     grpc_core::ExecCtx exec_ctx;
     69     b64 = grpc_base64_encode(orig, sizeof(orig) - i, url_safe, multiline);
     70     orig_decoded = grpc_base64_decode(b64, url_safe);
     71     GPR_ASSERT(GRPC_SLICE_LENGTH(orig_decoded) == (sizeof(orig) - i));
     72     GPR_ASSERT(buffers_are_equal(orig, GRPC_SLICE_START_PTR(orig_decoded),
     73                                  sizeof(orig) - i));
     74     grpc_slice_unref_internal(orig_decoded);
     75     gpr_free(b64);
     76   }
     77 }
     78 
     79 static void test_simple_encode_decode_b64_no_multiline(void) {
     80   test_simple_encode_decode_b64(0, 0);
     81 }
     82 
     83 static void test_simple_encode_decode_b64_multiline(void) {
     84   test_simple_encode_decode_b64(0, 1);
     85 }
     86 
     87 static void test_simple_encode_decode_b64_urlsafe_no_multiline(void) {
     88   test_simple_encode_decode_b64(1, 0);
     89 }
     90 
     91 static void test_simple_encode_decode_b64_urlsafe_multiline(void) {
     92   test_simple_encode_decode_b64(1, 1);
     93 }
     94 
     95 static void test_full_range_encode_decode_b64_no_multiline(void) {
     96   test_full_range_encode_decode_b64(0, 0);
     97 }
     98 
     99 static void test_full_range_encode_decode_b64_multiline(void) {
    100   test_full_range_encode_decode_b64(0, 1);
    101 }
    102 
    103 static void test_full_range_encode_decode_b64_urlsafe_no_multiline(void) {
    104   test_full_range_encode_decode_b64(1, 0);
    105 }
    106 
    107 static void test_full_range_encode_decode_b64_urlsafe_multiline(void) {
    108   test_full_range_encode_decode_b64(1, 1);
    109 }
    110 
    111 static void test_url_safe_unsafe_mismatch_failure(void) {
    112   unsigned char orig[256];
    113   size_t i;
    114   char* b64;
    115   grpc_slice orig_decoded;
    116   int url_safe = 1;
    117   for (i = 0; i < sizeof(orig); i++) orig[i] = static_cast<uint8_t>(i);
    118 
    119   grpc_core::ExecCtx exec_ctx;
    120   b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0);
    121   orig_decoded = grpc_base64_decode(b64, !url_safe);
    122   GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded));
    123   gpr_free(b64);
    124   grpc_slice_unref_internal(orig_decoded);
    125 
    126   b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0);
    127   orig_decoded = grpc_base64_decode(b64, url_safe);
    128   GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded));
    129   gpr_free(b64);
    130   grpc_slice_unref_internal(orig_decoded);
    131 }
    132 
    133 static void test_rfc4648_test_vectors(void) {
    134   char* b64;
    135 
    136   b64 = grpc_base64_encode("", 0, 0, 0);
    137   GPR_ASSERT(strcmp("", b64) == 0);
    138   gpr_free(b64);
    139 
    140   b64 = grpc_base64_encode("f", 1, 0, 0);
    141   GPR_ASSERT(strcmp("Zg==", b64) == 0);
    142   gpr_free(b64);
    143 
    144   b64 = grpc_base64_encode("fo", 2, 0, 0);
    145   GPR_ASSERT(strcmp("Zm8=", b64) == 0);
    146   gpr_free(b64);
    147 
    148   b64 = grpc_base64_encode("foo", 3, 0, 0);
    149   GPR_ASSERT(strcmp("Zm9v", b64) == 0);
    150   gpr_free(b64);
    151 
    152   b64 = grpc_base64_encode("foob", 4, 0, 0);
    153   GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0);
    154   gpr_free(b64);
    155 
    156   b64 = grpc_base64_encode("fooba", 5, 0, 0);
    157   GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0);
    158   gpr_free(b64);
    159 
    160   b64 = grpc_base64_encode("foobar", 6, 0, 0);
    161   GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0);
    162   gpr_free(b64);
    163 }
    164 
    165 static void test_unpadded_decode(void) {
    166   grpc_slice decoded;
    167 
    168   grpc_core::ExecCtx exec_ctx;
    169   decoded = grpc_base64_decode("Zm9vYmFy", 0);
    170   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
    171   GPR_ASSERT(grpc_slice_str_cmp(decoded, "foobar") == 0);
    172   grpc_slice_unref(decoded);
    173 
    174   decoded = grpc_base64_decode("Zm9vYmE", 0);
    175   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
    176   GPR_ASSERT(grpc_slice_str_cmp(decoded, "fooba") == 0);
    177   grpc_slice_unref(decoded);
    178 
    179   decoded = grpc_base64_decode("Zm9vYg", 0);
    180   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
    181   GPR_ASSERT(grpc_slice_str_cmp(decoded, "foob") == 0);
    182   grpc_slice_unref(decoded);
    183 
    184   decoded = grpc_base64_decode("Zm9v", 0);
    185   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
    186   GPR_ASSERT(grpc_slice_str_cmp(decoded, "foo") == 0);
    187   grpc_slice_unref(decoded);
    188 
    189   decoded = grpc_base64_decode("Zm8", 0);
    190   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
    191   GPR_ASSERT(grpc_slice_str_cmp(decoded, "fo") == 0);
    192   grpc_slice_unref(decoded);
    193 
    194   decoded = grpc_base64_decode("Zg", 0);
    195   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
    196   GPR_ASSERT(grpc_slice_str_cmp(decoded, "f") == 0);
    197   grpc_slice_unref(decoded);
    198 
    199   decoded = grpc_base64_decode("", 0);
    200   GPR_ASSERT(GRPC_SLICE_IS_EMPTY(decoded));
    201 }
    202 
    203 int main(int argc, char** argv) {
    204   grpc_test_init(argc, argv);
    205   grpc_init();
    206   test_simple_encode_decode_b64_no_multiline();
    207   test_simple_encode_decode_b64_multiline();
    208   test_simple_encode_decode_b64_urlsafe_no_multiline();
    209   test_simple_encode_decode_b64_urlsafe_multiline();
    210   test_full_range_encode_decode_b64_no_multiline();
    211   test_full_range_encode_decode_b64_multiline();
    212   test_full_range_encode_decode_b64_urlsafe_no_multiline();
    213   test_full_range_encode_decode_b64_urlsafe_multiline();
    214   test_url_safe_unsafe_mismatch_failure();
    215   test_rfc4648_test_vectors();
    216   test_unpadded_decode();
    217   grpc_shutdown();
    218   return 0;
    219 }
    220