ocpayload: Adding OCByteString support in representation
authorPhilippe Coval <philippe.coval@osg.samsung.com>
Fri, 1 Jul 2016 20:36:36 +0000 (22:36 +0200)
committerUze Choi <uzchoi@samsung.com>
Fri, 30 Sep 2016 07:34:26 +0000 (07:34 +0000)
Add Bytestring handling in OCRepPayloadClone()
 along arrays/vectors of them.

Also added in native java (JNI) part for android
 inspired by existing code, note for later,
 original code might be double checked for potential MLK
 regarding local references to allocated objects within loops.
 Maybe those unref are not mandatory
 as they "are freed automatically after the native method returns."
 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

Improved tests, it is assumed that contents of OCByteString
 are not duplicated when not wanted,
 plus style cleanup on surrounding code.

Note of my understanding of this design mixing C++ and C paradigms :

 - As OCByteString is a C structure there is no destructor
 - If assigned (no deep copy) into Payload class
   bytes will be freed by Payload's destructor as it "owns" it.
 - If contents are deep copied anywhere else
   then bytes should be also freed manually
   (in other classes' destructor ? like Payload).

Bug: https://jira.iotivity.org/browse/IOT-983
Change-Id: Icfa0657df9b332b4d11b737731636c8fb2a80001
Credits-to: youngman <yman.jung@samsung.com>
Origin: https://gerrit.iotivity.org/gerrit/#/c/8931/
Signed-off-by: Philippe Coval <philippe.coval@osg.samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/8931
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Dave Thaler <dthaler@microsoft.com>
(cherry picked from commit f2059ea75cb7f8966f59132fb05962b2f52e352b)
Reviewed-on: https://gerrit.iotivity.org/gerrit/12611
Reviewed-by: Uze Choi <uzchoi@samsung.com>
12 files changed:
android/android_api/base/jni/JniOcRepresentation.h
android/android_api/base/jni/JniOcStack.cpp
android/android_api/base/jni/JniOcStack.h
resource/csdk/octbstack_product.def
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocpayloadconvert.c
resource/include/AttributeValue.h
resource/include/OCRepresentation.h
resource/src/OCRepresentation.cpp
resource/unittests/OCRepresentationEncodingTest.cpp
resource/unittests/OCRepresentationTest.cpp

index e9acd35..dc85747 100644 (file)
@@ -154,6 +154,103 @@ struct JObjectConverter : boost::static_visitor < jobject >
         }
         return strArr;
     }
+    // OCByteString and arrays:
+    jobject operator()(const OCByteString &val) const
+    {
+        jbyteArray jByteArray = env->NewByteArray(val.len);
+        if (!jByteArray)
+        {
+            return nullptr;
+        }
+        env->SetByteArrayRegion(jByteArray, 0, val.len, reinterpret_cast<const jbyte *>(val.bytes));
+        if (env->ExceptionCheck())
+        {
+            env->DeleteLocalRef(jByteArray);
+            return nullptr;
+        }
+        return jByteArray;
+    }
+    jobject operator()(const std::vector<OCByteString> &val) const
+    {
+        jsize lenOuter = static_cast<jsize>(val.size());
+        jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_byte1DArray, nullptr);
+        if (!jOuterArr)
+        {
+            return nullptr;
+        }
+        for (jsize i = 0; i < lenOuter; ++i)
+        {
+            jbyteArray jByteArray = (jbyteArray) operator()(val[i]);
+            if (!jByteArray)
+            {
+                env->DeleteLocalRef(jOuterArr);
+                return nullptr;
+            }
+            env->SetObjectArrayElement(jOuterArr, i, static_cast<jobject>(jByteArray));
+            if (env->ExceptionCheck())
+            {
+                env->DeleteLocalRef(jByteArray);
+                env->DeleteLocalRef(jOuterArr);
+                return nullptr;
+            }
+            env->DeleteLocalRef(jByteArray);
+        }
+        return jOuterArr;
+    }
+    jobject operator()(const std::vector<std::vector<OCByteString>> &val) const
+    {
+        jsize lenOuter = static_cast<jsize>(val.size());
+        jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_byte2DArray, nullptr);
+        if (!jOuterArr)
+        {
+            return nullptr;
+        }
+        for (jsize i = 0; i < lenOuter; ++i)
+        {
+            jobjectArray jMiddleArr = (jobjectArray) operator()(val[i]);
+            if (!jMiddleArr)
+            {
+                env->DeleteLocalRef(jOuterArr);
+                return nullptr;
+            }
+            env->SetObjectArrayElement(jOuterArr, i, jMiddleArr);
+            if (env->ExceptionCheck())
+            {
+                env->DeleteLocalRef(jMiddleArr);
+                env->DeleteLocalRef(jOuterArr);
+                return nullptr;
+            }
+            env->DeleteLocalRef(jMiddleArr);
+        }
+        return jOuterArr;
+     }
+     jobject operator()(const std::vector<std::vector<std::vector<OCByteString>>> &val) const
+     {
+        jsize lenOuter = static_cast<jsize>(val.size());
+        jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_byte3DArray, nullptr);
+        if (!jOuterArr)
+        {
+            return nullptr;
+        }
+        for (jsize i = 0; i < lenOuter; ++i)
+        {
+            jobjectArray jMiddleArr = (jobjectArray) operator()(val[i]);
+            if (!jMiddleArr)
+            {
+                env->DeleteLocalRef(jOuterArr);
+                return nullptr;
+            }
+            env->SetObjectArrayElement(jOuterArr, i, jMiddleArr);
+            if (env->ExceptionCheck())
+            {
+                env->DeleteLocalRef(jMiddleArr);
+                env->DeleteLocalRef(jOuterArr);
+                return nullptr;
+            }
+            env->DeleteLocalRef(jMiddleArr);
+        }
+        return jOuterArr;
+    }
     jobject operator()(const std::vector<OC::OCRepresentation>& val) const
     {
         jsize len = static_cast<jsize>(val.size());
index c140551..f87cd1a 100644 (file)
@@ -39,6 +39,9 @@
 
 JavaVM* g_jvm = nullptr;
 
+jclass g_cls_byte1DArray = nullptr;
+jclass g_cls_byte2DArray = nullptr;
+jclass g_cls_byte3DArray = nullptr;
 jclass g_cls_Integer = nullptr;
 jclass g_cls_int1DArray = nullptr;
 jclass g_cls_int2DArray = nullptr;
@@ -201,6 +204,22 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
 
     jclass clazz = nullptr;
 
+    //byte
+    clazz = env->FindClass("[B");
+    VERIFY_VARIABLE_NULL(clazz);
+    g_cls_byte1DArray = (jclass)env->NewGlobalRef(clazz);
+    env->DeleteLocalRef(clazz);
+
+    clazz = env->FindClass("[[B");
+    VERIFY_VARIABLE_NULL(clazz);
+    g_cls_byte2DArray = (jclass)env->NewGlobalRef(clazz);
+    env->DeleteLocalRef(clazz);
+
+    clazz = env->FindClass("[[[B");
+    VERIFY_VARIABLE_NULL(clazz);
+    g_cls_byte3DArray = (jclass)env->NewGlobalRef(clazz);
+    env->DeleteLocalRef(clazz);
+
     //Integer
     clazz = env->FindClass("java/lang/Integer");
     VERIFY_VARIABLE_NULL(clazz);
@@ -658,6 +677,9 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
         env->DeleteGlobalRef(g_cls_OcSecureResource);
         env->DeleteGlobalRef(g_cls_OcProvisionResult);
         env->DeleteGlobalRef(g_cls_OcDirectPairDevice);
+        env->DeleteGlobalRef(g_cls_byte1DArray);
+        env->DeleteGlobalRef(g_cls_byte2DArray);
+        env->DeleteGlobalRef(g_cls_byte3DArray);
 #ifdef WITH_CLOUD
         env->DeleteGlobalRef(g_cls_OcAccountManager);
 #endif
index 51f856e..db5ea1e 100644 (file)
@@ -48,6 +48,9 @@ void throwOcException(JNIEnv* env, jobject ex);
 
 extern JavaVM* g_jvm;
 
+extern jclass g_cls_byte1DArray;
+extern jclass g_cls_byte2DArray;
+extern jclass g_cls_byte3DArray;
 extern jclass g_cls_Integer;
 extern jclass g_cls_int1DArray;
 extern jclass g_cls_int2DArray;
index b3c92c1..781eb2f 100644 (file)
@@ -74,6 +74,7 @@ OCRepPayloadClone
 OCRepPayloadCreate
 OCRepPayloadDestroy
 OCRepPayloadGetByteStringArray
+OCRepPayloadSetByteStringArrayAsOwner
 OCRepPayloadGetPropBool
 OCRepPayloadGetPropByteString
 OCRepPayloadGetPropInt
index 95ff3cb..7a7c4a0 100644 (file)
@@ -284,6 +284,14 @@ OCStringLL* OCCreateOCStringLL(const char* text);
  **/
 char* OCCreateString(const OCStringLL* ll);
 
+/**
+ * This function copies contents (and allocates if necessary)
+ * @param dest existing bytestring (or null to allocate here)
+ * @param source existing bytestring
+ * @return true of success false on any errors
+ **/
+bool OCByteStringCopy(OCByteString *dest, const OCByteString *source);
+
 #ifdef __cplusplus
 }
 #endif
index 2afac6f..2b17fdd 100644 (file)
@@ -175,6 +175,15 @@ static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue*
                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
             }
             break;
+        case OCREP_PROP_BYTE_STRING:
+            dest->arr.ocByteStrArray = (OCByteString*)OICMalloc(dimTotal * sizeof(OCByteString));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.ocByteStrArray, "Failed allocating memory");
+            for (size_t i = 0; i < dimTotal; ++i)
+            {
+                OCByteStringCopy(&dest->arr.ocByteStrArray[i], &source->arr.ocByteStrArray[i]);
+                VERIFY_PARAM_NON_NULL(TAG, dest->arr.ocByteStrArray[i].bytes, "Failed allocating memory");
+            }
+            break;
         default:
             OIC_LOG(ERROR, TAG, "CopyPropertyValueArray invalid type");
             break;
@@ -247,16 +256,19 @@ static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val)
                 OICFree(val->arr.iArray);
                 break;
             case OCREP_PROP_STRING:
-                for(size_t i = 0; i< dimTotal; ++i)
+                for(size_t i = 0; i < dimTotal; ++i)
                 {
                     OICFree(val->arr.strArray[i]);
                 }
                 OICFree(val->arr.strArray);
                 break;
             case OCREP_PROP_BYTE_STRING:
-                for (size_t i = 0; i< dimTotal; ++i)
+                for (size_t i = 0; i < dimTotal; ++i)
                 {
-                    OICFree(val->arr.ocByteStrArray[i].bytes);
+                    if (val->arr.ocByteStrArray[i].bytes)
+                    {
+                        OICFree(val->arr.ocByteStrArray[i].bytes);
+                    }
                 }
                 OICFree(val->arr.ocByteStrArray);
                 break;
@@ -521,6 +533,7 @@ static bool OCRepPayloadSetProp(OCRepPayload* payload, const char* name,
                return val->str != NULL;
         case OCREP_PROP_BYTE_STRING:
                val->ocByteStr = *(OCByteString*)value;
+               return val->ocByteStr.bytes != NULL;
                break;
         case OCREP_PROP_NULL:
                return val != NULL;
@@ -620,18 +633,13 @@ bool OCRepPayloadSetPropByteString(OCRepPayload* payload, const char* name, OCBy
         return false;
     }
 
-    OCByteString ocByteStr = {
-                    .bytes = (uint8_t*)OICMalloc(value.len * sizeof(uint8_t)),
-                    .len = value.len };
+    OCByteString ocByteStr = {NULL, 0};
+    bool b = OCByteStringCopy(&ocByteStr, &value);
 
-    if (!ocByteStr.bytes)
+    if (b)
     {
-        return false;
+        b = OCRepPayloadSetPropByteStringAsOwner(payload, name, &ocByteStr);
     }
-    memcpy(ocByteStr.bytes, value.bytes, ocByteStr.len);
-
-    bool b = OCRepPayloadSetPropByteStringAsOwner(payload, name, &ocByteStr);
-
     if (!b)
     {
         OICFree(ocByteStr.bytes);
@@ -1453,16 +1461,19 @@ OCStringLL* OCCreateOCStringLL(const char* text)
     for (head = backup; ; head = NULL)
     {
         token = (char *) strtok_r(head, delim, &tail);
-        if (!token) break;
+        if (!token)
+        {
+            break;
+        }
         iter = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL));
         VERIFY_PARAM_NON_NULL(TAG, iter, "Failed allocating memory");
         if (!result)
         {
-             result = iter;
+            result = iter;
         }
         else
         {
-             prev->next = iter;
+            prev->next = iter;
         }
         iter->value = OICStrdup(token);
         VERIFY_PARAM_NON_NULL(TAG, iter->value, "Failed allocating memory");
@@ -1495,7 +1506,7 @@ char* OCCreateString(const OCStringLL* ll)
     {
         len += strlen(it->value) + 1;
     }
-    len--; // renove trailing separator (just added above)
+    len--; // remove trailing separator (just added above)
     str = (char*) malloc(len + 1);
     if (!str)
     {
@@ -1528,6 +1539,36 @@ char* OCCreateString(const OCStringLL* ll)
     return str;
 }
 
+bool OCByteStringCopy(OCByteString* dest, const OCByteString* source)
+{
+    VERIFY_PARAM_NON_NULL(TAG, source, "Bad input");
+
+    if (!dest)
+    {
+        dest = (OCByteString *)OICMalloc(sizeof(OCByteString));
+        VERIFY_PARAM_NON_NULL(TAG, dest, "Failed allocating memory");
+    }
+    if (dest->bytes)
+    {
+        OICFree(dest->bytes);
+    }
+    dest->bytes = (uint8_t*)OICMalloc(source->len * sizeof(uint8_t));
+    VERIFY_PARAM_NON_NULL(TAG, dest->bytes, "Failed allocating memory");
+    memcpy(dest->bytes, source->bytes, source->len * sizeof(uint8_t));
+    dest->len = source->len;
+    return true;
+
+exit:
+    if (dest)
+    {
+        dest->len = 0;
+        OICFree(dest->bytes);
+        dest->bytes = NULL;
+    }
+
+    return false;
+}
+
 OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
 {
     if (!payload)
index e3dd927..cf5442f 100644 (file)
@@ -590,7 +590,7 @@ static int64_t OCConvertArrayItem(CborEncoder *array, const OCRepPayloadValueArr
             }
             break;
         case OCREP_PROP_BYTE_STRING:
-            if (!valArray->strArray[index])
+            if (!valArray->ocByteStrArray[index].len)
             {
                 err |= cbor_encode_null(array);
             }
index 5b9ca83..3315356 100644 (file)
@@ -54,6 +54,7 @@ namespace OC
         bool,
         std::string,
         OC::OCRepresentation,
+        OCByteString,
 
         // Sequences:
         std::vector<int>,
@@ -61,6 +62,7 @@ namespace OC
         std::vector<bool>,
         std::vector<std::string>,
         std::vector<OC::OCRepresentation>,
+        std::vector<OCByteString>,
 
         // Nested sequences:
         std::vector<std::vector<int>>,
@@ -78,6 +80,9 @@ namespace OC
         std::vector<std::vector<OC::OCRepresentation>>,
         std::vector<std::vector<std::vector<OC::OCRepresentation>>>,
 
+        std::vector<std::vector<OCByteString>>,
+        std::vector<std::vector<std::vector<OCByteString>>>,
+
         // used for binary data type
         std::vector<uint8_t>
     > AttributeValue;
@@ -91,7 +96,8 @@ namespace OC
         String,
         OCRepresentation,
         Vector,
-        Binary
+        Binary,
+        OCByteString
     };
 
     template<typename T>
@@ -134,6 +140,12 @@ namespace OC
     };
 
     template<>
+    struct AttributeTypeConvert<OCByteString>
+    {
+       BOOST_STATIC_CONSTEXPR AttributeType type = AttributeType::OCByteString;
+    };
+
+    template<>
     struct AttributeTypeConvert<std::vector<uint8_t>>
     {
         BOOST_STATIC_CONSTEXPR AttributeType type = AttributeType::Binary;
index c07974a..1e025eb 100644 (file)
@@ -333,6 +333,7 @@ namespace OC
                      std::is_same<T, bool>::value ||
                      std::is_same<T, std::string>::value ||
                      std::is_same<T, OCRepresentation>::value ||
+                     std::is_same<T, OCByteString>::value ||
                      std::is_same<T, std::vector<int>>::value ||
                      std::is_same<T, std::vector<std::vector<int>>>::value ||
                      std::is_same<T, std::vector<std::vector<std::vector<int>>>>::value ||
@@ -347,7 +348,10 @@ namespace OC
                      std::is_same<T, std::vector<std::vector<std::vector<std::string>>>>::value ||
                      std::is_same<T, std::vector<OCRepresentation>>::value ||
                      std::is_same<T, std::vector<std::vector<OCRepresentation>>>::value ||
-                     std::is_same<T, std::vector<std::vector<std::vector<OCRepresentation>>>>::value
+                     std::is_same<T, std::vector<std::vector<std::vector<OCRepresentation>>>>::value ||
+                     std::is_same<T, std::vector<OCByteString>>::value ||
+                     std::is_same<T, std::vector<std::vector<OCByteString>>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::vector<OCByteString>>>>::value
                      , int>::type = 0// enable_if
                     >
 #else
index 476d72b..8fe41d5 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <boost/lexical_cast.hpp>
 #include <algorithm>
+#include <iomanip>
 #include "ocpayload.h"
 #include "ocrandom.h"
 #include "oic_malloc.h"
@@ -369,6 +370,24 @@ namespace OC
     }
 
     template<>
+    void get_payload_array::copy_to_array(OCByteString item, void *array, size_t pos)
+    {
+        ((OCByteString *)array)[pos] = item;
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(OCByteString &item, void *array, size_t pos)
+    {
+        ((OCByteString *)array)[pos] = item;
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(const OCByteString &item, void *array, size_t pos)
+    {
+        ((OCByteString *)array)[pos] = item;
+    }
+
+    template<>
     void get_payload_array::copy_to_array(OC::OCRepresentation item, void* array, size_t pos)
     {
         ((OCRepPayload**)array)[pos] = item.getPayload();
@@ -403,6 +422,10 @@ namespace OC
                         (char**)vis.array,
                         vis.dimensions);
                 break;
+            case AttributeType::OCByteString:
+                OCRepPayloadSetByteStringArrayAsOwner(payload, item.attrname().c_str(),
+                                                      (OCByteString *)vis.array, vis.dimensions);
+                break;
             case AttributeType::OCRepresentation:
                 OCRepPayloadSetPropObjectArrayAsOwner(payload, item.attrname().c_str(),
                         (OCRepPayload**)vis.array, vis.dimensions);
@@ -454,6 +477,9 @@ namespace OC
                     OCRepPayloadSetPropString(root, val.attrname().c_str(),
                             static_cast<std::string>(val).c_str());
                     break;
+                case AttributeType::OCByteString:
+                    OCRepPayloadSetPropByteString(root, val.attrname().c_str(), val.getValue<OCByteString>());
+                    break;
                 case AttributeType::OCRepresentation:
                     OCRepPayloadSetPropObjectAsOwner(root, val.attrname().c_str(),
                             static_cast<OCRepresentation>(val).getPayload());
@@ -529,6 +555,19 @@ namespace OC
             return std::string{};
         }
     }
+
+    template<>
+    OCByteString OCRepresentation::payload_array_helper_copy<OCByteString>(
+        size_t index, const OCRepPayloadValue *pl)
+    {
+        OCByteString result {NULL, 0};
+        if (pl->arr.ocByteStrArray[index].len)
+        {
+            result = (pl->arr.ocByteStrArray[index]);
+        }
+        return result;
+    }
+
     template<>
     OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
             size_t index, const OCRepPayloadValue* pl)
@@ -612,6 +651,9 @@ namespace OC
             case OCREP_PROP_STRING:
                 payload_array_helper<std::string>(pl, calcArrayDepth(pl->arr.dimensions));
                 break;
+            case OCREP_PROP_BYTE_STRING:
+                payload_array_helper<OCByteString>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
             case OCREP_PROP_OBJECT:
                 payload_array_helper<OCRepresentation>(pl, calcArrayDepth(pl->arr.dimensions));
                 break;
@@ -923,6 +965,9 @@ namespace OC
             case AttributeType::String:
                 os << "String";
                 break;
+            case AttributeType::OCByteString:
+                os << "OCByteString";
+                break;
             case AttributeType::OCRepresentation:
                 os << "OCRepresentation";
                 break;
@@ -1216,6 +1261,24 @@ namespace OC
         str = "(null)";
     }
 
+    template <>
+    void to_string_visitor::operator()(std::vector<uint8_t> const &item)
+    {
+        std::ostringstream stream;
+        for (size_t i = 0; i < item.size(); i++ )
+        {
+            stream << "\\x" << std::hex << (int) item[i];
+        }
+        str = stream.str();
+    }
+
+    template<>
+    void to_string_visitor::operator()(OCByteString const &item)
+    {
+        std::vector<uint8_t> v(item.bytes, item.bytes + item.len);
+        operator()(v);
+    }
+
     template<>
     void to_string_visitor::operator()(OCRepresentation const& /*item*/)
     {
index 5e177be..54fc760 100644 (file)
 #include <oic_string.h>
 #include "payload_logging.h"
 
+bool operator==(const OCByteString& lhs, const OCByteString& rhs)
+{
+    bool result = (lhs.len == rhs.len);
+    if (result)
+    {
+        result = (memcmp(lhs.bytes, rhs.bytes, lhs.len) == 0);
+    }
+    return result;
+}
+
 namespace OC
 {
     bool operator==(const OC::NullType&, const OC::NullType&)
@@ -249,6 +259,13 @@ namespace OCRepresentationEncodingTest
         startRep.setValue("DoubleAttr", 3.333);
         startRep.setValue("BoolAttr", true);
         startRep.setValue("StringAttr", std::string("String attr"));
+
+        uint8_t binval[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
+                            0x9, 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
+                           };
+        OCByteString byteString = {binval, sizeof(binval)};
+        startRep.setValue("ByteStringAttr", byteString);
+
         OC::MessageContainer mc1;
         mc1.addRepresentation(startRep);
 
@@ -274,6 +291,8 @@ namespace OCRepresentationEncodingTest
         EXPECT_EQ(3.333, r.getValue<double>("DoubleAttr"));
         EXPECT_EQ(true, r.getValue<bool>("BoolAttr"));
         EXPECT_STREQ("String attr", r.getValue<std::string>("StringAttr").c_str());
+        const char *expectedByteString = "\\x1\\x2\\x3\\x4\\x5\\x6\\x7\\x8\\x9\\x0\\xa\\xb\\xc\\xd\\xe\\xf";
+        EXPECT_STREQ(expectedByteString, r.getValueToString("ByteStringAttr").c_str());
 
         OCPayloadDestroy(cparsed);
     }
@@ -331,8 +350,8 @@ namespace OCRepresentationEncodingTest
 
         uint8_t* cborData;
         size_t cborSize;
-        OCPayload* cparsed;
         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+        OCPayload* cparsed;
         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
                     cborData, cborSize));
         OCPayloadDestroy((OCPayload*)cstart);
@@ -375,11 +394,23 @@ namespace OCRepresentationEncodingTest
         std::vector<std::string> strarr {"item1", "item2", "item3", "item4"};
         std::vector<OC::OCRepresentation> objarr {subRep1, subRep2, subRep3};
 
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
+        OCByteString byteStringRef1 {binval1, sizeof(binval1)};
+        OCByteString byteString1 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString1, &byteStringRef1));
+        uint8_t binval2[] = {0x9, 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
+        OCByteString byteStringRef2 {binval2, sizeof(binval2)};
+        OCByteString byteString2 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString2, &byteStringRef2));
+        std::vector<OCByteString> bytestrarrRef {byteStringRef1, byteStringRef2 };
+        std::vector<OCByteString> bytestrarr {byteString1, byteString2 };
+
         startRep["iarr"] = iarr;
         startRep["darr"] = darr;
         startRep["barr"] = barr;
         startRep["strarr"] = strarr;
         startRep["objarr"] = objarr;
+        startRep["bytestrarr"] = bytestrarr;
 
         // Encode/decode
         OC::MessageContainer mc1;
@@ -391,16 +422,16 @@ namespace OCRepresentationEncodingTest
         uint8_t* cborData;
         size_t cborSize;
         OCPayload* cparsed;
-        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload *)cstart, &cborData, &cborSize));
         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
-                    cborData, cborSize));
-        OCPayloadDestroy((OCPayload*)cstart);
+                                              cborData, cborSize));
+        OCPayloadDestroy((OCPayload *)cstart);
         OICFree(cborData);
 
         OC::MessageContainer mc2;
         mc2.setPayload(cparsed);
         EXPECT_EQ(1u, mc2.representations().size());
-        const OC::OCRepresentationr = mc2.representations()[0];
+        const OC::OCRepresentation &r = mc2.representations()[0];
 
         // Test
         std::vector<int> iarr2 = r["iarr"];
@@ -408,12 +439,15 @@ namespace OCRepresentationEncodingTest
         std::vector<bool> barr2 = r["barr"];
         std::vector<std::string> strarr2 = r["strarr"];
         std::vector<OC::OCRepresentation> objarr2 = r["objarr"];
+        std::vector<OCByteString> bytestrarr2 = r["bytestrarr"];
 
         EXPECT_EQ(iarr, iarr2);
         EXPECT_EQ(darr, darr2);
         EXPECT_EQ(barr, barr2);
         EXPECT_EQ(strarr, strarr2);
         EXPECT_EQ(objarr, objarr2);
+
+        EXPECT_EQ(bytestrarrRef, bytestrarr2);
         OCPayloadDestroy(cparsed);
     }
 
@@ -438,32 +472,58 @@ namespace OCRepresentationEncodingTest
         std::vector<std::vector<OC::OCRepresentation>> objarr
         {{subRep1, subRep2, subRep3}, {subRep3, subRep2, subRep1}};
 
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4};
+        OCByteString byteStringRef1 {binval1, sizeof(binval1) };
+        OCByteString byteString1 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString1, &byteStringRef1));
+        uint8_t binval2[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString byteStringRef2 {binval2, sizeof(binval2) };
+        OCByteString byteString2 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString2, &byteStringRef2));
+        uint8_t binval3[] = {0x9, 0x0, 0xA, 0xB};
+        OCByteString byteStringRef3 {binval3, sizeof(binval3) };
+        OCByteString byteString3 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString3, &byteStringRef3));
+        uint8_t binval4[] = {0xC, 0xD, 0xE, 0xF};
+        OCByteString byteStringRef4 {binval4, sizeof(binval4) };
+        OCByteString byteString4 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString4, &byteStringRef4));
+        std::vector<std::vector<OCByteString>> bytestrarrRef
+        {
+            {byteStringRef1, byteStringRef2}, {byteStringRef3, byteStringRef4}
+        };
+        std::vector<std::vector<OCByteString>> bytestrarr
+        {
+            {byteString1, byteString2}, {byteString3, byteString4}
+        };
+
         startRep["iarr"] = iarr;
         startRep["darr"] = darr;
         startRep["barr"] = barr;
         startRep["strarr"] = strarr;
         startRep["objarr"] = objarr;
+        startRep["bytestrarr"] = bytestrarr;
 
         // Encode/decode
         OC::MessageContainer mc1;
         mc1.addRepresentation(startRep);
 
-        OCRepPayloadcstart = mc1.getPayload();
+        OCRepPayload *cstart = mc1.getPayload();
         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
 
         uint8_t* cborData;
         size_t cborSize;
         OCPayload* cparsed;
-        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload *)cstart, &cborData, &cborSize));
         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
-                    cborData, cborSize));
-        OCPayloadDestroy((OCPayload*)cstart);
+                                              cborData, cborSize));
+        OCPayloadDestroy((OCPayload *)cstart);
         OICFree(cborData);
 
         OC::MessageContainer mc2;
         mc2.setPayload(cparsed);
         EXPECT_EQ(1u, mc2.representations().size());
-        const OC::OCRepresentationr = mc2.representations()[0];
+        const OC::OCRepresentation &r = mc2.representations()[0];
 
         // Test
         std::vector<std::vector<int>> iarr2 = r["iarr"];
@@ -471,12 +531,16 @@ namespace OCRepresentationEncodingTest
         std::vector<std::vector<bool>> barr2 = r["barr"];
         std::vector<std::vector<std::string>> strarr2 = r["strarr"];
         std::vector<std::vector<OC::OCRepresentation>> objarr2 = r["objarr"];
+        std::vector<std::vector<OCByteString>> bytestrarr2 = r["bytestrarr"];
 
         EXPECT_EQ(iarr, iarr2);
         EXPECT_EQ(darr, darr2);
         EXPECT_EQ(barr, barr2);
         EXPECT_EQ(strarr, strarr2);
         EXPECT_EQ(objarr, objarr2);
+
+        EXPECT_EQ(bytestrarrRef, bytestrarr2);
+
         OCPayloadDestroy(cparsed);
     }
 
@@ -501,32 +565,62 @@ namespace OCRepresentationEncodingTest
         std::vector<std::vector<OC::OCRepresentation>> objarr
         {{subRep1, subRep3}, {subRep3, subRep2, subRep1}};
 
+        uint8_t binval1[] = {0x1};
+        OCByteString byteStringRef1 {binval1, sizeof(binval1) };
+        OCByteString byteString1 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString1, &byteStringRef1));
+        uint8_t binval3[] = {0x2, 0x3, 0x4};
+        OCByteString byteStringRef3 {binval3, sizeof(binval3) };
+        OCByteString byteString3 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString3, &byteStringRef3));
+        uint8_t binval4[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString byteStringRef4 {binval4, sizeof(binval4) };
+        OCByteString byteString4 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString4, &byteStringRef4));
+
+        std::vector<std::vector<OCByteString>> bytestrarrRef
+        {
+            {byteStringRef1}, {byteStringRef3, byteStringRef4}
+        };
+
+        std::vector<std::vector<OCByteString>> bytestrarr
+        {
+            {byteString1}, {byteString3, byteString4}
+        };
+
         startRep["iarr"] = iarr;
         startRep["darr"] = darr;
         startRep["barr"] = barr;
         startRep["strarr"] = strarr;
         startRep["objarr"] = objarr;
 
+        startRep["bytestrarr"] = bytestrarr;
+
+        EXPECT_STREQ("[[\\x1 ] [\\x2\\x3\\x4 \\x5\\x6\\x7\\x8 ] ]",
+                     startRep.getValueToString("bytestrarr").c_str());
         // Encode/decode
         OC::MessageContainer mc1;
         mc1.addRepresentation(startRep);
 
-        OCRepPayloadcstart = mc1.getPayload();
+        OCRepPayload *cstart = mc1.getPayload();
         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
 
-        uint8_tcborData;
+        uint8_t *cborData;
         size_t cborSize;
-        OCPayload* cparsed;
-        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
-        EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
-                    cborData, cborSize));
-        OCPayloadDestroy((OCPayload*)cstart);
+        OCPayload *cparsed;
+        OCStackResult result = OCConvertPayload((OCPayload *)cstart, &cborData, &cborSize);
+        EXPECT_EQ(OC_STACK_OK, result);
+        result = OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+                                cborData, cborSize);
+        EXPECT_EQ(OC_STACK_OK, result);
+
+        OCPayloadDestroy((OCPayload *)cstart);
         OICFree(cborData);
 
         OC::MessageContainer mc2;
         mc2.setPayload(cparsed);
         EXPECT_EQ(1u, mc2.representations().size());
-        const OC::OCRepresentationr = mc2.representations()[0];
+        const OC::OCRepresentation &r = mc2.representations()[0];
 
         // Test
         std::vector<std::vector<int>> iarr2 = r["iarr"];
@@ -535,6 +629,8 @@ namespace OCRepresentationEncodingTest
         std::vector<std::vector<std::string>> strarr2 = r["strarr"];
         std::vector<std::vector<OC::OCRepresentation>> objarr2 = r["objarr"];
 
+        std::vector<std::vector<OCByteString>> bytestrarr2 = r["bytestrarr"];
+
         // Note: due to the way that the CSDK works, all 2d arrays need to be rectangular.
         // Since std::vector doesn't require this, items received on the other side end up
         // being backfilled.  This section removes the backfilling
@@ -543,12 +639,16 @@ namespace OCRepresentationEncodingTest
         barr2[1].pop_back();
         strarr2[0].pop_back();
         objarr2[0].pop_back();
+        bytestrarr2[0].pop_back();
 
         EXPECT_EQ(iarr, iarr2);
         EXPECT_EQ(darr, darr2);
         EXPECT_EQ(barr, barr2);
         EXPECT_EQ(strarr, strarr2);
         EXPECT_EQ(objarr, objarr2);
+        EXPECT_EQ(bytestrarr.size(), bytestrarr2.size());
+        EXPECT_EQ(bytestrarrRef, bytestrarr2);
+
         OCPayloadDestroy(cparsed);
     }
 
@@ -587,32 +687,96 @@ namespace OCRepresentationEncodingTest
                 {{subRep3, subRep2},{subRep1, subRep2}}
             };
 
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4};
+        OCByteString byteStringRef1 {binval1, sizeof(binval1)};
+        OCByteString byteString1 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString1, &byteStringRef1));
+        uint8_t binval2[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString byteStringRef2 {binval2, sizeof(binval2)};
+        OCByteString byteString2 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString2, &byteStringRef2));
+        uint8_t binval3[] = {0x9, 0x0, 0xA, 0xB};
+        OCByteString byteStringRef3 {binval3, sizeof(binval3)};
+        OCByteString byteString3 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString3, &byteStringRef3));
+        uint8_t binval4[] = {0xC, 0xD, 0xE, 0xF};
+        OCByteString byteStringRef4 {binval4, sizeof(binval4)};
+        OCByteString byteString4 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString4, &byteStringRef4));
+        uint8_t binval5[] = {0x11, 0x12, 0x13, 0x14};
+        OCByteString byteStringRef5 {binval5, sizeof(binval5)};
+        OCByteString byteString5 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString5, &byteStringRef5));
+        uint8_t binval6[] = {0x15, 0x16, 0x17, 0x18};
+        OCByteString byteStringRef6 {binval6, sizeof(binval6)};
+        OCByteString byteString6 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString6, &byteStringRef6));
+        uint8_t binval7[] = {0x19, 0x10, 0x1A, 0x1B};
+        OCByteString byteStringRef7 {binval7, sizeof(binval7)};
+        OCByteString byteString7 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString7, &byteStringRef7));
+        uint8_t binval8[] = {0x1C, 0x1D, 0x1E, 0x1F};
+        OCByteString byteStringRef8 {binval8, sizeof(binval8)};
+        OCByteString byteString8 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString8, &byteStringRef8));
+        uint8_t binval9[] = {0x21, 0x22, 0x23, 0x24};
+        OCByteString byteStringRef9 {binval9, sizeof(binval9)};
+        OCByteString byteString9 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString9, &byteStringRef9));
+        uint8_t binval10[] = {0x25, 0x26, 0x27, 0x28};
+        OCByteString byteStringRef10 {binval10, sizeof(binval10)};
+        OCByteString byteString10 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString10, &byteStringRef10));
+        uint8_t binval11[] = {0x29, 0x20, 0x2A, 0x2B};
+        OCByteString byteStringRef11 {binval11, sizeof(binval11)};
+        OCByteString byteString11 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString11, &byteStringRef11));
+        uint8_t binval12[] = {0xFF};
+        OCByteString byteStringRef12 {binval12, sizeof(binval12)};
+        OCByteString byteString12 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString12, &byteStringRef12));
+
+        std::vector<std::vector<std::vector<OCByteString>>> bytestrarrRef
+        {
+            {{byteStringRef1, byteStringRef2}, {byteStringRef3, byteStringRef4}},
+            {{byteStringRef5, byteStringRef6}, {byteStringRef7, byteStringRef8}},
+            {{byteStringRef9, byteStringRef10}, {byteStringRef11, byteStringRef12}}
+        };
+
+        std::vector<std::vector<std::vector<OCByteString>>> bytestrarr
+        {
+            {{byteString1, byteString2}, {byteString3, byteString4}},
+            {{byteString5, byteString6}, {byteString7, byteString8}},
+            {{byteString9, byteString10}, {byteString11, byteString12}}
+        };
+
         startRep["iarr"] = iarr;
         startRep["darr"] = darr;
         startRep["barr"] = barr;
         startRep["strarr"] = strarr;
         startRep["objarr"] = objarr;
+        startRep["bytestrarr"] = bytestrarr;
 
         // Encode/decode
         OC::MessageContainer mc1;
         mc1.addRepresentation(startRep);
 
-        OCRepPayloadcstart = mc1.getPayload();
+        OCRepPayload *cstart = mc1.getPayload();
         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
 
-        uint8_tcborData;
+        uint8_t *cborData;
         size_t cborSize;
-        OCPayloadcparsed;
-        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+        OCPayload *cparsed;
+        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload *)cstart, &cborData, &cborSize));
         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
-                    cborData, cborSize));
-        OCPayloadDestroy((OCPayload*)cstart);
+                                              cborData, cborSize));
+        OCPayloadDestroy((OCPayload *)cstart);
         OICFree(cborData);
 
         OC::MessageContainer mc2;
         mc2.setPayload(cparsed);
         EXPECT_EQ(1u, mc2.representations().size());
-        const OC::OCRepresentationr = mc2.representations()[0];
+        const OC::OCRepresentation &r = mc2.representations()[0];
 
         // Test
         std::vector<std::vector<std::vector<int>>> iarr2 = r["iarr"];
@@ -620,12 +784,14 @@ namespace OCRepresentationEncodingTest
         std::vector<std::vector<std::vector<bool>>> barr2 = r["barr"];
         std::vector<std::vector<std::vector<std::string>>> strarr2 = r["strarr"];
         std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr2 = r["objarr"];
+        std::vector<std::vector<std::vector<OCByteString>>> bytestrarr2 = r["bytestrarr"];
 
         EXPECT_EQ(iarr, iarr2);
         EXPECT_EQ(darr, darr2);
         EXPECT_EQ(barr, barr2);
         EXPECT_EQ(strarr, strarr2);
         EXPECT_EQ(objarr, objarr2);
+        EXPECT_EQ(bytestrarrRef, bytestrarr2);
         OCPayloadDestroy(cparsed);
     }
 
@@ -673,32 +839,92 @@ namespace OCRepresentationEncodingTest
                 {{subRep3, subRep2}}
             };
 
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4};
+        OCByteString byteStringRef1 {binval1, sizeof(binval1)};
+        OCByteString byteString1 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString1, &byteStringRef1));
+        uint8_t binval2[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString byteStringRef2 {binval2, sizeof(binval2)};
+        OCByteString byteString2 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString2, &byteStringRef2));
+        uint8_t binval3[] = {0x9, 0x0, 0xA, 0xB};
+        OCByteString byteStringRef3 {binval3, sizeof(binval3)};
+        OCByteString byteString3 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString3, &byteStringRef3));
+        uint8_t binval4[] = {0xC, 0xD, 0xE, 0xF};
+        OCByteString byteStringRef4 {binval4, sizeof(binval4)};
+        OCByteString byteString4 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString4, &byteStringRef4));
+        uint8_t binval5[] = {0x11, 0x12, 0x13, 0x14};
+        OCByteString byteStringRef5 {binval5, sizeof(binval5)};
+        OCByteString byteString5 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString5, &byteStringRef5));
+        uint8_t binval6[] = {0x15, 0x16, 0x17, 0x18};
+        OCByteString byteStringRef6 {binval6, sizeof(binval6)};
+        OCByteString byteString6 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString6, &byteStringRef6));
+        uint8_t binval8[] = {0x1C, 0x1D, 0x1E, 0x1F};
+        OCByteString byteStringRef8 {binval8, sizeof(binval8)};
+        OCByteString byteString8 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString8, &byteStringRef8));
+        uint8_t binval9[] = {0x21, 0x22, 0x23, 0x24};
+        OCByteString byteStringRef9 {binval9, sizeof(binval9)};
+        OCByteString byteString9 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString9, &byteStringRef9));
+        uint8_t binval10[] = {0x25, 0x26, 0x27, 0x28};
+        OCByteString byteStringRef10 {binval10, sizeof(binval10)};
+        OCByteString byteString10 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString10, &byteStringRef10));
+        uint8_t binval11[] = {0x29, 0x20, 0x2A, 0x2B};
+        OCByteString byteStringRef11 {binval11, sizeof(binval11)};
+        OCByteString byteString11 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString11, &byteStringRef11));
+        uint8_t binval12[] = {0xFF};
+        OCByteString byteStringRef12 {binval12, sizeof(binval12)};
+        OCByteString byteString12 {NULL,0};
+        EXPECT_TRUE(OCByteStringCopy(&byteString12, &byteStringRef12));
+
+        std::vector<std::vector<std::vector<OCByteString>>> bytestrarrRef
+        {
+            {{byteStringRef1, byteStringRef2}, {byteStringRef3, byteStringRef4}},
+            {{byteStringRef5, byteStringRef6}, {byteStringRef8}},
+            {{byteStringRef9, byteStringRef10}, {byteStringRef11, byteStringRef12}}
+        };
+
+        std::vector<std::vector<std::vector<OCByteString>>> bytestrarr
+        {
+            {{byteString1, byteString2}, {byteString3, byteString4}},
+            {{byteString5, byteString6}, {byteString8}},
+            {{byteString9, byteString10}, {byteString11, byteString12}}
+        };
+
         startRep["iarr"] = iarr;
         startRep["darr"] = darr;
         startRep["barr"] = barr;
         startRep["strarr"] = strarr;
         startRep["objarr"] = objarr;
+        startRep["bytestrarr"] = bytestrarr;
 
         // Encode/decode
         OC::MessageContainer mc1;
         mc1.addRepresentation(startRep);
 
-        OCRepPayloadcstart = mc1.getPayload();
+        OCRepPayload *cstart = mc1.getPayload();
         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
 
-        uint8_tcborData;
+        uint8_t *cborData;
         size_t cborSize;
-        OCPayloadcparsed;
-        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+        OCPayload *cparsed;
+        EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload *)cstart, &cborData, &cborSize));
         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
-                    cborData, cborSize));
-        OCPayloadDestroy((OCPayload*)cstart);
+                                              cborData, cborSize));
+        OCPayloadDestroy((OCPayload *)cstart);
         OICFree(cborData);
 
         OC::MessageContainer mc2;
         mc2.setPayload(cparsed);
         EXPECT_EQ(1u, mc2.representations().size());
-        const OC::OCRepresentationr = mc2.representations()[0];
+        const OC::OCRepresentation &r = mc2.representations()[0];
 
         // Test
         std::vector<std::vector<std::vector<int>>> iarr2 = r["iarr"];
@@ -706,6 +932,7 @@ namespace OCRepresentationEncodingTest
         std::vector<std::vector<std::vector<bool>>> barr2 = r["barr"];
         std::vector<std::vector<std::vector<std::string>>> strarr2 = r["strarr"];
         std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr2 = r["objarr"];
+        std::vector<std::vector<std::vector<OCByteString>>> bytestrarr2 = r["bytestrarr"];
 
         // Note: due to the way that the CSDK works, all 3d arrays need to be cuboidal.
         // Since std::vector doesn't require this, items received on the other side end up
@@ -716,12 +943,14 @@ namespace OCRepresentationEncodingTest
         strarr2[1][1].pop_back();
         objarr2[1][1].pop_back();
         objarr2[2].pop_back();
+        bytestrarr2[1][1].pop_back();
 
         EXPECT_EQ(iarr, iarr2);
         EXPECT_EQ(darr, darr2);
         EXPECT_EQ(barr, barr2);
         EXPECT_EQ(strarr, strarr2);
         EXPECT_EQ(objarr, objarr2);
+        EXPECT_EQ(bytestrarrRef, bytestrarr2);
         OCPayloadDestroy(cparsed);
     }
 
index 5701fc2..eb4ac87 100644 (file)
@@ -148,6 +148,21 @@ namespace OCRepresentationTest
         EXPECT_EQ("OC::OCRepresentation", rep[AttrName].getValueToString());
     }
 
+    TEST(OCRepresentationValueToString, ByteString)
+    {
+        static const std::string AttrName = "ByteStringTest";
+        static uint8_t binval[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
+                                   0x9, 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
+
+        OCByteString bytestring {binval, sizeof(binval)};
+        OCRepresentation rep;
+
+        rep.setValue(AttrName, bytestring);
+        const char* expected = "\\x1\\x2\\x3\\x4\\x5\\x6\\x7\\x8"
+                               "\\x9\\x0\\xa\\xb\\xc\\xd\\xe\\xf";
+        EXPECT_STREQ(expected, rep.getValueToString(AttrName).c_str() );
+    }
+
     TEST(OCRepresentationValueToString, IntegerVector)
     {
         static const std::string AttrName = "VectorTest";
@@ -344,6 +359,125 @@ namespace OCRepresentationTest
         EXPECT_EQ(Expected, rep[AttrName].getValueToString());
     }
 
+    TEST(OCRepresentationValueToByteString, ByteStringVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4};
+        OCByteString s1 {binval1, sizeof(binval1)};
+        uint8_t binval2[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString s2 {binval2, sizeof(binval2)};
+        uint8_t binval3[] = {0x9, 0x0, 0xA, 0xB};
+        OCByteString s3 {binval3, sizeof(binval3)};
+        vector<OCByteString> vect {s1, s2, s3};
+
+        uint8_t binval4[] = {0xC, 0xD, 0xE, 0xF};
+        OCByteString s4 {binval4, sizeof(binval4)};
+        uint8_t binval5[] = {0x11, 0x12, 0x13, 0x14};
+        OCByteString s5 {binval5, sizeof(binval5)};
+        uint8_t binval6[] = {0x15, 0x16, 0x17, 0x18};
+        OCByteString s6 {binval6, sizeof(binval6)};
+        vector<OCByteString> vect2 {s4, s5, s6};
+
+        rep.setValue(AttrName, vect);
+        const char *expected1tob = "[\\x1\\x2\\x3\\x4 \\x5\\x6\\x7\\x8 \\x9\\x0\\xa\\xb ]";
+        EXPECT_EQ(expected1tob, rep.getValueToString(AttrName));
+        EXPECT_EQ(expected1tob, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, vect2);
+        const char *expectedcto18 = "[\\xc\\xd\\xe\\xf \\x11\\x12\\x13\\x14 \\x15\\x16\\x17\\x18 ]";
+        EXPECT_EQ(expectedcto18, rep.getValueToString(AttrName));
+        EXPECT_EQ(expectedcto18, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToByteString, ByteStringVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4};
+        OCByteString s1 {binval1, sizeof(binval1)};
+        uint8_t binval2[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString s2 {binval2, sizeof(binval2)};
+        uint8_t binval3[] = {0x9, 0x0, 0xA, 0xB};
+        OCByteString s3 {binval3, sizeof(binval3)};
+        vector<OCByteString> vect1 {s1, s2, s3};
+
+        uint8_t binval4[] = {0xC, 0xD, 0xE, 0xF};
+        OCByteString s4 {binval4, sizeof(binval4)};
+        uint8_t binval5[] = {0x11, 0x12, 0x13, 0x14};
+        OCByteString s5 {binval5, sizeof(binval5)};
+        uint8_t binval6[] = {0x15, 0x16, 0x17, 0x18};
+        OCByteString s6 {binval6, sizeof(binval6)};
+        vector<OCByteString> vect2 {s4, s5, s6};
+
+        vector<vector<OCByteString>> vect {vect1, vect2};
+
+        rep.setValue(AttrName, vect);
+
+        const char *expected =
+            "[["
+            "\\x1\\x2\\x3\\x4 \\x5\\x6\\x7\\x8 \\x9\\x0\\xa\\xb "
+            "] ["
+            "\\xc\\xd\\xe\\xf \\x11\\x12\\x13\\x14 \\x15\\x16\\x17\\x18 "
+            "] ]"
+            ;
+
+        EXPECT_EQ(expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToByteString, ByteStringVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        uint8_t binval1[] = {0x1, 0x2, 0x3, 0x4};
+        OCByteString s1 {binval1, sizeof(binval1)};
+        uint8_t binval2[] = {0x5, 0x6, 0x7, 0x8};
+        OCByteString s2 {binval2, sizeof(binval2)};
+        uint8_t binval3[] = {0x9, 0x0, 0xA, 0xB};
+        OCByteString s3 {binval3, sizeof(binval3)};
+        vector<OCByteString> vect11 {s1, s2, s3};
+
+        uint8_t binval4[] = {0xC, 0xD, 0xE, 0xF};
+        OCByteString s4 {binval4, sizeof(binval4)};
+        uint8_t binval5[] = {0x11, 0x12, 0x13, 0x14};
+        OCByteString s5 {binval5, sizeof(binval5)};
+        uint8_t binval6[] = {0x15, 0x16, 0x17, 0x18};
+        OCByteString s6 {binval6, sizeof(binval6)};
+        vector<OCByteString> vect12 {s4, s5, s6};
+
+        uint8_t binval7[] = {0x19, 0x10, 0x1A, 0x1B};
+        OCByteString s7 {binval7, sizeof(binval7)};
+        uint8_t binval8[] = {0x1C, 0x1D, 0x1E, 0x1F};
+        OCByteString s8 {binval8, sizeof(binval8)};
+        vector<OCByteString> vect21 {s7, s8};
+
+        uint8_t binval9[] = {0x21, 0x22, 0x23, 0x24};
+        OCByteString s9 {binval9, sizeof(binval9)};
+        vector<OCByteString> vect22 {s9};
+
+        vector<vector<OCByteString>> vect1 {vect11, vect12};
+        vector<vector<OCByteString>> vect2 {vect21, vect22};
+        vector<vector<vector<OCByteString>>> vect {vect1, vect2};
+        rep.setValue(AttrName, vect);
+        static const std::string expected =
+            "[[["
+            "\\x1\\x2\\x3\\x4 \\x5\\x6\\x7\\x8 \\x9\\x0\\xa\\xb "
+            "] ["
+            "\\xc\\xd\\xe\\xf \\x11\\x12\\x13\\x14 \\x15\\x16\\x17\\x18 "
+            "] ] [["
+            "\\x19\\x10\\x1a\\x1b \\x1c\\x1d\\x1e\\x1f "
+            "] ["
+            "\\x21\\x22\\x23\\x24 "
+            "] ] ]";
+
+        EXPECT_EQ(expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(expected, rep[AttrName].getValueToString());
+    }
+
     TEST(OCRepresentationValueToString, SubRepresentationVector)
     {
         static const std::string AttrName = "VectorTest";