PSA return status coverage script
Add infrastructure to run unit tests and collect the return values for
every PSA API function that returns psa_status_t.
./tests/scripts/psa_collect_statuses.py >statuses.txt
diff --git a/tests/psa_crypto_helpers.h b/tests/psa_crypto_helpers.h
index 3780d16..19303de 100644
--- a/tests/psa_crypto_helpers.h
+++ b/tests/psa_crypto_helpers.h
@@ -72,4 +72,59 @@
*/
#define PSA_DONE( ) test_helper_psa_done( __LINE__, __FILE__ )
+
+
+#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
+#include <psa/crypto.h>
+
+/** Name of the file where return statuses are logged by #RECORD_STATUS. */
+#define STATUS_LOG_FILE_NAME "statuses.log"
+
+static psa_status_t record_status( psa_status_t status,
+ const char *func,
+ const char *file, int line,
+ const char *expr )
+{
+ /* We open the log file on first use.
+ * We never close the log file, so the record_status feature is not
+ * compatible with resource leak detectors such as Asan.
+ */
+ static FILE *log;
+ if( log == NULL )
+ log = fopen( STATUS_LOG_FILE_NAME, "a" );
+ fprintf( log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr );
+ return( status );
+}
+
+/** Return value logging wrapper macro.
+ *
+ * Evaluate \p expr. Write a line recording its value to the log file
+ * #STATUS_LOG_FILE_NAME and return the value. The line is a colon-separated
+ * list of fields:
+ * ```
+ * value of expr:string:__FILE__:__LINE__:expr
+ * ```
+ *
+ * The test code does not call this macro explicitly because that would
+ * be very invasive. Instead, we instrument the source code by defining
+ * a bunch of wrapper macros like
+ * ```
+ * #define psa_crypto_init() RECORD_STATUS("psa_crypto_init", psa_crypto_init())
+ * ```
+ * These macro definitions must be present in `instrument_record_status.h`
+ * when building the test suites.
+ *
+ * \param string A string, normally a function name.
+ * \param expr An expression to evaluate, normally a call of the function
+ * whose name is in \p string. This expression must return
+ * a value of type #psa_status_t.
+ * \return The value of \p expr.
+ */
+#define RECORD_STATUS( string, expr ) \
+ record_status( ( expr ), string, __FILE__, __LINE__, #expr )
+
+#include "instrument_record_status.h"
+
+#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
+
#endif /* PSA_CRYPTO_HELPERS_H */