You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2018/01/09 02:52:47 UTC

[mynewt-mcumgr] branch master updated (22dcc8c -> dd91555)

This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-mcumgr.git.


    from 22dcc8c  Add stubs for unimplemented OS-specific functions.
     new f3295f3  Add cborattr library to mcumgr.
     new dd91555  Account for mcumgr's move to zephyr's ext/ dir.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CMakeLists.txt                                     |  28 ++
 {cmd/os_mgmt => cborattr}/Makefile                 |   4 +-
 cborattr/include/cborattr/cborattr.h               | 153 ++++++++
 {mgmt/port/mynewt => cborattr}/pkg.yml             |   8 +-
 cborattr/src/cborattr.c                            | 423 +++++++++++++++++++++
 {mgmt => cborattr}/syscfg.yml                      |  10 +-
 {mgmt => cborattr/test}/pkg.yml                    |  16 +-
 .../test/src/test_cborattr.c                       |  36 +-
 .../os_mgmt.h => cborattr/test/src/test_cborattr.h |  55 ++-
 .../test/src/test_cborattr_utils.c                 |  30 +-
 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   |  58 ++-
 .../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 +++++
 smp/port/zephyr/src/zephyr_smp.c                   |   2 +-
 22 files changed, 1948 insertions(+), 103 deletions(-)
 create mode 100644 CMakeLists.txt
 copy {cmd/os_mgmt => cborattr}/Makefile (50%)
 create mode 100644 cborattr/include/cborattr/cborattr.h
 copy {mgmt/port/mynewt => cborattr}/pkg.yml (86%)
 create mode 100644 cborattr/src/cborattr.c
 copy {mgmt => cborattr}/syscfg.yml (83%)
 copy {mgmt => cborattr/test}/pkg.yml (81%)
 copy mgmt/port/mynewt/include/mynewt_mgmt/mynewt_mgmt.h => cborattr/test/src/test_cborattr.c (55%)
 copy cmd/os_mgmt/include/os_mgmt/os_mgmt.h => cborattr/test/src/test_cborattr.h (52%)
 copy mgmt/port/mynewt/include/mynewt_mgmt/mynewt_mgmt.h => cborattr/test/src/test_cborattr_utils.c (69%)
 create mode 100644 cborattr/test/src/testcases/cborattr_decode1.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_bool_array.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_int_array.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_obj_array.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_object.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_object_array.c
 copy smp/include/smp/smp.h => cborattr/test/src/testcases/cborattr_decode_partial.c (54%)
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_simple.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_string_array.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_substring_key.c
 create mode 100644 cborattr/test/src/testcases/cborattr_decode_unnamed_array.c

-- 
To stop receiving notification emails like this one, please contact
['"commits@mynewt.apache.org" <co...@mynewt.apache.org>'].

[mynewt-mcumgr] 01/02: Add cborattr library to mcumgr.

Posted by cc...@apache.org.
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 f3295f3f93fd69500e2c8ed3cc502cff45cf6345
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Jan 8 14:04:49 2018 -0800

    Add cborattr library to mcumgr.
---
 cborattr/Makefile                                  |  17 +
 cborattr/include/cborattr/cborattr.h               | 153 ++++++++
 cborattr/pkg.yml                                   |  29 ++
 cborattr/src/cborattr.c                            | 423 +++++++++++++++++++++
 cborattr/syscfg.yml                                |  24 ++
 cborattr/test/pkg.yml                              |  31 ++
 cborattr/test/src/test_cborattr.c                  |  49 +++
 cborattr/test/src/test_cborattr.h                  |  58 +++
 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, 2094 insertions(+)

diff --git a/cborattr/Makefile b/cborattr/Makefile
new file mode 100644
index 0000000..a21a23c
--- /dev/null
+++ b/cborattr/Makefile
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2017 Intel Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+PREFIX ?= .
+OBJ_DIR ?= $(PREFIX)/obj
+LIB_DIR ?= $(PREFIX)/lib
+
+all:
+	mkdir -p $(OBJ_DIR) $(LIB_DIR)
+	$(CC) -c $(CFLAGS) -Iinclude -I$(CURDIR)/../tinycbor/src src/cborattr.c -o $(OBJ_DIR)/cborattr.o
+	$(AR) -rcs $(LIB_DIR)/libcborattr.a $(OBJ_DIR)/cborattr.o
+
+clean:
+	rm -rf $(OBJ_DIR) $(LIB_DIR)
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..0f62824
--- /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: encoding/cborattr 
+pkg.description: CBOR encoding/decoding library 
+pkg.author: "Apache Mynewt <de...@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..941a985
--- /dev/null
+++ b/cborattr/test/pkg.yml
@@ -0,0 +1,31 @@
+# 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: encoding/cborattr/test
+pkg.type: unittest
+pkg.description: "CBOR attr unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - encoding/tinycbor
+    - encoding/cborattr
+    - test/testutil
+
+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..2ffe515
--- /dev/null
+++ b/cborattr/test/src/test_cborattr.h
@@ -0,0 +1,58 @@
+/*
+ * 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" <co...@mynewt.apache.org>.

[mynewt-mcumgr] 02/02: Account for mcumgr's move to zephyr's ext/ dir.

Posted by cc...@apache.org.
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 dd915552d4e0f57846f2b8991c9a7287ee085d5a
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Jan 8 14:05:19 2018 -0800

    Account for mcumgr's move to zephyr's ext/ dir.
---
 CMakeLists.txt                   | 28 ++++++++++++++++++++++++++++
 smp/port/zephyr/src/zephyr_smp.c |  2 +-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..6c1359d
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,28 @@
+add_library(MCUMGR INTERFACE)
+
+zephyr_include_directories(MCUMGR INTERFACE 
+    cborattr/include
+    cmd/img_mgmt/include
+    cmd/os_mgmt/include
+    mgmt/include
+    smp/include
+    smp/port/zephyr/include
+)
+
+zephyr_library()
+zephyr_library_sources(
+    cborattr/src/cborattr.c
+    cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
+    cmd/img_mgmt/src/img_mgmt.c
+    cmd/img_mgmt/src/img_mgmt_state.c
+    cmd/img_mgmt/src/img_mgmt_util.c
+    cmd/img_mgmt/src/stubs.c
+    cmd/os_mgmt/src/os_mgmt.c
+    cmd/os_mgmt/src/stubs.c
+    cmd/os_mgmt/port/zephyr/src/zephyr_os_mgmt.c
+    mgmt/src/mgmt.c
+    smp/port/zephyr/src/zephyr_smp.c
+    smp/src/smp.c
+)
+zephyr_library_link_libraries(MCUMGR)
+target_link_libraries(MCUMGR INTERFACE zephyr_interface)
diff --git a/smp/port/zephyr/src/zephyr_smp.c b/smp/port/zephyr/src/zephyr_smp.c
index 823a67c..5daf110 100644
--- a/smp/port/zephyr/src/zephyr_smp.c
+++ b/smp/port/zephyr/src/zephyr_smp.c
@@ -1,7 +1,7 @@
 #include <zephyr.h>
 #include "mgmt/mgmt.h"
 #include "smp/smp.h"
-#include "znp/znp.h"
+#include "mgmt/znp.h"
 #include "zephyr_smp/zephyr_smp.h"
 
 static mgmt_alloc_rsp_fn zephyr_smp_alloc_rsp;

-- 
To stop receiving notification emails like this one, please contact
"commits@mynewt.apache.org" <co...@mynewt.apache.org>.