quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

host_test.function (26129B)


      1 #line 2 "suites/host_test.function"
      2 
      3 /**
      4  * \brief       Verifies that string is in string parameter format i.e. "<str>"
      5  *              It also strips enclosing '"' from the input string.
      6  *
      7  * \param str   String parameter.
      8  *
      9  * \return      0 if success else 1
     10  */
     11 static int verify_string(char **str)
     12 {
     13     if ((*str)[0] != '"' ||
     14         (*str)[strlen(*str) - 1] != '"') {
     15         mbedtls_fprintf(stderr,
     16                         "Expected string (with \"\") for parameter and got: %s\n", *str);
     17         return -1;
     18     }
     19 
     20     (*str)++;
     21     (*str)[strlen(*str) - 1] = '\0';
     22 
     23     return 0;
     24 }
     25 
     26 /**
     27  * \brief       Verifies that string is an integer. Also gives the converted
     28  *              integer value.
     29  *
     30  * \param str   Input string.
     31  * \param p_value Pointer to output value.
     32  *
     33  * \return      0 if success else 1
     34  */
     35 static int verify_int(char *str, intmax_t *p_value)
     36 {
     37     char *end = NULL;
     38     errno = 0;
     39     /* Limit the range to long: for large integers, the test framework will
     40      * use expressions anyway. */
     41     long value = strtol(str, &end, 0);
     42     if (errno == EINVAL || *end != '\0') {
     43         mbedtls_fprintf(stderr,
     44                         "Expected integer for parameter and got: %s\n", str);
     45         return KEY_VALUE_MAPPING_NOT_FOUND;
     46     }
     47     if (errno == ERANGE) {
     48         mbedtls_fprintf(stderr, "Integer out of range: %s\n", str);
     49         return KEY_VALUE_MAPPING_NOT_FOUND;
     50     }
     51     *p_value = value;
     52     return 0;
     53 }
     54 
     55 
     56 /**
     57  * \brief       Usage string.
     58  *
     59  */
     60 #define USAGE \
     61     "Usage: %s [OPTIONS] files...\n\n" \
     62     "   Command line arguments:\n" \
     63     "     files...          One or more test data files. If no file is\n" \
     64     "                       specified the following default test case\n" \
     65     "                       file is used:\n" \
     66     "                           %s\n\n" \
     67     "   Options:\n" \
     68     "     -v | --verbose    Display full information about each test\n" \
     69     "     -h | --help       Display this information\n\n", \
     70     argv[0], \
     71     "TESTCASE_FILENAME"
     72 
     73 
     74 /**
     75  * \brief       Read a line from the passed file pointer.
     76  *
     77  * \param f     FILE pointer
     78  * \param buf   Pointer to memory to hold read line.
     79  * \param len   Length of the buf.
     80  *
     81  * \return      0 if success else -1
     82  */
     83 static int get_line(FILE *f, char *buf, size_t len)
     84 {
     85     char *ret;
     86     int i = 0, str_len = 0, has_string = 0;
     87 
     88     /* Read until we get a valid line */
     89     do {
     90         ret = fgets(buf, len, f);
     91         if (ret == NULL) {
     92             return -1;
     93         }
     94 
     95         str_len = strlen(buf);
     96 
     97         /* Skip empty line and comment */
     98         if (str_len == 0 || buf[0] == '#') {
     99             continue;
    100         }
    101         has_string = 0;
    102         for (i = 0; i < str_len; i++) {
    103             char c = buf[i];
    104             if (c != ' ' && c != '\t' && c != '\n' &&
    105                 c != '\v' && c != '\f' && c != '\r') {
    106                 has_string = 1;
    107                 break;
    108             }
    109         }
    110     } while (!has_string);
    111 
    112     /* Strip new line and carriage return */
    113     ret = buf + strlen(buf);
    114     if (ret-- > buf && *ret == '\n') {
    115         *ret = '\0';
    116     }
    117     if (ret-- > buf && *ret == '\r') {
    118         *ret = '\0';
    119     }
    120 
    121     return 0;
    122 }
    123 
    124 /**
    125  * \brief       Splits string delimited by ':'. Ignores '\:'.
    126  *
    127  * \param buf           Input string
    128  * \param len           Input string length
    129  * \param params        Out params found
    130  * \param params_len    Out params array len
    131  *
    132  * \return      Count of strings found.
    133  */
    134 static int parse_arguments(char *buf, size_t len, char **params,
    135                            size_t params_len)
    136 {
    137     size_t cnt = 0, i;
    138     char *cur = buf;
    139     char *p = buf, *q;
    140 
    141     params[cnt++] = cur;
    142 
    143     while (*p != '\0' && p < (buf + len)) {
    144         if (*p == '\\') {
    145             p++;
    146             p++;
    147             continue;
    148         }
    149         if (*p == ':') {
    150             if (p + 1 < buf + len) {
    151                 cur = p + 1;
    152                 TEST_HELPER_ASSERT(cnt < params_len);
    153                 params[cnt++] = cur;
    154             }
    155             *p = '\0';
    156         }
    157 
    158         p++;
    159     }
    160 
    161     /* Replace backslash escapes in strings */
    162     for (i = 0; i < cnt; i++) {
    163         p = params[i];
    164         q = params[i];
    165 
    166         while (*p != '\0') {
    167             if (*p == '\\') {
    168                 ++p;
    169                 switch (*p) {
    170                     case 'n':
    171                         *p = '\n';
    172                         break;
    173                     default:
    174                         // Fall through to copying *p
    175                         break;
    176                 }
    177             }
    178             *(q++) = *(p++);
    179         }
    180         *q = '\0';
    181     }
    182 
    183     return cnt;
    184 }
    185 
    186 /**
    187  * \brief       Converts parameters into test function consumable parameters.
    188  *              Example: Input:  {"int", "0", "char*", "Hello",
    189  *                                "hex", "abef", "exp", "1"}
    190  *                      Output:  {
    191  *                                0,                // Verified int
    192  *                                "Hello",          // Verified string
    193  *                                2, { 0xab, 0xef },// Converted len,hex pair
    194  *                                9600              // Evaluated expression
    195  *                               }
    196  *
    197  *
    198  * \param cnt               Parameter array count.
    199  * \param params            Out array of found parameters.
    200  * \param int_params_store  Memory for storing processed integer parameters.
    201  *
    202  * \return      0 for success else 1
    203  */
    204 static int convert_params(size_t cnt, char **params,
    205                           mbedtls_test_argument_t *int_params_store)
    206 {
    207     char **cur = params;
    208     char **out = params;
    209     int ret = DISPATCH_TEST_SUCCESS;
    210 
    211     while (cur < params + cnt) {
    212         char *type = *cur++;
    213         char *val = *cur++;
    214 
    215         if (strcmp(type, "char*") == 0) {
    216             if (verify_string(&val) == 0) {
    217                 *out++ = val;
    218             } else {
    219                 ret = (DISPATCH_INVALID_TEST_DATA);
    220                 break;
    221             }
    222         } else if (strcmp(type, "int") == 0) {
    223             if (verify_int(val, &int_params_store->sint) == 0) {
    224                 *out++ = (char *) int_params_store++;
    225             } else {
    226                 ret = (DISPATCH_INVALID_TEST_DATA);
    227                 break;
    228             }
    229         } else if (strcmp(type, "hex") == 0) {
    230             if (verify_string(&val) == 0) {
    231                 size_t len;
    232 
    233                 TEST_HELPER_ASSERT(
    234                     mbedtls_test_unhexify((unsigned char *) val, strlen(val),
    235                                           val, &len) == 0);
    236 
    237                 int_params_store->len = len;
    238                 *out++ = val;
    239                 *out++ = (char *) (int_params_store++);
    240             } else {
    241                 ret = (DISPATCH_INVALID_TEST_DATA);
    242                 break;
    243             }
    244         } else if (strcmp(type, "exp") == 0) {
    245             int exp_id = strtol(val, NULL, 10);
    246             if (get_expression(exp_id, &int_params_store->sint) == 0) {
    247                 *out++ = (char *) int_params_store++;
    248             } else {
    249                 ret = (DISPATCH_INVALID_TEST_DATA);
    250                 break;
    251             }
    252         } else {
    253             ret = (DISPATCH_INVALID_TEST_DATA);
    254             break;
    255         }
    256     }
    257     return ret;
    258 }
    259 
    260 /**
    261  * \brief       Tests snprintf implementation with test input.
    262  *
    263  * \note
    264  * At high optimization levels (e.g. gcc -O3), this function may be
    265  * inlined in run_test_snprintf. This can trigger a spurious warning about
    266  * potential misuse of snprintf from gcc -Wformat-truncation (observed with
    267  * gcc 7.2). This warning makes tests in run_test_snprintf redundant on gcc
    268  * only. They are still valid for other compilers. Avoid this warning by
    269  * forbidding inlining of this function by gcc.
    270  *
    271  * \param n         Buffer test length.
    272  * \param ref_buf   Expected buffer.
    273  * \param ref_ret   Expected snprintf return value.
    274  *
    275  * \return      0 for success else 1
    276  */
    277 #if defined(__GNUC__)
    278 __attribute__((__noinline__))
    279 #endif
    280 static int test_snprintf(size_t n, const char *ref_buf, int ref_ret)
    281 {
    282     int ret;
    283     char buf[10] = "xxxxxxxxx";
    284     const char ref[10] = "xxxxxxxxx";
    285 
    286     if (n >= sizeof(buf)) {
    287         return -1;
    288     }
    289     ret = mbedtls_snprintf(buf, n, "%s", "123");
    290     if (ret < 0 || (size_t) ret >= n) {
    291         ret = -1;
    292     }
    293 
    294     if (strncmp(ref_buf, buf, sizeof(buf)) != 0 ||
    295         ref_ret != ret ||
    296         memcmp(buf + n, ref + n, sizeof(buf) - n) != 0) {
    297         return 1;
    298     }
    299 
    300     return 0;
    301 }
    302 
    303 /**
    304  * \brief       Tests snprintf implementation.
    305  *
    306  * \return      0 for success else 1
    307  */
    308 static int run_test_snprintf(void)
    309 {
    310     return test_snprintf(0, "xxxxxxxxx",  -1) != 0 ||
    311            test_snprintf(1, "",           -1) != 0 ||
    312            test_snprintf(2, "1",          -1) != 0 ||
    313            test_snprintf(3, "12",         -1) != 0 ||
    314            test_snprintf(4, "123",         3) != 0 ||
    315            test_snprintf(5, "123",         3) != 0;
    316 }
    317 
    318 /** \brief Write the description of the test case to the outcome CSV file.
    319  *
    320  * \param outcome_file  The file to write to.
    321  *                      If this is \c NULL, this function does nothing.
    322  * \param argv0         The test suite name.
    323  * \param test_case     The test case description.
    324  */
    325 static void write_outcome_entry(FILE *outcome_file,
    326                                 const char *argv0,
    327                                 const char *test_case)
    328 {
    329     /* The non-varying fields are initialized on first use. */
    330     static const char *platform = NULL;
    331     static const char *configuration = NULL;
    332     static const char *test_suite = NULL;
    333 
    334     if (outcome_file == NULL) {
    335         return;
    336     }
    337 
    338     if (platform == NULL) {
    339         platform = getenv("MBEDTLS_TEST_PLATFORM");
    340         if (platform == NULL) {
    341             platform = "unknown";
    342         }
    343     }
    344     if (configuration == NULL) {
    345         configuration = getenv("MBEDTLS_TEST_CONFIGURATION");
    346         if (configuration == NULL) {
    347             configuration = "unknown";
    348         }
    349     }
    350     if (test_suite == NULL) {
    351         test_suite = strrchr(argv0, '/');
    352         if (test_suite != NULL) {
    353             test_suite += 1; // skip the '/'
    354         } else {
    355             test_suite = argv0;
    356         }
    357     }
    358 
    359     /* Write the beginning of the outcome line.
    360      * Ignore errors: writing the outcome file is on a best-effort basis. */
    361     mbedtls_fprintf(outcome_file, "%s;%s;%s;%s;",
    362                     platform, configuration, test_suite, test_case);
    363 }
    364 
    365 /** \brief Write the result of the test case to the outcome CSV file.
    366  *
    367  * \param outcome_file  The file to write to.
    368  *                      If this is \c NULL, this function does nothing.
    369  * \param unmet_dep_count            The number of unmet dependencies.
    370  * \param unmet_dependencies         The array of unmet dependencies.
    371  * \param missing_unmet_dependencies Non-zero if there was a problem tracking
    372  *                                   all unmet dependencies, 0 otherwise.
    373  * \param ret                        The test dispatch status (DISPATCH_xxx).
    374  */
    375 static void write_outcome_result(FILE *outcome_file,
    376                                  size_t unmet_dep_count,
    377                                  int unmet_dependencies[],
    378                                  int missing_unmet_dependencies,
    379                                  int ret)
    380 {
    381     if (outcome_file == NULL) {
    382         return;
    383     }
    384 
    385     /* Write the end of the outcome line.
    386      * Ignore errors: writing the outcome file is on a best-effort basis. */
    387     switch (ret) {
    388         case DISPATCH_TEST_SUCCESS:
    389             if (unmet_dep_count > 0) {
    390                 size_t i;
    391                 mbedtls_fprintf(outcome_file, "SKIP");
    392                 for (i = 0; i < unmet_dep_count; i++) {
    393                     mbedtls_fprintf(outcome_file, "%c%d",
    394                                     i == 0 ? ';' : ':',
    395                                     unmet_dependencies[i]);
    396                 }
    397                 if (missing_unmet_dependencies) {
    398                     mbedtls_fprintf(outcome_file, ":...");
    399                 }
    400                 break;
    401             }
    402             switch (mbedtls_test_get_result()) {
    403                 case MBEDTLS_TEST_RESULT_SUCCESS:
    404                     mbedtls_fprintf(outcome_file, "PASS;");
    405                     break;
    406                 case MBEDTLS_TEST_RESULT_SKIPPED:
    407                     mbedtls_fprintf(outcome_file, "SKIP;Runtime skip");
    408                     break;
    409                 default:
    410                     mbedtls_fprintf(outcome_file, "FAIL;%s:%d:%s",
    411                                     mbedtls_get_test_filename(),
    412                                     mbedtls_test_get_line_no(),
    413                                     mbedtls_test_get_test());
    414                     break;
    415             }
    416             break;
    417         case DISPATCH_TEST_FN_NOT_FOUND:
    418             mbedtls_fprintf(outcome_file, "FAIL;Test function not found");
    419             break;
    420         case DISPATCH_INVALID_TEST_DATA:
    421             mbedtls_fprintf(outcome_file, "FAIL;Invalid test data");
    422             break;
    423         case DISPATCH_UNSUPPORTED_SUITE:
    424             mbedtls_fprintf(outcome_file, "SKIP;Unsupported suite");
    425             break;
    426         default:
    427             mbedtls_fprintf(outcome_file, "FAIL;Unknown cause");
    428             break;
    429     }
    430     mbedtls_fprintf(outcome_file, "\n");
    431     fflush(outcome_file);
    432 }
    433 
    434 #if defined(__unix__) ||                                \
    435     (defined(__APPLE__) && defined(__MACH__))
    436 #define MBEDTLS_HAVE_CHDIR
    437 #endif
    438 
    439 #if defined(MBEDTLS_HAVE_CHDIR)
    440 /** Try chdir to the directory containing argv0.
    441  *
    442  * Failures are silent.
    443  */
    444 static void try_chdir_if_supported(const char *argv0)
    445 {
    446     /* We might want to allow backslash as well, for Windows. But then we also
    447      * need to consider chdir() vs _chdir(), and different conventions
    448      * regarding paths in argv[0] (naively enabling this code with
    449      * backslash support on Windows leads to chdir into the wrong directory
    450      * on the CI). */
    451     const char *slash = strrchr(argv0, '/');
    452     if (slash == NULL) {
    453         return;
    454     }
    455     size_t path_size = slash - argv0 + 1;
    456     char *path = mbedtls_calloc(1, path_size);
    457     if (path == NULL) {
    458         return;
    459     }
    460     memcpy(path, argv0, path_size - 1);
    461     path[path_size - 1] = 0;
    462     int ret = chdir(path);
    463     if (ret != 0) {
    464         mbedtls_fprintf(stderr, "%s: note: chdir(\"%s\") failed.\n",
    465                         __func__, path);
    466     }
    467     mbedtls_free(path);
    468 }
    469 #else /* MBEDTLS_HAVE_CHDIR */
    470 /* No chdir() or no support for parsing argv[0] on this platform. */
    471 static void try_chdir_if_supported(const char *argv0)
    472 {
    473     (void) argv0;
    474     return;
    475 }
    476 #endif /* MBEDTLS_HAVE_CHDIR */
    477 
    478 /**
    479  * \brief       Desktop implementation of execute_tests().
    480  *              Parses command line and executes tests from
    481  *              supplied or default data file.
    482  *
    483  * \param argc  Command line argument count.
    484  * \param argv  Argument array.
    485  *
    486  * \return      Program exit status.
    487  */
    488 static int execute_tests(int argc, const char **argv)
    489 {
    490     /* Local Configurations and options */
    491     const char *default_filename = "DATA_FILE";
    492     const char *test_filename = NULL;
    493     const char **test_files = NULL;
    494     size_t testfile_count = 0;
    495     int option_verbose = 0;
    496     size_t function_id = 0;
    497 
    498     /* Other Local variables */
    499     int arg_index = 1;
    500     const char *next_arg;
    501     size_t testfile_index, i, cnt;
    502     int ret;
    503     unsigned total_errors = 0, total_tests = 0, total_skipped = 0;
    504     FILE *file;
    505     char buf[5000];
    506     char *params[50];
    507     /* Store for processed integer params. */
    508     mbedtls_test_argument_t int_params[50];
    509     void *pointer;
    510 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
    511     int stdout_fd = -1;
    512 #endif /* __unix__ || __APPLE__ __MACH__ */
    513     const char *outcome_file_name = getenv("MBEDTLS_TEST_OUTCOME_FILE");
    514     FILE *outcome_file = NULL;
    515 
    516 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
    517     !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
    518     unsigned char alloc_buf[1000000];
    519     mbedtls_memory_buffer_alloc_init(alloc_buf, sizeof(alloc_buf));
    520 #endif
    521 
    522 #if defined(MBEDTLS_TEST_MUTEX_USAGE)
    523     mbedtls_test_mutex_usage_init();
    524 #endif
    525 
    526     /*
    527      * The C standard doesn't guarantee that all-bits-0 is the representation
    528      * of a NULL pointer. We do however use that in our code for initializing
    529      * structures, which should work on every modern platform. Let's be sure.
    530      */
    531     memset(&pointer, 0, sizeof(void *));
    532     if (pointer != NULL) {
    533         mbedtls_fprintf(stderr, "all-bits-zero is not a NULL pointer\n");
    534         return 1;
    535     }
    536 
    537     /*
    538      * Make sure we have a snprintf that correctly zero-terminates
    539      */
    540     if (run_test_snprintf() != 0) {
    541         mbedtls_fprintf(stderr, "the snprintf implementation is broken\n");
    542         return 1;
    543     }
    544 
    545     if (outcome_file_name != NULL && *outcome_file_name != '\0') {
    546         outcome_file = fopen(outcome_file_name, "a");
    547         if (outcome_file == NULL) {
    548             mbedtls_fprintf(stderr, "Unable to open outcome file. Continuing anyway.\n");
    549         }
    550     }
    551 
    552     while (arg_index < argc) {
    553         next_arg = argv[arg_index];
    554 
    555         if (strcmp(next_arg, "--verbose") == 0 ||
    556             strcmp(next_arg, "-v") == 0) {
    557             option_verbose = 1;
    558         } else if (strcmp(next_arg, "--help") == 0 ||
    559                    strcmp(next_arg, "-h") == 0) {
    560             mbedtls_fprintf(stdout, USAGE);
    561             mbedtls_exit(EXIT_SUCCESS);
    562         } else {
    563             /* Not an option, therefore treat all further arguments as the file
    564              * list.
    565              */
    566             test_files = &argv[arg_index];
    567             testfile_count = argc - arg_index;
    568             break;
    569         }
    570 
    571         arg_index++;
    572     }
    573 
    574     /* If no files were specified, assume a default */
    575     if (test_files == NULL || testfile_count == 0) {
    576         test_files = &default_filename;
    577         testfile_count = 1;
    578     }
    579 
    580     /* Initialize the struct that holds information about the last test */
    581     mbedtls_test_info_reset();
    582 
    583     /* Now begin to execute the tests in the testfiles */
    584     for (testfile_index = 0;
    585          testfile_index < testfile_count;
    586          testfile_index++) {
    587         size_t unmet_dep_count = 0;
    588         int unmet_dependencies[20];
    589         int missing_unmet_dependencies = 0;
    590 
    591         test_filename = test_files[testfile_index];
    592 
    593         file = fopen(test_filename, "r");
    594         if (file == NULL) {
    595             mbedtls_fprintf(stderr, "Failed to open test file: %s\n",
    596                             test_filename);
    597             if (outcome_file != NULL) {
    598                 fclose(outcome_file);
    599             }
    600             return 1;
    601         }
    602 
    603         while (!feof(file)) {
    604             if (unmet_dep_count > 0) {
    605                 mbedtls_fprintf(stderr,
    606                                 "FATAL: Dep count larger than zero at start of loop\n");
    607                 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
    608             }
    609             unmet_dep_count = 0;
    610             missing_unmet_dependencies = 0;
    611 
    612             if ((ret = get_line(file, buf, sizeof(buf))) != 0) {
    613                 break;
    614             }
    615             mbedtls_fprintf(stdout, "%s%.66s",
    616                             mbedtls_test_get_result() == MBEDTLS_TEST_RESULT_FAILED ?
    617                             "\n" : "", buf);
    618             mbedtls_fprintf(stdout, " ");
    619             for (i = strlen(buf) + 1; i < 67; i++) {
    620                 mbedtls_fprintf(stdout, ".");
    621             }
    622             mbedtls_fprintf(stdout, " ");
    623             fflush(stdout);
    624             write_outcome_entry(outcome_file, argv[0], buf);
    625 
    626             total_tests++;
    627 
    628             if ((ret = get_line(file, buf, sizeof(buf))) != 0) {
    629                 break;
    630             }
    631             cnt = parse_arguments(buf, strlen(buf), params,
    632                                   sizeof(params) / sizeof(params[0]));
    633 
    634             if (strcmp(params[0], "depends_on") == 0) {
    635                 for (i = 1; i < cnt; i++) {
    636                     int dep_id = strtol(params[i], NULL, 10);
    637                     if (dep_check(dep_id) != DEPENDENCY_SUPPORTED) {
    638                         if (unmet_dep_count <
    639                             ARRAY_LENGTH(unmet_dependencies)) {
    640                             unmet_dependencies[unmet_dep_count] = dep_id;
    641                             unmet_dep_count++;
    642                         } else {
    643                             missing_unmet_dependencies = 1;
    644                         }
    645                     }
    646                 }
    647 
    648                 if ((ret = get_line(file, buf, sizeof(buf))) != 0) {
    649                     break;
    650                 }
    651                 cnt = parse_arguments(buf, strlen(buf), params,
    652                                       sizeof(params) / sizeof(params[0]));
    653             }
    654 
    655             // If there are no unmet dependencies execute the test
    656             if (unmet_dep_count == 0) {
    657                 mbedtls_test_info_reset();
    658 
    659 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
    660                 /* Suppress all output from the library unless we're verbose
    661                  * mode
    662                  */
    663                 if (!option_verbose) {
    664                     stdout_fd = redirect_output(stdout, "/dev/null");
    665                     if (stdout_fd == -1) {
    666                         /* Redirection has failed with no stdout so exit */
    667                         exit(1);
    668                     }
    669                 }
    670 #endif /* __unix__ || __APPLE__ __MACH__ */
    671 
    672                 function_id = strtoul(params[0], NULL, 10);
    673                 if ((ret = check_test(function_id)) == DISPATCH_TEST_SUCCESS) {
    674                     ret = convert_params(cnt - 1, params + 1, int_params);
    675                     if (DISPATCH_TEST_SUCCESS == ret) {
    676                         ret = dispatch_test(function_id, (void **) (params + 1));
    677                     }
    678                 }
    679 
    680 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
    681                 if (!option_verbose && restore_output(stdout, stdout_fd)) {
    682                     /* Redirection has failed with no stdout so exit */
    683                     exit(1);
    684                 }
    685 #endif /* __unix__ || __APPLE__ __MACH__ */
    686 
    687             }
    688 
    689             write_outcome_result(outcome_file,
    690                                  unmet_dep_count, unmet_dependencies,
    691                                  missing_unmet_dependencies,
    692                                  ret);
    693             if (unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE) {
    694                 total_skipped++;
    695                 mbedtls_fprintf(stdout, "----");
    696 
    697                 if (1 == option_verbose && ret == DISPATCH_UNSUPPORTED_SUITE) {
    698                     mbedtls_fprintf(stdout, "\n   Test Suite not enabled");
    699                 }
    700 
    701                 if (1 == option_verbose && unmet_dep_count > 0) {
    702                     mbedtls_fprintf(stdout, "\n   Unmet dependencies: ");
    703                     for (i = 0; i < unmet_dep_count; i++) {
    704                         mbedtls_fprintf(stdout, "%d ",
    705                                         unmet_dependencies[i]);
    706                     }
    707                     if (missing_unmet_dependencies) {
    708                         mbedtls_fprintf(stdout, "...");
    709                     }
    710                 }
    711                 mbedtls_fprintf(stdout, "\n");
    712                 fflush(stdout);
    713 
    714                 unmet_dep_count = 0;
    715                 missing_unmet_dependencies = 0;
    716             } else if (ret == DISPATCH_TEST_SUCCESS) {
    717                 if (mbedtls_test_get_result() == MBEDTLS_TEST_RESULT_SUCCESS) {
    718                     mbedtls_fprintf(stdout, "PASS\n");
    719                 } else if (mbedtls_test_get_result() == MBEDTLS_TEST_RESULT_SKIPPED) {
    720                     mbedtls_fprintf(stdout, "----\n");
    721                     total_skipped++;
    722                 } else {
    723                     char line_buffer[MBEDTLS_TEST_LINE_LENGTH];
    724 
    725                     total_errors++;
    726                     mbedtls_fprintf(stdout, "FAILED\n");
    727                     mbedtls_fprintf(stdout, "  %s\n  at ",
    728                                     mbedtls_test_get_test());
    729                     if (mbedtls_test_get_step() != (unsigned long) (-1)) {
    730                         mbedtls_fprintf(stdout, "step %lu, ",
    731                                         mbedtls_test_get_step());
    732                     }
    733                     mbedtls_fprintf(stdout, "line %d, %s",
    734                                     mbedtls_test_get_line_no(),
    735                                     mbedtls_get_test_filename());
    736 
    737                     mbedtls_test_get_line1(line_buffer);
    738                     if (line_buffer[0] != 0) {
    739                         mbedtls_fprintf(stdout, "\n  %s", line_buffer);
    740                     }
    741                     mbedtls_test_get_line2(line_buffer);
    742                     if (line_buffer[0] != 0) {
    743                         mbedtls_fprintf(stdout, "\n  %s", line_buffer);
    744                     }
    745                 }
    746                 fflush(stdout);
    747             } else if (ret == DISPATCH_INVALID_TEST_DATA) {
    748                 mbedtls_fprintf(stderr, "FAILED: FATAL PARSE ERROR\n");
    749                 fclose(file);
    750                 mbedtls_exit(2);
    751             } else if (ret == DISPATCH_TEST_FN_NOT_FOUND) {
    752                 mbedtls_fprintf(stderr, "FAILED: FATAL TEST FUNCTION NOT FOUND\n");
    753                 fclose(file);
    754                 mbedtls_exit(2);
    755             } else {
    756                 total_errors++;
    757             }
    758         }
    759         fclose(file);
    760     }
    761 
    762     if (outcome_file != NULL) {
    763         fclose(outcome_file);
    764     }
    765 
    766     mbedtls_fprintf(stdout,
    767                     "\n----------------------------------------------------------------------------\n\n");
    768     if (total_errors == 0) {
    769         mbedtls_fprintf(stdout, "PASSED");
    770     } else {
    771         mbedtls_fprintf(stdout, "FAILED");
    772     }
    773 
    774     mbedtls_fprintf(stdout, " (%u / %u tests (%u skipped))\n",
    775                     total_tests - total_errors, total_tests, total_skipped);
    776 
    777 #if defined(MBEDTLS_TEST_MUTEX_USAGE)
    778     mbedtls_test_mutex_usage_end();
    779 #endif
    780 
    781 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
    782     !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
    783 #if defined(MBEDTLS_MEMORY_DEBUG)
    784     mbedtls_memory_buffer_alloc_status();
    785 #endif
    786     mbedtls_memory_buffer_alloc_free();
    787 #endif
    788 
    789     return total_errors != 0;
    790 }