Progress on floating point, but not done: a lot more tests, a few bug fixes; also copyright notice for floating point files; also some work on test framework
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index d6fdc58..b259a6c 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -7,11 +7,13 @@
objects = {
/* Begin PBXBuildFile section */
+ E73B574E215713FA0080D658 /* half_precision_test.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B574D215713FA0080D658 /* half_precision_test.c */; };
E776E08F214AE07500E67947 /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E776E090214AE07500E67947 /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E776E091214AE07500E67947 /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E776E097214AE0C700E67947 /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E776E09D214AEEEA00E67947 /* basic_test.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E09C214AEEEA00E67947 /* basic_test.c */; };
+ E776E164214F81EC00E67947 /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E163214F81EC00E67947 /* ieee754.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -27,15 +29,19 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ E73B574C215713FA0080D658 /* half_precision_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = half_precision_test.h; path = test/half_precision_test.h; sourceTree = "<group>"; };
+ E73B574D215713FA0080D658 /* half_precision_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = half_precision_test.c; path = test/half_precision_test.c; sourceTree = "<group>"; };
E776E07C214ADF7F00E67947 /* QCBOR */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR; sourceTree = BUILT_PRODUCTS_DIR; };
- E776E08C214AE07400E67947 /* qcbor_encode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_encode.c; path = src/qcbor_encode.c; sourceTree = "<group>"; };
+ E776E08C214AE07400E67947 /* qcbor_encode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_encode.c; path = src/qcbor_encode.c; sourceTree = "<group>"; tabWidth = 3; };
E776E08D214AE07500E67947 /* UsefulBuf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UsefulBuf.c; path = src/UsefulBuf.c; sourceTree = "<group>"; };
- E776E08E214AE07500E67947 /* qcbor_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_decode.c; path = src/qcbor_decode.c; sourceTree = "<group>"; };
+ E776E08E214AE07500E67947 /* qcbor_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_decode.c; path = src/qcbor_decode.c; sourceTree = "<group>"; tabWidth = 3; };
E776E093214AE08B00E67947 /* qcbor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor.h; path = inc/qcbor.h; sourceTree = "<group>"; };
E776E094214AE09700E67947 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/UsefulBuf.h; sourceTree = "<group>"; };
E776E096214AE0C700E67947 /* cmd_line_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmd_line_main.c; sourceTree = "<group>"; };
E776E09B214AEEEA00E67947 /* basic_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = basic_test.h; path = test/basic_test.h; sourceTree = "<group>"; };
E776E09C214AEEEA00E67947 /* basic_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = basic_test.c; path = test/basic_test.c; sourceTree = "<group>"; };
+ E776E162214F81EC00E67947 /* ieee754.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee754.h; path = src/ieee754.h; sourceTree = "<group>"; };
+ E776E163214F81EC00E67947 /* ieee754.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ieee754.c; path = src/ieee754.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -71,6 +77,8 @@
E776E08B214AE06600E67947 /* src */ = {
isa = PBXGroup;
children = (
+ E776E163214F81EC00E67947 /* ieee754.c */,
+ E776E162214F81EC00E67947 /* ieee754.h */,
E776E08E214AE07500E67947 /* qcbor_decode.c */,
E776E08C214AE07400E67947 /* qcbor_encode.c */,
E776E08D214AE07500E67947 /* UsefulBuf.c */,
@@ -90,6 +98,8 @@
E776E095214AE0B600E67947 /* test */ = {
isa = PBXGroup;
children = (
+ E73B574D215713FA0080D658 /* half_precision_test.c */,
+ E73B574C215713FA0080D658 /* half_precision_test.h */,
E776E09C214AEEEA00E67947 /* basic_test.c */,
E776E09B214AEEEA00E67947 /* basic_test.h */,
);
@@ -152,8 +162,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ E73B574E215713FA0080D658 /* half_precision_test.c in Sources */,
E776E08F214AE07500E67947 /* qcbor_encode.c in Sources */,
E776E091214AE07500E67947 /* qcbor_decode.c in Sources */,
+ E776E164214F81EC00E67947 /* ieee754.c in Sources */,
E776E090214AE07500E67947 /* UsefulBuf.c in Sources */,
E776E097214AE0C700E67947 /* cmd_line_main.c in Sources */,
E776E09D214AEEEA00E67947 /* basic_test.c in Sources */,
@@ -260,6 +272,7 @@
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
diff --git a/cmd_line_main.c b/cmd_line_main.c
index 54adb50..5a68709 100644
--- a/cmd_line_main.c
+++ b/cmd_line_main.c
@@ -1,3 +1,29 @@
+/*==============================================================================
+ 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.
+
+ (This is the MIT license)
+ ==============================================================================*/
+
//
// main.c
// QCBOR
@@ -9,11 +35,22 @@
#include <stdio.h>
#include "basic_test.h"
+#include "half_precision_test.h"
+
+
+int fputs_wrapper(const char *szString, void *ctx)
+{
+ return fputs(szString, (FILE *)ctx);
+}
+
int main(int argc, const char * argv[]) {
- // insert code here...
- printf("Hello, World! %d\n", basic_test_one());
+ half_precision_decode_basic();
- return 0;
+ half_precision_encode_basic();
+
+ int nNumTestsFailed = run_tests(&fputs_wrapper, stdout, NULL);
+
+ return nNumTestsFailed;
}
diff --git a/inc/qcbor.h b/inc/qcbor.h
index a5d214d..7c7d6f9 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -896,10 +896,21 @@
This works the same as QCBOREncode_AddInt64_3() except it is for half-precision floats.
*/
+
void QCBOREncode_AddFloatAsHalf_3(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint64_t uTag, float fNum);
+#define QCBOREncode_AddFloatAsHalf(pCtx, fNum) \
+ QCBOREncode_AddFloatAsHalf_3((pCtx), NULL, QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, (fNum))
+
+#define QCBOREncode_AddFloatAsHalfToMap(pCtx, szLabel, fNum) \
+ QCBOREncode_AddFloatAsHalf_3((pCtx), (szLabel), QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, (fNum))
+
+#define QCBOREncode_AddFloatAsHalfToMapN(pCtx, nLabel, fNum) \
+ QCBOREncode_AddFloatAsHalf_3((pCtx), NULL, (nLabel), CBOR_TAG_NONE, (fNum))
+
+
/*
- @brief Add a half-precision floating point number to the encoded output
+ @brief Add a dynamically sized floating point number to the encoded output
@param[in] pCtx The encoding context to add the float to.
@param[in] szLabel The string map label for this integer value.
@@ -924,11 +935,20 @@
*/
-
void QCBOREncode_AddFloatAsSmallest_3(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint64_t uTag, float fNum);
+#define QCBOREncode_AddFloatAsSmallest(pCtx, fNum) \
+ QCBOREncode_AddFloatAsSmallest_3((pCtx), NULL, QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, (fNum))
+
+#define QCBOREncode_AddFloatAsSmallestToMap(pCtx, szLabel, fNum) \
+ QCBOREncode_AddFloatAsSmallest_3((pCtx), (szLabel), QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, (fNum))
+
+#define QCBOREncode_AddFloatAsSmallestToMapN(pCtx, nLabel, fNum) \
+ QCBOREncode_AddFloatAsSmallest_3((pCtx), NULL, (nLabel), CBOR_TAG_NONE, (fNum))
+
+
/*
- @brief Add a half-precision floating point number to the encoded output
+ @brief Add a dynamically sized floating point number to the encoded output
@param[in] pCtx The encoding context to add the float to.
@param[in] szLabel The string map label for this integer value.
@@ -943,9 +963,10 @@
conversion to single-precision, then it will be converted and encoded. If not, then
no conversion is performed and it sent as a double.
- Half-precision floating point numbers take up 2 bytes, half that of single-precision.
+ Half-precision floating point numbers take up 2 bytes, half that of single-precision,
+ one quarter of double-preceision
- This reduces the size of encoded messages a lot, maybe even by four if a lot of values are
+ This reduces the size of encoded messages a lot, maybe even by four if a most of values are
0, infinity or NaN.
On decode, these will always be represented has float or double. Half-precision values
@@ -954,11 +975,22 @@
using this approach can / should assume that floats received actually have the precision
of double. They should probably cast the float received to double.
- This works the same as QCBOREncode_AddInt64_3() except it is for half-precision floats.
+ This works the same as QCBOREncode_AddInt64_3() except it is for floating point types.
*/
+
void QCBOREncode_AddDoubleAsSmallest_3(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint64_t uTag, double dNum);
+#define QCBOREncode_AddDoubleAsSmallest(pCtx, dNum) \
+ QCBOREncode_AddDoubleAsSmallest_3((pCtx), NULL, QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, (dNum))
+
+#define QCBOREncode_AddDoubleAsSmallestToMap(pCtx, szLabel, dNum) \
+ QCBOREncode_AddDoubleAsSmallest_3((pCtx), (szLabel), QCBOR_NO_INT_LABEL, CBOR_TAG_NONE, (dNum))
+
+#define QCBOREncode_AddDoubleAsSmallestToMapN(pCtx, nLabel, dNum) \
+ QCBOREncode_AddDoubleAsSmallest_3((pCtx), NULL, (nLabel), CBOR_TAG_NONE, (dNum))
+
+
/**
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index d98ebd5..a1305d2 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -241,7 +241,7 @@
/* 3. Slide existing data to the right */
uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
- size_t uNumBytesToMove = me->UB.len - uInsertionPos; // PtrMath #2
+ size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2
uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
diff --git a/src/ieee754.c b/src/ieee754.c
index a5a65a3..bcad14d 100644
--- a/src/ieee754.c
+++ b/src/ieee754.c
@@ -1,3 +1,29 @@
+/*==============================================================================
+ 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.
+
+ (This is the MIT license)
+ ==============================================================================*/
+
//
// ieee754.c
// Indefinite
@@ -139,7 +165,7 @@
// Public function; see ieee754.h
-int16_t IEEE754_FloatToHalf(float f)
+uint16_t IEEE754_FloatToHalf(float f)
{
// Pull the three parts out of the single-precision float
const uint32_t uSingle = CopyFloatToUint32(f);
@@ -204,7 +230,7 @@
// Public function; see ieee754.h
-int16_t IEEE754_DoubleToHalf(double d)
+uint16_t IEEE754_DoubleToHalf(double d)
{
// Pull the three parts out of the double-precision float
const uint64_t uDouble = CopyDoubleToUint64(d);
diff --git a/src/ieee754.h b/src/ieee754.h
index ced4bcb..ba2b030 100644
--- a/src/ieee754.h
+++ b/src/ieee754.h
@@ -1,3 +1,28 @@
+/*==============================================================================
+ 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.
+
+ (This is the MIT license)
+ ==============================================================================*/
//
// ieee754.h
// Indefinite
@@ -53,11 +78,11 @@
*/
-int16_t IEEE754_FloatToHalf(float f);
+uint16_t IEEE754_FloatToHalf(float f);
float IEEE754_HalfToFloat(uint16_t uHalfPrecision);
-int16_t IEEE754_DoubleToHalf(double d);
+uint16_t IEEE754_DoubleToHalf(double d);
double IEEE754_HalfToDouble(uint16_t uHalfPrecision);
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 6aee680..806287d 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -302,11 +302,11 @@
nReturn = QCBOR_ERR_UNSUPPORTED;
break;
- case SINGLE_PREC_FLOAT:
+ case HALF_PREC_FLOAT:
pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
break;
- case HALF_PREC_FLOAT:
+ case SINGLE_PREC_FLOAT:
pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
break;
case DOUBLE_PREC_FLOAT:
diff --git a/test/basic_test.c b/test/basic_test.c
index e5f510c..7df09fc 100644
--- a/test/basic_test.c
+++ b/test/basic_test.c
@@ -1,3 +1,28 @@
+/*==============================================================================
+ 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.
+
+ (This is the MIT license)
+ ==============================================================================*/
//
// basic_test.c
// QCBOR
@@ -42,3 +67,110 @@
return 0;
}
+
+int fail_test()
+{
+ return -44;
+}
+
+
+/*
+ Convert a number up to 999999999 to a string. This is so sprintf doesn't
+ have to be linked in so as to minimized dependencies even in test code.
+
+ This function does pointer math. TODO: test this.
+ */
+const char *NumToString(int32_t nNum, UsefulBuf StringMem)
+{
+ const uint32_t uMax = 1000000000;
+
+ UsefulOutBuf OutBuf;
+ UsefulOutBuf_Init(&OutBuf, StringMem);
+
+ if(nNum < 0) {
+ UsefulOutBuf_AppendByte(&OutBuf, '-');
+ nNum = -nNum;
+ }
+ if(nNum > uMax-1) {
+ return "XXX";
+ }
+
+ bool bDidSomeOutput = false;
+ for(int n = uMax; n > 0; n/=10) {
+ int x = nNum/n;
+ if(x || bDidSomeOutput){
+ bDidSomeOutput = true;
+ UsefulOutBuf_AppendByte(&OutBuf, '0' + x);
+ nNum -= x * n;
+ }
+ }
+ if(!bDidSomeOutput){
+ UsefulOutBuf_AppendByte(&OutBuf, '0');
+ }
+ UsefulOutBuf_AppendByte(&OutBuf, '\0');
+
+ return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
+}
+
+
+
+typedef int (test_fun_t)(void);
+
+#define TEST_ENTRY(test_name) {#test_name, test_name},
+typedef struct {
+ const char *szTestName;
+ test_fun_t *test_fun;
+} test_entry;
+
+test_entry s_tests[] = {
+ TEST_ENTRY(basic_test_one)
+ TEST_ENTRY(fail_test)
+};
+
+
+int run_tests(outputstring output, void *poutCtx, int *pNumTestsRun)
+{
+ int nTestsFailed = 0;
+ int nTestsRun = 0;
+ UsefulBuf_MakeStackUB(StringStorage, 5);
+
+ test_entry *t;
+ const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry);
+
+ for(t = s_tests; t < s_tests_end; t++) {
+ int x = (t->test_fun)();
+ nTestsRun++;
+ if(output) {
+ (*output)(t->szTestName, poutCtx);
+ }
+
+ if(x) {
+ if(output) {
+ (*output)(" FAILED (returned ", poutCtx);
+ (*output)(NumToString(x, StringStorage), poutCtx);
+ (*output)(")\n", poutCtx);
+ }
+ nTestsFailed++;
+ } else {
+ if(output) {
+ (*output)( " PASSED\n", poutCtx);
+ }
+ }
+ }
+
+ if(pNumTestsRun) {
+ *pNumTestsRun = nTestsRun;
+ }
+
+ if(output) {
+ (*output)( "SUMMARY: ", poutCtx);
+ (*output)( NumToString(nTestsRun, StringStorage), poutCtx);
+ (*output)( " tests run; ", poutCtx);
+ (*output)( NumToString(nTestsFailed, StringStorage), poutCtx);
+ (*output)( " tests failed\n", poutCtx);
+ }
+
+ return nTestsFailed;
+}
+
+
diff --git a/test/basic_test.h b/test/basic_test.h
index ef6f396..e71f323 100644
--- a/test/basic_test.h
+++ b/test/basic_test.h
@@ -1,3 +1,28 @@
+/*==============================================================================
+ 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.
+
+ (This is the MIT license)
+ ==============================================================================*/
//
// basic_test.h
// QCBOR
@@ -5,10 +30,15 @@
// Created by Laurence Lundblade on 9/13/18.
// Copyright © 2018 Laurence Lundblade. All rights reserved.
//
+#include <stdio.h>
#ifndef basic_test_h
#define basic_test_h
int basic_test_one(void);
+typedef int (*outputstring)(const char *szString, void *ctx);
+int run_tests(outputstring output, void *poutCtx, int *pNumTestsRun);
+
+
#endif /* basic_test_h */