/* $Id: t_tmpfileplus.c $ */
/*
* $Date: 2016-06-01 03:31Z $
* $Revision: 2.0.0 $
* $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/.
*
* Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd
* <http://www.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;
  int keep;
  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);

  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 */
  keep = 1;
  fp = tmpfileplus(TEST_DIR, NULL, &pathname, keep);
  test_tempfile(fp, pathname);
  fclose(fp);
  test_closedfile(pathname, keep);
  if (pathname) free(pathname);

  fp = tmpfileplus_f(TEST_DIR, NULL, pathbuf, sizeof(pathbuf), keep);
  test_tempfile(fp, pathbuf);
  fclose(fp);
  test_closedfile(pathbuf, 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);
  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);
  assert(0 == pathbuf[0]);

  return 0;
}