/* This file is part of the Neper software package. */
/* Copyright (C) 2003-2014, Romain Quey. */
/* See the COPYING file in the top-level directory. */

#include"ned_testing_.h"

void
ned_testing (struct IN In, char *mod)
{
  int i, j, status, statuspre, failedqty, skippedqty, qty = 0;
  int *failed = NULL;
  int *skipped = NULL;
  char *precommand = ut_alloc_1d_char (1000);
  char *command = ut_alloc_1d_char (1000);
  char *string = ut_alloc_1d_char (1000);
  char **tmp = NULL;
  struct TEST Test;
  char* wd = ut_alloc_1d_char (1000); // working directory
  char* td = ut_alloc_1d_char (1000); // testing directory

  wd = getcwd (wd, 1000);
  sprintf (td, "%s/neper_testing", wd);

  ut_sys_mkdirp (td);

  neut_test_set_zero (&Test);

  ned_testing_init (mod, In.runmode, In.tests, &Test);

#ifndef HAVE_LIBMATHEVAL
  ut_print_message (1, 1, "libmatheval not available: some tests will be skipped.\n");
#endif

#ifndef HAVE_LIBSCOTCH
  ut_print_message (1, 1, "libscotch not available: some tests will be skipped.\n");
#endif

  ut_print_message (0, 1, "Testing module %s... (%d tests)\n", mod,
		    Test.Qty);

  if (Test.ModPreCom)
  {
    ut_print_message (0, 2, "Preparing...\n");
    ut_string_separate (Test.ModPreCom, ";", &tmp, &qty);

    for (i = 0; i < qty; i++)
    {
      if (strstr (tmp[i], "neper"))
      {
	sprintf (precommand, "%s > /dev/null 2> /dev/null", tmp[i]);
	ut_string_fnrs (precommand, "neper", In.bin, 1);
      }
      else
	strcpy (precommand, tmp[i]);

      if (chdir (td) != 0)
	abort ();
      status = system (precommand);
      if (chdir (wd) != 0)
	abort ();
      if (status != 0)
	ut_print_message (2, 3, "Module precommand failed: `%s'.\n",
	                  precommand);
    }
  }

  failedqty = 0;
  skippedqty = 0;
  for (i = 1; i <= Test.Qty; i++)
  {
    if (Test.PreCom[i])
    {
      if (strstr (Test.PreCom[i], "neper"))
      {
	sprintf (precommand, "%s > /dev/null 2> /dev/null", Test.PreCom[i]);
	ut_string_fnrs (precommand, "neper", In.bin, 1);
      }
      else
	strcpy (precommand, Test.PreCom[i]);
    }

    if (strcmp (mod, "-V") != 0)
      sprintf (command, "%s --rcfile none %s %s > /dev/null 2> /dev/null",
	       In.bin, mod, Test.Com[i]);
    else
      sprintf (command, "%s --rcfile none %s -imagesize 100:100 %s > /dev/null 2> /dev/null",
	       In.bin, mod, Test.Com[i]);

    sprintf (string, "  [%2d] %s ", Test.Id[i], Test.Com[i]);
    for (j = strlen (string) + 9; j < 64; j++)
      string = strcat (string, ".");

    ut_print_message (0, 1, "%s ", string);

    // Running pre-command(s) if necessary
    statuspre = 0;
    if (Test.PreCom[i])
    {
      if (chdir (td) != 0)
	abort ();
      statuspre = system (precommand);
      if (chdir (wd) != 0)
	abort ();
    }

    status = 0;
    if (!statuspre)
    {
      if (strstr (Test.ComDep[i], "libscotch"))
      {
#ifdef HAVE_LIBSCOTCH
	if (chdir (td) != 0)
	  abort ();
	status = system (command);
	if (chdir (wd) != 0)
	  abort ();
#else
	status = -2;
#endif
      }
      else if (strstr (Test.ComDep[i], "libmatheval"))
      {
#ifdef HAVE_LIBMATHEVAL
	if (chdir (td) != 0)
	  abort ();
	status = system (command);
	if (chdir (wd) != 0)
	  abort ();
#else
	status = -2;
#endif
      }
      else
      {
	if (chdir (td) != 0)
	  abort ();
	status = system (command);
	if (chdir (wd) != 0)
	  abort ();
      }
    }

    // http://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal
    if (!statuspre && !status)
      printf ("%s", "passed");
    else if (status == -2)
      printf ("%s", (isatty (1)) ? "\033[1;45mskipped\033[0m" : "skipped");
    else
      printf ("%s", (isatty (1)) ? "\033[1;41mfailed\033[0m" : "failed");

    printf ("\n");
    fflush (stdout);

    if (status == -2)
    {
      skipped = ut_realloc_1d_int (skipped, ++skippedqty);
      skipped[skippedqty - 1] = i;
    }
    else if (status != 0)
    {
      failed = ut_realloc_1d_int (failed, ++failedqty);
      failed[failedqty - 1] = i;
    }
  }

  ut_print_message (failedqty > 0 || skippedqty > 0, 2, "%d tests, passed: %d, skipped: %d, failed: %d.\n",
		    Test.Qty, Test.Qty - failedqty - skippedqty,
		    skippedqty, failedqty);

  if (skippedqty > 0)
  {
    ut_print_message (1, 2, "Skipped tests: ");
    ut_array_1d_int_fprintf_sep (stdout, skipped, skippedqty, ",", "%d");
  }

  if (failedqty > 0)
  {
    ut_print_message (1, 2, "Failed tests: ");
    ut_array_1d_int_fprintf_sep (stdout, failed, failedqty, ",", "%d");
  }

#ifdef HAVE_DEBUGGING
  if (failedqty == 0)
#endif
  {
    sprintf (command, "rm -r %s", td);
    if (system (command) != 0)
      abort ();
  }

  ut_free_1d_int (failed);
  ut_free_1d_int (skipped);
  ut_free_1d_char (precommand);
  ut_free_1d_char (command);
  ut_free_1d_char (string);
  ut_free_2d_char (tmp, qty);
  neut_test_free (&Test);
  ut_free_1d_char (wd);
  ut_free_1d_char (td);

  return;
}
