static inline int s_aws_run_test_case()

in GameLiftPlugin/Source/AWSSDK/Include/aws/testing/aws_test_harness.h [396:498]


static inline int s_aws_run_test_case(struct aws_test_harness *harness) {
    AWS_ASSERT(harness->run);
/*
 * MSVC compiler has a weird interactive pop-up in debug whenever 'abort()' is called, which can be triggered
 * by hitting any aws_assert or aws_pre_condition, causing the CI to hang. So disable the pop-up in tests.
 */
#ifdef _MSC_VER
    _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif

#if defined(_WIN32)
    SetUnhandledExceptionFilter(s_test_print_stack_trace);
    /* Set working directory to path to this exe */
    char cwd[512];
    DWORD len = GetModuleFileNameA(NULL, cwd, sizeof(cwd));
    DWORD idx = len - 1;
    while (idx && cwd[idx] != '\\') {
        idx--;
    }
    cwd[idx] = 0;
    SetCurrentDirectory(cwd);
#elif defined(AWS_HAVE_EXECINFO)
    struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);

    sa.sa_flags = SA_NODEFER;
    sa.sa_sigaction = s_print_stack_trace;

    sigaction(SIGSEGV, &sa, NULL);
#endif

    /* track allocations and report leaks in tests, unless suppressed */
    struct aws_allocator *allocator = NULL;
    if (harness->suppress_memcheck) {
        allocator = aws_default_allocator();
    } else {
        allocator = aws_mem_tracer_new(aws_default_allocator(), NULL, AWS_MEMTRACE_STACKS, 8);
    }

    /* wire up a logger to stderr by default, may be replaced by some tests */
    struct aws_logger err_logger;
    struct aws_logger_standard_options options;
    options.file = AWS_TESTING_REPORT_FD;
    options.level = AWS_LL_TRACE;
    options.filename = NULL;
    aws_logger_init_standard(&err_logger, aws_default_allocator(), &options);
    aws_logger_set(&err_logger);

    int test_res = AWS_OP_ERR;
    int setup_res = AWS_OP_SUCCESS;
    if (harness->on_before) {
        setup_res = harness->on_before(allocator, harness->ctx);
    }

    if (!setup_res) {
        test_res = harness->run(allocator, harness->ctx);
    }

    if (harness->on_after) {
        test_res |= harness->on_after(allocator, setup_res, harness->ctx);
    }

    if (test_res != AWS_OP_SUCCESS) {
        goto fail;
    }

    if (!harness->suppress_memcheck) {
        /* Reset the logger, as test can set their own logger and clean it up,
         * but aws_mem_tracer_dump() needs a valid logger to be active */
        aws_logger_set(&err_logger);

        const size_t leaked_allocations = aws_mem_tracer_count(allocator);
        const size_t leaked_bytes = aws_mem_tracer_bytes(allocator);
        if (leaked_bytes) {
            aws_mem_tracer_dump(allocator);
            PRINT_FAIL_WITHOUT_LOCATION(
                "Test leaked memory: %zu bytes %zu allocations", leaked_bytes, leaked_allocations);
            goto fail;
        }

        aws_mem_tracer_destroy(allocator);
    }

    aws_logger_set(NULL);
    aws_logger_clean_up(&err_logger);

    RETURN_SUCCESS("%s [ \033[32mOK\033[0m ]", harness->test_name);

fail:
    if (test_res == AWS_OP_SKIP) {
        fprintf(AWS_TESTING_REPORT_FD, "%s [ \033[32mSKIP\033[0m ]\n", harness->test_name);
    } else {
        PRINT_FAIL_WITHOUT_LOCATION("%s [ \033[31mFAILED\033[0m ]", harness->test_name);
    }
    /* Use _Exit() to terminate without cleaning up resources.
     * This prevents LeakSanitizer spam (yes, we know failing tests don't bother cleaning up).
     * It also prevents errors where threads that haven't cleaned are still using the logger declared in this fn. */
    fflush(AWS_TESTING_REPORT_FD);
    fflush(stdout);
    fflush(stderr);
    _Exit(test_res == AWS_OP_SKIP ? SKIP : FAILURE);
}