librlp

C library for the Recursive Length Prefix (RLP) serialization format
git clone git://git.defalsify.org/librlp.git
Log | Files | Refs | LICENSE

commit 2aff2fe9a2fd3c69a964dbcaa116f4ce673c42f1
parent acd17b34f02dc448454f2562b04205f6c94c5290
Author: nolash <dev@holbrook.no>
Date:   Sun, 11 Apr 2021 09:14:49 +0200

Refactor in preparation for decoder implementation

Diffstat:
MMakefile | 26++++++++++++++++++++++----
Asrc/decode.c | 0
Asrc/encode.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/encode.h | 0
Msrc/rlp.c | 99+++++++++++++++++--------------------------------------------------------------
Msrc/rlp.h | 22++++++++++++++++++----
Dtests/check_bits | 0
Atests/check_decoder.c | 42++++++++++++++++++++++++++++++++++++++++++
Atests/check_encoder.c | 276+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtests/check_rlp | 0
Mtests/check_rlp.c | 262+++----------------------------------------------------------------------------
Dtests/check_vector.c | 126-------------------------------------------------------------------------------
Atests/check_vectors.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 591 insertions(+), 465 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,16 +1,34 @@ build: gcc -I./src -g3 -c src/rlp.c -o src/rlp.o + gcc -I./src -g3 -c src/encode.c -o src/encode.o + gcc -I./src -g3 -c src/decode.c -o src/decode.o gcc -I./src -g3 -c src/bits.c -o src/bits.o gcc -I./src -g3 -c src/endian.c -o src/endian.o +build_lib: build + gcc -I./src -fPIC -shared -o librlp.so -Wl,-soname,librlp.so.0.0.1 src/encode.o src/decode.o src/bits.o src/endian.o + + tests_build: build - gcc -I./src -g3 tests/check_rlp.c src/bits.o src/rlp.o src/endian.o -o tests/check_rlp -lcheck - gcc -I./src -g3 tests/check_bits.c src/bits.o src/rlp.o src/endian.o -o tests/check_bits -lcheck - gcc -I./src -g3 tests/check_vector.c src/bits.o src/rlp.o src/endian.o -o tests/check_vector -lcheck + gcc -I./src -g3 tests/check_rlp.c src/rlp.o src/bits.o src/encode.o src/decode.o src/endian.o -o tests/check_rlp -lcheck + gcc -I./src -g3 tests/check_encoder.c src/rlp.o src/bits.o src/encode.o src/decode.o src/endian.o -o tests/check_encoder -lcheck + gcc -I./src -g3 tests/check_bits.c src/rlp.o src/bits.o src/encode.o src/decode.o src/endian.o -o tests/check_bits -lcheck + gcc -I./src -g3 tests/check_vectors.c src/rlp.o src/bits.o src/encode.o src/decode.o src/endian.o -o tests/check_vectors -lcheck + gcc -I./src -g3 tests/check_decoder.c src/rlp.o src/bits.o src/encode.o src/decode.o src/endian.o -o tests/check_decoder -lcheck check: tests_build tests/check_rlp + tests/check_encoder + tests/check_decoder tests/check_bits - tests/check_vector + tests/check_vectors + +.PHONY clean: + rm -v tests/check_rlp + rm -v tests/check_encoder + rm -v tests/check_decoder + rm -v tests/check_bits + rm -v tests/check_vectors + rm -v src/*.o .PHONY test: check diff --git a/src/decode.c b/src/decode.c diff --git a/src/encode.c b/src/encode.c @@ -0,0 +1,77 @@ +#include <stdint.h> +#include <string.h> + +#include "rlp.h" +#include "bits.h" +#include "endian.h" + + +int rlp_add(rlp_encoder_t *encoder, int len, const char *data) { + char v; + int lenlen; + size_t r; + + r = (size_t)encoder->ptr; + + if (len == 0) { + *(encoder->ptr) = 0x80; + encoder->ptr++; + } else { + v = (char)*data; + if (len == 1 && v < 56) { + *(encoder->ptr) = v; + encoder->ptr++; + } else { + v = (char)*data; + if (len < 56) { + *(encoder->ptr) = len + 0x80; + encoder->ptr++; + memcpy(encoder->ptr, data, len); + encoder->ptr += len; + } else { + lenlen = intbytes_le(sizeof(int), (char*)&len); + *(encoder->ptr) = lenlen + 0xb7; + encoder->ptr++; + to_endian(CONVERT_BIGENDIAN, lenlen, &len); + memcpy(encoder->ptr, &len, lenlen); + to_endian(CONVERT_PLATFORM, lenlen, &len); + encoder->ptr+=lenlen; + memcpy(encoder->ptr, data, len); + encoder->ptr+=len; + } + } + } + + return (int)(r - (size_t)encoder->ptr); +} + +int rlp_descend(rlp_encoder_t *encoder) { + encoder->depth++; + encoder->list_ptr[encoder->depth] = encoder->ptr; + return encoder->depth + 1; +} + +int rlp_ascend(rlp_encoder_t *encoder) { + size_t len; + char *ptr; + int lenlen; + + ptr = encoder->list_ptr[encoder->depth]; + len = encoder->ptr - ptr; + if (len < 56) { + memcpy(ptr + 1, ptr, len); + *(ptr) = 0xc0 + len; + encoder->ptr++; + } else { + lenlen = intbytes_le(sizeof(size_t), (char*)&len); + memcpy(ptr + 1 + lenlen, ptr, len); + *ptr = lenlen + 0xf7; + to_endian(CONVERT_BIGENDIAN, lenlen, &len); + memcpy(ptr+1, &len, lenlen); + to_endian(CONVERT_PLATFORM, lenlen, &len); + encoder->ptr += (lenlen + 1); + } + encoder->depth--; + + return encoder->depth + 1; +} diff --git a/src/encode.h b/src/encode.h diff --git a/src/rlp.c b/src/rlp.c @@ -1,93 +1,36 @@ -#include <stdint.h> #include <stdlib.h> -#include <string.h> #include "rlp.h" -#include "bits.h" -#include "endian.h" -int rlp_init(rlp_encoder_t *encoder, int buffer_capacity) { - encoder->buf = malloc(buffer_capacity); +int rlp_init(rlp_encoder_t *encoder, int buffer_capacity, char *content) { encoder->depth = -1; - encoder->ptr = encoder->buf; -} - -void rlp_free(rlp_encoder_t *encoder) { - free(encoder->buf); - encoder->ptr = NULL; -} - - -int rlp_add(rlp_encoder_t *encoder, int len, char *data) { - char v; - int lenlen; - size_t r; - - r = (size_t)encoder->ptr; - - if (len == 0) { - *(encoder->ptr) = 0x80; - encoder->ptr++; + if (content != NULL) { + encoder->buf = content; + encoder->alloc = 0; + encoder->state = RLP_DECODE; + encoder->ptr = encoder->buf + buffer_capacity; } else { - v = (char)*data; - if (len == 1 && v < 56) { - *(encoder->ptr) = v; - encoder->ptr++; - } else { - v = (char)*data; - if (len < 56) { - *(encoder->ptr) = len + 0x80; - encoder->ptr++; - memcpy(encoder->ptr, data, len); - encoder->ptr += len; - } else { - lenlen = intbytes_le(sizeof(int), (char*)&len); - *(encoder->ptr) = lenlen + 0xb7; - encoder->ptr++; - to_endian(CONVERT_BIGENDIAN, lenlen, &len); - memcpy(encoder->ptr, &len, lenlen); - to_endian(CONVERT_PLATFORM, lenlen, &len); - encoder->ptr+=lenlen; - memcpy(encoder->ptr, data, len); - encoder->ptr+=len; - } - } + encoder->buf = malloc(buffer_capacity); + encoder->alloc = 1; + encoder->state = RLP_ENCODE; + encoder->ptr = encoder->buf; } - - return (int)(r - (size_t)encoder->ptr); } -int rlp_descend(rlp_encoder_t *encoder) { - encoder->depth++; - encoder->list_ptr[encoder->depth] = encoder->ptr; - return encoder->depth + 1; -} - -int rlp_ascend(rlp_encoder_t *encoder) { - size_t len; - char *ptr; - int lenlen; - - ptr = encoder->list_ptr[encoder->depth]; - len = encoder->ptr - ptr; - if (len < 56) { - memcpy(ptr + 1, ptr, len); - *(ptr) = 0xc0 + len; - encoder->ptr++; - } else { - lenlen = intbytes_le(sizeof(size_t), (char*)&len); - memcpy(ptr + 1 + lenlen, ptr, len); - *ptr = lenlen + 0xf7; - to_endian(CONVERT_BIGENDIAN, lenlen, &len); - memcpy(ptr+1, &len, lenlen); - to_endian(CONVERT_PLATFORM, lenlen, &len); - encoder->ptr += (lenlen + 1); +void rlp_free(rlp_encoder_t *encoder) { + if (encoder->alloc) { + free(encoder->buf); } - encoder->depth--; - - return encoder->depth + 1; + encoder->ptr = NULL; } size_t rlp_length(rlp_encoder_t *encoder) { return encoder->ptr - encoder->buf; } + + +int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest) { + *zdest = encoder->buf; + *zl = rlp_length(encoder); + return 0; +} diff --git a/src/rlp.h b/src/rlp.h @@ -1,26 +1,40 @@ #ifndef RLP_T_ #define RLP_T_ -#include <stdint.h> #include <stdlib.h> #ifndef RLP_MAX_LIST_DEPTH #define RLP_MAX_LIST_DEPTH 1024 #endif +enum rlp_state { + RLP_ENCODE, + RLP_DECODE, + RLP_LIST, + RLP_STRING, + RLP_END, + RLP_ERR, +}; + + typedef struct rlp_encoder { + char *buf; int depth; + enum rlp_state state; char *list_ptr[RLP_MAX_LIST_DEPTH]; - char *buf; char *ptr; + char alloc; } rlp_encoder_t; -int rlp_init(rlp_encoder_t *encoder, int buffer_capacity); + +int rlp_init(rlp_encoder_t *encoder, int buffer_capacity, char *content); void rlp_free(rlp_encoder_t *encoder); int rlp_descend(rlp_encoder_t *encoder); int rlp_ascend(rlp_encoder_t *encoder); -int rlp_add(rlp_encoder_t *encoder, int len, char *data); +int rlp_add(rlp_encoder_t *encoder, int len, const char *data); size_t rlp_length(rlp_encoder_t *encoder); +int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest); + #endif diff --git a/tests/check_bits b/tests/check_bits Binary files differ. diff --git a/tests/check_decoder.c b/tests/check_decoder.c @@ -0,0 +1,42 @@ +#include <check.h> +#include <stdlib.h> +#include <string.h> + +#include "rlp.h" + + +START_TEST(rlp_decode_single) { + +} +END_TEST + + +Suite *rlp_decode_suite(void) { + Suite *s; + TCase *tcb; + + s = suite_create("rlp_decode"); + tcb = tcase_create("bytes"); + tcase_add_test(tcb, rlp_decode_single); + suite_add_tcase(s, tcb); + + + return s; +} + + +int main(void) { + int num_fail; + + Suite *s; + SRunner *sr; + + s = rlp_decode_suite(); + sr = srunner_create(s); + + srunner_run_all(sr, CK_VERBOSE); + num_fail = srunner_ntests_failed(sr); + srunner_free(sr); + + return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/check_encoder.c b/tests/check_encoder.c @@ -0,0 +1,276 @@ +#include <check.h> +#include <stdlib.h> + +#include "rlp.h" + + + +START_TEST(rlp_encode_single_zero_byte_test) { + char v = 0x00; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + rlp_add(&encoder, 1, &v); + ck_assert_mem_eq(encoder.buf, &v, 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_empty_byte_test) { + char v = 0x80; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + rlp_add(&encoder, 0, NULL); + ck_assert_mem_eq(encoder.buf, &v, 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_single_byte_test) { + char v = 55; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + rlp_add(&encoder, 1, &v); + ck_assert_mem_eq(encoder.buf, &v, 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_single_byte_with_length_test) { + char l = 0x81; + char v = 56; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + rlp_add(&encoder, 1, &v); + ck_assert_mem_eq(encoder.buf, &l, 1); + ck_assert_mem_eq(encoder.buf+1, &v, 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_short_bytes_with_length_test) { + char l = 0xb7; + char v[55]; + v[54] = 42; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + rlp_add(&encoder, 55, (char*)&v); + ck_assert_mem_eq(encoder.buf, &l, 1); + ck_assert_mem_eq(encoder.buf+55, (char*)&(v[54]), 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_long_bytes_with_length_test) { + char l = 0xb8; + char ll = 56; + char v[56]; + v[55] = 42; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + rlp_add(&encoder, 56, (char*)&v); + ck_assert_mem_eq(encoder.buf, &l, 1); + ck_assert_mem_eq(encoder.buf+1, &ll, 1); + ck_assert_mem_eq(encoder.buf+57, (char*)&(v[55]), 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_descend_state_test) { + int r; + char *ptr_chk; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + r = rlp_descend(&encoder); + ck_assert_ptr_eq(encoder.ptr, encoder.list_ptr[encoder.depth]); + ptr_chk = encoder.ptr; + ck_assert_int_eq(1, r); + ck_assert_int_eq(encoder.depth, 0); + + r = rlp_descend(&encoder); + ck_assert_ptr_eq(encoder.ptr, encoder.list_ptr[encoder.depth]); + ck_assert_ptr_eq(ptr_chk, encoder.list_ptr[encoder.depth-1]); + ck_assert_int_eq(2, r); + ck_assert_int_eq(encoder.depth, 1); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_roundtrip_state_test) { + char one = 42; + char two = 13; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + r = rlp_descend(&encoder); + ck_assert_int_eq(r, 1); + rlp_add(&encoder, 1, &one); + rlp_add(&encoder, 1, &two); + ck_assert_int_eq(encoder.depth, 0); + + r = rlp_ascend(&encoder); + ck_assert_int_eq(r, 0); + ck_assert_int_eq(encoder.depth, -1); + + rlp_free(&encoder); +} +END_TEST + + + +START_TEST(rlp_encode_list_single_depth_test) { + char one = 42; + char two = 13; + char target[3] = {0xc2, 42, 13}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + r = rlp_descend(&encoder); + rlp_add(&encoder, 1, &one); + rlp_add(&encoder, 1, &two); + r = rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, target, 3); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_adjacent_test) { + char one[2] = {42, 13}; + char two[3] = {0x66, 0x6f, 0x6f}; + char target[8] = {0xc2, 42, 13, 0xc4, 0x83, 0x66, 0x6f, 0x6f}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + r = rlp_descend(&encoder); + rlp_add(&encoder, 1, &one[0]); + rlp_add(&encoder, 1, &one[1]); + r = rlp_ascend(&encoder); + r = rlp_descend(&encoder); + rlp_add(&encoder, 3, two); + r = rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, target, 8); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_nested_test) { + char one[2] = {42, 13}; + char two[3] = {0x66, 0x6f, 0x6f}; + char target[8] = {0xc7, 42, 13, 0xc4, 0x83, 0x66, 0x6f, 0x6f}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + r = rlp_descend(&encoder); + rlp_add(&encoder, 1, &one[0]); + rlp_add(&encoder, 1, &one[1]); + r = rlp_descend(&encoder); + rlp_add(&encoder, 3, two); + r = rlp_ascend(&encoder); + r = rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, target, 8); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_encode_list_long_test) { + char v[56]; + char target[4] = {0xf8, 58, 0xb8, 56}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024, NULL); + + r = rlp_descend(&encoder); + rlp_add(&encoder, 56, (char*)v); + r = rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, target, 4); + + rlp_free(&encoder); +} +END_TEST + +Suite *rlp_suite(void) { + Suite *s; + TCase *tci; + TCase *tcb; + TCase *tcl; + + s = suite_create("Rlp"); + tcb = tcase_create("Bytes"); + tcl = tcase_create("List"); + + tcase_add_test(tcb, rlp_encode_empty_byte_test); + tcase_add_test(tcb, rlp_encode_single_zero_byte_test); + tcase_add_test(tcb, rlp_encode_single_byte_test); + tcase_add_test(tcb, rlp_encode_single_byte_with_length_test); + tcase_add_test(tcb, rlp_encode_short_bytes_with_length_test); + tcase_add_test(tcb, rlp_encode_long_bytes_with_length_test); + suite_add_tcase(s, tcb); + + tcase_add_test(tcl, rlp_encode_list_descend_state_test); + tcase_add_test(tcl, rlp_encode_list_roundtrip_state_test); + tcase_add_test(tcl, rlp_encode_list_single_depth_test); + tcase_add_test(tcl, rlp_encode_list_adjacent_test); + tcase_add_test(tcl, rlp_encode_list_nested_test); + tcase_add_test(tcl, rlp_encode_list_long_test); + suite_add_tcase(s, tcl); + + return s; +} + + +int main(void) { + int num_fail; + + Suite *s; + SRunner *sr; + + s = rlp_suite(); + sr = srunner_create(s); + + srunner_run_all(sr, CK_VERBOSE); + num_fail = srunner_ntests_failed(sr); + srunner_free(sr); + + return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/check_rlp b/tests/check_rlp Binary files differ. diff --git a/tests/check_rlp.c b/tests/check_rlp.c @@ -1,271 +1,27 @@ #include <check.h> -#include <stdlib.h> #include "rlp.h" -START_TEST(rlp_init_test) { - rlp_encoder_t encoder; - - rlp_init(&encoder, 1024); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_single_zero_byte_test) { - char v = 0x00; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - rlp_add(&encoder, 1, &v); - ck_assert_mem_eq(encoder.buf, &v, 1); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_empty_byte_test) { - char v = 0x80; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - rlp_add(&encoder, 0, NULL); - ck_assert_mem_eq(encoder.buf, &v, 1); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_single_byte_test) { - char v = 55; +START_TEST(rlp_init_alloc_test) { rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - rlp_add(&encoder, 1, &v); - ck_assert_mem_eq(encoder.buf, &v, 1); + rlp_init(&encoder, 1024, NULL); rlp_free(&encoder); } END_TEST -START_TEST(rlp_encode_single_byte_with_length_test) { - char l = 0x81; - char v = 56; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - rlp_add(&encoder, 1, &v); - ck_assert_mem_eq(encoder.buf, &l, 1); - ck_assert_mem_eq(encoder.buf+1, &v, 1); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_short_bytes_with_length_test) { - char l = 0xb7; - char v[55]; - v[54] = 42; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - rlp_add(&encoder, 55, (char*)&v); - ck_assert_mem_eq(encoder.buf, &l, 1); - ck_assert_mem_eq(encoder.buf+55, (char*)&(v[54]), 1); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_long_bytes_with_length_test) { - char l = 0xb8; - char ll = 56; - char v[56]; - v[55] = 42; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - rlp_add(&encoder, 56, (char*)&v); - ck_assert_mem_eq(encoder.buf, &l, 1); - ck_assert_mem_eq(encoder.buf+1, &ll, 1); - ck_assert_mem_eq(encoder.buf+57, (char*)&(v[55]), 1); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_list_descend_state_test) { - int r; - char *ptr_chk; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - r = rlp_descend(&encoder); - ck_assert_ptr_eq(encoder.ptr, encoder.list_ptr[encoder.depth]); - ptr_chk = encoder.ptr; - ck_assert_int_eq(1, r); - ck_assert_int_eq(encoder.depth, 0); - - r = rlp_descend(&encoder); - ck_assert_ptr_eq(encoder.ptr, encoder.list_ptr[encoder.depth]); - ck_assert_ptr_eq(ptr_chk, encoder.list_ptr[encoder.depth-1]); - ck_assert_int_eq(2, r); - ck_assert_int_eq(encoder.depth, 1); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_list_roundtrip_state_test) { - char one = 42; - char two = 13; - int r; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - r = rlp_descend(&encoder); - ck_assert_int_eq(r, 1); - rlp_add(&encoder, 1, &one); - rlp_add(&encoder, 1, &two); - ck_assert_int_eq(encoder.depth, 0); - - r = rlp_ascend(&encoder); - ck_assert_int_eq(r, 0); - ck_assert_int_eq(encoder.depth, -1); - - rlp_free(&encoder); -} -END_TEST - - - -START_TEST(rlp_encode_list_single_depth_test) { - char one = 42; - char two = 13; - char target[3] = {0xc2, 42, 13}; - int r; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - r = rlp_descend(&encoder); - rlp_add(&encoder, 1, &one); - rlp_add(&encoder, 1, &two); - r = rlp_ascend(&encoder); - ck_assert_mem_eq(encoder.buf, target, 3); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_list_adjacent_test) { - char one[2] = {42, 13}; - char two[3] = {0x66, 0x6f, 0x6f}; - char target[8] = {0xc2, 42, 13, 0xc4, 0x83, 0x66, 0x6f, 0x6f}; - int r; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - r = rlp_descend(&encoder); - rlp_add(&encoder, 1, &one[0]); - rlp_add(&encoder, 1, &one[1]); - r = rlp_ascend(&encoder); - r = rlp_descend(&encoder); - rlp_add(&encoder, 3, two); - r = rlp_ascend(&encoder); - ck_assert_mem_eq(encoder.buf, target, 8); - - rlp_free(&encoder); -} -END_TEST - - -START_TEST(rlp_encode_list_nested_test) { - char one[2] = {42, 13}; - char two[3] = {0x66, 0x6f, 0x6f}; - char target[8] = {0xc7, 42, 13, 0xc4, 0x83, 0x66, 0x6f, 0x6f}; - int r; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - r = rlp_descend(&encoder); - rlp_add(&encoder, 1, &one[0]); - rlp_add(&encoder, 1, &one[1]); - r = rlp_descend(&encoder); - rlp_add(&encoder, 3, two); - r = rlp_ascend(&encoder); - r = rlp_ascend(&encoder); - ck_assert_mem_eq(encoder.buf, target, 8); - - rlp_free(&encoder); -} -END_TEST - -START_TEST(rlp_encode_list_long_test) { - char v[56]; - char target[4] = {0xf8, 58, 0xb8, 56}; - int r; - - rlp_encoder_t encoder; - rlp_init(&encoder, 1024); - - r = rlp_descend(&encoder); - rlp_add(&encoder, 56, (char*)v); - r = rlp_ascend(&encoder); - ck_assert_mem_eq(encoder.buf, target, 4); - - rlp_free(&encoder); -} -END_TEST - -Suite *rlp_suite(void) { +Suite *rlp_init_suite(void) { Suite *s; - TCase *tci; - TCase *tcb; - TCase *tcl; - - s = suite_create("Rlp"); - tci = tcase_create("Init"); - tcb = tcase_create("Bytes"); - tcl = tcase_create("List"); - - tcase_add_test(tci, rlp_init_test); - suite_add_tcase(s, tci); + TCase *tc; - tcase_add_test(tcb, rlp_encode_empty_byte_test); - tcase_add_test(tcb, rlp_encode_single_zero_byte_test); - tcase_add_test(tcb, rlp_encode_single_byte_test); - tcase_add_test(tcb, rlp_encode_single_byte_with_length_test); - tcase_add_test(tcb, rlp_encode_short_bytes_with_length_test); - tcase_add_test(tcb, rlp_encode_long_bytes_with_length_test); - suite_add_tcase(s, tcb); + s = suite_create("rlp"); + tc = tcase_create("init"); - tcase_add_test(tcl, rlp_encode_list_descend_state_test); - tcase_add_test(tcl, rlp_encode_list_roundtrip_state_test); - tcase_add_test(tcl, rlp_encode_list_single_depth_test); - tcase_add_test(tcl, rlp_encode_list_adjacent_test); - tcase_add_test(tcl, rlp_encode_list_nested_test); - tcase_add_test(tcl, rlp_encode_list_long_test); - suite_add_tcase(s, tcl); + tcase_add_test(tc, rlp_init_alloc_test); + suite_add_tcase(s, tc); return s; } @@ -277,7 +33,7 @@ int main(void) { Suite *s; SRunner *sr; - s = rlp_suite(); + s = rlp_init_suite(); sr = srunner_create(s); srunner_run_all(sr, CK_VERBOSE); diff --git a/tests/check_vector.c b/tests/check_vector.c @@ -1,126 +0,0 @@ -#include <check.h> -#include <stdlib.h> -#include <string.h> - -#include "rlp.h" - -START_TEST(rlp_dog_test) { - rlp_encoder_t encoder; - - rlp_init(&encoder, 1024); - char *x_dog = "dog"; - char r_dog[4] = {0x83, 'd', 'o', 'g'}; - rlp_add(&encoder, 3, x_dog); - ck_assert_mem_eq(encoder.buf, r_dog, 4); - ck_assert_int_eq(rlp_length(&encoder), 4); - - rlp_free(&encoder); -} -END_TEST - -START_TEST(rlp_catdog_test) { - rlp_encoder_t encoder; - - rlp_init(&encoder, 1024); - - char *x_dog = "dog"; - char *x_cat = "cat"; - char r_catdog[9] = {0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g'}; - rlp_descend(&encoder); - rlp_add(&encoder, 3, x_cat); - rlp_add(&encoder, 3, x_dog); - rlp_ascend(&encoder); - ck_assert_mem_eq(encoder.buf, r_catdog, 9); - ck_assert_int_eq(rlp_length(&encoder), 9); - - rlp_free(&encoder); -} -END_TEST - -START_TEST(rlp_lorem_test) { - rlp_encoder_t encoder; - - rlp_init(&encoder, 1024); - - char *lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; - char target[2] = {0xb8, 0x38}; - - rlp_add(&encoder, strlen(lorem), lorem); - ck_assert_mem_eq(encoder.buf, target, 2); - ck_assert_mem_eq(encoder.buf+2, lorem, strlen(lorem)); - ck_assert_int_eq(rlp_length(&encoder), 2 + strlen(lorem)); - - rlp_free(&encoder); -} -END_TEST - -START_TEST(rlp_set_theoretical_representation_of_three) { - - char target[8] = {0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0}; - - rlp_encoder_t encoder; - - rlp_init(&encoder, 1024); - - // [  []  [ [] ]  [ [] [ []] ]  ] - rlp_descend(&encoder); - - rlp_descend(&encoder); - rlp_ascend(&encoder); - - rlp_descend(&encoder); - rlp_descend(&encoder); - rlp_ascend(&encoder); - rlp_ascend(&encoder); - - rlp_descend(&encoder); - rlp_descend(&encoder); - rlp_ascend(&encoder); - rlp_descend(&encoder); - rlp_descend(&encoder); - rlp_ascend(&encoder); - rlp_ascend(&encoder); - rlp_ascend(&encoder); - - rlp_ascend(&encoder); - - ck_assert_mem_eq(encoder.buf, target, 8); - ck_assert_int_eq(rlp_length(&encoder), 8); - - rlp_free(&encoder); -} -END_TEST - - -Suite *rlp_vector_suite(void) { - Suite *s; - TCase *tcb; - - s = suite_create("rlp_vector"); - tcb = tcase_create("basic"); // examples from https://eth.wiki/fundamentals/rlp - tcase_add_test(tcb, rlp_dog_test); - tcase_add_test(tcb, rlp_catdog_test); - tcase_add_test(tcb, rlp_lorem_test); - tcase_add_test(tcb, rlp_set_theoretical_representation_of_three); - suite_add_tcase(s, tcb); - - - return s; -} - - -int main(void) { - int num_fail; - - Suite *s; - SRunner *sr; - - s = rlp_vector_suite(); - sr = srunner_create(s); - - srunner_run_all(sr, CK_VERBOSE); - num_fail = srunner_ntests_failed(sr); - srunner_free(sr); - - return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/tests/check_vectors.c b/tests/check_vectors.c @@ -0,0 +1,126 @@ +#include <check.h> +#include <stdlib.h> +#include <string.h> + +#include "rlp.h" + +START_TEST(rlp_dog_test) { + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024, NULL); + char *x_dog = "dog"; + char r_dog[4] = {0x83, 'd', 'o', 'g'}; + rlp_add(&encoder, 3, x_dog); + ck_assert_mem_eq(encoder.buf, r_dog, 4); + ck_assert_int_eq(rlp_length(&encoder), 4); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_catdog_test) { + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024, NULL); + + char *x_dog = "dog"; + char *x_cat = "cat"; + char r_catdog[9] = {0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g'}; + rlp_descend(&encoder); + rlp_add(&encoder, 3, x_cat); + rlp_add(&encoder, 3, x_dog); + rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, r_catdog, 9); + ck_assert_int_eq(rlp_length(&encoder), 9); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_lorem_test) { + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024, NULL); + + char *lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; + char target[2] = {0xb8, 0x38}; + + rlp_add(&encoder, strlen(lorem), lorem); + ck_assert_mem_eq(encoder.buf, target, 2); + ck_assert_mem_eq(encoder.buf+2, lorem, strlen(lorem)); + ck_assert_int_eq(rlp_length(&encoder), 2 + strlen(lorem)); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_set_theoretical_representation_of_three) { + + char target[8] = {0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0}; + + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024, NULL); + + // [  []  [ [] ]  [ [] [ []] ]  ] + rlp_descend(&encoder); + + rlp_descend(&encoder); + rlp_ascend(&encoder); + + rlp_descend(&encoder); + rlp_descend(&encoder); + rlp_ascend(&encoder); + rlp_ascend(&encoder); + + rlp_descend(&encoder); + rlp_descend(&encoder); + rlp_ascend(&encoder); + rlp_descend(&encoder); + rlp_descend(&encoder); + rlp_ascend(&encoder); + rlp_ascend(&encoder); + rlp_ascend(&encoder); + + rlp_ascend(&encoder); + + ck_assert_mem_eq(encoder.buf, target, 8); + ck_assert_int_eq(rlp_length(&encoder), 8); + + rlp_free(&encoder); +} +END_TEST + + +Suite *rlp_vector_suite(void) { + Suite *s; + TCase *tcb; + + s = suite_create("rlp_vector"); + tcb = tcase_create("basic"); // examples from https://eth.wiki/fundamentals/rlp + tcase_add_test(tcb, rlp_dog_test); + tcase_add_test(tcb, rlp_catdog_test); + tcase_add_test(tcb, rlp_lorem_test); + tcase_add_test(tcb, rlp_set_theoretical_representation_of_three); + suite_add_tcase(s, tcb); + + + return s; +} + + +int main(void) { + int num_fail; + + Suite *s; + SRunner *sr; + + s = rlp_vector_suite(); + sr = srunner_create(s); + + srunner_run_all(sr, CK_VERBOSE); + num_fail = srunner_ntests_failed(sr); + srunner_free(sr); + + return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}