This is an automated email from the ASF dual-hosted git repository. ccollins pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-mcumgr.git
commit b3b7c5ecd9b9f43fdc641e4a0d7c95d21892cd66 Author: Christopher Collins <ccoll...@apache.org> AuthorDate: Wed Jan 17 17:13:14 2018 -0800 cborattr library This is used for parsing incoming mcumgr requests. Destructures mcumgr packets and populates corresponding field variables. This comes from Apache Mynewt. --- cborattr/CMakeLists.txt | 7 + cborattr/include/cborattr/cborattr.h | 153 ++++++++ cborattr/pkg.yml | 29 ++ cborattr/src/cborattr.c | 423 +++++++++++++++++++++ cborattr/syscfg.yml | 24 ++ cborattr/test/pkg.yml | 30 ++ cborattr/test/src/test_cborattr.c | 49 +++ cborattr/test/src/test_cborattr.h | 57 +++ cborattr/test/src/test_cborattr_utils.c | 35 ++ cborattr/test/src/testcases/cborattr_decode1.c | 83 ++++ .../src/testcases/cborattr_decode_bool_array.c | 101 +++++ .../test/src/testcases/cborattr_decode_int_array.c | 143 +++++++ .../test/src/testcases/cborattr_decode_obj_array.c | 109 ++++++ .../test/src/testcases/cborattr_decode_object.c | 198 ++++++++++ .../src/testcases/cborattr_decode_object_array.c | 126 ++++++ .../test/src/testcases/cborattr_decode_partial.c | 47 +++ .../test/src/testcases/cborattr_decode_simple.c | 123 ++++++ .../src/testcases/cborattr_decode_string_array.c | 135 +++++++ .../src/testcases/cborattr_decode_substring_key.c | 111 ++++++ .../src/testcases/cborattr_decode_unnamed_array.c | 99 +++++ 20 files changed, 2082 insertions(+) diff --git a/cborattr/CMakeLists.txt b/cborattr/CMakeLists.txt new file mode 100644 index 0000000..2f22bd0 --- /dev/null +++ b/cborattr/CMakeLists.txt @@ -0,0 +1,7 @@ +target_include_directories(MCUMGR INTERFACE + include +) + +zephyr_library_sources( + cborattr/src/cborattr.c +) diff --git a/cborattr/include/cborattr/cborattr.h b/cborattr/include/cborattr/cborattr.h new file mode 100644 index 0000000..1cc14b3 --- /dev/null +++ b/cborattr/include/cborattr/cborattr.h @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef CBORATTR_H +#define CBORATTR_H + +#include <stdbool.h> +#include <stdint.h> +#include <ctype.h> +#include <stdio.h> +#include <sys/types.h> +#include "cbor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This library wraps the tinycbor decoder with a attribute based decoder + * suitable for decoding a binary version of json. Specifically, the + * contents of the cbor contains pairs of attributes. where the attribute + * is a key/value pair. keys are always text strings, but values can be + * many different things (enumerated below) */ + +typedef enum CborAttrType { + CborAttrIntegerType = 1, + CborAttrUnsignedIntegerType, + CborAttrByteStringType, + CborAttrTextStringType, + CborAttrBooleanType, + CborAttrFloatType, + CborAttrDoubleType, + CborAttrArrayType, + CborAttrObjectType, + CborAttrStructObjectType, + CborAttrNullType, +} CborAttrType; + +struct cbor_attr_t; + +struct cbor_enum_t { + char *name; + long long int value; +}; + +struct cbor_array_t { + CborAttrType element_type; + union { + struct { + const struct cbor_attr_t *subtype; + char *base; + size_t stride; + } objects; + struct { + char **ptrs; + char *store; + int storelen; + } strings; + struct { + long long int *store; + } integers; + struct { + long long unsigned int *store; + } uintegers; + struct { + double *store; + } reals; + struct { + bool *store; + } booleans; + } arr; + int *count; + int maxlen; +}; + +struct cbor_attr_t { + char *attribute; + CborAttrType type; + union { + long long int *integer; + long long unsigned int *uinteger; + double *real; + float *fval; + char *string; + bool *boolean; + struct byte_string { + uint8_t *data; + size_t *len; + } bytestring; + struct cbor_array_t array; + size_t offset; + struct cbor_attr_t *obj; + } addr; + union { + long long int integer; + double real; + bool boolean; + float fval; + } dflt; + size_t len; + bool nodefault; +}; + +/* + * Use the following macros to declare template initializers for + * CborAttrStructObjectType arrays. Writing the equivalents out by hand is + * error-prone. + * + * CBOR_STRUCT_OBJECT takes a structure name s, and a fieldname f in s. + * + * CBOR_STRUCT_ARRAY takes the name of a structure array, a pointer to a an + * initializer defining the subobject type, and the address of an integer to + * store the length in. + */ +#define CBORATTR_STRUCT_OBJECT(s, f) .addr.offset = offsetof(s, f) +#define CBORATTR_STRUCT_ARRAY(a, e, n) \ + .addr.array.element_type = CborAttrStructObjectType, \ + .addr.array.arr.objects.subtype = e, \ + .addr.array.arr.objects.base = (char*)a, \ + .addr.array.arr.objects.stride = sizeof(a[0]), \ + .addr.array.count = n, \ + .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0])) + +#define CBORATTR_ATTR_UNNAMED (char *)(-1) + +int cbor_read_object(struct CborValue *, const struct cbor_attr_t *); +int cbor_read_array(struct CborValue *, const struct cbor_array_t *); + +int cbor_read_flat_attrs(const uint8_t *data, int len, + const struct cbor_attr_t *attrs); + +#ifdef __cplusplus +} +#endif + +#endif /* CBORATTR_H */ + diff --git a/cborattr/pkg.yml b/cborattr/pkg.yml new file mode 100644 index 0000000..8495f95 --- /dev/null +++ b/cborattr/pkg.yml @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: cborattr +pkg.description: CBOR encoding/decoding library +pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - "encoding/tinycbor" + +pkg.cflags.FLOAT_USER: -DFLOAT_SUPPORT diff --git a/cborattr/src/cborattr.c b/cborattr/src/cborattr.c new file mode 100644 index 0000000..46cdc23 --- /dev/null +++ b/cborattr/src/cborattr.c @@ -0,0 +1,423 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +//#include <syscfg/syscfg.h> +#include "cborattr/cborattr.h" +#include "cbor.h" +#include "cbor_buf_reader.h" + +#define CBORATTR_MAX_SIZE 512 + +/* this maps a CborType to a matching CborAtter Type. The mapping is not + * one-to-one because of signedness of integers + * and therefore we need a function to do this trickery */ +static int +valid_attr_type(CborType ct, CborAttrType at) +{ + switch (at) { + case CborAttrIntegerType: + case CborAttrUnsignedIntegerType: + if (ct == CborIntegerType) { + return 1; + } + break; + case CborAttrByteStringType: + if (ct == CborByteStringType) { + return 1; + } + break; + case CborAttrTextStringType: + if (ct == CborTextStringType) { + return 1; + } + break; + case CborAttrBooleanType: + if (ct == CborBooleanType) { + return 1; + } +#if FLOAT_SUPPORT + case CborAttrFloatType: + if (ct == CborFloatType) { + return 1; + } + break; + case CborAttrDoubleType: + if (ct == CborDoubleType) { + return 1; + } + break; +#endif + case CborAttrArrayType: + if (ct == CborArrayType) { + return 1; + } + break; + case CborAttrObjectType: + if (ct == CborMapType) { + return 1; + } + break; + case CborAttrNullType: + if (ct == CborNullType) { + return 1; + } + break; + default: + break; + } + return 0; +} + +/* this function find the pointer to the memory location to + * write or read and attribute from the cbor_attr_r structure */ +static char * +cbor_target_address(const struct cbor_attr_t *cursor, + const struct cbor_array_t *parent, int offset) +{ + char *targetaddr = NULL; + + if (parent == NULL || parent->element_type != CborAttrStructObjectType) { + /* ordinary case - use the address in the cursor structure */ + switch (cursor->type) { + case CborAttrNullType: + targetaddr = NULL; + break; + case CborAttrIntegerType: + targetaddr = (char *)&cursor->addr.integer[offset]; + break; + case CborAttrUnsignedIntegerType: + targetaddr = (char *)&cursor->addr.uinteger[offset]; + break; +#if FLOAT_SUPPORT + case CborAttrFloatType: + targetaddr = (char *)&cursor->addr.fval[offset]; + break; + case CborAttrDoubleType: + targetaddr = (char *)&cursor->addr.real[offset]; + break; +#endif + case CborAttrByteStringType: + targetaddr = (char *) cursor->addr.bytestring.data; + break; + case CborAttrTextStringType: + targetaddr = cursor->addr.string; + break; + case CborAttrBooleanType: + targetaddr = (char *)&cursor->addr.boolean[offset]; + break; + default: + targetaddr = NULL; + break; + } + } else { + /* tricky case - hacking a member in an array of structures */ + targetaddr = + parent->arr.objects.base + (offset * parent->arr.objects.stride) + + cursor->addr.offset; + } + return targetaddr; +} + +static int +cbor_internal_read_object(CborValue *root_value, + const struct cbor_attr_t *attrs, + const struct cbor_array_t *parent, + int offset) +{ + const struct cbor_attr_t *cursor, *best_match; + char attrbuf[CBORATTR_MAX_SIZE + 1]; + void *lptr; + CborValue cur_value; + CborError err = 0; + size_t len; + CborType type = CborInvalidType; + + /* stuff fields with defaults in case they're omitted in the JSON input */ + for (cursor = attrs; cursor->attribute != NULL; cursor++) { + if (!cursor->nodefault) { + lptr = cbor_target_address(cursor, parent, offset); + if (lptr != NULL) { + switch (cursor->type) { + case CborAttrIntegerType: + memcpy(lptr, &cursor->dflt.integer, sizeof(long long int)); + break; + case CborAttrUnsignedIntegerType: + memcpy(lptr, &cursor->dflt.integer, + sizeof(long long unsigned int)); + break; + case CborAttrBooleanType: + memcpy(lptr, &cursor->dflt.boolean, sizeof(bool)); + break; +#if FLOAT_SUPPORT + case CborAttrFloatType: + memcpy(lptr, &cursor->dflt.fval, sizeof(float)); + break; + case CborAttrDoubleType: + memcpy(lptr, &cursor->dflt.real, sizeof(double)); + break; +#endif + default: + break; + } + } + } + } + + if (cbor_value_is_map(root_value)) { + err |= cbor_value_enter_container(root_value, &cur_value); + } else { + err |= CborErrorIllegalType; + return err; + } + + /* contains key value pairs */ + while (cbor_value_is_valid(&cur_value) && !err) { + /* get the attribute */ + if (cbor_value_is_text_string(&cur_value)) { + if (cbor_value_calculate_string_length(&cur_value, &len) == 0) { + if (len > CBORATTR_MAX_SIZE) { + err |= CborErrorDataTooLarge; + break; + } + err |= cbor_value_copy_text_string(&cur_value, attrbuf, &len, + NULL); + } + + /* at least get the type of the next value so we can match the + * attribute name and type for a perfect match */ + err |= cbor_value_advance(&cur_value); + if (cbor_value_is_valid(&cur_value)) { + type = cbor_value_get_type(&cur_value); + } else { + err |= CborErrorIllegalType; + break; + } + } else { + attrbuf[0] = '\0'; + type = cbor_value_get_type(&cur_value); + } + + /* find this attribute in our list */ + best_match = NULL; + for (cursor = attrs; cursor->attribute != NULL; cursor++) { + if (valid_attr_type(type, cursor->type)) { + if (cursor->attribute == CBORATTR_ATTR_UNNAMED && + attrbuf[0] == '\0') { + best_match = cursor; + } else if (strlen(cursor->attribute) == len && + !memcmp(cursor->attribute, attrbuf, len)) { + break; + } + } + } + if (!cursor->attribute && best_match) { + cursor = best_match; + } + /* we found a match */ + if (cursor->attribute != NULL) { + lptr = cbor_target_address(cursor, parent, offset); + switch (cursor->type) { + case CborAttrNullType: + /* nothing to do */ + break; + case CborAttrBooleanType: + err |= cbor_value_get_boolean(&cur_value, lptr); + break; + case CborAttrIntegerType: + err |= cbor_value_get_int64(&cur_value, lptr); + break; + case CborAttrUnsignedIntegerType: + err |= cbor_value_get_uint64(&cur_value, lptr); + break; +#if FLOAT_SUPPORT + case CborAttrFloatType: + err |= cbor_value_get_float(&cur_value, lptr); + break; + case CborAttrDoubleType: + err |= cbor_value_get_double(&cur_value, lptr); + break; +#endif + case CborAttrByteStringType: { + size_t len = cursor->len; + err |= cbor_value_copy_byte_string(&cur_value, lptr, + &len, NULL); + *cursor->addr.bytestring.len = len; + break; + } + case CborAttrTextStringType: { + size_t len = cursor->len; + err |= cbor_value_copy_text_string(&cur_value, lptr, + &len, NULL); + break; + } + case CborAttrArrayType: + err |= cbor_read_array(&cur_value, &cursor->addr.array); + continue; + case CborAttrObjectType: + err |= cbor_internal_read_object(&cur_value, cursor->addr.obj, + NULL, 0); + continue; + default: + err |= CborErrorIllegalType; + } + } + cbor_value_advance(&cur_value); + } + if (!err) { + /* that should be it for this container */ + err |= cbor_value_leave_container(root_value, &cur_value); + } + return err; +} + +int +cbor_read_array(struct CborValue *value, const struct cbor_array_t *arr) +{ + CborError err = 0; + struct CborValue elem; + int off, arrcount; + size_t len; + void *lptr; + char *tp; + + err = cbor_value_enter_container(value, &elem); + if (err) { + return err; + } + arrcount = 0; + tp = arr->arr.strings.store; + for (off = 0; off < arr->maxlen; off++) { + switch (arr->element_type) { + case CborAttrBooleanType: + lptr = &arr->arr.booleans.store[off]; + err |= cbor_value_get_boolean(&elem, lptr); + break; + case CborAttrIntegerType: + lptr = &arr->arr.integers.store[off]; + err |= cbor_value_get_int64(&elem, lptr); + break; + case CborAttrUnsignedIntegerType: + lptr = &arr->arr.uintegers.store[off]; + err |= cbor_value_get_uint64(&elem, lptr); + break; +#if FLOAT_SUPPORT + case CborAttrFloatType: + case CborAttrDoubleType: + lptr = &arr->arr.reals.store[off]; + err |= cbor_value_get_double(&elem, lptr); + break; +#endif + case CborAttrTextStringType: + len = arr->arr.strings.storelen - (tp - arr->arr.strings.store); + err |= cbor_value_copy_text_string(&elem, tp, &len, NULL); + arr->arr.strings.ptrs[off] = tp; + tp += len + 1; + break; + case CborAttrStructObjectType: + err |= cbor_internal_read_object(&elem, arr->arr.objects.subtype, + arr, off); + break; + default: + err |= CborErrorIllegalType; + break; + } + arrcount++; + if (arr->element_type != CborAttrStructObjectType) { + err |= cbor_value_advance(&elem); + } + if (!cbor_value_is_valid(&elem)) { + break; + } + } + if (arr->count) { + *arr->count = arrcount; + } + while (!cbor_value_at_end(&elem)) { + err |= CborErrorDataTooLarge; + cbor_value_advance(&elem); + } + err |= cbor_value_leave_container(value, &elem); + return err; +} + +int +cbor_read_object(struct CborValue *value, const struct cbor_attr_t *attrs) +{ + int st; + + st = cbor_internal_read_object(value, attrs, NULL, 0); + return st; +} + +/* + * Read in cbor key/values from flat buffer pointed by data, and fill them + * into attrs. + * + * @param data Pointer to beginning of cbor encoded data + * @param len Number of bytes in the buffer + * @param attrs Array of cbor objects to look for. + * + * @return 0 on success; non-zero on failure. + */ +int +cbor_read_flat_attrs(const uint8_t *data, int len, + const struct cbor_attr_t *attrs) +{ + struct cbor_buf_reader reader; + struct CborParser parser; + struct CborValue value; + CborError err; + + cbor_buf_reader_init(&reader, data, len); + err = cbor_parser_cust_reader_init(&reader.r, 0, &parser, &value); + if (err != CborNoError) { + return -1; + } + return cbor_read_object(&value, attrs); +} + +#if 0 +/* + * Read in cbor key/values from os_mbuf pointed by m, and fill them + * into attrs. + * + * @param m Pointer to os_mbuf containing cbor encoded data + * @param off Offset into mbuf where cbor data begins + * @param len Number of bytes to decode + * @param attrs Array of cbor objects to look for. + * + * @return 0 on success; non-zero on failure. + */ +int +cbor_read_mbuf_attrs(struct os_mbuf *m, uint16_t off, uint16_t len, + const struct cbor_attr_t *attrs) +{ + struct cbor_mbuf_reader cmr; + struct CborParser parser; + struct CborValue value; + CborError err; + + cbor_mbuf_reader_init(&cmr, m, off); + err = cbor_parser_init(&cmr.r, 0, &parser, &value); + if (err != CborNoError) { + return -1; + } + return cbor_read_object(&value, attrs); +} +#endif diff --git a/cborattr/syscfg.yml b/cborattr/syscfg.yml new file mode 100644 index 0000000..cc93c26 --- /dev/null +++ b/cborattr/syscfg.yml @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# Package: mgmt/imgmgr + +syscfg.defs: + CBORATTR_MAX_SIZE: + description: 'The maximum size of a CBOR attribute during decoding' + value: 512 diff --git a/cborattr/test/pkg.yml b/cborattr/test/pkg.yml new file mode 100644 index 0000000..071ca5f --- /dev/null +++ b/cborattr/test/pkg.yml @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +pkg.name: cborattr/test +pkg.type: unittest +pkg.description: "CBOR attr unit tests." +pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - '@mynewt-mcumgr/ext/tinycbor' + - '@mynewt-mcumgr/cborattr' + +pkg.deps.SELFTEST: + - sys/console/stub diff --git a/cborattr/test/src/test_cborattr.c b/cborattr/test/src/test_cborattr.c new file mode 100644 index 0000000..0a64039 --- /dev/null +++ b/cborattr/test/src/test_cborattr.c @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "testutil/testutil.h" +#include "test_cborattr.h" + +TEST_SUITE(test_cborattr_suite) +{ + test_cborattr_decode1(); + test_cborattr_decode_partial(); + test_cborattr_decode_simple(); + test_cborattr_decode_object(); + test_cborattr_decode_int_array(); + test_cborattr_decode_bool_array(); + test_cborattr_decode_string_array(); + test_cborattr_decode_object_array(); + test_cborattr_decode_unnamed_array(); + test_cborattr_decode_substring_key(); +} + +#if MYNEWT_VAL(SELFTEST) +int +main(int argc, char **argv) +{ + sysinit(); + + test_cborattr_suite(); + + return tu_any_failed; +} +#endif diff --git a/cborattr/test/src/test_cborattr.h b/cborattr/test/src/test_cborattr.h new file mode 100644 index 0000000..815048f --- /dev/null +++ b/cborattr/test/src/test_cborattr.h @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef TEST_CBORATTR_H +#define TEST_CBORATTR_H + +#include <assert.h> +#include <string.h> +#include "testutil/testutil.h" +#include "test_cborattr.h" +#include "tinycbor/cbor.h" +#include "cborattr/cborattr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Returns test data. + */ +const uint8_t *test_str1(int *len); + +/* + * Testcases + */ +TEST_CASE_DECL(test_cborattr_decode1); +TEST_CASE_DECL(test_cborattr_decode_partial); +TEST_CASE_DECL(test_cborattr_decode_simple); +TEST_CASE_DECL(test_cborattr_decode_object); +TEST_CASE_DECL(test_cborattr_decode_int_array); +TEST_CASE_DECL(test_cborattr_decode_bool_array); +TEST_CASE_DECL(test_cborattr_decode_string_array); +TEST_CASE_DECL(test_cborattr_decode_object_array); +TEST_CASE_DECL(test_cborattr_decode_unnamed_array); +TEST_CASE_DECL(test_cborattr_decode_substring_key); + +#ifdef __cplusplus +} +#endif + +#endif /* TEST_CBORATTR_H */ + diff --git a/cborattr/test/src/test_cborattr_utils.c b/cborattr/test/src/test_cborattr_utils.c new file mode 100644 index 0000000..0a43766 --- /dev/null +++ b/cborattr/test/src/test_cborattr_utils.c @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "test_cborattr.h" +/* + * {"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"} + */ +static const uint8_t test_data1[] = { + 0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, + 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, + 0x44, 0x61, 0x65, 0x61, 0x45 +}; + +const uint8_t * +test_str1(int *len) +{ + *len = sizeof(test_data1); + return (test_data1); +} diff --git a/cborattr/test/src/testcases/cborattr_decode1.c b/cborattr/test/src/testcases/cborattr_decode1.c new file mode 100644 index 0000000..1b6cddf --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode1.c @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Simple decoding. + */ +TEST_CASE(test_cborattr_decode1) +{ + const uint8_t *data; + int len; + int rc; + char test_str_a[4] = { '\0' }; + char test_str_b[4] = { '\0' }; + char test_str_c[4] = { '\0' }; + char test_str_d[4] = { '\0' }; + char test_str_e[4] = { '\0' }; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrTextStringType, + .addr.string = test_str_a, + .len = sizeof(test_str_a), + .nodefault = true + }, + [1] = { + .attribute = "b", + .type = CborAttrTextStringType, + .addr.string = test_str_b, + .len = sizeof(test_str_b), + .nodefault = true + }, + [2] = { + .attribute = "c", + .type = CborAttrTextStringType, + .addr.string = test_str_c, + .len = sizeof(test_str_c), + .nodefault = true + }, + [3] = { + .attribute = "d", + .type = CborAttrTextStringType, + .addr.string = test_str_d, + .len = sizeof(test_str_d), + .nodefault = true, + }, + [4] = { + .attribute = "e", + .type = CborAttrTextStringType, + .addr.string = test_str_e, + .len = sizeof(test_str_e), + .nodefault = true, + }, + [5] = { + .attribute = NULL + } + }; + + data = test_str1(&len); + rc = cbor_read_flat_attrs(data, len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!strcmp(test_str_a, "A")); + TEST_ASSERT(!strcmp(test_str_b, "B")); + TEST_ASSERT(!strcmp(test_str_c, "C")); + TEST_ASSERT(!strcmp(test_str_d, "D")); + TEST_ASSERT(!strcmp(test_str_e, "E")); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_bool_array.c b/cborattr/test/src/testcases/cborattr_decode_bool_array.c new file mode 100644 index 0000000..71520c4 --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_bool_array.c @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_bool_array(void) +{ + CborEncoder data; + CborEncoder array; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * a: [true,true,false] + */ + cbor_encode_text_stringz(&data, "a"); + + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + cbor_encode_boolean(&array, true); + cbor_encode_boolean(&array, true); + cbor_encode_boolean(&array, false); + cbor_encoder_close_container(&data, &array); + + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * array of booleans + */ +TEST_CASE(test_cborattr_decode_bool_array) +{ + int rc; + bool arr_data[5]; + int arr_cnt = 0; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrArrayType, + .addr.array.element_type = CborAttrBooleanType, + .addr.array.arr.booleans.store = arr_data, + .addr.array.count = &arr_cnt, + .addr.array.maxlen = sizeof(arr_data) / sizeof(arr_data[0]), + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + + test_encode_bool_array(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 3); + TEST_ASSERT(arr_data[0] == true); + TEST_ASSERT(arr_data[1] == true); + TEST_ASSERT(arr_data[2] == false); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_int_array.c b/cborattr/test/src/testcases/cborattr_decode_int_array.c new file mode 100644 index 0000000..96bc8cc --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_int_array.c @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_int_array(void) +{ + CborEncoder data; + CborEncoder array; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * a: [1,2,33,15,-4] + */ + cbor_encode_text_stringz(&data, "a"); + + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + cbor_encode_int(&array, 1); + cbor_encode_int(&array, 2); + cbor_encode_int(&array, 33); + cbor_encode_int(&array, 15); + cbor_encode_int(&array, -4); + cbor_encoder_close_container(&data, &array); + + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * integer array + */ +TEST_CASE(test_cborattr_decode_int_array) +{ + int rc; + int64_t arr_data[5]; + int64_t b_int; + int arr_cnt = 0; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrArrayType, + .addr.array.element_type = CborAttrIntegerType, + .addr.array.arr.integers.store = arr_data, + .addr.array.count = &arr_cnt, + .addr.array.maxlen = sizeof(arr_data) / sizeof(arr_data[0]), + .nodefault = true + }, + [1] = { + .attribute = "b", + .type = CborAttrIntegerType, + .addr.integer = &b_int, + .dflt.integer = 1 + }, + [2] = { + .attribute = NULL + } + }; + struct cbor_attr_t test_attrs_small[] = { + [0] = { + .attribute = "a", + .type = CborAttrArrayType, + .addr.array.element_type = CborAttrIntegerType, + .addr.array.arr.integers.store = arr_data, + .addr.array.count = &arr_cnt, + .addr.array.maxlen = 1, + .nodefault = true + }, + [1] = { + .attribute = "b", + .type = CborAttrIntegerType, + .addr.integer = &b_int, + .dflt.integer = 1 + }, + [2] = { + .attribute = NULL + } + }; + + test_encode_int_array(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 5); + TEST_ASSERT(arr_data[0] == 1); + TEST_ASSERT(arr_data[1] == 2); + TEST_ASSERT(arr_data[2] == 33); + TEST_ASSERT(arr_data[3] == 15); + TEST_ASSERT(arr_data[4] == -4); + TEST_ASSERT(b_int == 1); + + memset(arr_data, 0, sizeof(arr_data)); + b_int = 0; + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs_small); + TEST_ASSERT(rc == CborErrorDataTooLarge); + TEST_ASSERT(arr_cnt == 1); + TEST_ASSERT(arr_data[0] == 1); + TEST_ASSERT(arr_data[1] == 0); + TEST_ASSERT(b_int == 1); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_obj_array.c b/cborattr/test/src/testcases/cborattr_decode_obj_array.c new file mode 100644 index 0000000..57c46cd --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_obj_array.c @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_obj_array(void) +{ + CborEncoder data; + CborEncoder array; + CborEncoder obj; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * a: [{ n:"a", v:1}, {n:"b", v:2} ] + */ + cbor_encode_text_stringz(&data, "a"); + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + + cbor_encoder_create_map(&array, &obj, CborIndefiniteLength); + cbor_encode_text_stringz(&obj, "n"); + cbor_encode_text_stringz(&obj, "a"); + cbor_encode_text_stringz(&obj, "v"); + cbor_encode_int(&obj, 1); + cbor_encoder_close_container(&array, &obj); + + cbor_encoder_create_map(&array, &obj, CborIndefiniteLength); + cbor_encode_text_stringz(&obj, "n"); + cbor_encode_text_stringz(&obj, "b"); + cbor_encode_text_stringz(&obj, "v"); + cbor_encode_int(&obj, 2); + cbor_encoder_close_container(&array, &obj); + + cbor_encoder_close_container(&data, &array); + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * object array + */ +TEST_CASE(test_cborattr_decode_obj_array) +{ + int rc; + char arr_data[4]; + int arr_cnt; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrArrayType, + .addr.array.element_type = CborAttrNullType, + .addr.array.arr.objects.base = arr_data, + .addr.array.count = &arr_cnt, + .addr.array.maxlen = 4, + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + + test_encode_obj_array(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 2); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_object.c b/cborattr/test/src/testcases/cborattr_decode_object.c new file mode 100644 index 0000000..25a32d2 --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_object.c @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_data(void) +{ + CborEncoder test_data; + CborEncoder sub_obj; + + test_cbor_len = 0; + cbor_encoder_init(&test_encoder, &test_writer, 0); + cbor_encoder_create_map(&test_encoder, &test_data, CborIndefiniteLength); + + /* + * p: { bm : 7 } + */ + cbor_encode_text_stringz(&test_data, "p"); + + cbor_encoder_create_map(&test_data, &sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&test_data, "bm"); + cbor_encode_int(&test_data, 7); + cbor_encoder_close_container(&test_data, &sub_obj); + + cbor_encoder_close_container(&test_encoder, &test_data); +} + +static void +test_encode_data_complex(void) +{ + CborEncoder test_data; + CborEncoder sub_obj; + CborEncoder sub_sub_obj; + + test_cbor_len = 0; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + cbor_encoder_create_map(&test_encoder, &test_data, CborIndefiniteLength); + + /* + * p: { bm : 7 }, c: { d : { i : 1 } }, a: 3 + */ + cbor_encode_text_stringz(&test_data, "p"); + + cbor_encoder_create_map(&test_data, &sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&test_data, "bm"); + cbor_encode_int(&test_data, 7); + cbor_encoder_close_container(&test_data, &sub_obj); + + cbor_encode_text_stringz(&test_data, "c"); + cbor_encoder_create_map(&test_data, &sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&sub_obj, "d"); + + cbor_encoder_create_map(&sub_obj, &sub_sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&sub_sub_obj, "i"); + cbor_encode_int(&sub_sub_obj, 1); + cbor_encoder_close_container(&sub_obj, &sub_sub_obj); + cbor_encoder_close_container(&test_data, &sub_obj); + + cbor_encode_text_stringz(&test_data, "a"); + cbor_encode_int(&test_data, 3); + + cbor_encoder_close_container(&test_encoder, &test_data); +} + +/* + * Simple decoding. + */ +TEST_CASE(test_cborattr_decode_object) +{ + int rc; + int64_t bm_val = 0; + struct cbor_attr_t test_sub_attr_bm[] = { + [0] = { + .attribute = "bm", + .type = CborAttrIntegerType, + .addr.integer = &bm_val, + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "p", + .type = CborAttrObjectType, + .addr.obj = test_sub_attr_bm, + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + int64_t a_val = 0; + int64_t i_val = 0; + struct cbor_attr_t test_sub_sub_attr[] = { + [0] = { + .attribute = "i", + .type = CborAttrIntegerType, + .addr.integer = &i_val, + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + struct cbor_attr_t test_sub_attr_d[] = { + [0] = { + .attribute = "d", + .type = CborAttrObjectType, + .addr.obj = test_sub_sub_attr, + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + struct cbor_attr_t test_attr_complex[] = { + [0] = { + .attribute = "c", + .type = CborAttrObjectType, + .addr.obj = test_sub_attr_d, + .nodefault = true + }, + [1] = { + .attribute = "a", + .type = CborAttrIntegerType, + .addr.integer = &a_val, + .nodefault = true + }, + [2] = { + .attribute = "p", + .type = CborAttrObjectType, + .addr.obj = test_sub_attr_bm, + .nodefault = true + }, + [3] = { + .attribute = NULL + } + }; + + test_encode_data(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(bm_val == 7); + + test_encode_data_complex(); + + bm_val = 0; + i_val = 0; + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attr_complex); + TEST_ASSERT(rc == 0); + TEST_ASSERT(bm_val == 7); + TEST_ASSERT(i_val == 1); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_object_array.c b/cborattr/test/src/testcases/cborattr_decode_object_array.c new file mode 100644 index 0000000..82cc34f --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_object_array.c @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_object_array(void) +{ + CborEncoder data; + CborEncoder array; + CborEncoder sub_obj; + + test_cbor_len = 0; + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * a: [ { h:"str1"}, {h:"2str"}, {h:"str3"}] + */ + cbor_encode_text_stringz(&data, "a"); + + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + + cbor_encoder_create_map(&array, &sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&sub_obj, "h"); + cbor_encode_text_stringz(&sub_obj, "str1"); + cbor_encoder_close_container(&array, &sub_obj); + + cbor_encoder_create_map(&array, &sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&sub_obj, "h"); + cbor_encode_text_stringz(&sub_obj, "2str"); + cbor_encoder_close_container(&array, &sub_obj); + + cbor_encoder_create_map(&array, &sub_obj, CborIndefiniteLength); + cbor_encode_text_stringz(&sub_obj, "h"); + cbor_encode_text_stringz(&sub_obj, "str3"); + cbor_encoder_close_container(&array, &sub_obj); + + cbor_encoder_close_container(&data, &array); + + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * object array + */ +TEST_CASE(test_cborattr_decode_object_array) +{ + int rc; + struct h_obj { + char h_data[32]; + } arr_objs[5]; + int arr_cnt = 0; + struct cbor_attr_t sub_attr[] = { + [0] = { + .attribute = "h", + .type = CborAttrTextStringType, + CBORATTR_STRUCT_OBJECT(struct h_obj, h_data), + .len = sizeof(arr_objs[0].h_data) + }, + [1] = { + .attribute = NULL + } + }; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrArrayType, + CBORATTR_STRUCT_ARRAY(arr_objs, sub_attr, &arr_cnt), + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + + test_encode_object_array(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 3); + TEST_ASSERT(!strcmp(arr_objs[0].h_data, "str1")); + TEST_ASSERT(!strcmp(arr_objs[1].h_data, "2str")); + TEST_ASSERT(!strcmp(arr_objs[2].h_data, "str3")); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_partial.c b/cborattr/test/src/testcases/cborattr_decode_partial.c new file mode 100644 index 0000000..df0b8d4 --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_partial.c @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Simple decoding. Only have key for one of the key/value pairs. + */ +TEST_CASE(test_cborattr_decode_partial) +{ + const uint8_t *data; + int len; + int rc; + char test_str_b[4] = { '\0' }; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "b", + .type = CborAttrTextStringType, + .addr.string = test_str_b, + .len = sizeof(test_str_b), + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + + data = test_str1(&len); + rc = cbor_read_flat_attrs(data, len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!strcmp(test_str_b, "B")); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_simple.c b/cborattr/test/src/testcases/cborattr_decode_simple.c new file mode 100644 index 0000000..9e206e1 --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_simple.c @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_data(void) +{ + CborEncoder test_data; + uint8_t data[4] = { 0, 1, 2 }; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &test_data, CborIndefiniteLength); + /* + * a:22 + */ + cbor_encode_text_stringz(&test_data, "a"); + cbor_encode_uint(&test_data, 22); + + /* + * b:-13 + */ + cbor_encode_text_stringz(&test_data, "b"); + cbor_encode_int(&test_data, -13); + + /* + * c:0x000102 + */ + cbor_encode_text_stringz(&test_data, "c"); + cbor_encode_byte_string(&test_data, data, 3); + cbor_encoder_close_container(&test_encoder, &test_data); + + /* + * XXX add other data types to encode here. + */ + +} + +/* + * Simple decoding. + */ +TEST_CASE(test_cborattr_decode_simple) +{ + int rc; + uint64_t a_val = 0; + int64_t b_val = 0; + uint8_t c_data[4]; + size_t c_len; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrIntegerType, + .addr.uinteger = &a_val, + .nodefault = true + }, + [1] = { + .attribute = "b", + .type = CborAttrIntegerType, + .addr.integer = &b_val, + .nodefault = true + }, + [2] = { + .attribute = "c", + .type = CborAttrByteStringType, + .addr.bytestring.data = c_data, + .addr.bytestring.len = &c_len, + .len = sizeof(c_data) + }, + [3] = { + .attribute = NULL + } + }; + + test_encode_data(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(a_val == 22); + TEST_ASSERT(b_val == -13); + TEST_ASSERT(c_len == 3); + TEST_ASSERT(c_data[0] == 0 && c_data[1] == 1 && c_data[2] == 2); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_string_array.c b/cborattr/test/src/testcases/cborattr_decode_string_array.c new file mode 100644 index 0000000..d68e8df --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_string_array.c @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_string_array_one(void) +{ + CborEncoder data; + CborEncoder array; + + test_cbor_len = 0; + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * a: ["asdf"] + */ + cbor_encode_text_stringz(&data, "a"); + + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + cbor_encode_text_stringz(&array, "asdf"); + cbor_encoder_close_container(&data, &array); + + cbor_encoder_close_container(&test_encoder, &data); +} + +static void +test_encode_string_array_three(void) +{ + CborEncoder data; + CborEncoder array; + + test_cbor_len = 0; + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * a: ["asdf", "k", "blurb"] + */ + cbor_encode_text_stringz(&data, "a"); + + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + cbor_encode_text_stringz(&array, "asdf"); + cbor_encode_text_stringz(&array, "k"); + cbor_encode_text_stringz(&array, "blurb"); + cbor_encoder_close_container(&data, &array); + + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * string array + */ +TEST_CASE(test_cborattr_decode_string_array) +{ + int rc; + char *str_ptrs[5]; + char arr_data[256]; + int arr_cnt = 0; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "a", + .type = CborAttrArrayType, + .addr.array.element_type = CborAttrTextStringType, + .addr.array.arr.strings.ptrs = str_ptrs, + .addr.array.arr.strings.store = arr_data, + .addr.array.arr.strings.storelen = sizeof(arr_data), + .addr.array.count = &arr_cnt, + .addr.array.maxlen = sizeof(arr_data) / sizeof(arr_data[0]), + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + + test_encode_string_array_one(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 1); + TEST_ASSERT(!strcmp(str_ptrs[0], "asdf")); + + test_encode_string_array_three(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 3); + TEST_ASSERT(!strcmp(str_ptrs[0], "asdf")); + TEST_ASSERT(!strcmp(str_ptrs[1], "k")); + TEST_ASSERT(!strcmp(str_ptrs[2], "blurb")); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_substring_key.c b/cborattr/test/src/testcases/cborattr_decode_substring_key.c new file mode 100644 index 0000000..6eee774 --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_substring_key.c @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_substring_key(void) +{ + CborEncoder data; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + + /* + * { "a": "A", "aa": "AA", "aaa" : "AAA" } + */ + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + cbor_encode_text_stringz(&data, "a"); + cbor_encode_text_stringz(&data, "A"); + cbor_encode_text_stringz(&data, "aa"); + cbor_encode_text_stringz(&data, "AA"); + cbor_encode_text_stringz(&data, "aaa"); + cbor_encode_text_stringz(&data, "AAA"); + + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * substring key + */ +TEST_CASE(test_cborattr_decode_substring_key) +{ + int rc; + char test_str_1a[4] = { '\0' }; + char test_str_2a[4] = { '\0' }; + char test_str_3a[4] = { '\0' }; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = "aaa", + .type = CborAttrTextStringType, + .addr.string = test_str_3a, + .len = sizeof(test_str_3a), + .nodefault = true + }, + [1] = { + .attribute = "aa", + .type = CborAttrTextStringType, + .addr.string = test_str_2a, + .len = sizeof(test_str_2a), + .nodefault = true + }, + [2] = { + .attribute = "a", + .type = CborAttrTextStringType, + .addr.string = test_str_1a, + .len = sizeof(test_str_1a), + .nodefault = true + }, + [3] = { + .attribute = NULL + } + }; + + test_encode_substring_key(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!strcmp(test_str_1a, "A")); + TEST_ASSERT(!strcmp(test_str_2a, "AA")); + TEST_ASSERT(!strcmp(test_str_3a, "AAA")); +} diff --git a/cborattr/test/src/testcases/cborattr_decode_unnamed_array.c b/cborattr/test/src/testcases/cborattr_decode_unnamed_array.c new file mode 100644 index 0000000..c4446b8 --- /dev/null +++ b/cborattr/test/src/testcases/cborattr_decode_unnamed_array.c @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "test_cborattr.h" + +/* + * Where we collect cbor data. + */ +static uint8_t test_cbor_buf[1024]; +static int test_cbor_len; + +/* + * CBOR encoder data structures. + */ +static int test_cbor_wr(struct cbor_encoder_writer *, const char *, int); +static CborEncoder test_encoder; +static struct cbor_encoder_writer test_writer = { + .write = test_cbor_wr +}; + +static int +test_cbor_wr(struct cbor_encoder_writer *cew, const char *data, int len) +{ + memcpy(test_cbor_buf + test_cbor_len, data, len); + test_cbor_len += len; + + assert(test_cbor_len < sizeof(test_cbor_buf)); + return 0; +} + +static void +test_encode_unnamed_array(void) +{ + CborEncoder data; + CborEncoder array; + + cbor_encoder_init(&test_encoder, &test_writer, 0); + + cbor_encoder_create_map(&test_encoder, &data, CborIndefiniteLength); + + /* + * [1,2,33] + */ + cbor_encoder_create_array(&data, &array, CborIndefiniteLength); + cbor_encode_int(&array, 1); + cbor_encode_int(&array, 2); + cbor_encode_int(&array, 33); + cbor_encoder_close_container(&data, &array); + + cbor_encoder_close_container(&test_encoder, &data); +} + +/* + * integer array + */ +TEST_CASE(test_cborattr_decode_unnamed_array) +{ + int rc; + int64_t arr_data[5]; + int arr_cnt = 0; + struct cbor_attr_t test_attrs[] = { + [0] = { + .attribute = CBORATTR_ATTR_UNNAMED, + .type = CborAttrArrayType, + .addr.array.element_type = CborAttrIntegerType, + .addr.array.arr.integers.store = arr_data, + .addr.array.count = &arr_cnt, + .addr.array.maxlen = sizeof(arr_data) / sizeof(arr_data[0]), + .nodefault = true + }, + [1] = { + .attribute = NULL + } + }; + + test_encode_unnamed_array(); + + rc = cbor_read_flat_attrs(test_cbor_buf, test_cbor_len, test_attrs); + TEST_ASSERT(rc == 0); + TEST_ASSERT(arr_cnt == 3); + TEST_ASSERT(arr_data[0] == 1); + TEST_ASSERT(arr_data[1] == 2); + TEST_ASSERT(arr_data[2] == 33); +} -- To stop receiving notification emails like this one, please contact "commits@mynewt.apache.org" <commits@mynewt.apache.org>.