// Suggested regression tests for PcapDirectoryDispatchForTimeRange() in
// src/source-pcap-file-directory-helper.c.
//
// source-pcap-file-directory-helper.c has no unit tests in oisf/main today, so
// three pieces are needed:
//
// 1. The tests, appended at the end of source-pcap-file-directory-helper.c
//    together with their registration function:

#ifdef UNITTESTS

/** \test CleanupPcapFileDirectoryVars(NULL) must not crash. */
static int PcapDirectoryHelperCleanupNullTest(void)
{
    CleanupPcapFileDirectoryVars(NULL);
    PASS;
}

/** \test CleanupPendingFile(NULL) must not crash. */
static int PcapDirectoryHelperCleanupPendingFileNullTest(void)
{
    CleanupPendingFile(NULL);
    PASS;
}

/**
 * \test After CleanupPcapFileFileVars() the pointer
 *       must be NULLed before any early return so that
 *       CleanupPcapFileDirectoryVars() cannot double-free it on teardown.
 *
 *       Simulates the FAILED branch of PcapDirectoryDispatchForTimeRange():
 *         pv->current_file = pftv;
 *         PcapFileDispatch(pftv);          -- returns TM_ECODE_FAILED
 *         CleanupPcapFileFileVars(pftv);   -- frees pftv
 *         pv->current_file = NULL;         -- the fix
 *         ... early return ...
 *       Then thread teardown calls CleanupPcapFileDirectoryVars(pv).
 *       Without the fix, current_file would still point at freed memory and
 *       CleanupPcapFileDirectoryVars would call CleanupPcapFileFileVars again
 *       (double-free / use-after-free).
 */
static int PcapDirectoryHelperCurrentFileNullAfterFileCleanupTest(void)
{
    PcapFileDirectoryVars *pv = SCCalloc(1, sizeof(PcapFileDirectoryVars));
    FAIL_IF_NULL(pv);
    TAILQ_INIT(&pv->directory_content);

    PcapFileFileVars *pftv = SCCalloc(1, sizeof(PcapFileFileVars));
    if (unlikely(pftv == NULL)) {
        SCFree(pv);
        FAIL;
    }

    pv->current_file = pftv;

    /* mirror the fixed code path in PcapDirectoryDispatchForTimeRange */
    CleanupPcapFileFileVars(pftv);
    pv->current_file = NULL;

    /* verify the invariant the fix establishes */
    FAIL_IF_NOT_NULL(pv->current_file);

    /* teardown must not double-free; hands ownership of pv to the callee */
    CleanupPcapFileDirectoryVars(pv);
    PASS;
}

void PcapDirectoryHelperRegisterTests(void)
{
    UtRegisterTest("PcapDirectoryHelperCleanupNullTest",
                   PcapDirectoryHelperCleanupNullTest);
    UtRegisterTest("PcapDirectoryHelperCleanupPendingFileNullTest",
                   PcapDirectoryHelperCleanupPendingFileNullTest);
    UtRegisterTest("PcapDirectoryHelperCurrentFileNullAfterFileCleanupTest",
                   PcapDirectoryHelperCurrentFileNullAfterFileCleanupTest);
}
#endif /* UNITTESTS */

// 2. The declaration, in src/source-pcap-file-directory-helper.h before the
//    final #endif:
//
//        #ifdef UNITTESTS
//        void PcapDirectoryHelperRegisterTests(void);
//        #endif
//
// 3. The call, in src/runmode-unittests.c right after
//    SourcePcapFileHelperRegisterTests():
//
//        PcapDirectoryHelperRegisterTests();
//
//    and, next to the existing `#include "source-pcap-file-helper.h"`:
//
//        #include "source-pcap-file-directory-helper.h"
