/* $Id: t_tmpfileplus.c $ */
/*
* $Date: 2026-08-29 10:11Z $
* $Revision: 2.1.1 $
* $Author: dai $
*/

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*
* Copyright (c) 2012-26 David Ireland, DI Management Services Pty Ltd
* <https://di-mgt.com.au/contact/>.
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <assert.h>
#include "tmpfileplus.h"

/* Choose test directory suitable for Windows or Linux */
#ifdef _WIN32
#define TEST_DIR "C:\\Test"
#else
#define TEST_DIR "./Test"
#endif

int test_tempfile(FILE *fp, char *pathname)
{
    time_t now;
    clock_t clk;

    printf("\nTESTING: ");
    printf("pathname=[%s]\n", (pathname ? pathname : "NULL"));
    if (fp) {
        int i;
        int c;
        printf("fp is valid\n");
        /* Write the time now and the alphabet to our temp file */
        time(&now);
        fprintf(fp, "%s", ctime(&now));
        clk = clock();
        fprintf(fp, "clock=%#x ms\n", (unsigned)clk);
        for (i = 0; i < 26; i++)
            fputc('A'+i, fp);

        rewind(fp);
        printf("DATA:\n");
        while ((c = fgetc(fp)) != EOF)
        {
            putchar(c);
        }
        printf("\n");

    }
    else {
        printf("ERROR: fp is not valid!\n");
        assert(fp);
    }

    return 0;
}

int test_closedfile(const char *tempfile, int keep)
{
    FILE *fp;
    if (tempfile) {
        printf("After closing...\n");
        /* See if file still exists */
        fp = fopen(tempfile, "rb");
        if (fp) {
            printf("File '%s' EXISTS%s\n", tempfile, (keep ? ", as expected" : " ERROR!"));
            fclose(fp);
            assert(keep);
        }
        else {
            printf("File '%s' DOES NOT exist%s\n", tempfile, (!keep ? ", as expected" : " ERROR!"));
            assert(!keep);
        }
    }
    return 0;
}


int main(void)
{
    FILE *fp;
    char *pathname;
    char pathbuf[FILENAME_MAX];
    size_t flen;

    /* Test with no pathname, like tmpfile() */
    fp = tmpfileplus(NULL, NULL, NULL, 0);
    test_tempfile(fp, NULL);
    fclose(fp);

    fp = tmpfileplus_f(NULL, NULL, NULL, 0, 0);
    test_tempfile(fp, NULL);
    fclose(fp);

    /* Test with a pathname */
    fp = tmpfileplus(NULL, NULL, &pathname, 0);
    test_tempfile(fp, pathname);
    fclose(fp);
    test_closedfile(pathname, 0);
    if (pathname) free(pathname);

    fp = tmpfileplus_f(NULL, NULL, pathbuf, sizeof(pathbuf), 0);
    test_tempfile(fp, pathbuf);
    fclose(fp);
    test_closedfile(pathbuf, 0);
    /* Remember this "standard" length for later */
    flen = strlen(pathbuf);
    assert(flen > 0);

    /* Test with a given prefix */
    fp = tmpfileplus(NULL, "THIS-", &pathname, 0);
    test_tempfile(fp, pathname);
    fclose(fp);
    test_closedfile(pathname, 0);
    if (pathname) free(pathname);

    /* Use fixed-length buffer - no need to free pathname */
    fp = tmpfileplus_f(NULL, "THIS-", pathbuf, sizeof(pathbuf), 0);
    test_tempfile(fp, pathbuf);
    fclose(fp);
    test_closedfile(pathbuf, 0);

    /* Test with a specified directory
       -- directory "C:\Test" (Windows) or "./Test" (Linux) must exist 
       -- otherwise default is used */
    fp = tmpfileplus(TEST_DIR, "THAT~", &pathname, 0);
    test_tempfile(fp, pathname);
    fclose(fp);
    test_closedfile(pathname, 0);
    if (pathname) free(pathname);

    fp = tmpfileplus_f(TEST_DIR, "THAT~", pathbuf, sizeof(pathbuf), 0);
    test_tempfile(fp, pathbuf);
    fclose(fp);
    test_closedfile(pathbuf, 0);

    /* Test with a specified directory but keep the file */
    fp = tmpfileplus(TEST_DIR, NULL, &pathname, TMPFILE_KEEP);
    test_tempfile(fp, pathname);
    fclose(fp);
    test_closedfile(pathname, TMPFILE_KEEP);
    if (pathname) free(pathname);

    fp = tmpfileplus_f(TEST_DIR, NULL, pathbuf, sizeof(pathbuf), TMPFILE_KEEP);
    test_tempfile(fp, pathbuf);
    fclose(fp);
    test_closedfile(pathbuf, TMPFILE_KEEP);

    // New in v2.1 - specify filename extension

    /* Test with a pathname */
    fp = tmpfileplus_ex(NULL, NULL, ".txt", &pathname, 0);
    test_tempfile(fp, pathname);
    fclose(fp);
    test_closedfile(pathname, 0);
    if (pathname) free(pathname);

    fp = tmpfileplus_ex_f(NULL, NULL, ".txt", pathbuf, sizeof(pathbuf), 0);
    test_tempfile(fp, pathbuf);
    fclose(fp);
    test_closedfile(pathbuf, 0);

    fp = tmpfileplus_ex_f(TEST_DIR, "TMPFILEPLUS-", ".txt", pathbuf, sizeof(pathbuf), TMPFILE_KEEP);
    test_tempfile(fp, pathbuf);
    fclose(fp);
    test_closedfile(pathbuf, TMPFILE_KEEP);

    /* Test with too short buffer - this should fail */
    printf("\nTest with too short buffer...\n");
    pathbuf[0] = 0;
    fp = tmpfileplus_f(NULL, NULL, pathbuf, 5, 0);
    printf("fp=%p, errno=%d\n", fp, errno);
    assert(!fp);
    printf("Expected error: %s\n", strerror(errno));
    assert(0 == pathbuf[0]);

    /* Try an off-by-one error */
    pathbuf[0] = 0;
    fp = tmpfileplus_f(NULL, NULL, pathbuf, flen, 1);
    printf("fp=%p, errno=%d\n", fp, errno);
    assert(!fp);
    printf("Expected error: %s\n", strerror(errno));
    assert(0 == pathbuf[0]);

    printf("\nALL DONE.\n");

    return 0;
}