Remove malloc dependency in tests. Give list of tests to run on command line. Describe tests in README.md
diff --git a/README.md b/README.md
index 00d458d..2e1efd3 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,8 @@
 ## Characteristics
 
 **Implemented in C with minimal dependecy** – Only dependencies are
-C99, stdint.h, stddef.h, stdbool.h and string.h making it highly
-portable. There are no #ifdefs.
+C99, <stdint.h>, <stddef.h>, <stdbool.h> and <string.h> making it highly
+portable. There are no #ifdefs to be configured at all.
 
 **Focused on C / native data representation** – Simpler code because
 there is no support for encoding/decoding to/from JSON, pretty
@@ -28,13 +28,13 @@
   length strings is not supported, but is also not necessary or
   preferred.
 
-**Extensible and General** – Provides a way to handle data types that
+**Extensible and general** – Provides a way to handle data types that
   are not directly supported.
 
-**Secure Coding Style** – Uses a construct called UsefulBuf as a
+**Secure coding style** – Uses a construct called UsefulBuf as a
   discipline for very safe coding the handling of binary data.
 
-**Small Code Size** – When optimized for size using the compiler -Os
+**Small code size** – When optimized for size using the compiler -Os
   option, x86 code is less than 5KB (~1.1B encode, ~2.8KB decode,
   ~0.4KB common).
 
@@ -42,6 +42,11 @@
   separated from the implementation. It can be put to use without
   reading the source.
 
+  **Comprehensive test suite** – Easy to verify on a new platform
+  or OS with the test suite. The test suite dependencies are also
+  minimal, only additionally requiring <math.h> for floating point
+  tests.
+
 ## Code Status
 
 QCBOR was originally developed by Qualcomm. It was [open sourced
diff --git a/cmd_line_main.c b/cmd_line_main.c
index 927beee..29b8488 100644
--- a/cmd_line_main.c
+++ b/cmd_line_main.c
@@ -1,5 +1,7 @@
 /*==============================================================================
- cmd_line_mainc.c -- basic tests for qcbor encoder / decoder
+ cmd_line_mainc.c -- Runs tests for QCBOR encoder / decoder
+
+ Created on 9/13/18.
 
  Copyright (c) 2018, Laurence Lundblade.
  All rights reserved.
@@ -30,49 +32,30 @@
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  ==============================================================================*/
-//  Created by Laurence Lundblade on 9/13/18.
+
 
 #include <stdio.h>
 #include "run_tests.h"
-#include "qcbor.h" // just to print sizes of the structures.
 
 
-int fputs_wrapper(const char *szString, void *ctx)
+/*
+ This is an implementation of OutputStringCB built using stdio. If
+ you don't have stdio, replaces this is
+ */
+static void fputs_wrapper(const char *szString, void *ctx)
 {
-    return fputs(szString, (FILE *)ctx);
-}
-
-
-static void PrintSize(const char *szWhat, uint32_t uSize)
-{
-    UsefulBuf_MAKE_STACK_UB(foo, 20);
-
-    fputs_wrapper(szWhat, stdout);
-    fputs_wrapper(" ", stdout);
-    fputs_wrapper(NumToString(uSize,foo), stdout);
-    fputs_wrapper("\n", stdout);
+    fputs(szString, (FILE *)ctx);
 }
 
 
 int main(int argc, const char * argv[])
 {
-    // Type and size of return from sizeof() varies. These will never be large so cast is safe
-    PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting));
-    PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting));
-    PrintSize("sizeof(QCBOREncodeContext)", (uint32_t)sizeof(QCBOREncodeContext));
-    PrintSize("sizeof(QCBORDecodeContext)", (uint32_t)sizeof(QCBORDecodeContext));
-    PrintSize("sizeof(QCBORDecodeNesting)", (uint32_t)sizeof(QCBORDecodeNesting));
-    PrintSize("sizeof(QCBORItem)", (uint32_t)sizeof(QCBORItem));
-    PrintSize("sizeof(QCBORStringAllocator)", (uint32_t)sizeof(QCBORStringAllocator));
-    fputs_wrapper("\n", stdout);
+   (void)argc; // Avoid unused parameter error
 
-    int nNumTestsFailed = 0;
+   // This call prints out sizes of data structures to remind us
+   // to keep them small.
+   PrintSizes(&fputs_wrapper, stdout);
 
-    if(argc > 1) {
-        nNumTestsFailed += run_tests(argv[1], &fputs_wrapper, stdout, NULL);
-    } else {
-        nNumTestsFailed += run_tests(NULL, &fputs_wrapper, stdout, NULL);
-    }
-
-    return nNumTestsFailed;
+   // This runs all the tests
+   return RunTests(argv+1, &fputs_wrapper, stdout, NULL);
 }
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 3fe705c..021c150 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -30,11 +30,11 @@
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  ==============================================================================*/
 
-#include "qcbor.h"
 #include "qcbor_decode_tests.h"
+#include "qcbor.h"
 #include <string.h>
 #include <math.h> // for fabs()
-#include <stdlib.h>
+
 
 #ifdef  PRINT_FUNCTIONS_FOR_DEBUGGING
 #include <stdio.h>
@@ -44,14 +44,14 @@
    if(szLabel) {
       printf("%s ", szLabel);
    }
-   
+
    size_t i;
    for(i = 0; i < Buf.len; i++) {
       uint8_t Z = ((uint8_t *)Buf.ptr)[i];
       printf("%02x ", Z);
    }
    printf("\n");
-   
+
    fflush(stdout);
 }
 
@@ -444,6 +444,8 @@
 
  */
 
+static uint8_t spSimpleArrayBuffer[50];
+
 static int CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen)
 {
    QCBOREncodeContext ECtx;
@@ -453,7 +455,7 @@
    *pEncodedLen = INT32_MAX;
 
    // loop runs CBOR encoding twice. First with no buffer to
-   // calucate the length so buffer can be allocated correctly,
+   // calculate 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});
@@ -464,25 +466,24 @@
       QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"haven token", 11}));
       QCBOREncode_CloseArray(&ECtx);
 
-      UsefulBufC Encoded;
-      if(QCBOREncode_Finish(&ECtx, &Encoded))
+      if(QCBOREncode_FinishGetSize(&ECtx, pEncodedLen))
          goto Done;
 
       if(*pEncoded != NULL) {
-         *pEncodedLen = Encoded.len;
          nReturn = 0;
          goto Done;
       }
-      *pEncoded = malloc(Encoded.len);
-      if(*pEncoded == NULL) {
-         nReturn = -1;
+
+      // Use static buffer to avoid dependency on malloc()
+      if(*pEncodedLen > sizeof(spSimpleArrayBuffer)) {
          goto Done;
       }
+      *pEncoded = spSimpleArrayBuffer;
 
    } while(1);
-Done:
-   return (nReturn);
 
+Done:
+   return nReturn;
 }
 
 
@@ -1418,12 +1419,12 @@
    if(nLen >= nLenMax) {
       return;
    }
-   
+
    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);
@@ -1472,9 +1473,9 @@
    // 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;
 }
 
@@ -2679,7 +2680,7 @@
    const UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded));
 
    QCBORDecode_Init(&DC, CopyOf, QCBOR_DECODE_MODE_NORMAL);
-   UsefulBuf_Set(Pool, '/'); 
+   UsefulBuf_Set(Pool, '/');
    QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying.
 
    QCBORItem Item1, Item2, Item3, Item4;
diff --git a/test/run_tests.c b/test/run_tests.c
index ef5a16f..0297de9 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -1,8 +1,9 @@
-
 /*==============================================================================
  run_tests.c -- test aggregator and results reporting
 
- Copyright (c) 2018, Laurence Lundblade.
+ Created on 9/30/18
+
+ Copyright (c) 2018-2019, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -30,7 +31,6 @@
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  ==============================================================================*/
-//  Created by Laurence Lundblade on 9/30/18.
 
 
 #include "run_tests.h"
@@ -42,13 +42,17 @@
 #include "qcbor_encode_tests.h"
 #include "UsefulBuf_Tests.h"
 
-// Used to test the test runner
+
+
+// Used to test RunTests
 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.
@@ -87,6 +91,7 @@
 
 
 
+
 typedef int (test_fun_t)(void);
 typedef const char * (test_fun2_t)(void);
 
@@ -163,7 +168,7 @@
 };
 
 
-int run_tests(const char *szTestName, outputstring output, void *poutCtx, int *pNumTestsRun)
+int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *poutCtx, int *pNumTestsRun)
 {
     int nTestsFailed = 0;
     int nTestsRun = 0;
@@ -173,30 +178,43 @@
     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(szTestNames[0]) {
+            // Some tests have been named
+            const char **szRequestedNames;
+            for(szRequestedNames = szTestNames; *szRequestedNames;  szRequestedNames++) {
+                if(!strcmp(t2->szTestName, *szRequestedNames)) {
+                    break; // Name matched
+                }
+            }
+            if(*szRequestedNames == NULL) {
+                // Didn't match this test
+                continue;
+            }
+        } else {
+            // no tests named, but don't run "disabled" tests
+            if(!t2->bEnabled) {
+                // Don't run disabled tests when all tests are being run
+                // as indicated by no specific test names being given
+                continue;
+            }
         }
-        if(szTestName && strcmp(szTestName, t2->szTestName)) {
-            continue;
-        }
+
         const char * szTestResult = (t2->test_fun)();
         nTestsRun++;
-        if(output) {
-            (*output)(t2->szTestName, poutCtx);
+        if(pfOutput) {
+            (*pfOutput)(t2->szTestName, poutCtx);
         }
 
         if(szTestResult) {
-            if(output) {
-                (*output)(" FAILED (returned ", poutCtx);
-                (*output)(szTestResult, poutCtx);
-                (*output)(")\n", poutCtx);
+            if(pfOutput) {
+                (*pfOutput)(" FAILED (returned ", poutCtx);
+                (*pfOutput)(szTestResult, poutCtx);
+                (*pfOutput)(")\n", poutCtx);
             }
             nTestsFailed++;
         } else {
-            if(output) {
-                (*output)( " PASSED\n", poutCtx);
+            if(pfOutput) {
+                (*pfOutput)( " PASSED\n", poutCtx);
             }
         }
     }
@@ -206,30 +224,43 @@
     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(szTestNames[0]) {
+            // Some tests have been named
+            const char **szRequestedNames;
+            for(szRequestedNames = szTestNames; *szRequestedNames;  szRequestedNames++) {
+                if(!strcmp(t->szTestName, *szRequestedNames)) {
+                    break; // Name matched
+                }
+            }
+            if(*szRequestedNames == NULL) {
+                // Didn't match this test
+                continue;
+            }
+        } else {
+            // no tests named, but don't run "disabled" tests
+            if(!t->bEnabled) {
+                // Don't run disabled tests when all tests are being run
+                // as indicated by no specific test names being given
+                continue;
+            }
         }
-        if(szTestName && strcmp(szTestName, t->szTestName)) {
-            continue;
-        }
+
         int nTestResult = (t->test_fun)();
         nTestsRun++;
-        if(output) {
-            (*output)(t->szTestName, poutCtx);
+        if(pfOutput) {
+            (*pfOutput)(t->szTestName, poutCtx);
         }
 
         if(nTestResult) {
-            if(output) {
-                (*output)(" FAILED (returned ", poutCtx);
-                (*output)(NumToString(nTestResult, StringStorage), poutCtx);
-                (*output)(")\n", poutCtx);
+            if(pfOutput) {
+                (*pfOutput)(" FAILED (returned ", poutCtx);
+                (*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx);
+                (*pfOutput)(")\n", poutCtx);
             }
             nTestsFailed++;
         } else {
-            if(output) {
-                (*output)( " PASSED\n", poutCtx);
+            if(pfOutput) {
+                (*pfOutput)( " PASSED\n", poutCtx);
             }
         }
     }
@@ -238,13 +269,40 @@
         *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);
+    if(pfOutput) {
+        (*pfOutput)( "SUMMARY: ", poutCtx);
+        (*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx);
+        (*pfOutput)( " tests run; ", poutCtx);
+        (*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx);
+        (*pfOutput)( " tests failed\n", poutCtx);
     }
 
     return nTestsFailed;
 }
+
+
+
+
+static void PrintSize(const char *szWhat, uint32_t uSize, OutputStringCB pfOutput, void *pOutCtx)
+{
+    UsefulBuf_MAKE_STACK_UB(foo, 20);
+
+    (*pfOutput)(szWhat, pOutCtx);
+    (*pfOutput)(" ", pOutCtx);
+    (*pfOutput)(NumToString(uSize,foo), pOutCtx);
+    (*pfOutput)("\n", pOutCtx);
+}
+
+void PrintSizes(OutputStringCB pfOutput, void *pOutCtx)
+{
+    // Type and size of return from sizeof() varies. These will never be large so cast is safe
+    PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBOREncodeContext)", (uint32_t)sizeof(QCBOREncodeContext), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBORDecodeNesting)", (uint32_t)sizeof(QCBORDecodeNesting), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBORDecodeContext)", (uint32_t)sizeof(QCBORDecodeContext), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBORItem)", (uint32_t)sizeof(QCBORItem), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBORStringAllocator)", (uint32_t)sizeof(QCBORStringAllocator), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBORTagListIn)", (uint32_t)sizeof(QCBORTagListIn), pfOutput, pOutCtx);
+    PrintSize("sizeof(QCBORTagListOut)", (uint32_t)sizeof(QCBORTagListOut), pfOutput, pOutCtx);
+    (*pfOutput)("\n", pOutCtx);
+}
diff --git a/test/run_tests.h b/test/run_tests.h
index 431ef22..91d6c65 100644
--- a/test/run_tests.h
+++ b/test/run_tests.h
@@ -2,6 +2,8 @@
 /*==============================================================================
  run_tests.c -- test aggregator and results reporting
 
+ Created 9/30/18.
+
  Copyright (c) 2018, Laurence Lundblade.
  All rights reserved.
 
@@ -30,14 +32,41 @@
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  ==============================================================================*/
-//  Created by Laurence Lundblade on 9/30/18.
-typedef int (*outputstring)(const char *szString, void *ctx);
-
-int run_tests(const char *szTestName, outputstring output, void *poutCtx, int *pNumTestsRun);
 
 
-#include <stdint.h>
-#include "UsefulBuf.h"
+/**
+ @brief Type for function to output a text string
 
-const char *NumToString(int32_t nNum, UsefulBuf StringMem);
+ @param[in] szString   The string to output
+ @param[in] pOutCtx    A context pointer; NULL if not needed
+
+ This is a prototype of a function to be passed to run_tests() to
+ output text strings.  This can be implemented with stdio (if
+ available) using a straight call to fputs() where the FILE *
+ is passed as the ctx.
+*/
+typedef void (*OutputStringCB)(const char *szString, void *pOutCtx);
+
+
+/**
+ @brief Runs the QCBOR tests
+
+ @param[in] szTestNames    An argv-style list of test names to run. If
+                           empty, all are run.
+ @param[in] pfOutput         Function that is called to output text strings.
+ @param[in] pOutCtx        Context pointer passed to output function.
+ @param[out] pNumTestsRun  Returns the number of tests run. May be NULL.
+
+ @return The number of tests that failed. Zero means overall success.
+ */
+int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *pOutCtx, int *pNumTestsRun);
+
+
+/**
+ @brief Print sizes of encoder / decoder contexts.
+
+ @param[in] pfOutput         Function that is called to output text strings.
+ @param[in] pOutCtx        Context pointer passed to output function.
+ */
+void PrintSizes(OutputStringCB pfOutput, void *pOutCtx);