get run_tests in the right directory
diff --git a/test/run_tests.h b/test/run_tests.h
new file mode 100644
index 0000000..013b6e5
--- /dev/null
+++ b/test/run_tests.h
@@ -0,0 +1,153 @@
+
+/*==============================================================================
+ run_tests.c -- test aggregator and results reporting
+ 
+ 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)
+ ==============================================================================*/
+//  Created by Laurence Lundblade on 9/30/18.
+
+
+#include "run_tests.h"
+#include "UsefulBuf.h"
+#include <stdbool.h>
+
+#include "half_precision_test.h"
+#include "basic_test.h"
+#include "bstrwrap_tests.h"
+
+// Used to test the test runner
+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(half_precision_encode_basic),
+    TEST_ENTRY(half_precision_decode_basic),
+    TEST_ENTRY(half_precision_to_float_transitive_test),
+    TEST_ENTRY(double_as_smallest_encode_basic),
+    TEST_ENTRY(half_precision_to_float_vs_rfc_test),
+    TEST_ENTRY(bstrwraptest),
+    TEST_ENTRY(bstr_wrap_error_test),
+    TEST_ENTRY(bstr_wrap_nest_test),
+    TEST_ENTRY(cose_sign1_tbs_test),
+    //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;
+}