From ba450e2bacbeb113e7e025c4e43acba231059f2b Mon Sep 17 00:00:00 2001 From: Kyunghwan Kwon Date: Wed, 24 Aug 2022 12:55:51 +0900 Subject: [PATCH] Add examples (#7) --- .github/workflows/build.yml | 26 ++++++ .github/workflows/release.yml | 41 ++++++++ .gitignore | 1 + CHANGELOG.md | 3 + Makefile | 16 +++- README.md | 5 +- examples/complex.c | 170 ++++++++++++++++++++++++++++++++++ examples/example.h | 40 ++++++++ examples/simple.c | 77 +++++++++++++++ include/cbor/helper.h | 8 ++ src/decoder.c | 6 +- src/helper.c | 31 +++++++ src/parser.c | 9 +- tests/runners/example.mk | 25 +++++ tests/src/example_test.cpp | 141 ++++++++++++++++++++++++++++ 15 files changed, 584 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 examples/complex.c create mode 100644 examples/example.h create mode 100644 examples/simple.c create mode 100644 tests/runners/example.mk create mode 100644 tests/src/example_test.cpp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..db33141 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,26 @@ +name: build + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + name: Compile and Test + runs-on: ubuntu-latest + steps: + - name: Clone Repository + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + - name: Compile + run: make + - name: Install test framework + run: make -C tests install + - name: Unit Test + run: make -C tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..48bbbd3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: release + +on: + push: + tags: + - '*' + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Clone Repository + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + - name: Compile + run: make + - name: Install test framework + run: make -C tests install + - name: Unit Test + run: make -C tests + - name: Get Version + id: get_version + run: echo "::set-output name=VERSION::$(cat build/version.txt)" + - name: Create Release + id: create_release + uses: actions/create-release@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.get_version.outputs.VERSION }} + release_name: ${{ steps.get_version.outputs.VERSION }} + body: | + ${{ steps.get_version.outputs.VERSION }} + + ## Features + ## Bug Fixes + draft: false + prerelease: false diff --git a/.gitignore b/.gitignore index f38e568..ba085c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build *cscope.* tests/cpputest +.cache diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..06bab5a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## v0.1.0 - August 24, 2022 + +The initial release. diff --git a/Makefile b/Makefile index 3aaa9df..4bc1b1f 100644 --- a/Makefile +++ b/Makefile @@ -33,10 +33,6 @@ OD := $(CROSS_COMPILE_PREFIX)objdump NM := $(CROSS_COMPILE_PREFIX)nm CFLAGS := \ - -mcpu=cortex-m0 \ - -mthumb \ - -mabi=aapcs \ - \ -std=c99 \ -static \ -ffreestanding \ @@ -79,8 +75,20 @@ CFLAGS := \ \ -Wno-error=pedantic +ifneq ($(CROSS_COMPILE),) +CFLAGS += \ + -mcpu=cortex-m0 \ + -mthumb \ + -mabi=aapcs +endif + +VERSION ?= $(shell git describe --long --tags --dirty --always) +version-list := $(subst -, , $(VERSION)) +VERSION_TAG := $(strip $(word 1, $(version-list))) + all: $(OBJS) $(Q)$(SZ) -t --common $(sort $(OBJS)) + @echo $(VERSION_TAG) > $(BUILDIR)/version.txt $(BUILDIR)/%.o: %.c $(MAKEFILE_LIST) $(info compiling $<) diff --git a/README.md b/README.md index eb6a740..e856147 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ union { int8_t i8; int16_t i16; int32_t i32; - int64_t i64 + int64_t i64; float f32; double f64; uint8_t s[MTU]; @@ -94,14 +94,13 @@ cbor_writer_t writer; cbor_writer_init(&reader, buf, sizeof(buf)); -cbor_encode_map_indefinite(&writer); +cbor_encode_map(&writer, 2); /* 1st */ cbor_encode_text_string(&writer, "key"); cbor_encode_text_string(&writer, "value"); /* 2nd */ cbor_encode_text_string(&writer, "age"); cbor_encode_negative_integer(&writer, -1); -cbor_encode_break(&writer); ``` ## Limitation diff --git a/examples/complex.c b/examples/complex.c new file mode 100644 index 0000000..4a9e01c --- /dev/null +++ b/examples/complex.c @@ -0,0 +1,170 @@ +#include "example.h" + +#include "cbor/decoder.h" +#include "cbor/parser.h" +#include "cbor/helper.h" + +static void do_unknown(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + if (item->type == CBOR_ITEM_SIMPLE_VALUE) { + cbor_decode(reader, item, &p->type, sizeof(p->type)); + } else if (item->type == CBOR_ITEM_STRING && item->size == 16) { + cbor_decode(reader, item, &p->uuid, sizeof(p->uuid)); + } +} +static void do_timestamp(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &p->time, sizeof(p->time)); +} +static void do_acc_x(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &(p->data.acc.x), sizeof(p->data.acc.x)); +} +static void do_acc_y(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &(p->data.acc.y), sizeof(p->data.acc.y)); +} +static void do_acc_z(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &(p->data.acc.z), sizeof(p->data.acc.z)); +} +static void do_gyr_x(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &(p->data.gyro.x), sizeof(p->data.gyro.x)); +} +static void do_gyr_y(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &(p->data.gyro.y), sizeof(p->data.gyro.y)); +} +static void do_gyr_z(cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + struct udt *p = (struct udt *)udt; + cbor_decode(reader, item, &(p->data.gyro.z), sizeof(p->data.gyro.z)); +} + +static struct converter { + void const *primary; + void const *secondary; + void (*run)(cbor_reader_t const *reader, cbor_item_t const *item, void *udt); +} converters[] = { + { .primary = "t", .secondary = NULL, .run = do_timestamp }, + { .primary = "x", .secondary = "acc", .run = do_acc_x }, + { .primary = "y", .secondary = "acc", .run = do_acc_y }, + { .primary = "z", .secondary = "acc", .run = do_acc_z }, + { .primary = "x", .secondary = "gyro", .run = do_gyr_x }, + { .primary = "y", .secondary = "gyro", .run = do_gyr_y }, + { .primary = "z", .secondary = "gyro", .run = do_gyr_z }, +}; + +static void (*get_converter(void const *primary, size_t primary_len, + void const *secondary, size_t secondary_len)) + (cbor_reader_t const *reader, cbor_item_t const *item, void *udt) +{ + if ((primary == NULL && secondary == NULL) || + (primary_len == 0 && secondary_len == 0)) { + return do_unknown; + } + + for (size_t i = 0; i < sizeof(converters) / sizeof(converters[0]); i++) { + struct converter const *p = &converters[i]; + if (p->primary && memcmp(p->primary, primary, primary_len)) { + continue; + } else if (p->secondary && memcmp(p->secondary, secondary, secondary_len)) { + continue; + } + + if (p->primary || p->secondary) { + return p->run; + } + } + + return do_unknown; +} + +static void convert(cbor_reader_t const *reader, cbor_item_t const *item, + cbor_item_t const *parent, void *udt) +{ + void const *primary = NULL; + void const *secondary = NULL; + size_t primary_len = 0; + size_t secondary_len = 0; + + if (parent != NULL && parent->type == CBOR_ITEM_MAP) { + if ((item - parent) % 2) { /* key */ + return; + } + + if (parent->offset > 1) { + secondary = cbor_decode_pointer(reader, parent-1); + secondary_len = (parent-1)->size; + } + + primary = cbor_decode_pointer(reader, item-1); + primary_len = (item-1)->size; + } + + get_converter(primary, primary_len, secondary, secondary_len) + (reader, item, udt); +} + +/* + sample_data[] = { 0x9f, 0xe1, 0x50, 0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, + 0xd3, 0xa4, 0x56, 0x42, 0x66, 0x14, 0x17, 0x40, 0x00, 0xbf, + 0x61, 0x74, 0x1a, 0x63, 0x04, 0x4b, 0xa5, 0x64, 0x64, 0x61, + 0x74, 0x61, 0xa2, 0x63, 0x61, 0x63, 0x63, 0xa3, 0x61, 0x78, + 0xf9, 0x00, 0x00, 0x61, 0x79, 0xf9, 0x00, 0x00, 0x61, 0x7a, + 0xfa, 0x41, 0x1c, 0xf5, 0xc3, 0x64, 0x67, 0x79, 0x72, 0x6f, + 0xa3, 0x61, 0x78, 0xfa, 0x40, 0xc9, 0x99, 0x9a, 0x61, 0x79, + 0xf9, 0x00, 0x00, 0x61, 0x7a, 0xf9, 0x00, 0x00, 0xff, 0xff + }; + + generated by: + cbor_writer_init(&writer, writer_buffer, sizeof(writer_buffer)); + cbor_encode_array_indefinite(&writer); + cbor_encode_simple(&writer, 1); + cbor_encode_byte_string(&writer, uuid, sizeof(uuid)); + cbor_encode_map_indefinite(&writer); + cbor_encode_text_string(&writer, "t"); + cbor_encode_unsigned_integer(&writer, 1661225893); + cbor_encode_text_string(&writer, "data"); + cbor_encode_map(&writer, 2); + cbor_encode_text_string(&writer, "acc"); + cbor_encode_map(&writer, 3); + cbor_encode_text_string(&writer, "x"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "y"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "z"); + cbor_encode_float(&writer, 9.81f); + cbor_encode_text_string(&writer, "gyro"); + cbor_encode_map(&writer, 3); + cbor_encode_text_string(&writer, "x"); + cbor_encode_float(&writer, 6.3f); + cbor_encode_text_string(&writer, "y"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "z"); + cbor_encode_float(&writer, 0.f); + cbor_encode_break(&writer); + cbor_encode_break(&writer); + + See the test case: tests/src/example_test.cpp + */ +void complex_example(void const *data, size_t datasize, void *udt) +{ + cbor_reader_t reader; + cbor_item_t items[32]; + size_t n; + + cbor_reader_init(&reader, data, datasize); + cbor_error_t err = cbor_parse(&reader, items, sizeof(items) / sizeof(items[0]), &n); + if (err == CBOR_SUCCESS || err == CBOR_BREAK) { + cbor_iterate(&reader, items, n, 0, convert, udt); + } +} diff --git a/examples/example.h b/examples/example.h new file mode 100644 index 0000000..0c3bbff --- /dev/null +++ b/examples/example.h @@ -0,0 +1,40 @@ +#ifndef CBOR_EXAMPLE_H +#define CBOR_EXAMPLE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include + +/* User-defined Data Type */ +struct udt { + uint32_t time; + uint8_t type; + uint8_t uuid[16]; + struct { + struct { + float x; + float y; + float z; + } acc; + struct { + float x; + float y; + float z; + } gyro; + } data; +}; + +typedef void (*example_writer)(void const *data, size_t datasize); + +void simple_example(example_writer print); +void complex_example(void const *data, size_t datasize, void *udt); + +#if defined(__cplusplus) +} +#endif + +#endif /* CBOR_EXAMPLE_H */ diff --git a/examples/simple.c b/examples/simple.c new file mode 100644 index 0000000..5d75ba9 --- /dev/null +++ b/examples/simple.c @@ -0,0 +1,77 @@ +#include "example.h" + +#include + +#include "cbor/encoder.h" +#include "cbor/ieee754.h" +#include "cbor/decoder.h" +#include "cbor/parser.h" +#include "cbor/helper.h" + +union cbor_value { + int8_t i8; + int16_t i16; + int32_t i32; + int64_t i64; + float f32; + double f64; + uint8_t *bin; + char *str; + uint8_t str_copy[16]; +}; + +static void print_cbor(cbor_reader_t const *reader, cbor_item_t const *item, example_writer print) +{ + union cbor_value val; + + memset(&val, 0, sizeof(val)); + cbor_decode(reader, item, &val, sizeof(val)); + + switch (item->type) { + case CBOR_ITEM_INTEGER: { + char buf[16]; + int len = sprintf(buf, "%d", val.i32); + print(buf, (size_t)len); + } break; + case CBOR_ITEM_STRING: + print(val.str_copy, item->size); + break; + case CBOR_ITEM_SIMPLE_VALUE: + print(val.i8 == 1? "true" : "false", 4); + default: + break; + } +} + +static size_t encode_simple_data(void *buf, size_t bufsize) +{ + cbor_writer_t writer; + cbor_writer_init(&writer, buf, bufsize); + + cbor_encode_text_string(&writer, "Hello, World!"); + cbor_encode_unsigned_integer(&writer, 1661225893); + cbor_encode_bool(&writer, true); + + return cbor_writer_len(&writer); +} + +static void decode_simple_data(void const *data, size_t datasize, example_writer print) +{ + cbor_reader_t reader; + cbor_item_t items[16]; + size_t n; + + cbor_reader_init(&reader, data, datasize); + cbor_parse(&reader, items, sizeof(items) / sizeof(items[0]), &n); + + for (size_t i = 0; i < n; i++) { + print_cbor(&reader, &items[i], print); + } +} + +void simple_example(example_writer print) +{ + uint8_t buf[32]; + size_t len = encode_simple_data(buf, sizeof(buf)); + decode_simple_data(buf, len, print); +} diff --git a/include/cbor/helper.h b/include/cbor/helper.h index 9c4ec1d..0285040 100644 --- a/include/cbor/helper.h +++ b/include/cbor/helper.h @@ -10,6 +10,14 @@ extern "C" { const char *cbor_stringify_error(cbor_error_t err); const char *cbor_stringify_item(cbor_item_t *item); +size_t cbor_iterate(cbor_reader_t const *reader, + cbor_item_t const *items, size_t nr_items, + cbor_item_t const *parent, + void (*callback_each)(cbor_reader_t const *reader, + cbor_item_t const *item, cbor_item_t const *parent, + void *udt), + void *udt); + #if defined(__cplusplus) } #endif diff --git a/src/decoder.c b/src/decoder.c index 2ce72d0..d1c53aa 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -5,7 +5,7 @@ #define MIN(a, b) (((a) > (b))? (b) : (a)) #endif -typedef cbor_error_t (*item_callback_t)(cbor_item_t const *item, +typedef cbor_error_t (*item_decoder_t)(cbor_item_t const *item, uint8_t const *msg, uint8_t *buf, size_t bufsize); static cbor_error_t decode_pass(cbor_item_t const *item, uint8_t const *msg, @@ -19,7 +19,7 @@ static cbor_error_t decode_float(cbor_item_t const *item, uint8_t const *msg, static cbor_error_t decode_simple(cbor_item_t const *item, uint8_t const *msg, uint8_t *buf, size_t bufsize); -static const item_callback_t callbacks[] = { +static const item_decoder_t decoders[] = { decode_pass, /* 0: CBOR_ITEM_UNKNOWN */ decode_integer, /* 1: CBOR_ITEM_INTEGER */ decode_string, /* 2: CBOR_ITEM_STRING */ @@ -158,5 +158,5 @@ cbor_error_t cbor_decode(cbor_reader_t const *reader, cbor_item_t const *item, return CBOR_OVERRUN; } - return callbacks[item->type](item, reader->msg, (uint8_t *)buf, bufsize); + return decoders[item->type](item, reader->msg, (uint8_t *)buf, bufsize); } diff --git a/src/helper.c b/src/helper.c index 8710ad1..7992bf6 100644 --- a/src/helper.c +++ b/src/helper.c @@ -1,4 +1,35 @@ #include "cbor/helper.h" +#include "cbor/decoder.h" + +size_t cbor_iterate(cbor_reader_t const *reader, + cbor_item_t const *items, size_t nr_items, + cbor_item_t const *parent, + void (*callback_each)(cbor_reader_t const *reader, + cbor_item_t const *item, cbor_item_t const *parent, + void *udt), + void *udt) +{ + size_t offset = 0; + size_t i = 0; + + for (i = 0; i < nr_items; i++) { + cbor_item_t const *item = &items[i+offset]; + + if (item->type == CBOR_ITEM_MAP || item->type == CBOR_ITEM_ARRAY) { + size_t len = item->type == CBOR_ITEM_MAP? item->size*2 : item->size; + offset += cbor_iterate(reader, item+1, len, item, callback_each, udt); + continue; + } + + if (cbor_decode(reader, item, 0, 0) == CBOR_BREAK) { + break; + } + + (*callback_each)(reader, item, parent, udt); + } + + return i + offset; +} const char *cbor_stringify_error(cbor_error_t err) { diff --git a/src/parser.c b/src/parser.c index 3a5d652..7b0b5e8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -24,7 +24,7 @@ struct parser_context { }; -typedef cbor_error_t (*major_type_callback_t)(struct parser_context *ctx); +typedef cbor_error_t (*type_parser_t)(struct parser_context *ctx); static cbor_error_t do_integer(struct parser_context *ctx); static cbor_error_t do_string(struct parser_context *ctx); @@ -32,8 +32,8 @@ static cbor_error_t do_recursive(struct parser_context *ctx); static cbor_error_t do_tag(struct parser_context *ctx); static cbor_error_t do_float_and_other(struct parser_context *ctx); -/* 8 callbacks for 3-bit major type */ -static const major_type_callback_t callbacks[] = { +/* 8 parsers for 3-bit major type */ +static const type_parser_t parsers[] = { do_integer, /* 0: unsigned integer */ do_integer, /* 1: negative integer */ do_string, /* 2: byte string */ @@ -43,7 +43,6 @@ static const major_type_callback_t callbacks[] = { do_tag, /* 6: tag */ do_float_and_other, /* 7: float, simple value, and break */ }; -_Static_assert(sizeof(callbacks) == 8 * sizeof(major_type_callback_t), ""); static bool has_valid_following_bytes(const struct parser_context *ctx, cbor_error_t *err) @@ -106,7 +105,7 @@ static cbor_error_t parse(struct parser_context *ctx, size_t maxitems) break; } - err = callbacks[ctx->major_type](ctx); + err = parsers[ctx->major_type](ctx); if (err == CBOR_BREAK) { if (ctx->reader->msgidx == ctx->reader->msgsize) { diff --git a/tests/runners/example.mk b/tests/runners/example.mk new file mode 100644 index 0000000..96e0e55 --- /dev/null +++ b/tests/runners/example.mk @@ -0,0 +1,25 @@ +COMPONENT_NAME = example + +SRC_FILES = \ + ../examples/simple.c \ + ../examples/complex.c \ + ../src/encoder.c \ + ../src/ieee754.c \ + ../src/decoder.c \ + ../src/parser.c \ + ../src/helper.c \ + ../src/common.c \ + +TEST_SRC_FILES = \ + src/example_test.cpp \ + src/test_all.cpp \ + +INCLUDE_DIRS = \ + ../examples \ + ../include \ + $(CPPUTEST_HOME)/include \ + +MOCKS_SRC_DIRS = +CPPUTEST_CPPFLAGS = -DCBOR_RECURSION_MAX_LEVEL=8 + +include MakefileRunner.mk diff --git a/tests/src/example_test.cpp b/tests/src/example_test.cpp new file mode 100644 index 0000000..7d7a575 --- /dev/null +++ b/tests/src/example_test.cpp @@ -0,0 +1,141 @@ +#include "CppUTest/TestHarness.h" +#include "CppUTest/TestHarness_c.h" +#include "CppUTestExt/MockSupport.h" + +#include "example.h" +#include "cbor/encoder.h" + +class StringComparator : public MockNamedValueComparator +{ +public: + virtual bool isEqual(const void *object1, const void *object2) + { + if (strcmp((const char *)object1, (const char *)object2) != 0) { + return false; + } + + return true; + } + virtual SimpleString valueToString(const void* object) + { + return StringFrom(object); + } +}; + +static void print(void const *data, size_t datasize) +{ + mock().actualCall(__func__) + .withParameterOfType("stringType", "data", data) + .withParameter("datasize", datasize); +} + +TEST_GROUP(Example) { + cbor_writer_t writer; + uint8_t writer_buffer[1024]; + + void setup(void) { + static StringComparator StrComparator; + mock().installComparator("stringType", StrComparator); + cbor_writer_init(&writer, writer_buffer, sizeof(writer_buffer)); + } + void teardown(void) { + mock().checkExpectations(); + mock().removeAllComparatorsAndCopiers(); + mock().clear(); + } +}; + +TEST(Example, ShouldConvertToUserDefinedDataType) { + cbor_encode_map_indefinite(&writer); + cbor_encode_text_string(&writer, "t"); + cbor_encode_unsigned_integer(&writer, 1661225893); + cbor_encode_text_string(&writer, "data"); + cbor_encode_map(&writer, 2); + cbor_encode_text_string(&writer, "acc"); + cbor_encode_map(&writer, 3); + cbor_encode_text_string(&writer, "x"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "y"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "z"); + cbor_encode_float(&writer, 9.81f); + cbor_encode_text_string(&writer, "gyro"); + cbor_encode_map(&writer, 3); + cbor_encode_text_string(&writer, "x"); + cbor_encode_float(&writer, 6.3f); + cbor_encode_text_string(&writer, "y"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "z"); + cbor_encode_float(&writer, 0.f); + cbor_encode_break(&writer); + + struct udt udt = { 0, }; + complex_example(cbor_writer_get_encoded(&writer), cbor_writer_len(&writer), &udt); + + LONGS_EQUAL(1661225893, udt.time); + DOUBLES_EQUAL(0., (double)udt.data.acc.x, 0.01); + DOUBLES_EQUAL(0., (double)udt.data.acc.y, 0.01); + DOUBLES_EQUAL(9.81, (double)udt.data.acc.z, 0.01); + DOUBLES_EQUAL(6.3, (double)udt.data.gyro.x, 0.01); + DOUBLES_EQUAL(0., (double)udt.data.gyro.y, 0.01); + DOUBLES_EQUAL(0., (double)udt.data.gyro.z, 0.01); +} + +TEST(Example, ShouldConvertToUserDefinedDataType2) { + uint8_t const uuid[] = { 0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, + 0xa4, 0x56, 0x42, 0x66, 0x14, 0x17, 0x40, 0x00 }; + cbor_encode_array_indefinite(&writer); + cbor_encode_simple(&writer, 1); + cbor_encode_byte_string(&writer, uuid, sizeof(uuid)); + cbor_encode_map_indefinite(&writer); + cbor_encode_text_string(&writer, "t"); + cbor_encode_unsigned_integer(&writer, 1661225893); + cbor_encode_text_string(&writer, "data"); + cbor_encode_map(&writer, 2); + cbor_encode_text_string(&writer, "acc"); + cbor_encode_map(&writer, 3); + cbor_encode_text_string(&writer, "x"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "y"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "z"); + cbor_encode_float(&writer, 9.81f); + cbor_encode_text_string(&writer, "gyro"); + cbor_encode_map(&writer, 3); + cbor_encode_text_string(&writer, "x"); + cbor_encode_float(&writer, 6.3f); + cbor_encode_text_string(&writer, "y"); + cbor_encode_float(&writer, 0.f); + cbor_encode_text_string(&writer, "z"); + cbor_encode_float(&writer, 0.f); + cbor_encode_break(&writer); + cbor_encode_break(&writer); + + struct udt udt = { 0, }; + complex_example(cbor_writer_get_encoded(&writer), cbor_writer_len(&writer), &udt); + + LONGS_EQUAL(1661225893, udt.time); + DOUBLES_EQUAL(0., (double)udt.data.acc.x, 0.01); + DOUBLES_EQUAL(0., (double)udt.data.acc.y, 0.01); + DOUBLES_EQUAL(9.81, (double)udt.data.acc.z, 0.01); + DOUBLES_EQUAL(6.3, (double)udt.data.gyro.x, 0.01); + DOUBLES_EQUAL(0., (double)udt.data.gyro.y, 0.01); + DOUBLES_EQUAL(0., (double)udt.data.gyro.z, 0.01); + + LONGS_EQUAL(1, udt.type); + MEMCMP_EQUAL(uuid, udt.uuid, sizeof(uuid)); +} + +TEST(Example, ShouldPrintString_WhenSimpleExampleCalled) { + mock().expectOneCall("print") + .withParameterOfType("stringType", "data", "Hello, World!") + .withParameter("datasize", 13); + mock().expectOneCall("print") + .withParameterOfType("stringType", "data", "1661225893") + .withParameter("datasize", 10); + mock().expectOneCall("print") + .withParameterOfType("stringType", "data", "true") + .withParameter("datasize", 4); + + simple_example(print); +}