blob: ae94a7f60fdc2fd65030e50f3c00e9a116490f61 [file] [log] [blame]
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
==============================================================================*/
/*==============================================================================
Modifications beyond the version released on CAF are under the MIT license:
Copyright 2018 Laurence Lundblade
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==============================================================================*/
#include "qcbor.h"
#include "qcbor_encode_tests.h"
#include <strings.h>
#include <stdlib.h>
// TODO: -- test on a 32-bit machine)
// TODO: test QCBOR_MAX_ITEMS_IN_ARRAY (this is very large...)
#ifdef PRINT_FUNCTIONS_FOR_DEBUGGINGXX
#include <stdio.h>
// ifdef these out to not have compiler warnings
static void printencoded(const uint8_t *pEncoded, size_t nLen)
{
int i;
for(i = 0; i < nLen; i++) {
uint8_t Z = pEncoded[i];
printf("%02x ", Z);
}
printf("\n");
fflush(stdout);
}
#endif
#include <stdio.h>
int Compare(UsefulBufC U1, UsefulBufC U2) {
int i;
for(i = 0; i < U1.len; i++) {
if(((uint8_t *)U1.ptr)[i] != ((uint8_t *)U2.ptr)[i]) {
printf("%d 0x%x 0x%x\n", i, ((uint8_t *)U1.ptr)[i], ((uint8_t *)U2.ptr)[i]);
return 1;
}
}
return 0;
}
/*#define CheckResults(Enc, Expected) \
UsefulBuf_Compare(Enc, (UsefulBufC){Expected, sizeof(Expected)}) */
#define CheckResults(Enc, Expected) \
Compare(Enc, (UsefulBufC){Expected, sizeof(Expected)})
/*
Some very minimal tests.
*/
int basic_encode_test()
{
// Very simple CBOR, a map with one boolean that is true in it
UsefulBuf_MakeStackUB(MemoryForEncoded, 100);
QCBOREncodeContext EC;
QCBOREncode_Init(&EC, MemoryForEncoded);
QCBOREncode_OpenMap(&EC);
QCBOREncode_AddBoolToMapN(&EC, 66, true);
QCBOREncode_CloseMap(&EC);
UsefulBufC Encoded;
if(QCBOREncode_Finish2(&EC, &Encoded)) {
return -3;
}
// Decode it and see that is right
QCBORDecodeContext DC;
QCBORItem Item;
QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_MAP) {
return -1;
}
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_TRUE) {
return -1;
}
if(QCBORDecode_Finish(&DC)) {
return -2;
}
// Make another encoded message with the CBOR from the previous put into this one
UsefulBuf_MakeStackUB(MemoryForEncoded2, 100);
QCBOREncode_Init(&EC, MemoryForEncoded2);
QCBOREncode_OpenArray(&EC);
QCBOREncode_AddUInt64(&EC, 451);
QCBOREncode_AddEncoded(&EC, Encoded);
QCBOREncode_OpenMap(&EC);
QCBOREncode_AddEncodedToMapN(&EC, -70000, Encoded);
QCBOREncode_CloseMap(&EC);
QCBOREncode_CloseArray(&EC);
UsefulBufC Encoded2;
if(QCBOREncode_Finish2(&EC, &Encoded2)) {
return -3;
}
/*
[ // 0 1:3
451, // 1 1:2
{ // 1 1:2 2:1
66: true // 2 1:1
},
{ // 1 1:1 2:1
-70000: { // 2 1:1 2:1 3:1
66: true // 3 XXXXXX
}
}
]
83 # array(3)
19 01C3 # unsigned(451)
A1 # map(1)
18 42 # unsigned(66)
F5 # primitive(21)
A1 # map(1)
3A 0001116F # negative(69999)
A1 # map(1)
18 42 # unsigned(66)
F5 # primitive(21)
*/
// Decode it and see if it is OK
QCBORDecode_Init(&DC, Encoded2, QCBOR_DECODE_MODE_NORMAL);
// 0 1:3
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) {
return -1;
}
// 1 1:2
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_INT64 || Item.val.uint64 != 451) {
return -1;
}
// 1 1:2 2:1
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) {
return -1;
}
// 2 1:1
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_TRUE) {
return -1;
}
// 1 1:1 2:1
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) {
return -1;
}
// 2 1:1 2:1 3:1
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1 || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != -70000) {
return -1;
}
// 3 XXXXXX
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_TRUE || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != 66) {
return -1;
}
if(QCBORDecode_Finish(&DC)) {
return -2;
}
return 0;
}
static const uint8_t pExpectedEncodedAll[] = {
0x98, 0x29, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8,
0x64, 0x1a, 0x05, 0x5d, 0x23, 0x15, 0x65, 0x49, 0x4e, 0x54,
0x36, 0x34, 0xd8, 0x4c, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x16,
0xaf, 0x2b, 0x15, 0x00, 0x38, 0x2b, 0xa4, 0x63, 0x4c, 0x42,
0x4c, 0x18, 0x4d, 0x23, 0x18, 0x58, 0x78, 0x1a, 0x4e, 0x45,
0x47, 0x4c, 0x42, 0x4c, 0x54, 0x48, 0x41, 0x54, 0x20, 0x49,
0x53, 0x20, 0x4b, 0x49, 0x4e, 0x44, 0x20, 0x4f, 0x46, 0x20,
0x4c, 0x4f, 0x4e, 0x47, 0x3b, 0x00, 0x00, 0x02, 0x2d, 0x9a,
0xc6, 0x94, 0x55, 0x3a, 0x05, 0xf5, 0xe0, 0xff, 0x3a, 0x2f,
0xaf, 0x07, 0xff, 0x65, 0x4a, 0x61, 0x69, 0x6d, 0x65, 0xd8,
0x58, 0xfa, 0x40, 0x49, 0x0f, 0xd0, 0x66, 0x53, 0x74, 0x72,
0x65, 0x65, 0x74, 0xd8, 0x63, 0xfb, 0x40, 0x21, 0x4f, 0x01,
0x96, 0xd8, 0xf4, 0xf9, 0xfa, 0x3f, 0x80, 0x00, 0x00, 0xfb,
0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x63,
0x66, 0x6f, 0x6f, 0xfa, 0x45, 0x98, 0xb8, 0x00, 0x39, 0x03,
0xe6, 0xfa, 0x44, 0x79, 0xc0, 0x00, 0x66, 0x66, 0x6f, 0x6f,
0x66, 0x6f, 0x6f, 0xfb, 0x41, 0x58, 0xf7, 0x7d, 0xc0, 0x00,
0x00, 0x00, 0x39, 0xaf, 0xc6, 0xfb, 0x40, 0xf5, 0xba, 0x70,
0x00, 0x00, 0x00, 0x00, 0xc1, 0x1a, 0x8e, 0x15, 0x1c, 0x8a,
0xa3, 0x74, 0x4c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65,
0x44, 0x65, 0x6e, 0x69, 0x73, 0x52, 0x69, 0x74, 0x63, 0x68,
0x69, 0x65, 0xc1, 0x1a, 0x53, 0x72, 0x4e, 0x00, 0x66, 0x74,
0x69, 0x6d, 0x65, 0x28, 0x29, 0xc1, 0x1a, 0x58, 0x0d, 0x41,
0x72, 0x39, 0x07, 0xb0, 0xc1, 0x1a, 0x58, 0x0d, 0x3f, 0x76,
0x42, 0xff, 0x00, 0xa3, 0x66, 0x62, 0x69, 0x6e, 0x62, 0x69,
0x6e, 0xda, 0x00, 0x01, 0x86, 0xa0, 0x41, 0x00, 0x66, 0x62,
0x6c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x01, 0x02, 0x03, 0x00,
0x44, 0x04, 0x02, 0x03, 0xfe, 0x6f, 0x62, 0x61, 0x72, 0x20,
0x62, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x62, 0x61,
0x72, 0x64, 0x6f, 0x6f, 0x66, 0x0a, 0xd8, 0x20, 0x78, 0x6b,
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, 0x74, 0x61,
0x63, 0x6b, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x65, 0x73, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x32, 0x38, 0x30, 0x35, 0x39,
0x36, 0x39, 0x37, 0x2f, 0x68, 0x6f, 0x77, 0x2d, 0x64, 0x6f,
0x2d, 0x69, 0x2d, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x2d,
0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x2d, 0x64, 0x65,
0x62, 0x75, 0x67, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2d, 0x62, 0x75, 0x69, 0x6c,
0x64, 0x73, 0x2d, 0x69, 0x6e, 0x2d, 0x78, 0x63, 0x6f, 0x64,
0x65, 0x2d, 0x36, 0x2d, 0x37, 0x2d, 0x38, 0xd8, 0x22, 0x78,
0x1c, 0x59, 0x57, 0x35, 0x35, 0x49, 0x47, 0x4e, 0x68, 0x63,
0x6d, 0x35, 0x68, 0x62, 0x43, 0x42, 0x77, 0x62, 0x47, 0x56,
0x68, 0x63, 0x33, 0x56, 0x79, 0x5a, 0x51, 0x3d, 0x3d, 0xd8,
0x23, 0x67, 0x5b, 0x5e, 0x61, 0x62, 0x63, 0x5d, 0x2b, 0xd8,
0x24, 0x79, 0x01, 0x57, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e,
0x30, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74,
0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65,
0x64, 0x3b, 0x0a, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72,
0x79, 0x3d, 0x22, 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75,
0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74,
0x22, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61,
0x72, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x20, 0x69, 0x6e, 0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66,
0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d,
0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61,
0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f,
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65,
0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61,
0x69, 0x6e, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69,
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79,
0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58,
0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72,
0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e,
0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a,
0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69,
0x6e, 0x3b, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
0x2d, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68,
0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65,
0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74,
0x2e, 0x74, 0x78, 0x74, 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69,
0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20,
0x74, 0x65, 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58,
0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79,
0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x2d, 0xae, 0x65, 0x23,
0x23, 0x23, 0x23, 0x23, 0x6f, 0x66, 0x6f, 0x6f, 0x20, 0x62,
0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, 0x6f, 0x6f,
0x64, 0x5f, 0x5f, 0x5f, 0x5f, 0x67, 0x66, 0x6f, 0x6f, 0x20,
0x62, 0x61, 0x72, 0x66, 0x28, 0x29, 0x28, 0x29, 0x28, 0x29,
0xd9, 0x03, 0xe8, 0x6b, 0x72, 0x61, 0x62, 0x20, 0x72, 0x61,
0x62, 0x20, 0x6f, 0x6f, 0x66, 0x16, 0x6f, 0x66, 0x6f, 0x6f,
0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66,
0x6f, 0x6f, 0x62, 0x5e, 0x5e, 0x69, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x66, 0x18, 0x63, 0x6d, 0x66, 0x66,
0x66, 0x66, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x66, 0x63, 0x52, 0x46, 0x43, 0xd8, 0x20, 0x78, 0x31, 0x68,
0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x6f, 0x6f,
0x6c, 0x73, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72,
0x67, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x2f, 0x72, 0x66, 0x63,
0x37, 0x30, 0x34, 0x39, 0x23, 0x73, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x2d, 0x32, 0x2e, 0x34, 0x2e, 0x35, 0x18, 0x89,
0xd8, 0x20, 0x6f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
0x63, 0x62, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x2f, 0x68, 0x77,
0x68, 0x65, 0x6e, 0x69, 0x6d, 0x36, 0x34, 0xd8, 0x22, 0x6c,
0x63, 0x47, 0x78, 0x6c, 0x59, 0x58, 0x4e, 0x31, 0x63, 0x6d,
0x55, 0x75, 0x18, 0x40, 0xd8, 0x22, 0x68, 0x63, 0x33, 0x56,
0x79, 0x5a, 0x53, 0x34, 0x3d, 0x64, 0x70, 0x6f, 0x70, 0x6f,
0xd8, 0x23, 0x68, 0x31, 0x30, 0x30, 0x5c, 0x73, 0x2a, 0x6d,
0x6b, 0x38, 0x32, 0xd8, 0x23, 0x66, 0x70, 0x65, 0x72, 0x6c,
0x5c, 0x42, 0x63, 0x4e, 0x65, 0x64, 0xd8, 0x24, 0x79, 0x01,
0x57, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x43,
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70,
0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61,
0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0a,
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22,
0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61,
0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x22, 0x0a, 0x0a,
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20,
0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e,
0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, 0x6f, 0x72, 0x6d,
0x61, 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58,
0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20,
0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65,
0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0a,
0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x74, 0x65,
0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58,
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74,
0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65,
0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x0a,
0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69,
0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e,
0x74, 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d,
0x65, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
0x74, 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69,
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61,
0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x65, 0x78,
0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65,
0x78, 0x74, 0x2d, 0x2d, 0x0a, 0xd8, 0x24, 0x79, 0x01, 0x57,
0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x43, 0x6f,
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65,
0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72,
0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0a, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22, 0x58,
0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72,
0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x22, 0x0a, 0x0a, 0x54,
0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6d,
0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, 0x20,
0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61,
0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58,
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74,
0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65,
0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0a, 0x0a,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x74, 0x65, 0x78,
0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65,
0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78,
0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x0a, 0x43,
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, 0x73,
0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20,
0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74,
0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65,
0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74,
0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63,
0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74,
0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, 0x78,
0x74, 0x2d, 0x2d, 0xc0, 0x74, 0x32, 0x30, 0x30, 0x33, 0x2d,
0x31, 0x32, 0x2d, 0x31, 0x33, 0x54, 0x31, 0x38, 0x3a, 0x33,
0x30, 0x3a, 0x30, 0x32, 0x5a, 0xa2, 0x68, 0x42, 0x65, 0x64,
0x20, 0x74, 0x69, 0x6d, 0x65, 0xc0, 0x78, 0x1c, 0x32, 0x30,
0x30, 0x33, 0x2d, 0x31, 0x32, 0x2d, 0x31, 0x33, 0x54, 0x31,
0x38, 0x3a, 0x33, 0x30, 0x3a, 0x30, 0x32, 0x2e, 0x32, 0x35,
0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x18, 0x58, 0xc0, 0x78,
0x1c, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x31, 0x32, 0x2d, 0x31,
0x33, 0x54, 0x31, 0x38, 0x3a, 0x33, 0x30, 0x3a, 0x30, 0x32,
0x2e, 0x32, 0x35, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xf7,
0xa3, 0x64, 0x64, 0x61, 0x72, 0x65, 0xd8, 0x42, 0xf5, 0x62,
0x75, 0x75, 0xf4, 0x1a, 0x00, 0x0b, 0x41, 0x62, 0xf6, 0x80,
0xa3, 0x78, 0x1c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x74, 0x61, 0x67, 0x67, 0x65, 0x64, 0x20,
0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x61, 0x72, 0x72, 0x61,
0x79, 0xd9, 0x04, 0x45, 0x80, 0x65, 0x61, 0x6c, 0x61, 0x62,
0x6c, 0x80, 0x18, 0x2a, 0x80, 0xa1, 0x68, 0x69, 0x6e, 0x20,
0x61, 0x20, 0x6d, 0x61, 0x70, 0xa1, 0x19, 0x15, 0xb4, 0xa1,
0x6e, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x61,
0x20, 0x69, 0x6e, 0x20, 0x61, 0xd9, 0x23, 0x7f, 0xa0, 0xa5,
0x62, 0x73, 0x31, 0xd8, 0x58, 0xf8, 0xff, 0x62, 0x73, 0x32,
0xe0, 0x62, 0x73, 0x33, 0xd8, 0x58, 0xf8, 0x21, 0x1a, 0x05,
0x44, 0x8c, 0x06, 0xd8, 0x58, 0xf8, 0xff, 0x18, 0x59, 0xd8,
0x58, 0xf3, 0xd8, 0x25, 0x50, 0x53, 0x4d, 0x41, 0x52, 0x54,
0x43, 0x53, 0x4c, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41,
0x32, 0xa2, 0x64, 0x55, 0x55, 0x55, 0x55, 0xd8, 0x25, 0x50,
0x53, 0x4d, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4c, 0x54, 0x54,
0x43, 0x46, 0x49, 0x43, 0x41, 0x32, 0x18, 0x63, 0xd8, 0x25,
0x50, 0x53, 0x4d, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4c, 0x54,
0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32, 0xf5, 0xf4, 0xa2,
0x71, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0xf5, 0x19,
0x10, 0x41, 0xf5, 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x63, 0x42, 0x4E, 0x2B,
0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x40, 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x63, 0x42, 0x4E, 0x2D, 0xC3, 0x49,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
0x3F, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
static const char *szMIME = "\
MIME-Version: 1.0\n\
Content-Type: multipart/mixed;\n\
boundary=\"XXXXboundary text\"\n\
\n\
This is a multipart message in MIME format.\n\
\n\
--XXXXboundary text\n\
Content-Type: text/plain\n\
\n\
this is the body text\n\
\n\
--XXXXboundary text\n\
Content-Type: text/plain;\n\
Content-Disposition: attachment;\n\
filename=\"test.txt\"\n\
\n\
this is the attachment text\n\
\n\
--XXXXboundary text--";
int AllAddMethodsTest()
{
QCBOREncodeContext ECtx;
int nReturn = 0;
uint8_t pEncoded[3000];
size_t nEncodedLen = sizeof(pEncoded);
QCBOREncode_Init(&ECtx, (UsefulBuf){pEncoded, nEncodedLen});
QCBOREncode_OpenArray(&ECtx);
// Non-map ints
QCBOREncode_AddUInt64_3(&ECtx, "UINT62", QCBOR_NO_INT_LABEL, 100, 89989909);
QCBOREncode_AddInt64_3(&ECtx, "INT64", QCBOR_NO_INT_LABEL, 76, 77689989909);
QCBOREncode_AddUInt64(&ECtx,0);
QCBOREncode_AddInt64(&ECtx, -44);
// ints that go in maps
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddUInt64ToMap(&ECtx, "LBL", 77);
QCBOREncode_AddUInt64ToMapN(&ECtx, -4, 88);
QCBOREncode_AddInt64ToMap(&ECtx, "NEGLBLTHAT IS KIND OF LONG", -2394893489238);
QCBOREncode_AddInt64ToMapN(&ECtx, -100000000, -800000000);
QCBOREncode_CloseMap(&ECtx);
// floats and doubles
QCBOREncode_AddFloat_3(&ECtx, "Jaime", QCBOR_NO_INT_LABEL, 88, 3.14159);
QCBOREncode_AddDouble_3(&ECtx, "Street", QCBOR_NO_INT_LABEL, 99, 8.654309);
QCBOREncode_AddFloat(&ECtx, 1);
QCBOREncode_AddDouble(&ECtx, 1);
// floats and doubles that go in map
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddFloatToMap(&ECtx, "foo", 4887);
QCBOREncode_AddFloatToMapN(&ECtx, -999, 999);
QCBOREncode_AddDoubleToMap(&ECtx, "foofoo", 6544887);
QCBOREncode_AddDoubleToMapN(&ECtx, -44999, 88999);
QCBOREncode_CloseMap(&ECtx);
// Epoch Date
QCBOREncode_AddDateEpoch(&ECtx, 2383748234);
// Epoch date with labels
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddDateEpoch_2(&ECtx, "LongLiveDenisRitchie", QCBOR_NO_INT_LABEL, 1400000000);
QCBOREncode_AddDateEpochToMap(&ECtx, "time()", 1477263730);
QCBOREncode_AddDateEpochToMapN(&ECtx, -1969, 1477263222);
QCBOREncode_CloseMap(&ECtx);
// Binary blobs
QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {(uint8_t []){0xff, 0x00}, 2}));
// binary blobs in maps
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddBytes_3(&ECtx, "binbin", QCBOR_NO_INT_LABEL, 100000, ((UsefulBufC) {(uint8_t []){0x00}, 1}));
QCBOREncode_AddBytesToMap(&ECtx, "blabel", ((UsefulBufC){(uint8_t []){0x01, 0x02, 0x03}, 3}));
QCBOREncode_AddBytesToMapN(&ECtx, 0, ((UsefulBufC){(uint8_t []){0x04, 0x02, 0x03, 0xfe}, 4}));
QCBOREncode_CloseMap(&ECtx);
// text blobs
QCBOREncode_AddText(&ECtx, SZLiteralToUsefulBufC("bar bar foo bar"));
QCBOREncode_AddSZString(&ECtx, "oof\n");
QCBOREncode_AddURI(&ECtx, SZLiteralToUsefulBufC("http://stackoverflow.com/questions/28059697/how-do-i-toggle-between-debug-and-release-builds-in-xcode-6-7-8"));
QCBOREncode_AddB64Text(&ECtx, SZLiteralToUsefulBufC("YW55IGNhcm5hbCBwbGVhc3VyZQ=="));
QCBOREncode_AddRegex(&ECtx, SZLiteralToUsefulBufC("[^abc]+"));
QCBOREncode_AddMIMEData(&ECtx, UsefulBuf_FromSZ(szMIME));
// text blobs in maps
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddTextToMap(&ECtx, "#####", SZLiteralToUsefulBufC("foo bar foo foo"));
QCBOREncode_AddText_3(&ECtx, "____", QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, SZLiteralToUsefulBufC("foo bar"));
QCBOREncode_AddSZString_3(&ECtx, "()()()", QCBOR_NO_INT_LABEL, 1000, "rab rab oof");
QCBOREncode_AddTextToMapN(&ECtx,22, SZLiteralToUsefulBufC("foo foo foo foo"));
QCBOREncode_AddSZStringToMap(&ECtx, "^^", "oooooooof");
QCBOREncode_AddSZStringToMapN(&ECtx, 99, "ffffoooooooof");
QCBOREncode_AddURIToMap(&ECtx, "RFC", SZLiteralToUsefulBufC("https://tools.ietf.org/html/rfc7049#section-2.4.5"));
QCBOREncode_AddURIToMapN(&ECtx, 0x89, SZLiteralToUsefulBufC("http://cbor.me/"));
QCBOREncode_AddB64TextToMap(&ECtx, "whenim64", SZLiteralToUsefulBufC("cGxlYXN1cmUu"));
QCBOREncode_AddB64TextToMapN(&ECtx, 64, SZLiteralToUsefulBufC("c3VyZS4="));
QCBOREncode_AddRegexToMap(&ECtx, "popo", SZLiteralToUsefulBufC("100\\s*mk")); // x code string literal bug
QCBOREncode_AddRegexToMapN(&ECtx, -51, SZLiteralToUsefulBufC("perl\\B")); // x code string literal bug
QCBOREncode_AddMIMEDataToMap(&ECtx, "Ned", UsefulBuf_FromSZ(szMIME));
QCBOREncode_AddMIMEDataToMapN(&ECtx, 10, UsefulBuf_FromSZ(szMIME));
QCBOREncode_CloseMap(&ECtx);
// Date strings
QCBOREncode_AddDateString(&ECtx, "2003-12-13T18:30:02Z");
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddDateStringToMap(&ECtx, "Bed time", "2003-12-13T18:30:02.25+01:00");
QCBOREncode_AddDateStringToMapN(&ECtx, 88, "2003-12-13T18:30:02.25+01:00");
QCBOREncode_CloseMap(&ECtx);
// true / false ...
QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF);
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddSimple_3(&ECtx, "dare", QCBOR_NO_INT_LABEL, 66, CBOR_SIMPLEV_TRUE);
QCBOREncode_AddSimpleToMap(&ECtx, "uu", CBOR_SIMPLEV_FALSE);
QCBOREncode_AddSimpleToMapN(&ECtx, 737634, CBOR_SIMPLEV_NULL);
QCBOREncode_CloseMap(&ECtx);
// opening an array
QCBOREncode_OpenArray(&ECtx);
QCBOREncode_CloseArray(&ECtx);
// opening arrays in a map
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_OpenArray_3(&ECtx, "label and tagged empty array", QCBOR_NO_INT_LABEL, 1093);
QCBOREncode_CloseArray(&ECtx);
QCBOREncode_OpenArrayInMap(&ECtx, "alabl");
QCBOREncode_CloseArray(&ECtx);
QCBOREncode_OpenArrayInMapN(&ECtx, 42);
QCBOREncode_CloseArray(&ECtx);
QCBOREncode_CloseMap(&ECtx);
// opening maps with labels and tagging
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_OpenMapInMap(&ECtx, "in a map");
QCBOREncode_OpenMapInMapN(&ECtx, 5556);
QCBOREncode_OpenMap_3(&ECtx, "in a in a in a", QCBOR_NO_INT_LABEL, 9087);
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseMap(&ECtx);
// Extended simple values (these are not standard...)
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddRawSimple_3(&ECtx, "s1", QCBOR_NO_INT_LABEL, 88, 255);
QCBOREncode_AddRawSimple_3(&ECtx, "s2", QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, 0);
QCBOREncode_AddRawSimple_3(&ECtx, "s3", QCBOR_NO_INT_LABEL, 88, 33);
QCBOREncode_AddRawSimple_3(&ECtx, NULL, 88378374, 88, 255);
QCBOREncode_AddRawSimple_3(&ECtx, NULL, 89, 88, 19);
QCBOREncode_CloseMap(&ECtx);
// UUIDs
static uint8_t ppppUUID[] = {0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4C, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32};
UsefulBufC XXUUID = ByteArrayLiteralToUsefulBufC(ppppUUID);
QCBOREncode_AddBinaryUUID(&ECtx, XXUUID);
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddBinaryUUIDToMap(&ECtx, "UUUU", XXUUID);
QCBOREncode_AddBinaryUUIDToMapN(&ECtx, 99, XXUUID);
QCBOREncode_CloseMap(&ECtx);
// Bool
QCBOREncode_AddBool(&ECtx, true);
QCBOREncode_AddBool(&ECtx, false);
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddBoolToMap(&ECtx, "George is the man", true);
QCBOREncode_AddBoolToMapN(&ECtx, 010101, true);
QCBOREncode_CloseMap(&ECtx);
static uint8_t pBignum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
UsefulBufC BIGNUM = ByteArrayLiteralToUsefulBufC(pBignum);
QCBOREncode_AddPositiveBignum(&ECtx, BIGNUM);
QCBOREncode_AddNegativeBignum(&ECtx, BIGNUM);
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddPositiveBignumToMap(&ECtx, "BN+", BIGNUM);
QCBOREncode_AddPositiveBignumToMapN(&ECtx, 64, BIGNUM);
QCBOREncode_AddNegativeBignumToMap(&ECtx, "BN-", BIGNUM);
QCBOREncode_AddNegativeBignumToMapN(&ECtx, -64, BIGNUM);
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseArray(&ECtx);
UsefulBufC Enc;
if(QCBOREncode_Finish2(&ECtx, &Enc)) {
nReturn = -1;
goto Done;
}
//printencodedE(Enc);
if(CheckResults(Enc, pExpectedEncodedAll))
nReturn = -1;
Done:
return nReturn;
}
// todo -- add a test for counting the top level items and adding it back in with AddRaw()
static const uint8_t pExpectedEncodedInts[] = {
0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff,
0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff,
0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff,
0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01,
0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39,
0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd,
0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38,
0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00,
0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18,
0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00,
0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff,
0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00,
0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02,
0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff,
0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a,
0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff,
0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff};
/*
Test the generation of integers. This also ends up testing
encoding of all the different lengths. It encodes integers
of many lengths and values, especially around the boundaries
for different types of integers. It compares the output
to expected values generated from http://cbor.me.
*/
int IntegerValuesTest1()
{
QCBOREncodeContext ECtx;
int nReturn = 0;
uint8_t pEncoded[1000];
size_t nEncodedLen = sizeof(pEncoded);
QCBOREncode_Init(&ECtx, (UsefulBuf){pEncoded, nEncodedLen});
QCBOREncode_OpenArray(&ECtx);
QCBOREncode_AddInt64(&ECtx, -9223372036854775807LL - 1);
QCBOREncode_AddInt64(&ECtx, -4294967297);
QCBOREncode_AddInt64(&ECtx, -4294967296);
QCBOREncode_AddInt64(&ECtx, -4294967295);
QCBOREncode_AddInt64(&ECtx, -4294967294);
QCBOREncode_AddInt64(&ECtx, -2147483648);
QCBOREncode_AddInt64(&ECtx, -2147483647);
QCBOREncode_AddInt64(&ECtx, -65538);
QCBOREncode_AddInt64(&ECtx, -65537);
QCBOREncode_AddInt64(&ECtx, -65536);
QCBOREncode_AddInt64(&ECtx, -65535);
QCBOREncode_AddInt64(&ECtx, -65534);
QCBOREncode_AddInt64(&ECtx, -257);
QCBOREncode_AddInt64(&ECtx, -256);
QCBOREncode_AddInt64(&ECtx, -255);
QCBOREncode_AddInt64(&ECtx, -254);
QCBOREncode_AddInt64(&ECtx, -25);
QCBOREncode_AddInt64(&ECtx, -24);
QCBOREncode_AddInt64(&ECtx, -23);
QCBOREncode_AddInt64(&ECtx, -1);
QCBOREncode_AddInt64(&ECtx, 0);
QCBOREncode_AddUInt64(&ECtx, 0ULL);
QCBOREncode_AddInt64(&ECtx, 1);
QCBOREncode_AddInt64(&ECtx, 22);
QCBOREncode_AddInt64(&ECtx, 23);
QCBOREncode_AddInt64(&ECtx, 24);
QCBOREncode_AddInt64(&ECtx, 25);
QCBOREncode_AddInt64(&ECtx, 26);
QCBOREncode_AddInt64(&ECtx, 254);
QCBOREncode_AddInt64(&ECtx, 255);
QCBOREncode_AddInt64(&ECtx, 256);
QCBOREncode_AddInt64(&ECtx, 257);
QCBOREncode_AddInt64(&ECtx, 65534);
QCBOREncode_AddInt64(&ECtx, 65535);
QCBOREncode_AddInt64(&ECtx, 65536);
QCBOREncode_AddInt64(&ECtx, 65537);
QCBOREncode_AddInt64(&ECtx, 65538);
QCBOREncode_AddInt64(&ECtx, 2147483647);
QCBOREncode_AddInt64(&ECtx, 2147483647);
QCBOREncode_AddInt64(&ECtx, 2147483648);
QCBOREncode_AddInt64(&ECtx, 2147483649);
QCBOREncode_AddInt64(&ECtx, 4294967294);
QCBOREncode_AddInt64(&ECtx, 4294967295);
QCBOREncode_AddInt64(&ECtx, 4294967296);
QCBOREncode_AddInt64(&ECtx, 4294967297);
QCBOREncode_AddInt64(&ECtx, 9223372036854775807LL);
QCBOREncode_AddUInt64(&ECtx, 18446744073709551615ULL);
QCBOREncode_CloseArray(&ECtx);
UsefulBufC Enc;
if(QCBOREncode_Finish2(&ECtx, &Enc)) {
nReturn = -1;
}
if(CheckResults(Enc, pExpectedEncodedInts))
return -1;
if(Enc.len != sizeof(pExpectedEncodedInts) || bcmp(pEncoded, pExpectedEncodedInts, Enc.len))
nReturn = -1;
//printencoded(pEncoded, nEncodedLen);
return(nReturn);
}
static uint8_t pExpectedEncodedSimple[] = {
0x85, 0xf5, 0xf4, 0xf6, 0xf7, 0xa1, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7};
int SimpleValuesTest1()
{
QCBOREncodeContext ECtx;
int nReturn = 0;
uint8_t pEncoded[100];
size_t nEncodedLen = sizeof(pEncoded);
QCBOREncode_Init(&ECtx, (UsefulBuf) {pEncoded, nEncodedLen});
QCBOREncode_OpenArray(&ECtx);
QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_TRUE);
QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_FALSE);
QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_NULL);
QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF);
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddSimpleToMap(&ECtx, "UNDef", CBOR_SIMPLEV_UNDEF);
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseArray(&ECtx);
UsefulBufC ECBOR;
if(QCBOREncode_Finish2(&ECtx, &ECBOR)) {
nReturn = -1;
}
if(ECBOR.len != sizeof(pExpectedEncodedSimple) || bcmp(pEncoded, pExpectedEncodedSimple, ECBOR.len))
nReturn = -1;
// printencoded(pEncoded, nEncodedLen);
return(nReturn);
}
static uint8_t pExpectedEncodedDates[] = {
0x83, 0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, 0x2d, 0x32, 0x31, 0x54,
0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, 0x30, 0x30,
0x5a, 0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0, 0xa2,
0x78, 0x19, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65,
0x20, 0x44, 0x61, 0x74, 0x65, 0x20, 0x66, 0x72,
0x6f, 0x6d, 0x20, 0x52, 0x46, 0x43, 0x20, 0x33,
0x33, 0x33, 0x39, 0xc0, 0x77, 0x31, 0x39, 0x38,
0x35, 0x2d, 0x30, 0x34, 0x2d, 0x31, 0x32, 0x54,
0x32, 0x33, 0x3a, 0x32, 0x30, 0x3a, 0x35, 0x30,
0x2e, 0x35, 0x32, 0x5a, 0x62, 0x53, 0x44, 0xc1,
0x19, 0x03, 0xe7
};
int EncodeDateTest()
{
QCBOREncodeContext ECtx;
int nReturn = 0;
uint8_t pEncoded[1000];
size_t nEncodedLen = sizeof(pEncoded);
QCBOREncode_Init(&ECtx, (UsefulBuf){pEncoded, nEncodedLen});
QCBOREncode_OpenArray(&ECtx);
QCBOREncode_AddDateString(&ECtx, "2013-03-21T20:04:00Z"); // from CBOR RFC
QCBOREncode_AddDateEpoch(&ECtx, 1363896240); // from CBOR RFC
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddDateStringToMap(&ECtx, "Sample Date from RFC 3339", "1985-04-12T23:20:50.52Z");
QCBOREncode_AddDateEpochToMap(&ECtx, "SD", 999);
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseArray(&ECtx);
if(QCBOREncode_Finish(&ECtx, &nEncodedLen)) {
nReturn = -1;
}
if(nEncodedLen != sizeof(pExpectedEncodedDates) || bcmp(pEncoded, pExpectedEncodedDates, nEncodedLen))
nReturn = -1;
//printencoded(pEncoded, nEncodedLen);
return(nReturn);
}
int ArrayNestingTest1()
{
QCBOREncodeContext ECtx;
int i;
int nReturn = 0;
UsefulBuf_MakeStackUB(Encode, 100);
QCBOREncode_Init(&ECtx, Encode);
for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) {
QCBOREncode_OpenArray(&ECtx);
}
for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) {
QCBOREncode_CloseArray(&ECtx);
}
size_t nEncodedLen;
if(QCBOREncode_Finish(&ECtx, &nEncodedLen)) {
printf("ArrayNestingTest1 Failed\n");
nReturn = -1;
}
//printencoded(pEncoded, nEncodedLen);
return(nReturn);
}
int ArrayNestingTest2()
{
QCBOREncodeContext ECtx;
int i;
int nReturn = 0;
UsefulBuf_MakeStackUB(Encode, 100);
QCBOREncode_Init(&ECtx, Encode);
for(i = QCBOR_MAX_ARRAY_NESTING+1; i; i--) {
QCBOREncode_OpenArray(&ECtx);
}
for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) {
QCBOREncode_CloseArray(&ECtx);
}
size_t nEncodedLen;
if(QCBOREncode_Finish(&ECtx, &nEncodedLen) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) {
nReturn = -1;
}
return(nReturn);
}
int ArrayNestingTest3()
{
QCBOREncodeContext ECtx;
int i;
int nReturn = 0;
UsefulBuf_MakeStackUB(Encode, 100);
QCBOREncode_Init(&ECtx, Encode);
for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) {
QCBOREncode_OpenArray(&ECtx);
}
for(i = QCBOR_MAX_ARRAY_NESTING+1 ; i; i--) {
QCBOREncode_CloseArray(&ECtx);
}
size_t nEncodedLen;
if(QCBOREncode_Finish(&ECtx, &nEncodedLen) != QCBOR_ERR_TOO_MANY_CLOSES) {
nReturn = -1;
}
return(nReturn);
}
#if 0
static uint8_t s_pFiveArrarys[] = {0x81, 0x81, 0x81, 0x81, 0x80};
static int EncodeRaw(uint8_t **pEncoded, size_t *pEncodedLen)
{
QCBOREncodeContext ECtx;
int nReturn = -1;
*pEncoded = NULL;
*pEncodedLen = INT32_MAX; // largest buffer this CBOR implementation will deal with
// loop runs CBOR encoding twice. First with no buffer to
// calucate the length so buffer can be allocated correctly,
// and last with the buffer to do the actual encoding
do {
QCBOREncode_Init(&ECtx, *pEncoded, *pEncodedLen);
QCBOREncode_OpenArray(&ECtx);
QCBOREncode_AddRaw(&ECtx, (EncodedCBORC){((UsefulBufC) {s_pFiveArrarys, 5}), 1});
QCBOREncode_AddRaw(&ECtx, (EncodedCBORC){((UsefulBufC) {pExpectedEncodedInts, sizeof(pExpectedEncodedInts)}), 1});
QCBOREncode_CloseArray(&ECtx);
if(QCBOREncode_Finish(&ECtx, pEncodedLen))
goto Done;
if(*pEncoded != NULL) {
nReturn = 0;
goto Done;
}
*pEncoded = malloc(*pEncodedLen);
} while(1);
Done:
return(nReturn);
}
// Validated at http://cbor.me and by manually examining its output
static uint8_t s_pEncodeRawExpected[] = {
0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x98, 0x2f,
0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, 0xff, 0x3a,
0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, 0xff, 0xff,
0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, 0x3a, 0x7f,
0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, 0x00, 0x01,
0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, 0xff, 0xff,
0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, 0x39, 0x01,
0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, 0xfd, 0x38,
0x18, 0x37, 0x36, 0x20, 0x00, 0x00, 0x01, 0x16,
0x17, 0x18, 0x18, 0x18, 0x19, 0x18, 0x1a, 0x18,
0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, 0x19, 0x01,
0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, 0xff, 0x1a,
0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x01, 0x00,
0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, 0x1a, 0x7f,
0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, 0xff, 0xff,
0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x00,
0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, 0xfe, 0x1a,
0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int EncodeRawTest()
{
uint8_t *pEncodedRaw;
size_t nEncodedRawLen;
if(EncodeRaw(&pEncodedRaw, &nEncodedRawLen)) {
return(-1);
}
//printencoded(pEncodedRaw, nEncodedRawLen);
int nReturn = 0;
if(nEncodedRawLen != sizeof(s_pEncodeRawExpected) || memcmp(s_pEncodeRawExpected, pEncodedRaw, sizeof(s_pEncodeRawExpected)))
nReturn = 1;
return(nReturn);
}
#endif
static int CreateMap(uint8_t **pEncoded, size_t *pEncodedLen)
{
QCBOREncodeContext ECtx;
int nReturn = -1;
*pEncoded = NULL;
*pEncodedLen = INT32_MAX;
// loop runs CBOR encoding twice. First with no buffer to
// calucate the length so buffer can be allocated correctly,
// and last with the buffer to do the actual encoding
do {
QCBOREncode_Init(&ECtx, (UsefulBuf){*pEncoded, *pEncodedLen});
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddInt64ToMap(&ECtx, "first integer", 42);
QCBOREncode_OpenArrayInMap(&ECtx, "an array of two strings");
QCBOREncode_AddText(&ECtx, ((UsefulBufC) {"string1", 7}));
QCBOREncode_AddText(&ECtx, ((UsefulBufC) {"string2", 7}));
QCBOREncode_CloseArray(&ECtx);
QCBOREncode_OpenMapInMap(&ECtx, "map in a map");
QCBOREncode_AddBytesToMap(&ECtx,"bytes 1", ((UsefulBufC) { "xxxx", 4}));
QCBOREncode_AddBytesToMap(&ECtx, "bytes 2",((UsefulBufC) { "yyyy", 4}));
QCBOREncode_AddInt64ToMap(&ECtx, "another int", 98);
QCBOREncode_AddTextToMap(&ECtx, "text 2", ((UsefulBufC) {"lies, damn lies and statistics", 30}));
QCBOREncode_CloseMap(&ECtx);
QCBOREncode_CloseMap(&ECtx);
if(QCBOREncode_Finish(&ECtx, pEncodedLen))
goto Done;
if(*pEncoded != NULL) {
nReturn = 0;
goto Done;
}
*pEncoded = malloc(*pEncodedLen);
} while(1);
Done:
return(nReturn);
}
static uint8_t pValidMapEncoded[] = {
0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a,
0x77, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x77, 0x6f, 0x20,
0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x67,
0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
0x6d, 0x61, 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, 0x44, 0x78, 0x78, 0x78, 0x78,
0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, 0x6e, 0x6f,
0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32,
0x78, 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73 } ;
int MapEncodeTest()
{
uint8_t *pEncodedMaps;
size_t nEncodedMapLen;
if(CreateMap(&pEncodedMaps, &nEncodedMapLen)) {
return(-1);
}
//printencoded(pEncodedMaps, nEncodedMapLen);
int nReturn = 0;
if(memcmp(pValidMapEncoded, pEncodedMaps, sizeof(pValidMapEncoded)))
nReturn = 1;
return(nReturn);
}
/*
@brief Encode the RTIC results
@param[in] nRResult CBOR_SIMPLEV_TRUE, CBOR_SIMPLEV_FALSE or CBOR_SIMPLEV_NULL
@param[in] time Time stamp in UNIX epoch time or 0 for no time stamp
@param[in] szAlexString Diagnostic code.
@param[in[ pOut Buffer to put the result in
@param[in/out] pnLen Size of pOut buffer when called; length of data output in buffer on return
@return
One of the CBOR encoder errors. QCBOR_SUCCESS, which is has value 0, if no error.
The size of pOut should be 30 bytes plus the length of pnLen. If you make it too
short an error will be returned. This function will never write off the end
of the buffer passed to it.
If the result is 0, then the correct encoded CBOR is in pOut and *pnLen is the
length of the encoded CBOR.
*/
int FormatRTICResults(int nRResult, uint64_t time, const char *szType, const char *szAlexString, uint8_t *pOut, size_t *pnLen)
{
// Buffer that the result will be written in to
// It is fixed size and small that a stack variable will be fine
// QCBOREncode will never write off the end of this buffer. If it won't fit QCBOREncode_Finish will return an error.
// Context for the encoder
QCBOREncodeContext ECtx;
QCBOREncode_Init(&ECtx, (UsefulBuf){pOut, *pnLen});
// All the RTIC results are grouped in a CBOR Map which will get turned into a JSON Object
// Contents are label / value pairs
QCBOREncode_OpenMap(&ECtx);
{ // Brace / indention just to show CBOR encoding nesting
// The result: 0 if scan happened and found nothing; 1 if it happened and found something wrong; 2 if it didn't happen
QCBOREncode_AddSimpleToMap(&ECtx, "integrity", nRResult);
// Add the diagnostic code
QCBOREncode_AddSZStringToMap(&ECtx, "type", szType);
// Add a time stamp
if(time) {
QCBOREncode_AddDateEpochToMap(&ECtx, "time", time);
}
// Add the diagnostic code
QCBOREncode_AddSZStringToMap(&ECtx, "diag", szAlexString);
// Open a subordinate map for telemtry data
QCBOREncode_OpenMapInMap(&ECtx, "telemetry");
{ // Brace / indention just to show CBOR encoding nesting
// Add a few fake integers and buffers for now.
QCBOREncode_AddInt64ToMap(&ECtx, "Shoe Size", 12);
// Add a few fake integers and buffers for now.
QCBOREncode_AddInt64ToMap(&ECtx, "IQ", 0xffffffff);
// Add a few fake integers and buffers for now.
const uint8_t pPV[] = {0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01};
UsefulBufC WSPV = {pPV, sizeof(pPV)};
QCBOREncode_AddBytesToMap(&ECtx, "WhaleSharkPatternVector", WSPV);
}
}
// Close the telemetry map
QCBOREncode_CloseMap(&ECtx);
// Close the map
QCBOREncode_CloseMap(&ECtx);
return QCBOREncode_Finish(&ECtx, pnLen);
}
static const uint8_t pExpectedRTIC[] = {0xa5, 0x69, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0xf4, 0x64, 0x74, 0x79, 0x70, 0x65, 0x66, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x64, 0x74, 0x69, 0x6d, 0x65, 0xc1, 0x1a, 0x58, 0x0d, 0x41, 0x72, 0x64, 0x64, 0x69, 0x61, 0x67, 0x6a, 0x30, 0x78, 0x41, 0x31, 0x65, 0x43, 0x35, 0x30, 0x30, 0x31, 0x69, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0xa3, 0x69, 0x53, 0x68, 0x6f, 0x65, 0x20, 0x53, 0x69, 0x7a, 0x65, 0x0c, 0x62, 0x49, 0x51, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x77, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x53, 0x68, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01};
int RTICResultsTest()
{
uint8_t out[200];
size_t len = sizeof(out);
int nResult = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730, "recent", "0xA1eC5001", out, &len);
if(nResult)
return -1;
if(memcmp(pExpectedRTIC, out, sizeof(pExpectedRTIC)))
return 1;
//printencoded(out, len);
return 0;
}
/*
Very basic bstr wrapping test
*/
int bstrwraptest()
{
UsefulBuf_MakeStackUB(MemoryForEncoded, 100);
QCBOREncodeContext EC;
QCBOREncode_Init(&EC, MemoryForEncoded);
QCBOREncode_OpenArray(&EC);
QCBOREncode_AddUInt64(&EC, 451);
QCBOREncode_BstrWrap(&EC);
QCBOREncode_AddUInt64(&EC, 466);
UsefulBufC Wrapped;
QCBOREncode_CloseBstrWrap(&EC, &Wrapped);
QCBOREncode_CloseArray(&EC);
UsefulBufC Encoded;
if(QCBOREncode_Finish2(&EC, &Encoded)) {
return -1;
}
const uint8_t pExpected[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2};
if(UsefulBuf_Compare(UsefulBuf_FromByteArrayLiteral(pExpected), Encoded)) {
return -2;
}
return 0;
}
int bstr_wrap_error_test()
{
// -------------- Test closing a bstrwrap when it is an array that is open -----------
UsefulBuf_MakeStackUB(MemoryForEncoded, 100);
QCBOREncodeContext EC;
QCBOREncode_Init(&EC, MemoryForEncoded);
QCBOREncode_OpenArray(&EC);
QCBOREncode_AddUInt64(&EC, 451);
QCBOREncode_BstrWrap(&EC);
QCBOREncode_AddUInt64(&EC, 466);
QCBOREncode_OpenArray(&EC);
UsefulBufC Wrapped;
QCBOREncode_CloseBstrWrap(&EC, &Wrapped);
QCBOREncode_CloseArray(&EC);
UsefulBufC Encoded2;
if(QCBOREncode_Finish2(&EC, &Encoded2) != QCBOR_ERR_CLOSE_MISMATCH) {
return -1;
}
// ----------- test closing a bstrwrap when nothing is open ---------------------
QCBOREncode_Init(&EC, MemoryForEncoded);
QCBOREncode_CloseBstrWrap(&EC, &Wrapped);
if(QCBOREncode_Finish2(&EC, &Encoded2) != QCBOR_ERR_TOO_MANY_CLOSES) {
return -2;
}
// --------------- test nesting too deep ----------------------------------
QCBOREncode_Init(&EC, MemoryForEncoded);
for(int i = 1; i < 18; i++) {
QCBOREncode_BstrWrap(&EC);
}
QCBOREncode_AddBool(&EC, true);
for(int i = 1; i < 18; i++) {
QCBOREncode_CloseBstrWrap(&EC, &Wrapped);
}
if(QCBOREncode_Finish2(&EC, &Encoded2) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) {
return -3;
}
return 0;
}
// Part of bstr_wrap_nest_test
/*
83 array with three
53 byte string with 19 bytes
01 #1
50 byte string with 16 bytes
02
4D byte string with 13 bytes
03
4A byte string with 10 bytes
04
47 byte string with 7 bytes
05
44 byte string with 4 bytes
06
41 byte string with 1 byte
07
01
02
03
04
05
06
07
A2 map with two items
18 20 label for byte string
54 byte string of length 20
82 Array with two items
10 The integer value 10
A2 map with two items
18 21 label for byte string
44 byte string with 4 bytes
81 array with 1 item
11 integer value 11
18 30 integer value 30
18 40 integer label 40
65 68 65 6C 6C 6F text string hello
18 31 integer value 31
18 41 integer label 41
65 68 65 6C 6C 6F text string hello
*/
static const uint8_t sExpectedDeepBstr[] =
{
0x83, 0x56, 0x00, 0x53, 0x01, 0x50, 0x02, 0x4D,
0x03, 0x4A, 0x04, 0x47, 0x05, 0x44, 0x06, 0x41,
0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0xA2, 0x18, 0x20, 0x54, 0x82, 0x10, 0xA2,
0x18, 0x21, 0x44, 0x81, 0x11, 0x18, 0x30, 0x18,
0x40, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x18,
0x31, 0x18, 0x41, 0x65, 0x68, 0x65, 0x6C, 0x6C,
0x6F
};
// Part of bstr_wrap_nest_test
static int decode_next_nested(UsefulBufC Wrapped)
{
int nReturn;
QCBORDecodeContext DC;
QCBORDecode_Init(&DC, Wrapped, QCBOR_DECODE_MODE_NORMAL);
QCBORItem Item;
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_INT64) {
return -12;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn == QCBOR_ERR_HIT_END) {
return 0;
}
if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
return -13;
}
nReturn = decode_next_nested(Item.val.string);
if(nReturn) {
return nReturn;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -14;
}
if(Item.uDataType != QCBOR_TYPE_INT64) {
return -15;
}
if(QCBORDecode_Finish(&DC)) {
return -16;
}
return 0;
}
// Part of bstr_wrap_nest_test
static int decode_next_nested2(UsefulBufC Wrapped)
{
int nReturn;
QCBORDecodeContext DC;
QCBORDecode_Init(&DC, Wrapped, QCBOR_DECODE_MODE_NORMAL);
QCBORItem Item;
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_ARRAY) {
return -12;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_INT64) {
return -12;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_MAP) {
return 0;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
return -13;
}
nReturn = decode_next_nested2(Item.val.string);
if(nReturn) {
return nReturn;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
return -12;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_INT64) {
return -12;
}
if(QCBORDecode_Finish(&DC)) {
return -16;
}
return 0;
}
int bstr_wrap_nest_test()
{
UsefulBuf_MakeStackUB(MemoryForEncoded, 300);
QCBOREncodeContext EC;
QCBOREncode_Init(&EC, MemoryForEncoded);
// ---- Make a complicated nested CBOR structure ---
QCBOREncode_OpenArray(&EC);
for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING-2; i++) {
QCBOREncode_BstrWrap(&EC);
QCBOREncode_AddUInt64(&EC, i);
}
for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING-2; i++) {
QCBOREncode_CloseBstrWrap(&EC, NULL);
QCBOREncode_AddUInt64(&EC, i);
}
for(int i = 0; i < (QCBOR_MAX_ARRAY_NESTING-2)/3; i++) {
QCBOREncode_OpenMap(&EC);
QCBOREncode_BstrWrapMapN(&EC, i+0x20);
QCBOREncode_OpenArray(&EC);
QCBOREncode_AddUInt64(&EC, i+0x10);
}
for(int i = 0; i < (QCBOR_MAX_ARRAY_NESTING-2)/3; i++) {
QCBOREncode_CloseArray(&EC);
QCBOREncode_AddUInt64(&EC, i+0x30);
QCBOREncode_CloseBstrWrap(&EC, NULL);
QCBOREncode_AddSZStringToMapN(&EC, i+0x40, "hello");
QCBOREncode_CloseMap(&EC);
}
QCBOREncode_CloseArray(&EC);
UsefulBufC Encoded;
if(QCBOREncode_Finish2(&EC, &Encoded)) {
return -1;
}
// ---Compare it to expected. Expected was hand checked with use of CBOR playground ----
if(UsefulBuf_Compare(UsefulBuf_FromByteArrayLiteral(sExpectedDeepBstr), Encoded)) {
return -25;
}
// ---- Decode it and see if it is OK ------
QCBORDecodeContext DC;
QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL);
QCBORItem Item;
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) {
return -2;
}
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
return -3;
}
int nReturn = decode_next_nested(Item.val.string);
if(nReturn) {
return nReturn;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_INT64) {
return -12;
}
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 2) {
return -2;
}
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
return -3;
}
nReturn = decode_next_nested2(Item.val.string);
if(nReturn) {
return nReturn;
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
if(nReturn) {
return -11;
}
if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
return -12;
}
if(QCBORDecode_Finish(&DC)) {
return -16;
}
return 0;
}
/*
this corresponds exactly to the example in RFC 8152
section C.2.1. This doesn't actually verify the signature
though that would be nice as it would make the test
really good. That would require bring in ECDSA crypto
to this test.
*/
int cose_sign1_tbs_test()
{
// All of this is from RFC 8152 C.2.1
const char *szKid = "11";
UsefulBufC Kid = UsefulBuf_FromSZ(szKid);
const char *szPayload = "This is the content.";
UsefulBufC Payload = UsefulBuf_FromSZ(szPayload);
const uint8_t pProtectedHeaders[] = {0xa1, 0x01, 0x26};
UsefulBufC ProtectedHeaders = UsefulBuf_FromByteArrayLiteral(pProtectedHeaders);
const uint8_t sSignature[] = {
0x8e, 0xb3, 0x3e, 0x4c, 0xa3, 0x1d, 0x1c, 0x46, 0x5a, 0xb0,
0x5a, 0xac, 0x34, 0xcc, 0x6b, 0x23, 0xd5, 0x8f, 0xef, 0x5c,
0x08, 0x31, 0x06, 0xc4, 0xd2, 0x5a, 0x91, 0xae, 0xf0, 0xb0,
0x11, 0x7e, 0x2a, 0xf9, 0xa2, 0x91, 0xaa, 0x32, 0xe1, 0x4a,
0xb8, 0x34, 0xdc, 0x56, 0xed, 0x2a, 0x22, 0x34, 0x44, 0x54,
0x7e, 0x01, 0xf1, 0x1d, 0x3b, 0x09, 0x16, 0xe5, 0xa4, 0xc3,
0x45, 0xca, 0xcb, 0x36};
// It would be good to compare this to the output from
// a COSE implementation like COSE-C. It has been checked
// against the CBOR playground.
UsefulBufC Signature = UsefulBuf_FromByteArrayLiteral(sSignature);
const uint8_t sExpected[] = {
0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA1, 0x04, 0x42, 0x31,
0x31, 0x54, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
0x74, 0x68, 0x65, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E,
0x74, 0x2E, 0x58, 0x40, 0x8E, 0xB3, 0x3E, 0x4C, 0xA3, 0x1D,
0x1C, 0x46, 0x5A, 0xB0, 0x5A, 0xAC, 0x34, 0xCC, 0x6B, 0x23,
0xD5, 0x8F, 0xEF, 0x5C, 0x08, 0x31, 0x06, 0xC4, 0xD2, 0x5A,
0x91, 0xAE, 0xF0, 0xB0, 0x11, 0x7E, 0x2A, 0xF9, 0xA2, 0x91,
0xAA, 0x32, 0xE1, 0x4A, 0xB8, 0x34, 0xDC, 0x56, 0xED, 0x2A,
0x22, 0x34, 0x44, 0x54, 0x7E, 0x01, 0xF1, 0x1D, 0x3B, 0x09,
0x16, 0xE5, 0xA4, 0xC3, 0x45, 0xCA, 0xCB, 0x36};
UsefulBufC Expected = UsefulBuf_FromByteArrayLiteral(sExpected);
UsefulBuf_MakeStackUB(MemoryForEncoded, 98);
QCBOREncodeContext EC;
QCBOREncode_Init(&EC, MemoryForEncoded);
// top level array for cose sign1, 18 is the tag for COSE sign
QCBOREncode_OpenArray_3(&EC, NULL, QCBOR_NO_INT_LABEL, 18);
// Add protected headers
QCBOREncode_AddBytes(&EC, ProtectedHeaders);
// Empty map with unprotected headers
QCBOREncode_OpenMap(&EC);
QCBOREncode_AddBytesToMapN(&EC, 4, Kid);
QCBOREncode_CloseMap(&EC);
// The payload
UsefulBufC WrappedPayload;
QCBOREncode_BstrWrap(&EC);
QCBOREncode_AddEncoded(&EC, Payload); // Payload is not actually CBOR in example C.2.1
QCBOREncode_CloseBstrWrap(&EC, &WrappedPayload);
// Check we got back the actual payload expected
if(UsefulBuf_Compare(WrappedPayload, Payload)) {
return -1;
}
// The signature
QCBOREncode_AddBytes(&EC, Signature);
QCBOREncode_CloseArray(&EC);
// Finish and check the results
UsefulBufC COSE_Sign1;
if(QCBOREncode_Finish2(&EC, &COSE_Sign1)) {
return -2;
}
// 98 is the size from RFC 8152 C.2.1
if(COSE_Sign1.len != 98) {
return -3;
}
if(UsefulBuf_Compare(COSE_Sign1, Expected)) {
return -4;
}
return 0;
}