/* Adapted from the DejaGnu unit testing header.
   Copyright (C) 2000-2016 Free Software Foundation, Inc.
   Copyright (C) 2024 The poke Authors.

   This file is NOT part of DejaGnu.  */

/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __DEJAGNU_H__
#define __DEJAGNU_H__

#include <config.h>

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

/* If you have problems with DejaGnu dropping failed, untested, or
 * unresolved messages generated by a unit testcase, then:  */

/* #define _DEJAGNU_WAIT_  */

#ifdef _DEJAGNU_WAIT_
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#endif

static int passed;
static int failed;
static int untest;
static int unresolve;
static int xfailed;
static int xpassed;

static char buffer[512];

static void
deja_wait (void)
{
#ifdef _DEJAGNU_WAIT_
  fd_set rfds;
  struct timeval tv;

  FD_ZERO (&rfds);
  tv.tv_sec = 0;
  tv.tv_usec = 1;

  select (0, &rfds, NULL, NULL, &tv);
#endif
}

static inline void
pass (const char* fmt, ...)
{
  va_list ap;

  passed++;
  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tPASSED: %s\n", buffer);
  deja_wait ();
}

static inline void
xpass (const char* fmt, ...)
{
  va_list ap;

  passed++;
  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tXPASSED: %s\n", buffer);
  deja_wait ();
}

static inline void
fail (const char* fmt, ...)
{
  va_list ap;

  failed++;
  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tFAILED: %s\n", buffer);
  deja_wait ();
}

static inline void
xfail (const char* fmt, ...)
{
  va_list ap;

  failed++;
  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tXFAILED: %s\n", buffer);
  deja_wait ();
}

static inline void
untested (const char* fmt, ...)
{
  va_list ap;

  untest++;
  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tUNTESTED: %s\n", buffer);
  deja_wait ();
}

static inline void
unresolved (const char* fmt, ...)
{
  va_list ap;

  unresolve++;
  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tUNRESOLVED: %s\n", buffer);
  deja_wait ();
}

static inline void
note (const char* fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  vsnprintf (buffer, sizeof (buffer), fmt, ap);
  va_end (ap);
  printf ("\tNOTE: %s\n", buffer);
  deja_wait ();
}

static inline void
totals (void)
{
  printf ("\nTotals:\n");
  printf ("\t#passed:\t\t%d\n", passed);
  printf ("\t#real failed:\t\t%d\n", failed);
  if (xfailed)
    printf ("\t#expected failures:\t\t%d\n", xfailed);
  if (untest)
    printf ("\t#untested:\t\t%d\n", untest);
  if (unresolve)
    printf ("\t#unresolved:\t\t%d\n", unresolve);
}

#endif /* _DEJAGNU_H_ */
