bstr enter test is working (but still more work and testing to do)
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index e49b8c7..41a7b56 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -1934,6 +1934,12 @@
}
+static inline size_t UsefulInputBuf_GetLength(UsefulInputBuf *pMe)
+{
+ return pMe->UB.len;
+}
+
+
static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
{
if(uPos > pMe->UB.len) {
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index a4b4dfe..114a171 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -1051,6 +1051,30 @@
+/*
+ TODO: get rid of this
+
+ int64_t
+ uint64_t
+ int32_t
+ uint32_t
+ int16_t
+ uint16_t
+ int8_t
+ uint8_t
+
+ 8 types. 12 functions for each --> 96 functions
+
+ 7 converter functions
+
+ foreach type
+ for each conversion option
+ for each fetch option
+
+
+
+ */
+
/**
@brief Decode next item as a signed 64-bit integer.
@@ -1535,7 +1559,7 @@
Next item must be map or this generates an error.
-This puts the decoder in map mode which narrows
+This puts the decoder in bounded mode which narrows
decoding to the map entered and enables use of
getting items by label.
@@ -1544,24 +1568,31 @@
Call QCBORDecode_ExitMap() to exit the current map
decoding level. When all map decoding layers are exited
- then map mode is fully exited.
+ then bounded mode is fully exited.
- While in map mode, GetNext works as usual on the
+ While in bounded mode, GetNext works as usual on the
map and the standard in-order traversal cursor
is maintained. Attempts to get items off the end of the
- map will give error XXX (rather going to the next
- item after the map as it would when not in map
+ map will give error QCBOR_ERR_NO_MORE_ITEMS (rather going to the next
+ item after the map as it would when not in bounded
mode).
- You can rewind the inorder traversal cursor to the
+ TODO: You can rewind the inorder traversal cursor to the
beginning of the map with RewindMap().
Exiting leaves the cursor at the
data item following the last entry in the map.
- Entering and Exiting map mode consumes the whole
- map and its contents as a GetNext after exiting
- will return the item after the map. */
+ Entering and Exiting a map is a way to skip over
+ an entire map and its contents. After the Exit,
+ the pre-order traversal cursor will be at the
+ first item after the map.
+
+ Bounded mode also works for arrays and bstr wrapped CBOR.
+ Bounded mode levels nest with each entry into a bounded
+ map, array or wrapped bstr increasing narrowing the
+ traversal and each Exit broading it until the top is reached.
+ */
static void QCBORDecode_EnterMap(QCBORDecodeContext *pCtx);
void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pCtx, int64_t nLabel);
@@ -1587,8 +1618,6 @@
/*
-
-
This is for use on some CBOR that has been wrapped in a
byte string. There are several ways that this can occur.
@@ -1609,7 +1638,7 @@
as a CWT, then the COSE payload is CBOR.
To enter into CBOR of this type use the
- \ref QCBOR_WRAP as the \c uTagRequirement argument.
+ \ref QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE as the \c uTagRequirement argument.
Note that byte string wrapped CBOR can also be
decoded by getting the byte string with QCBORDecode_GetItem() or
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index 7be7023..6f8f89b 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -125,7 +125,7 @@
#define QCBOR_NEST_TYPE_ARRAY 0x02
#define QCBOR_NEST_TYPE_MAP 0x03
#define QCBOR_NEST_TYPE_IS_INDEFINITE 0x40
-#define QCBOR_NEST_TYPE_IS_BOUND 0x80
+#define QCBOR_NEST_TYPE_IS_BOUNDED 0x80
/*
#define QCBOR_NEST_TYPE_BSTR 0x00
@@ -159,19 +159,21 @@
} mm;
struct {
uint16_t uCountCursor;
- uint32_t uEndOffset;
+ //uint32_t uEndOffset;
} bs;
} u;
- uint32_t uEndOffset;
+ uint32_t uPreviousEndOffset;
+ uint32_t uEndOfBstr;
uint8_t uType;
uint32_t uOffset;
uint16_t uCount; // Cursor
uint8_t uMajorType; // TODO: one bit?
- uint8_t uMapMode; // Used by map mode TODO: one bit?
+ uint8_t bBoundedMode; // Used by map mode TODO: one bit?
uint16_t uSaveCount; // Used by map mode
} pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING1+1],
*pCurrent,
- *pCurrentMap;
+ *pCurrentBounded,
+ *tmp; // TODO: fix this
uint8_t uNestType[QCBOR_MAX_ARRAY_NESTING1+1];
} QCBORDecodeNesting;
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 05059e4..a5e8066 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -134,7 +134,8 @@
inline static bool DecodeNesting_InBoundedMode(const QCBORDecodeNesting *pNesting)
{
- return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_BOUND;
+ return pNesting->pCurrent->bBoundedMode;
+ //return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_BOUNDED;
}
/*inline static bool IsArray(const QCBORDecodeNesting *pNesting)
@@ -166,8 +167,8 @@
inline static bool
DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
{
- if(pNesting->pCurrentMap && DecodeNesting_InBoundedMode(pNesting)) {
- if(pNesting->pCurrentMap->uCount == 0) {
+ if(pNesting->pCurrentBounded && DecodeNesting_InBoundedMode(pNesting)) {
+ if(pNesting->pCurrentBounded->uCount == 0) {
// In map mode and consumed all items, so it is the end
return true;
} else {
@@ -194,7 +195,7 @@
{
// Check in DecodeNesting_Descend and never having
// QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
- return (uint8_t)(pNesting->pCurrentMap - &(pNesting->pMapsAndArrays[0]));
+ return (uint8_t)(pNesting->pCurrentBounded - &(pNesting->pMapsAndArrays[0]));
}
inline static int
@@ -210,7 +211,7 @@
inline static bool
DecodeNesting_BoundedIsType(const QCBORDecodeNesting *pNesting, uint8_t uType)
{
- if(pNesting->pCurrentMap->uMajorType == uType) {
+ if(pNesting->pCurrentBounded->uMajorType == uType) {
return true;
} else {
return false;
@@ -247,18 +248,19 @@
inline static void
DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
{
- /* Have descended into this is called. The job here is just to mark it in bounded mode */
- pNesting->pCurrentMap = pNesting->pCurrent;
- pNesting->pCurrentMap->uType |= QCBOR_NEST_TYPE_IS_BOUND;
+ /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
+ pNesting->pCurrentBounded = pNesting->pCurrent;
+ pNesting->pCurrent->bBoundedMode = true;
+ //pNesting->pCurrentBounded->uType |= QCBOR_NEST_TYPE_IS_BOUNDED;
// Cast to uint32_t is safe because QCBOR restricts encoded input to < UINT32_MAX
- pNesting->pCurrentMap->uOffset = (uint32_t)uOffset;
+ pNesting->pCurrentBounded->uOffset = (uint32_t)uOffset;
}
inline static QCBORError
-DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uQCBORType, uint64_t uCount, uint32_t uEndOffset)
+DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uQCBORType, uint64_t uCount, uint32_t uEndOffset, uint32_t uEndOfBstr)
{
QCBORError nReturn = QCBOR_SUCCESS;
@@ -288,8 +290,9 @@
pNesting->pCurrent->uMajorType = uQCBORType;
pNesting->pCurrent->uCount = (uint16_t)uCount;
pNesting->pCurrent->uSaveCount = (uint16_t)uCount;
- pNesting->pCurrent->uEndOffset = uEndOffset;
- pNesting->pCurrent->uMapMode = 0;
+ pNesting->pCurrent->uPreviousEndOffset = uEndOffset;
+ pNesting->pCurrent->uEndOfBstr = uEndOfBstr;
+ pNesting->pCurrent->bBoundedMode = false;
Done:
return nReturn;;
@@ -298,8 +301,11 @@
inline static void
-DecodeNesting_Init(QCBORDecodeNesting *pNesting)
+DecodeNesting_Init(QCBORDecodeNesting *pNesting, size_t uEndOffset)
{
+ pNesting->pMapsAndArrays[0].uMajorType = QCBOR_TYPE_BYTE_STRING;
+ // TODO: is cast in the right place?
+ pNesting->pMapsAndArrays[0].uPreviousEndOffset = (uint32_t)uEndOffset;
pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
}
@@ -307,7 +313,7 @@
static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
{
*pSave = *pNesting;
- pNesting->pCurrent = pNesting->pCurrentMap;
+ pNesting->pCurrent = pNesting->pCurrentBounded;
if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
pNesting->pCurrent->uCount = pNesting->pCurrent->uSaveCount;
@@ -405,7 +411,7 @@
// Don't bother with error check on decode mode. If a bad value is
// passed it will just act as if the default normal mode of 0 was set.
me->uDecodeMode = (uint8_t)nDecodeMode;
- DecodeNesting_Init(&(me->nesting));
+ DecodeNesting_Init(&(me->nesting), EncodedCBOR.len);
for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
me->auMappedTags[i] = CBOR_TAG_INVALID16;
}
@@ -1268,7 +1274,7 @@
// ascend if decrements are enough to close out a definite length array/map
if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount != 0) {
// If the new item is array or map, the nesting level descends
- uReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount, 0L);
+ uReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount, 0L, 0L);
// Maps and arrays do count in as items in the map/array that encloses
// them so a decrement needs to be done for them too, but that is done
// only when all the items in them have been processed, not when they
@@ -2101,7 +2107,7 @@
#include <stdio.h>
void printdecode(QCBORDecodeContext *pMe, const char *szName)
{
- printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
+ printf("---%s--%d--%d--\narrow is current bounded level\nLevel Count Type S-Offset SaveCount Bounded E-Offset\n",
szName,
(uint32_t)pMe->InBuf.cursor,
(uint32_t)pMe->InBuf.UB.len);
@@ -2109,16 +2115,18 @@
if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
break;
}
- printf("%2s %2d %5d %s %6u %2d %d\n",
- pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
+ printf("%2s %2d %5d %s %6u %5d %d %5d\n",
+ pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
i,
pMe->nesting.pMapsAndArrays[i].uCount,
- pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
+ pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? "map " :
(pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
- (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
+ (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
+ (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? "none " : "?????"))),
pMe->nesting.pMapsAndArrays[i].uOffset,
pMe->nesting.pMapsAndArrays[i].uSaveCount,
- pMe->nesting.pMapsAndArrays[i].uMapMode
+ pMe->nesting.pMapsAndArrays[i].bBoundedMode,
+ pMe->nesting.pMapsAndArrays[i].uPreviousEndOffset
);
}
@@ -2257,7 +2265,7 @@
DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
// Reposition to search from the start of the map / array
- UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentMap->uOffset);
+ UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentBounded->uOffset);
/* Loop over all the items in the map. They could be
* deeply nested and this should handle both definite
@@ -2557,7 +2565,7 @@
*/
/* Seek to the data item that is the map or array */
UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
- pMe->nesting.pCurrent = pMe->nesting.pCurrentMap; // TODO: part of DecodeNesting
+ pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
// TODO: check error?
QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
@@ -2686,11 +2694,11 @@
pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end.
/* Before acending, mark this level as no longer in bound mode. */
- pMe->nesting.pCurrentMap->uType &= ~QCBOR_NEST_TYPE_IS_BOUND;
+ pMe->nesting.pCurrentBounded->bBoundedMode = false;
// Always go up one level
// Need error check to know level is bounded mode and not at top level
- pMe->nesting.pCurrent = pMe->nesting.pCurrentMap - 1; // TODO error check
+ pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded - 1; // TODO error check
uErr = Ascender(pMe);
if(uErr != QCBOR_SUCCESS) {
@@ -2700,12 +2708,12 @@
/* Also ascend to the next higest bounded mode level if
there is one. */
while(1) {
- pMe->nesting.pCurrentMap--;
+ pMe->nesting.pCurrentBounded--;
if(DecodeNesting_InBoundedMode(&(pMe->nesting))) {
break;
}
- if(pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[0])) {
- pMe->nesting.pCurrentMap = NULL;
+ if(pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[0])) {
+ pMe->nesting.pCurrentBounded = NULL;
break;
}
}
@@ -2739,7 +2747,7 @@
goto Done;;
}
- // TODO: check for the other wrapped CBOR
+ // TODO: check for the other wrapped CBOR tag
const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
uError = CheckTagRequirement(TagSpec, pItem->uDataType);
@@ -2747,22 +2755,36 @@
goto Done;
}
- *pBstr = pItem->val.string;
+ //if(pMe->nesting.pCurrent)
+ pMe->nesting.pCurrent->uCount++; // Don't count the bstr yet
+
+ if(pBstr) {
+ *pBstr = pItem->val.string;
+ }
+
+ const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
// Need to move UIB input cursor to the right place
// Really this is a subtraction and an assignment; not much code
// There is a range check in the seek.
- const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
+ // The bstr was just consumed so the cursor is at the next item after it
- UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset - pItem->val.string.len);
+ const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
- UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOffset);
+
+ UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
+
+ UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
// TODO: comment on cast
- uError = DecodeNesting_Descend(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING, UINT16_MAX, (uint32_t)uEndOffset);
+ uError = DecodeNesting_Descend(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING, UINT16_MAX, (uint32_t)uPreviousLength, (uint32_t)uEndOfBstr);
+ pMe->nesting.pCurrent->bBoundedMode = true;
+ pMe->nesting.pCurrentBounded = pMe->nesting.pCurrent;
Done:
+ printdecode(pMe, "Entered Bstr");
+
return uError;
}
@@ -2776,7 +2798,7 @@
}
/* Get the data item that is the map that is being searched */
- QCBORItem Item;
+ QCBORItem Item;
pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
@@ -2801,15 +2823,49 @@
QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
pMe->uLastError = (uint8_t)FarfWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
-
}
-void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pCtx)
+void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
{
- // TODO: write this code
- // Need to set the cursor to end of the bstr and length to the next length
- // above in the nesting tree (or the top level length).
-
+ /* Reset the length of the Useful\InputBuf to what it was before
+ the bstr wrapped CBOR was entered
+ */
+ UsefulInputBuf_SetBufferLen(&(pMe->InBuf), pMe->nesting.pCurrentBounded->uPreviousEndOffset);
+
+ // Put the pre-order traversal cursor in the right place
+ UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentBounded->uEndOfBstr);
+
+ // Invalidate the cached bounded mode end.
+ pMe->uMapEndOffset = UINT32_MAX;
+
+
+ // Always go up one level
+ // Need error check to know level is bounded mode and not at top level
+ pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded - 1; // TODO error check
+
+ QCBORError uErr = Ascender(pMe);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
+
+ /* Also ascend to the next highest bounded mode level if
+ there is one. */
+ while(1) {
+ pMe->nesting.pCurrentBounded--;
+ if(DecodeNesting_InBoundedMode(&(pMe->nesting))) {
+ break;
+ }
+ if(pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[0])) {
+ //pMe->nesting.pCurrentBounded = NULL;
+ break;
+ }
+ }
+
+ pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded;
+
+Done:
+ // TODO: set last error here
+ printdecode(pMe, "Exited Bstr");
}
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 3a21720..e81c579 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -4804,3 +4804,94 @@
return 0;
}
+
+/*
+A sequence with
+ A wrapping bstr
+ containing a map
+ 1
+ 2
+ A wrapping bstr
+ containing an array
+ 3
+ wrapping bstr
+ 4
+ 5
+ 6
+ array
+ 7
+ 8
+
+ */
+
+static UsefulBufC foo(UsefulBuf ffo)
+{
+ UsefulBufC Encoded;
+ QCBOREncodeContext EC;
+ QCBORError uErr;
+
+ QCBOREncode_Init(&EC, ffo);
+
+ QCBOREncode_BstrWrap(&EC);
+ QCBOREncode_OpenMap(&EC);
+ QCBOREncode_AddInt64ToMapN(&EC, 100, 1);
+ QCBOREncode_AddInt64ToMapN(&EC, 200, 2);
+ QCBOREncode_CloseMap(&EC);
+ QCBOREncode_BstrWrap(&EC);
+ QCBOREncode_OpenArray(&EC);
+ QCBOREncode_AddInt64(&EC, 3);
+ QCBOREncode_BstrWrap(&EC);
+ QCBOREncode_AddInt64(&EC, 4);
+ QCBOREncode_CloseBstrWrap(&EC, NULL);
+ QCBOREncode_AddInt64(&EC, 5);
+ QCBOREncode_CloseArray(&EC);
+ QCBOREncode_CloseBstrWrap(&EC, NULL);
+ QCBOREncode_AddInt64(&EC, 6);
+ QCBOREncode_CloseBstrWrap(&EC, NULL);
+ QCBOREncode_OpenArray(&EC);
+ QCBOREncode_AddInt64(&EC, 7);
+ QCBOREncode_AddInt64(&EC, 8);
+ QCBOREncode_CloseArray(&EC);
+
+ uErr = QCBOREncode_Finish(&EC, &Encoded);
+
+ return Encoded;
+}
+
+
+int32_t EnterBstrTest()
+{
+ MakeUsefulBufOnStack(ffo, 100);
+
+ QCBORDecodeContext DC;
+
+ QCBORDecode_Init(&DC, foo(ffo), 0);
+
+ int64_t i1, i2, i3, i4, i5, i6, i7, i8;
+
+
+ QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE, NULL);
+ QCBORDecode_EnterMap(&DC);
+ QCBORDecode_GetInt64InMapN(&DC, 100, &i1);
+ QCBORDecode_GetInt64InMapN(&DC, 200, &i2);
+ QCBORDecode_ExitMap(&DC);
+ QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE, NULL);
+ QCBORDecode_EnterArray(&DC);
+ QCBORDecode_GetInt64(&DC, &i3);
+ QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE, NULL);
+ QCBORDecode_GetInt64(&DC, &i4);
+ QCBORDecode_ExitBstrWrapped(&DC);
+ QCBORDecode_GetInt64(&DC, &i5);
+ QCBORDecode_ExitArray(&DC);
+ QCBORDecode_ExitBstrWrapped(&DC);
+ QCBORDecode_GetInt64(&DC, &i6);
+ QCBORDecode_ExitBstrWrapped(&DC);
+ QCBORDecode_EnterArray(&DC);
+ QCBORDecode_GetInt64(&DC, &i7);
+ QCBORDecode_GetInt64(&DC, &i8);
+ QCBORDecode_ExitArray(&DC);
+
+ QCBORError uErr = QCBORDecode_Finish(&DC);
+
+ return (int32_t)uErr;
+}
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 5bb0d48..9c83109 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -266,4 +266,11 @@
*/
int32_t IntToTests(void);
+
+/*
+ Test the decoding of bstr-wrapped CBOR.
+ */
+int32_t EnterBstrTest(void);
+
+
#endif /* defined(__QCBOR__qcbort_decode_tests__) */
diff --git a/test/run_tests.c b/test/run_tests.c
index a719654..35e6c9d 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -56,6 +56,7 @@
static test_entry s_tests[] = {
+ TEST_ENTRY(EnterBstrTest),
TEST_ENTRY(IntegerConvertTest),
TEST_ENTRY(EnterMapTest),
TEST_ENTRY(QCBORHeadTest),