Reduce test time for main set of decoding tests. Allow the BigComprehensiveTest to be run separately
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 3cdec80..3fe705c 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -36,23 +36,29 @@
#include <math.h> // for fabs()
#include <stdlib.h>
-#ifdef PRINT_FUNCTIONS_FOR_DEBUGGINGXX
+#ifdef PRINT_FUNCTIONS_FOR_DEBUGGING
#include <stdio.h>
-static void printencoded(const char *szLabel, const uint8_t *pEncoded, size_t nLen)
+
+static void PrintUsefulBufC(const char *szLabel, UsefulBufC Buf)
{
if(szLabel) {
printf("%s ", szLabel);
}
-
+
size_t i;
- for(i = 0; i < nLen; i++) {
- uint8_t Z = pEncoded[i];
+ for(i = 0; i < Buf.len; i++) {
+ uint8_t Z = ((uint8_t *)Buf.ptr)[i];
printf("%02x ", Z);
}
printf("\n");
-
+
fflush(stdout);
}
+
+/*static void printencoded(const char *szLabel, const uint8_t *pEncoded, size_t nLen)
+{
+ PrintUsefulBufC(szLabel, (UsefulBufC){pEncoded, nLen});
+}*/
#endif
@@ -1404,61 +1410,75 @@
}
-
-
-static void Recurser(uint8_t *pBuf, int nLen, int nLenMax)
+/* Try all 256 values of the byte at nLen including recursing for
+ each of the values to try values at nLen+1 ... up to nLenMax
+ */
+static void ComprehensiveInputRecurser(uint8_t *pBuf, int nLen, int nLenMax)
{
-
if(nLen >= nLenMax) {
return;
}
-
- //printf("__%d__%d__\n", nLen, nLenMax);
-
- for(int i = 0; i < 256; i++) {
- pBuf[nLen] = i;
-
- QCBORDecodeContext DCtx;
- QCBORItem Item;
- int nCBORError;
-
+
+ for(int inputByte = 0; inputByte < 256; inputByte++) {
+ // Set up the input
+ pBuf[nLen] = inputByte;
const UsefulBufC Input = {pBuf, nLen+1};
-
+
+ // Get ready to parse
+ QCBORDecodeContext DCtx;
QCBORDecode_Init(&DCtx, Input, QCBOR_DECODE_MODE_NORMAL);
+ // Parse by getting the next item until an error occurs
+ // Just about every possible decoder error can occur here
+ // The goal of this test is not to check for the correct
+ // error since that is not really possible. It is to
+ // see that there is no crash on hostile input.
while(1) {
- nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
- if(QCBOR_ERR_HIT_END == nCBORError) {
- break;
- }
+ QCBORItem Item;
+ QCBORError nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
if(nCBORError != QCBOR_SUCCESS) {
- if(nCBORError != QCBOR_ERR_UNSUPPORTED && nCBORError != QCBOR_ERR_HIT_END && nCBORError != QCBOR_ERR_INVALID_CBOR) {
- }
break;
}
}
-
- Recurser(pBuf, nLen+1, nLenMax);
+ ComprehensiveInputRecurser(pBuf, nLen+1, nLenMax);
}
}
/*
- Runs all possible input strings of a given length. This is set to 3 to make the test
- run in reasonable time.
- Main point of this test is to not crash.
+ Public function for initialization. See header qcbor.h
*/
-
int ComprehensiveInputTest()
{
- uint8_t pBuf[3]; // 3 keeps it running in reasonable time. 4 takes tens of minutes.
+ // Size 2 tests 64K inputs and runs quickly
+ uint8_t pBuf[2];
- Recurser(pBuf, 0, sizeof(pBuf));
+ ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf));
return 0;
}
+
+/*
+ Public function for initialization. See header qcbor.h
+ */
+int BigComprehensiveInputTest()
+{
+ // size 3 tests 16 million inputs and runs OK
+ // in seconds on fast machines. Size 4 takes
+ // 10+ minutes and 5 half a day on fast
+ // machines. This test is kept separate from
+ // the others so as to no slow down the use
+ // of them as a very frequent regression.
+ uint8_t pBuf[3]; //
+
+ ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf));
+
+ return 0;
+}
+
+
static uint8_t spDateTestInput[] = {
0xc0, // tag for string date
0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 8a91929..6ba71b4 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -138,12 +138,27 @@
/*
- Generate all possible input strings up to length x and tries to parse them completely
+ Parses all possible inputs that are two bytes long. Main point
+ is that the test doesn't crash as it doesn't evaluate the
+ input for correctness in any way.
+
+ (Parsing all possible 3 byte strings takes too long on all but
+ very fast machines).
*/
int ComprehensiveInputTest(void);
/*
+ Parses all possible inputs that are four bytes long. Main point
+ is that the test doesn't crash as it doesn't evaluate the
+ input for correctness in any way. This runs very slow, so it
+ is only practical as a once-in-a-while regression test on
+ fast machines.
+ */
+int BigComprehensiveInputTest(void);
+
+
+/*
Thest the date types -- epoch and strings
*/
int DateParseTest(void);
diff --git a/test/run_tests.c b/test/run_tests.c
index 876456f..d1f997b 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -91,15 +91,19 @@
typedef const char * (test_fun2_t)(void);
-#define TEST_ENTRY(test_name) {#test_name, test_name}
+#define TEST_ENTRY(test_name) {#test_name, test_name, true}
+#define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false}
+
typedef struct {
- const char *szTestName;
+ const char *szTestName;
test_fun_t *test_fun;
+ bool bEnabled;
} test_entry;
typedef struct {
const char *szTestName;
test_fun2_t *test_fun;
+ bool bEnabled;
} test_entry2;
test_entry2 s_tests2[] = {
@@ -153,6 +157,7 @@
TEST_ENTRY(BstrWrapNestTest),
TEST_ENTRY(CoseSign1TBSTest),
TEST_ENTRY(StringDecoderModeFailTest),
+ TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
//TEST_ENTRY(fail_test),
};
@@ -167,19 +172,24 @@
const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);
for(t2 = s_tests2; t2 < s_tests2_end; t2++) {
+ if(!t2->bEnabled && !szTestName) {
+ // Don't run disabled tests when all tests are being run
+ // as indicated by no specific test name being given
+ continue;
+ }
if(szTestName && strcmp(szTestName, t2->szTestName)) {
continue;
}
- const char * x = (t2->test_fun)();
+ const char * szTestResult = (t2->test_fun)();
nTestsRun++;
if(output) {
(*output)(t2->szTestName, poutCtx);
}
- if(x) {
+ if(szTestResult) {
if(output) {
(*output)(" FAILED (returned ", poutCtx);
- (*output)(x, poutCtx);
+ (*output)(szTestResult, poutCtx);
(*output)(")\n", poutCtx);
}
nTestsFailed++;
@@ -195,19 +205,24 @@
const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry);
for(t = s_tests; t < s_tests_end; t++) {
+ if(!t->bEnabled && !szTestName) {
+ // Don't run disabled tests when all tests are being run
+ // as indicated by no specific test name being given
+ continue;
+ }
if(szTestName && strcmp(szTestName, t->szTestName)) {
continue;
}
- int x = (t->test_fun)();
+ int nTestResult = (t->test_fun)();
nTestsRun++;
if(output) {
(*output)(t->szTestName, poutCtx);
}
- if(x) {
+ if(nTestResult) {
if(output) {
(*output)(" FAILED (returned ", poutCtx);
- (*output)(NumToString(x, StringStorage), poutCtx);
+ (*output)(NumToString(nTestResult, StringStorage), poutCtx);
(*output)(")\n", poutCtx);
}
nTestsFailed++;