Merge branch 'security-CKM' into 'master'
[platform/upstream/iotivity.git] / resource / unittests / OCRepresentationEncodingTest.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <gtest/gtest.h>
22 #include <OCApi.h>
23 #include <OCRepresentation.h>
24 #include <octypes.h>
25 #include <ocpayload.h>
26 #include <ocpayloadcbor.h>
27 #include <oic_malloc.h>
28
29 namespace OC
30 {
31     bool operator==(const OC::NullType&, const OC::NullType&)
32     {
33         return true;
34     }
35
36     bool operator==(const OC::OCRepresentation& lhs, const OC::OCRepresentation& rhs)
37     {
38         return lhs.getUri() == rhs.getUri() &&
39             lhs.getChildren() == rhs.getChildren() &&
40             lhs.getResourceInterfaces() == rhs.getResourceInterfaces() &&
41             lhs.getResourceTypes() == rhs.getResourceTypes() &&
42             lhs.m_values == rhs.m_values;
43     }
44 }
45 // these tests validate the OCRepresentation->OCPayload, OCPayload->CBOR,
46 // CBOR->OCPayload and OCPayload->OCRepresentation conversions
47 namespace OCRepresentationEncodingTest
48 {
49
50     static const char uri1[] = "/testuri";
51     static const uint8_t sid1[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
52     static const char devicename1[] = "device name";
53     static const char specver1[] = "spec version";
54     static const char dmver1[] = "data model version";
55     // Device Payloads
56     TEST(DeviceDiscoveryEncoding, Normal)
57     {
58         OCDevicePayload* device = OCDevicePayloadCreate(
59                 uri1,
60                 sid1,
61                 devicename1,
62                 specver1,
63                 dmver1);
64
65         EXPECT_STREQ(uri1, device->uri);
66         EXPECT_STREQ(devicename1, device->deviceName);
67         EXPECT_STREQ(specver1, device->specVersion);
68         EXPECT_STREQ(dmver1, device->dataModelVersion);
69         EXPECT_EQ(PAYLOAD_TYPE_DEVICE, ((OCPayload*)device)->type);
70
71         for (uint8_t i = 1; i <= sizeof(sid1); ++i)
72         {
73             EXPECT_EQ(i, sid1[i - 1]);
74         }
75
76         uint8_t* cborData;
77         size_t cborSize;
78         OCPayload* parsedDevice;
79         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)device, &cborData, &cborSize));
80         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&parsedDevice, PAYLOAD_TYPE_DEVICE,
81                     cborData, cborSize));
82         OICFree(cborData);
83
84         EXPECT_STREQ(device->uri, ((OCDevicePayload*)parsedDevice)->uri);
85         EXPECT_STREQ(device->deviceName, ((OCDevicePayload*)parsedDevice)->deviceName);
86         EXPECT_STREQ(device->specVersion, ((OCDevicePayload*)parsedDevice)->specVersion);
87         EXPECT_STREQ(device->dataModelVersion, ((OCDevicePayload*)parsedDevice)->dataModelVersion);
88         EXPECT_EQ(device->base.type, ((OCDevicePayload*)parsedDevice)->base.type);
89
90         OCPayloadDestroy((OCPayload*)device);
91
92         OC::MessageContainer mc;
93         mc.setPayload(parsedDevice);
94         EXPECT_EQ(1u, mc.representations().size());
95         const OC::OCRepresentation& r = mc.representations()[0];
96         EXPECT_STREQ(uri1, r.getUri().c_str());
97         EXPECT_STREQ(devicename1, r.getValue<std::string>(OC_RSRVD_DEVICE_NAME).c_str());
98         EXPECT_STREQ(specver1, r.getValue<std::string>(OC_RSRVD_SPEC_VERSION).c_str());
99         EXPECT_STREQ(dmver1, r.getValue<std::string>(OC_RSRVD_DATA_MODEL_VERSION).c_str());
100
101
102         OCPayloadDestroy(parsedDevice);
103     }
104
105     static char pfid1[] = "pfid";
106     static char mfgnm1[] = "mfgnm";
107     static char mfgurl1[] = "mfgurl";
108     static char modelnum1[] = "modelnum";
109     static char dom1[] = "dom";
110     static char pfver1[] = "pfver";
111     static char osver1[] = "osver";
112     static char hwver1[] = "hwver";
113     static char fwver1[] = "fwver";
114     static char url1[] = "url";
115     static char time1[] = "time";
116
117     // Platform Payloads
118     TEST(PlatformDiscoveryEncoding, Normal)
119     {
120         OCPlatformInfo info {pfid1, mfgnm1, mfgurl1, modelnum1, dom1, pfver1, osver1, hwver1,
121             fwver1, url1, time1};
122         OCPlatformPayload* platform = OCPlatformPayloadCreate(uri1, &info);
123         EXPECT_EQ(PAYLOAD_TYPE_PLATFORM, ((OCPayload*)platform)->type);
124         EXPECT_STREQ(uri1, platform->uri);
125         EXPECT_STREQ(pfid1, platform->info.platformID);
126         EXPECT_STREQ(mfgnm1, platform->info.manufacturerName);
127         EXPECT_STREQ(mfgurl1, platform->info.manufacturerUrl);
128         EXPECT_STREQ(modelnum1, platform->info.modelNumber);
129         EXPECT_STREQ(dom1, platform->info.dateOfManufacture);
130         EXPECT_STREQ(pfver1, platform->info.platformVersion);
131         EXPECT_STREQ(osver1, platform->info.operatingSystemVersion);
132         EXPECT_STREQ(hwver1, platform->info.hardwareVersion);
133         EXPECT_STREQ(fwver1, platform->info.firmwareVersion);
134         EXPECT_STREQ(url1, platform->info.supportUrl);
135         EXPECT_STREQ(time1, platform->info.systemTime);
136
137         uint8_t* cborData;
138         size_t cborSize;
139         OCPayload* parsedPlatform;
140         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)platform, &cborData, &cborSize));
141         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&parsedPlatform, PAYLOAD_TYPE_PLATFORM,
142                     cborData, cborSize));
143         OICFree(cborData);
144
145         EXPECT_EQ(platform->base.type, ((OCPlatformPayload*)parsedPlatform)->base.type);
146         OCPlatformPayload* platform2 = (OCPlatformPayload*)parsedPlatform;
147         EXPECT_STREQ(platform->uri, platform2->uri);
148         EXPECT_STREQ(platform->info.platformID, platform2->info.platformID);
149         EXPECT_STREQ(platform->info.manufacturerName, platform->info.manufacturerName);
150         EXPECT_STREQ(platform->info.manufacturerUrl, platform->info.manufacturerUrl);
151         EXPECT_STREQ(platform->info.modelNumber, platform->info.modelNumber);
152         EXPECT_STREQ(platform->info.dateOfManufacture, platform->info.dateOfManufacture);
153         EXPECT_STREQ(platform->info.platformVersion, platform->info.platformVersion);
154         EXPECT_STREQ(platform->info.operatingSystemVersion, platform->info.operatingSystemVersion);
155         EXPECT_STREQ(platform->info.hardwareVersion, platform->info.hardwareVersion);
156         EXPECT_STREQ(platform->info.firmwareVersion, platform->info.firmwareVersion);
157         EXPECT_STREQ(platform->info.supportUrl, platform->info.supportUrl);
158         EXPECT_STREQ(platform->info.systemTime, platform2->info.systemTime);
159
160         OCPayloadDestroy((OCPayload*)platform);
161
162         OC::MessageContainer mc;
163         mc.setPayload(parsedPlatform);
164         EXPECT_EQ(1u, mc.representations().size());
165         const OC::OCRepresentation& r = mc.representations()[0];
166         EXPECT_STREQ(uri1, r.getUri().c_str());
167         EXPECT_STREQ(pfid1, r.getValue<std::string>(OC_RSRVD_PLATFORM_ID).c_str());
168         EXPECT_STREQ(mfgnm1, r.getValue<std::string>(OC_RSRVD_MFG_NAME).c_str());
169         EXPECT_STREQ(mfgurl1, r.getValue<std::string>(OC_RSRVD_MFG_URL).c_str());
170         EXPECT_STREQ(modelnum1, r.getValue<std::string>(OC_RSRVD_MODEL_NUM).c_str());
171         EXPECT_STREQ(dom1, r.getValue<std::string>(OC_RSRVD_MFG_DATE).c_str());
172         EXPECT_STREQ(pfver1, r.getValue<std::string>(OC_RSRVD_PLATFORM_VERSION).c_str());
173         EXPECT_STREQ(osver1, r.getValue<std::string>(OC_RSRVD_OS_VERSION).c_str());
174         EXPECT_STREQ(hwver1, r.getValue<std::string>(OC_RSRVD_HARDWARE_VERSION).c_str());
175         EXPECT_STREQ(fwver1, r.getValue<std::string>(OC_RSRVD_FIRMWARE_VERSION).c_str());
176         EXPECT_STREQ(url1, r.getValue<std::string>(OC_RSRVD_SUPPORT_URL).c_str());
177         EXPECT_STREQ(time1, r.getValue<std::string>(OC_RSRVD_SYSTEM_TIME).c_str());
178
179         OCPayloadDestroy(parsedPlatform);
180     }
181
182     // Representation Payloads
183     TEST(RepresentationEncoding, BaseAttributeTypes)
184     {
185         OC::OCRepresentation startRep;
186         startRep.setNULL("NullAttr");
187         startRep.setValue("IntAttr", 77);
188         startRep.setValue("DoubleAttr", 3.333);
189         startRep.setValue("BoolAttr", true);
190         startRep.setValue("StringAttr", std::string("String attr"));
191         OC::MessageContainer mc1;
192         mc1.addRepresentation(startRep);
193
194         OCRepPayload* cstart = mc1.getPayload();
195         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
196
197         uint8_t* cborData;
198         size_t cborSize;
199         OCPayload* cparsed;
200         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
201         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
202                     cborData, cborSize));
203         OCPayloadDestroy((OCPayload*)cstart);
204         OICFree(cborData);
205
206         OC::MessageContainer mc2;
207         mc2.setPayload(cparsed);
208         EXPECT_EQ(1u, mc2.representations().size());
209         const OC::OCRepresentation& r = mc2.representations()[0];
210
211         EXPECT_TRUE(r.isNULL("NullAttr"));
212         EXPECT_EQ(77, r.getValue<int>("IntAttr"));
213         EXPECT_EQ(3.333, r.getValue<double>("DoubleAttr"));
214         EXPECT_EQ(true, r.getValue<bool>("BoolAttr"));
215         EXPECT_STREQ("String attr", r.getValue<std::string>("StringAttr").c_str());
216
217         OCPayloadDestroy(cparsed);
218     }
219
220     TEST(RepresentationEncoding, RepAttribute)
221     {
222         OC::OCRepresentation startRep;
223         OC::OCRepresentation subRep;
224         subRep.setNULL("NullAttr");
225         subRep.setValue("IntAttr", 77);
226         subRep.setValue("DoubleAttr", 3.333);
227         subRep.setValue("BoolAttr", true);
228         subRep.setValue("StringAttr", std::string("String attr"));
229         startRep.setValue("Sub", subRep);
230
231         OC::MessageContainer mc1;
232         mc1.addRepresentation(startRep);
233
234         OCRepPayload* cstart = mc1.getPayload();
235         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
236
237         uint8_t* cborData;
238         size_t cborSize;
239         OCPayload* cparsed;
240         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
241         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
242                     cborData, cborSize));
243         OCPayloadDestroy((OCPayload*)cstart);
244         OICFree(cborData);
245
246         OC::MessageContainer mc2;
247         mc2.setPayload(cparsed);
248         EXPECT_EQ(1u, mc2.representations().size());
249         const OC::OCRepresentation& r = mc2.representations()[0];
250
251         OC::OCRepresentation newSubRep = r["Sub"];
252
253         EXPECT_TRUE(newSubRep.isNULL("NullAttr"));
254         EXPECT_EQ(77, newSubRep.getValue<int>("IntAttr"));
255         EXPECT_EQ(3.333, newSubRep.getValue<double>("DoubleAttr"));
256         EXPECT_EQ(true, newSubRep.getValue<bool>("BoolAttr"));
257         EXPECT_STREQ("String attr", newSubRep.getValue<std::string>("StringAttr").c_str());
258         OCPayloadDestroy(cparsed);
259     }
260
261     TEST(RepresentationEncoding, OneDVectors)
262     {
263         // Setup
264         OC::OCRepresentation startRep;
265
266         OC::OCRepresentation subRep1;
267         OC::OCRepresentation subRep2;
268         OC::OCRepresentation subRep3;
269         subRep1.setNULL("NullAttr");
270         subRep1.setValue("IntAttr", 77);
271         subRep2.setValue("DoubleAttr", 3.333);
272         subRep2.setValue("BoolAttr", true);
273         subRep3.setValue("StringAttr", std::string("String attr"));
274
275         std::vector<int> iarr {1,2,3,4,5,6,7,8,9};
276         std::vector<double> darr {1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9};
277         std::vector<bool> barr {false, true, false, false, true, true};
278         std::vector<std::string> strarr {"item1", "item2", "item3", "item4"};
279         std::vector<OC::OCRepresentation> objarr {subRep1, subRep2, subRep3};
280
281         startRep["iarr"] = iarr;
282         startRep["darr"] = darr;
283         startRep["barr"] = barr;
284         startRep["strarr"] = strarr;
285         startRep["objarr"] = objarr;
286
287         // Encode/decode
288         OC::MessageContainer mc1;
289         mc1.addRepresentation(startRep);
290
291         OCRepPayload* cstart = mc1.getPayload();
292         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
293
294         uint8_t* cborData;
295         size_t cborSize;
296         OCPayload* cparsed;
297         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
298         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
299                     cborData, cborSize));
300         OCPayloadDestroy((OCPayload*)cstart);
301         OICFree(cborData);
302
303         OC::MessageContainer mc2;
304         mc2.setPayload(cparsed);
305         EXPECT_EQ(1u, mc2.representations().size());
306         const OC::OCRepresentation& r = mc2.representations()[0];
307
308         // Test
309         std::vector<int> iarr2 = r["iarr"];
310         std::vector<double> darr2 = r["darr"];
311         std::vector<bool> barr2 = r["barr"];
312         std::vector<std::string> strarr2 = r["strarr"];
313         std::vector<OC::OCRepresentation> objarr2 = r["objarr"];
314
315         EXPECT_EQ(iarr, iarr2);
316         EXPECT_EQ(darr, darr2);
317         EXPECT_EQ(barr, barr2);
318         EXPECT_EQ(strarr, strarr2);
319         EXPECT_EQ(objarr, objarr2);
320         OCPayloadDestroy(cparsed);
321     }
322
323     TEST(RepresentationEncoding, TwoDVectors)
324     {
325         // Setup
326         OC::OCRepresentation startRep;
327
328         OC::OCRepresentation subRep1;
329         OC::OCRepresentation subRep2;
330         OC::OCRepresentation subRep3;
331         subRep1.setNULL("NullAttr");
332         subRep1.setValue("IntAttr", 77);
333         subRep2.setValue("DoubleAttr", 3.333);
334         subRep2.setValue("BoolAttr", true);
335         subRep3.setValue("StringAttr", std::string("String attr"));
336
337         std::vector<std::vector<int>> iarr {{1,2,3},{4,5,6},{7,8,9}};
338         std::vector<std::vector<double>> darr {{1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9}};
339         std::vector<std::vector<bool>> barr {{false, true}, {false, false}, {true, true}};
340         std::vector<std::vector<std::string>> strarr {{"item1", "item2"}, {"item3", "item4"}};
341         std::vector<std::vector<OC::OCRepresentation>> objarr
342         {{subRep1, subRep2, subRep3}, {subRep3, subRep2, subRep1}};
343
344         startRep["iarr"] = iarr;
345         startRep["darr"] = darr;
346         startRep["barr"] = barr;
347         startRep["strarr"] = strarr;
348         startRep["objarr"] = objarr;
349
350         // Encode/decode
351         OC::MessageContainer mc1;
352         mc1.addRepresentation(startRep);
353
354         OCRepPayload* cstart = mc1.getPayload();
355         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
356
357         uint8_t* cborData;
358         size_t cborSize;
359         OCPayload* cparsed;
360         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
361         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
362                     cborData, cborSize));
363         OCPayloadDestroy((OCPayload*)cstart);
364         OICFree(cborData);
365
366         OC::MessageContainer mc2;
367         mc2.setPayload(cparsed);
368         EXPECT_EQ(1u, mc2.representations().size());
369         const OC::OCRepresentation& r = mc2.representations()[0];
370
371         // Test
372         std::vector<std::vector<int>> iarr2 = r["iarr"];
373         std::vector<std::vector<double>> darr2 = r["darr"];
374         std::vector<std::vector<bool>> barr2 = r["barr"];
375         std::vector<std::vector<std::string>> strarr2 = r["strarr"];
376         std::vector<std::vector<OC::OCRepresentation>> objarr2 = r["objarr"];
377
378         EXPECT_EQ(iarr, iarr2);
379         EXPECT_EQ(darr, darr2);
380         EXPECT_EQ(barr, barr2);
381         EXPECT_EQ(strarr, strarr2);
382         EXPECT_EQ(objarr, objarr2);
383         OCPayloadDestroy(cparsed);
384     }
385
386     TEST(RepresentationEncoding, TwoDVectorsJagged)
387     {
388         // Setup
389         OC::OCRepresentation startRep;
390
391         OC::OCRepresentation subRep1;
392         OC::OCRepresentation subRep2;
393         OC::OCRepresentation subRep3;
394         subRep1.setNULL("NullAttr");
395         subRep1.setValue("IntAttr", 77);
396         subRep2.setValue("DoubleAttr", 3.333);
397         subRep2.setValue("BoolAttr", true);
398         subRep3.setValue("StringAttr", std::string("String attr"));
399
400         std::vector<std::vector<int>> iarr {{1,2,3},{4,6},{7,8,9}};
401         std::vector<std::vector<double>> darr {{1.1,2.2,3.3},{4.4,5.5,6.6},{8.8,9.9}};
402         std::vector<std::vector<bool>> barr {{false, true}, {false}, {true, true}};
403         std::vector<std::vector<std::string>> strarr {{"item1"}, {"item3", "item4"}};
404         std::vector<std::vector<OC::OCRepresentation>> objarr
405         {{subRep1, subRep3}, {subRep3, subRep2, subRep1}};
406
407         startRep["iarr"] = iarr;
408         startRep["darr"] = darr;
409         startRep["barr"] = barr;
410         startRep["strarr"] = strarr;
411         startRep["objarr"] = objarr;
412
413         // Encode/decode
414         OC::MessageContainer mc1;
415         mc1.addRepresentation(startRep);
416
417         OCRepPayload* cstart = mc1.getPayload();
418         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
419
420         uint8_t* cborData;
421         size_t cborSize;
422         OCPayload* cparsed;
423         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
424         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
425                     cborData, cborSize));
426         OCPayloadDestroy((OCPayload*)cstart);
427         OICFree(cborData);
428
429         OC::MessageContainer mc2;
430         mc2.setPayload(cparsed);
431         EXPECT_EQ(1u, mc2.representations().size());
432         const OC::OCRepresentation& r = mc2.representations()[0];
433
434         // Test
435         std::vector<std::vector<int>> iarr2 = r["iarr"];
436         std::vector<std::vector<double>> darr2 = r["darr"];
437         std::vector<std::vector<bool>> barr2 = r["barr"];
438         std::vector<std::vector<std::string>> strarr2 = r["strarr"];
439         std::vector<std::vector<OC::OCRepresentation>> objarr2 = r["objarr"];
440
441         // Note: due to the way that the CSDK works, all 2d arrays need to be rectangular.
442         // Since std::vector doesn't require this, items received on the other side end up
443         // being backfilled.  This section removes the backfilling
444         iarr2[1].pop_back();
445         darr2[2].pop_back();
446         barr2[1].pop_back();
447         strarr2[0].pop_back();
448         objarr2[0].pop_back();
449
450         EXPECT_EQ(iarr, iarr2);
451         EXPECT_EQ(darr, darr2);
452         EXPECT_EQ(barr, barr2);
453         EXPECT_EQ(strarr, strarr2);
454         EXPECT_EQ(objarr, objarr2);
455         OCPayloadDestroy(cparsed);
456     }
457
458     TEST(RepresentationEncoding, ThreeDVectors)
459     {
460         // Setup
461         OC::OCRepresentation startRep;
462
463         OC::OCRepresentation subRep1;
464         OC::OCRepresentation subRep2;
465         OC::OCRepresentation subRep3;
466         subRep1.setNULL("NullAttr");
467         subRep1.setValue("IntAttr", 77);
468         subRep2.setValue("DoubleAttr", 3.333);
469         subRep2.setValue("BoolAttr", true);
470         subRep3.setValue("StringAttr", std::string("String attr"));
471
472         std::vector<std::vector<std::vector<int>>> iarr
473             {{{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}},{{13,14,15},{16,17,18}}};
474         std::vector<std::vector<std::vector<double>>> darr
475             {{{1.1,2.2,3.3},{4.4,5.5,6.6}},
476                 {{7.7,8.7,9.7},{10.7,11.7,12.7}},
477                 {{13.7,14.7,15.7},{16.7,17.7,18.7}}};
478         std::vector<std::vector<std::vector<bool>>> barr
479             {{{false, true},{true, false}},{{false, true},{true, false}}};
480         std::vector<std::vector<std::vector<std::string>>> strarr
481             {
482                 {{"item1", "item2"},{"item3", "item4"}},
483                 {{"item5", "item6"},{"item7", "item8"}},
484                 {{"item9", "item10"},{"item11", ""}}
485             };
486         std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr
487             {
488                 {{subRep1, subRep2},{subRep3, subRep1}},
489                 {{subRep2, subRep3},{subRep2, subRep1}},
490                 {{subRep3, subRep2},{subRep1, subRep2}}
491             };
492
493         startRep["iarr"] = iarr;
494         startRep["darr"] = darr;
495         startRep["barr"] = barr;
496         startRep["strarr"] = strarr;
497         startRep["objarr"] = objarr;
498
499         // Encode/decode
500         OC::MessageContainer mc1;
501         mc1.addRepresentation(startRep);
502
503         OCRepPayload* cstart = mc1.getPayload();
504         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
505
506         uint8_t* cborData;
507         size_t cborSize;
508         OCPayload* cparsed;
509         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
510         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
511                     cborData, cborSize));
512         OCPayloadDestroy((OCPayload*)cstart);
513         OICFree(cborData);
514
515         OC::MessageContainer mc2;
516         mc2.setPayload(cparsed);
517         EXPECT_EQ(1u, mc2.representations().size());
518         const OC::OCRepresentation& r = mc2.representations()[0];
519
520         // Test
521         std::vector<std::vector<std::vector<int>>> iarr2 = r["iarr"];
522         std::vector<std::vector<std::vector<double>>> darr2 = r["darr"];
523         std::vector<std::vector<std::vector<bool>>> barr2 = r["barr"];
524         std::vector<std::vector<std::vector<std::string>>> strarr2 = r["strarr"];
525         std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr2 = r["objarr"];
526
527         EXPECT_EQ(iarr, iarr2);
528         EXPECT_EQ(darr, darr2);
529         EXPECT_EQ(barr, barr2);
530         EXPECT_EQ(strarr, strarr2);
531         EXPECT_EQ(objarr, objarr2);
532         OCPayloadDestroy(cparsed);
533     }
534
535     TEST(RepresentationEncoding, ThreeDVectorsJagged)
536     {
537         // Setup
538         OC::OCRepresentation startRep;
539
540         OC::OCRepresentation subRep1;
541         OC::OCRepresentation subRep2;
542         OC::OCRepresentation subRep3;
543         subRep1.setNULL("NullAttr");
544         subRep1.setValue("IntAttr", 77);
545         subRep2.setValue("DoubleAttr", 3.333);
546         subRep2.setValue("BoolAttr", true);
547         subRep3.setValue("StringAttr", std::string("String attr"));
548
549         std::vector<std::vector<std::vector<int>>> iarr
550             {
551                 {{1,2,3},{4,5,6}},
552                 {{7,8,9},{10,12}},
553                 {{13,14,15},{16,17,18}}
554             };
555         std::vector<std::vector<std::vector<double>>> darr
556             {
557                 {{1.1,2.2,3.3},{4.4,5.5,6.6}},
558                 {{7.7,8.7,9.7},{10.7,12.7}},
559                 {{13.7,14.7,15.7},{16.7,17.7,18.7}}
560             };
561         std::vector<std::vector<std::vector<bool>>> barr
562             {
563                 {{false, true},{true}},
564                 {{false, true},{true, false}}
565             };
566         std::vector<std::vector<std::vector<std::string>>> strarr
567             {
568                 {{"item1", "item2"},{"item3", "item4"}},
569                 {{"item5", "item6"},{"item8"}},
570                 {{"item9", "item10"},{"item11", ""}}
571             };
572         std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr
573             {
574                 {{subRep1, subRep2},{subRep3, subRep1}},
575                 {{subRep2, subRep3},{subRep2}},
576                 {{subRep3, subRep2}}
577             };
578
579         startRep["iarr"] = iarr;
580         startRep["darr"] = darr;
581         startRep["barr"] = barr;
582         startRep["strarr"] = strarr;
583         startRep["objarr"] = objarr;
584
585         // Encode/decode
586         OC::MessageContainer mc1;
587         mc1.addRepresentation(startRep);
588
589         OCRepPayload* cstart = mc1.getPayload();
590         EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
591
592         uint8_t* cborData;
593         size_t cborSize;
594         OCPayload* cparsed;
595         EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
596         EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
597                     cborData, cborSize));
598         OCPayloadDestroy((OCPayload*)cstart);
599         OICFree(cborData);
600
601         OC::MessageContainer mc2;
602         mc2.setPayload(cparsed);
603         EXPECT_EQ(1u, mc2.representations().size());
604         const OC::OCRepresentation& r = mc2.representations()[0];
605
606         // Test
607         std::vector<std::vector<std::vector<int>>> iarr2 = r["iarr"];
608         std::vector<std::vector<std::vector<double>>> darr2 = r["darr"];
609         std::vector<std::vector<std::vector<bool>>> barr2 = r["barr"];
610         std::vector<std::vector<std::vector<std::string>>> strarr2 = r["strarr"];
611         std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr2 = r["objarr"];
612
613         // Note: due to the way that the CSDK works, all 3d arrays need to be cuboidal.
614         // Since std::vector doesn't require this, items received on the other side end up
615         // being backfilled.  This section removes the backfilling
616         iarr2[1][1].pop_back();
617         darr2[1][1].pop_back();
618         barr2[0][1].pop_back();
619         strarr2[1][1].pop_back();
620         objarr2[1][1].pop_back();
621         objarr2[2].pop_back();
622
623         EXPECT_EQ(iarr, iarr2);
624         EXPECT_EQ(darr, darr2);
625         EXPECT_EQ(barr, barr2);
626         EXPECT_EQ(strarr, strarr2);
627         EXPECT_EQ(objarr, objarr2);
628         OCPayloadDestroy(cparsed);
629     }
630 }