basic.c (4317B)
1 /* 2 * RESP encoding and decoding tests using finwo/assert. 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 8 9 #include "../src/resp.h" 10 #include "test.h" 11 12 /* Write encoded buf to pipe, read back one RESP value. Caller resp_frees result. */ 13 static resp_object *round_trip(const char *buf, size_t len) { 14 int fd[2]; 15 if (pipe(fd) != 0) return NULL; 16 ssize_t n = write(fd[1], buf, len); 17 close(fd[1]); 18 if (n != (ssize_t)len) { 19 close(fd[0]); 20 return NULL; 21 } 22 resp_object *o = resp_read(fd[0]); 23 close(fd[0]); 24 return o; 25 } 26 27 void test_resp_encode_decode_bulk(void) { 28 resp_object bulk = {.type = RESPT_BULK, .u = {.s = strdup("hello")}}; 29 const resp_object *av[] = {&bulk}; 30 char *buf = NULL; 31 size_t len = 0; 32 ASSERT_EQUALS(0, resp_encode_array(1, av, &buf, &len)); 33 ASSERT("encoded", buf != NULL && len > 0); 34 resp_object *dec = round_trip(buf, len); 35 ASSERT("decode non-NULL", dec != NULL); 36 ASSERT_EQUALS(RESPT_ARRAY, dec->type); 37 ASSERT_EQUALS(1, (int)dec->u.arr.n); 38 ASSERT_EQUALS(RESPT_BULK, dec->u.arr.elem[0].type); 39 ASSERT_STRING_EQUALS("hello", dec->u.arr.elem[0].u.s); 40 resp_free(dec); 41 free(buf); 42 free(bulk.u.s); 43 } 44 45 void test_resp_encode_decode_int(void) { 46 resp_object iobj = {.type = RESPT_INT, .u = {.i = -42}}; 47 const resp_object *av[] = {&iobj}; 48 char *buf = NULL; 49 size_t len = 0; 50 ASSERT_EQUALS(0, resp_encode_array(1, av, &buf, &len)); 51 resp_object *dec = round_trip(buf, len); 52 ASSERT("decode non-NULL", dec != NULL); 53 ASSERT_EQUALS(RESPT_ARRAY, dec->type); 54 ASSERT_EQUALS(1, (int)dec->u.arr.n); 55 ASSERT_EQUALS(RESPT_INT, dec->u.arr.elem[0].type); 56 ASSERT_EQUALS(-42, (int)dec->u.arr.elem[0].u.i); 57 resp_free(dec); 58 free(buf); 59 } 60 61 void test_resp_encode_decode_array_of_strings(void) { 62 resp_object k = {.type = RESPT_BULK, .u = {.s = strdup("key")}}; 63 resp_object v = {.type = RESPT_BULK, .u = {.s = strdup("value")}}; 64 const resp_object *av[] = {&k, &v}; 65 char *buf = NULL; 66 size_t len = 0; 67 ASSERT_EQUALS(0, resp_encode_array(2, av, &buf, &len)); 68 resp_object *dec = round_trip(buf, len); 69 ASSERT("decode non-NULL", dec != NULL); 70 ASSERT_EQUALS(RESPT_ARRAY, dec->type); 71 ASSERT_EQUALS(2, (int)dec->u.arr.n); 72 ASSERT_EQUALS(RESPT_BULK, dec->u.arr.elem[0].type); 73 ASSERT_EQUALS(RESPT_BULK, dec->u.arr.elem[1].type); 74 ASSERT_STRING_EQUALS("key", dec->u.arr.elem[0].u.s); 75 ASSERT_STRING_EQUALS("value", dec->u.arr.elem[1].u.s); 76 resp_free(dec); 77 free(buf); 78 free(k.u.s); 79 free(v.u.s); 80 } 81 82 void test_resp_map_get_string(void) { 83 resp_object k1 = {.type = RESPT_BULK, .u = {.s = strdup("a")}}; 84 resp_object v1 = {.type = RESPT_BULK, .u = {.s = strdup("1")}}; 85 resp_object k2 = {.type = RESPT_BULK, .u = {.s = strdup("b")}}; 86 resp_object v2 = {.type = RESPT_BULK, .u = {.s = strdup("2")}}; 87 resp_object *map = calloc(1, sizeof(resp_object)); 88 ASSERT("map alloc", map != NULL); 89 map->type = RESPT_ARRAY; 90 map->u.arr.n = 4; 91 map->u.arr.elem = calloc(4, sizeof(resp_object)); 92 map->u.arr.elem[0] = k1; 93 map->u.arr.elem[1] = v1; 94 map->u.arr.elem[2] = k2; 95 map->u.arr.elem[3] = v2; 96 ASSERT_STRING_EQUALS("1", resp_map_get_string(map, "a")); 97 ASSERT_STRING_EQUALS("2", resp_map_get_string(map, "b")); 98 ASSERT("missing key returns NULL", resp_map_get_string(map, "c") == NULL); 99 resp_free(map); 100 } 101 102 void test_resp_map_get_missing_key(void) { 103 resp_object *map = resp_array_init(); 104 ASSERT("map alloc", map != NULL); 105 ASSERT("missing key NULL", resp_map_get_string(map, "x") == NULL); 106 ASSERT("resp_map_get NULL", resp_map_get(map, "x") == NULL); 107 resp_free(map); 108 } 109 110 void test_resp_read_invalid_returns_null(void) { 111 int fd[2]; 112 ASSERT_EQUALS(0, pipe(fd)); 113 if (write(fd[1], "X\r\n", 3) != 3) { 114 close(fd[0]); 115 close(fd[1]); 116 return; 117 } 118 close(fd[1]); 119 resp_object *o = resp_read(fd[0]); 120 close(fd[0]); 121 ASSERT("invalid type byte returns NULL", o == NULL); 122 } 123 124 int main(void) { 125 RUN(test_resp_encode_decode_bulk); 126 RUN(test_resp_encode_decode_int); 127 RUN(test_resp_encode_decode_array_of_strings); 128 RUN(test_resp_map_get_string); 129 RUN(test_resp_map_get_missing_key); 130 RUN(test_resp_read_invalid_returns_null); 131 return TEST_REPORT(); 132 }