From 48aa060db9fda67e8f040d79f6ae648d463cba75 Mon Sep 17 00:00:00 2001 From: Philippe Coval Date: Fri, 1 Jul 2016 22:36:36 +0200 Subject: [PATCH] ocpayload: Adding OCByteString support in representation 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 Origin: https://gerrit.iotivity.org/gerrit/#/c/8931/ Signed-off-by: Philippe Coval Reviewed-on: https://gerrit.iotivity.org/gerrit/8931 Tested-by: jenkins-iotivity Reviewed-by: Dave Thaler (cherry picked from commit f2059ea75cb7f8966f59132fb05962b2f52e352b) Reviewed-on: https://gerrit.iotivity.org/gerrit/12611 Reviewed-by: Uze Choi --- android/android_api/base/jni/JniOcRepresentation.h | 97 +++++++ android/android_api/base/jni/JniOcStack.cpp | 22 ++ android/android_api/base/jni/JniOcStack.h | 3 + resource/csdk/octbstack_product.def | 1 + resource/csdk/stack/include/ocpayload.h | 8 + resource/csdk/stack/src/ocpayload.c | 73 +++-- resource/csdk/stack/src/ocpayloadconvert.c | 2 +- resource/include/AttributeValue.h | 14 +- resource/include/OCRepresentation.h | 6 +- resource/src/OCRepresentation.cpp | 63 +++++ .../unittests/OCRepresentationEncodingTest.cpp | 293 ++++++++++++++++++--- resource/unittests/OCRepresentationTest.cpp | 134 ++++++++++ 12 files changed, 665 insertions(+), 51 deletions(-) diff --git a/android/android_api/base/jni/JniOcRepresentation.h b/android/android_api/base/jni/JniOcRepresentation.h index e9acd35..dc85747 100644 --- a/android/android_api/base/jni/JniOcRepresentation.h +++ b/android/android_api/base/jni/JniOcRepresentation.h @@ -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(val.bytes)); + if (env->ExceptionCheck()) + { + env->DeleteLocalRef(jByteArray); + return nullptr; + } + return jByteArray; + } + jobject operator()(const std::vector &val) const + { + jsize lenOuter = static_cast(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(jByteArray)); + if (env->ExceptionCheck()) + { + env->DeleteLocalRef(jByteArray); + env->DeleteLocalRef(jOuterArr); + return nullptr; + } + env->DeleteLocalRef(jByteArray); + } + return jOuterArr; + } + jobject operator()(const std::vector> &val) const + { + jsize lenOuter = static_cast(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>> &val) const + { + jsize lenOuter = static_cast(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& val) const { jsize len = static_cast(val.size()); diff --git a/android/android_api/base/jni/JniOcStack.cpp b/android/android_api/base/jni/JniOcStack.cpp index c140551..f87cd1a 100644 --- a/android/android_api/base/jni/JniOcStack.cpp +++ b/android/android_api/base/jni/JniOcStack.cpp @@ -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 diff --git a/android/android_api/base/jni/JniOcStack.h b/android/android_api/base/jni/JniOcStack.h index 51f856e..db5ea1e 100644 --- a/android/android_api/base/jni/JniOcStack.h +++ b/android/android_api/base/jni/JniOcStack.h @@ -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; diff --git a/resource/csdk/octbstack_product.def b/resource/csdk/octbstack_product.def index b3c92c1..781eb2f 100644 --- a/resource/csdk/octbstack_product.def +++ b/resource/csdk/octbstack_product.def @@ -74,6 +74,7 @@ OCRepPayloadClone OCRepPayloadCreate OCRepPayloadDestroy OCRepPayloadGetByteStringArray +OCRepPayloadSetByteStringArrayAsOwner OCRepPayloadGetPropBool OCRepPayloadGetPropByteString OCRepPayloadGetPropInt diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h index 95ff3cb..7a7c4a0 100644 --- a/resource/csdk/stack/include/ocpayload.h +++ b/resource/csdk/stack/include/ocpayload.h @@ -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 diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index 2afac6f..2b17fdd 100644 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -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) diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index e3dd927..cf5442f 100644 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -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); } diff --git a/resource/include/AttributeValue.h b/resource/include/AttributeValue.h index 5b9ca83..3315356 100644 --- a/resource/include/AttributeValue.h +++ b/resource/include/AttributeValue.h @@ -54,6 +54,7 @@ namespace OC bool, std::string, OC::OCRepresentation, + OCByteString, // Sequences: std::vector, @@ -61,6 +62,7 @@ namespace OC std::vector, std::vector, std::vector, + std::vector, // Nested sequences: std::vector>, @@ -78,6 +80,9 @@ namespace OC std::vector>, std::vector>>, + std::vector>, + std::vector>>, + // used for binary data type std::vector > AttributeValue; @@ -91,7 +96,8 @@ namespace OC String, OCRepresentation, Vector, - Binary + Binary, + OCByteString }; template @@ -134,6 +140,12 @@ namespace OC }; template<> + struct AttributeTypeConvert + { + BOOST_STATIC_CONSTEXPR AttributeType type = AttributeType::OCByteString; + }; + + template<> struct AttributeTypeConvert> { BOOST_STATIC_CONSTEXPR AttributeType type = AttributeType::Binary; diff --git a/resource/include/OCRepresentation.h b/resource/include/OCRepresentation.h index c07974a..1e025eb 100644 --- a/resource/include/OCRepresentation.h +++ b/resource/include/OCRepresentation.h @@ -333,6 +333,7 @@ namespace OC std::is_same::value || std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same>::value || std::is_same>>::value || std::is_same>>>::value || @@ -347,7 +348,10 @@ namespace OC std::is_same>>>::value || std::is_same>::value || std::is_same>>::value || - std::is_same>>>::value + std::is_same>>>::value || + std::is_same>::value || + std::is_same>>::value || + std::is_same>>>::value , int>::type = 0// enable_if > #else diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp index 476d72b..8fe41d5 100644 --- a/resource/src/OCRepresentation.cpp +++ b/resource/src/OCRepresentation.cpp @@ -30,6 +30,7 @@ #include #include +#include #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(val).c_str()); break; + case AttributeType::OCByteString: + OCRepPayloadSetPropByteString(root, val.attrname().c_str(), val.getValue()); + break; case AttributeType::OCRepresentation: OCRepPayloadSetPropObjectAsOwner(root, val.attrname().c_str(), static_cast(val).getPayload()); @@ -529,6 +555,19 @@ namespace OC return std::string{}; } } + + template<> + OCByteString OCRepresentation::payload_array_helper_copy( + 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( size_t index, const OCRepPayloadValue* pl) @@ -612,6 +651,9 @@ namespace OC case OCREP_PROP_STRING: payload_array_helper(pl, calcArrayDepth(pl->arr.dimensions)); break; + case OCREP_PROP_BYTE_STRING: + payload_array_helper(pl, calcArrayDepth(pl->arr.dimensions)); + break; case OCREP_PROP_OBJECT: payload_array_helper(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 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 v(item.bytes, item.bytes + item.len); + operator()(v); + } + template<> void to_string_visitor::operator()(OCRepresentation const& /*item*/) { diff --git a/resource/unittests/OCRepresentationEncodingTest.cpp b/resource/unittests/OCRepresentationEncodingTest.cpp index 5e177be..54fc760 100644 --- a/resource/unittests/OCRepresentationEncodingTest.cpp +++ b/resource/unittests/OCRepresentationEncodingTest.cpp @@ -29,6 +29,16 @@ #include #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("DoubleAttr")); EXPECT_EQ(true, r.getValue("BoolAttr")); EXPECT_STREQ("String attr", r.getValue("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 strarr {"item1", "item2", "item3", "item4"}; std::vector 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 bytestrarrRef {byteStringRef1, byteStringRef2 }; + std::vector 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::OCRepresentation& r = mc2.representations()[0]; + const OC::OCRepresentation &r = mc2.representations()[0]; // Test std::vector iarr2 = r["iarr"]; @@ -408,12 +439,15 @@ namespace OCRepresentationEncodingTest std::vector barr2 = r["barr"]; std::vector strarr2 = r["strarr"]; std::vector objarr2 = r["objarr"]; + std::vector 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> 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> bytestrarrRef + { + {byteStringRef1, byteStringRef2}, {byteStringRef3, byteStringRef4} + }; + std::vector> 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); - OCRepPayload* cstart = 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::OCRepresentation& r = mc2.representations()[0]; + const OC::OCRepresentation &r = mc2.representations()[0]; // Test std::vector> iarr2 = r["iarr"]; @@ -471,12 +531,16 @@ namespace OCRepresentationEncodingTest std::vector> barr2 = r["barr"]; std::vector> strarr2 = r["strarr"]; std::vector> objarr2 = r["objarr"]; + std::vector> 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> 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> bytestrarrRef + { + {byteStringRef1}, {byteStringRef3, byteStringRef4} + }; + + std::vector> 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); - OCRepPayload* cstart = mc1.getPayload(); + OCRepPayload *cstart = mc1.getPayload(); EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type); - uint8_t* cborData; + 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::OCRepresentation& r = mc2.representations()[0]; + const OC::OCRepresentation &r = mc2.representations()[0]; // Test std::vector> iarr2 = r["iarr"]; @@ -535,6 +629,8 @@ namespace OCRepresentationEncodingTest std::vector> strarr2 = r["strarr"]; std::vector> objarr2 = r["objarr"]; + std::vector> 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>> bytestrarrRef + { + {{byteStringRef1, byteStringRef2}, {byteStringRef3, byteStringRef4}}, + {{byteStringRef5, byteStringRef6}, {byteStringRef7, byteStringRef8}}, + {{byteStringRef9, byteStringRef10}, {byteStringRef11, byteStringRef12}} + }; + + std::vector>> 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); - OCRepPayload* cstart = mc1.getPayload(); + OCRepPayload *cstart = mc1.getPayload(); EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type); - uint8_t* cborData; + 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, 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::OCRepresentation& r = mc2.representations()[0]; + const OC::OCRepresentation &r = mc2.representations()[0]; // Test std::vector>> iarr2 = r["iarr"]; @@ -620,12 +784,14 @@ namespace OCRepresentationEncodingTest std::vector>> barr2 = r["barr"]; std::vector>> strarr2 = r["strarr"]; std::vector>> objarr2 = r["objarr"]; + std::vector>> 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>> bytestrarrRef + { + {{byteStringRef1, byteStringRef2}, {byteStringRef3, byteStringRef4}}, + {{byteStringRef5, byteStringRef6}, {byteStringRef8}}, + {{byteStringRef9, byteStringRef10}, {byteStringRef11, byteStringRef12}} + }; + + std::vector>> 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); - OCRepPayload* cstart = mc1.getPayload(); + OCRepPayload *cstart = mc1.getPayload(); EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type); - uint8_t* cborData; + 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, 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::OCRepresentation& r = mc2.representations()[0]; + const OC::OCRepresentation &r = mc2.representations()[0]; // Test std::vector>> iarr2 = r["iarr"]; @@ -706,6 +932,7 @@ namespace OCRepresentationEncodingTest std::vector>> barr2 = r["barr"]; std::vector>> strarr2 = r["strarr"]; std::vector>> objarr2 = r["objarr"]; + std::vector>> 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); } diff --git a/resource/unittests/OCRepresentationTest.cpp b/resource/unittests/OCRepresentationTest.cpp index 5701fc2..eb4ac87 100644 --- a/resource/unittests/OCRepresentationTest.cpp +++ b/resource/unittests/OCRepresentationTest.cpp @@ -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 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 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 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 vect2 {s4, s5, s6}; + + vector> 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 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 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 vect21 {s7, s8}; + + uint8_t binval9[] = {0x21, 0x22, 0x23, 0x24}; + OCByteString s9 {binval9, sizeof(binval9)}; + vector vect22 {s9}; + + vector> vect1 {vect11, vect12}; + vector> vect2 {vect21, vect22}; + vector>> 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"; -- 2.7.4