pdf-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pdf-devel] Built-in unit test framework


From: Aleksander Morgado
Subject: [pdf-devel] Built-in unit test framework
Date: Tue, 22 Apr 2008 16:51:41 +0200
User-agent: Thunderbird 2.0.0.12 (Macintosh/20080213)

Hi all,

I finished the simple and small replacement of Check (No-Check):
- May be enabled at configure time: ./configure --enable-nocheck
- Runs on Windows OS and systems that don't have Check available.
- Always runs in no-fork mode.
- Generates ut.log file with the same format as done by the real Check.
- The API (check.h) is equivalent to the one provided by the real Check,
so there is no need to modify the unit tests implementation.
- The dumps to stdout are completely equivalent to the ones dumped by
the real Check framework.

I attach the changes and new files.

Regards,

-Aleksander


Index: torture/unit/Makefile.am
===================================================================
RCS file: /cvsroot/pdf/libgnupdf/torture/unit/Makefile.am,v
retrieving revision 1.9
diff -r1.9 Makefile.am
19c19,36
< if CHECK
---
> 
> 
> 
> #Only generate unit tests if Check framework is available or No-Check utility
> # is requested...
> if COMPILE_UT
> 
> 
> #Check for Check and No-Check :-)
> if NOCHECK
>   NOCHECK_SRC = nocheck/check.h \
>                 nocheck/check.c
>   NOCHECK_CFLAGS = -Inocheck/
> else
>   CHECK_LIBS = -lcheck
> endif #NOCHECK
> 
> 
28c45,48
< LDADD = -lcheck $(top_srcdir)/src/libgnupdf.la $(INTL_MACOSX_LIBS) 
$(ICONV_LIBS)
---
> LDADD = $(CHECK_LIBS) \
>         $(top_srcdir)/src/libgnupdf.la \
>         $(INTL_MACOSX_LIBS) \
>         $(ICONV_LIBS)
31,32c51,54
<               -I$(top_srcdir)/src -I$(top_srcdir)/src/base \
<               -I$(top_srcdir)/src/object
---
>               -I$(top_srcdir)/src \
>               -I$(top_srcdir)/src/base \
>               -I$(top_srcdir)/src/object \
>               $(NOCHECK_CFLAGS)
128c150,153
< runtests_SOURCES = runtests.c $(TSUITE_FILES) $(TEST_FILES)
---
> runtests_SOURCES = runtests.c \
>                    $(NOCHECK_SRC) \
>                    $(TSUITE_FILES) \
>                    $(TEST_FILES)
136c161
< endif # CHECK
---
> endif # COMPILE_UT
Index: torture/unit/runtests.c
===================================================================
RCS file: /cvsroot/pdf/libgnupdf/torture/unit/runtests.c,v
retrieving revision 1.6
diff -r1.6 runtests.c
9c9
< 
---
> #include <stdio.h>

Index: configure.ac
===================================================================
RCS file: /cvsroot/pdf/libgnupdf/configure.ac,v
retrieving revision 1.33
diff -r1.33 configure.ac
54a55,57
> if test "x$have_check" = "xno"; then
>   AC_DEFINE([HAVE_CHECK], [1], [Check Unit Test Framework])
> fi
185a189,215
> 
> 
> dnl nocheck (simple replacement of Check framework when this is not available)
> use_nocheck=no
> AC_ARG_ENABLE([nocheck], AS_HELP_STRING([--enable-nocheck],
>                                       [Use built-in nocheck instead of Check 
> (default is NO)]), 
>               [use_nocheck=yes], [use_nocheck=no])
> if test "x$use_nocheck" = "xyes"; then
>   AC_DEFINE([HAVE_NOCHECK], [1], [Use No-Check instead of Check])
> fi
> AM_CONDITIONAL([NOCHECK], [test "x$use_nocheck" = "xyes"])
> 
> 
> 
> dnl Check if Unit testing support is available with Check or No-Check
> ut_support=no
> AM_CONDITIONAL([COMPILE_UT], [test "x$use_nocheck" = "xyes" -o "x$have_check" 
> = "xyes"])
> if test "x$use_nocheck" = "xyes"; then
>   ut_framework="(builtin No-Check)"
>   ut_support=yes
> else
>   if test "x$have_check" = "xyes"; then
>     ut_framework="(Check)"
>     ut_support=yes
>   fi
> fi
> 
218c248
<   With unit tests support?                  ${have_check}
---
>   With unit tests support?                  ${ut_support} ${ut_framework}

/* -*- mode: C -*- Time-stamp: ""
 *
 *       File:         check.h
 *       Date:         Fri Apr 18 20:29:04 2008
 *
 *       GNU PDF Library - Simple way to run unit tests without Check...
 *
 */

/* Copyright (C) 2008 Free Software Foundation, Inc. */

/* 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 _CHECK_H
#define _CHECK_H

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

#include <config.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif /* HAVE_MALLOC_H */


#define INITIAL_SIZE 128


/* Type for a test function */
typedef void (*TFun) (int);


/* Definition of a test case */
typedef struct _nocheck_TCase {
  char  *name;
  TFun  *elements;
  long  n;
  long  size;
} TCase;
/* Create test case */
TCase *tcase_create (const char *name);
/* Add test function to test case */
void tcase_add_test (TCase *tc, TFun tf);


/* Definition of suite */
typedef struct _nocheck_Suite {
  char  *name;
  TCase **elements;
  long   n;
  long   size;
} Suite;
/* Create suite */
Suite *suite_create (const char *name);
/* Add test case to suite */
void suite_add_tcase (Suite *s, TCase *tc);


/* Definition of 'Suite Runner' */
typedef struct _nocheck_SRunner {
  Suite  **elements;
  long    n;
  long    size;
} SRunner;
/* Create suite runner */
SRunner *srunner_create (Suite *s);
/* Add suite to suite runner */
void srunner_add_suite (SRunner *sr, Suite *s);
/* Free suite runner and its contents */
void srunner_free (SRunner *sr);




enum print_output {
  CK_SILENT,
  CK_MINIMAL,
  CK_NORMAL,
  CK_VERBOSE,
  CK_ENV,
  CK_LAST
};

/* Run all tests */
void srunner_run_all (SRunner *sr, enum print_output print_mode);


/* Other needed functions */
int srunner_ntests_failed (SRunner *sr);
void tcase_fn_start (const char *fname, const char *file, int line);
void srunner_set_log (SRunner *sr, const char *fname);




/* Test start and end points definition */
#define START_TEST(__testname)\
static void __testname (int __attribute__((unused)) _i)\
{\
   const char *test_name = ""# __testname; \
   tcase_fn_start (""# __testname, __FILE__, __LINE__);

#define END_TEST \
  _fail_unless(1, test_name, __FILE__, __LINE__,"Passed"); \
}



/* Support for fail_if and fail_unless */
void _fail_unless (int result,
                   const char *test,
                   const char *file,
                   int line,
                   const char *expr,
                   ...);

#define fail_unless(expr, ...) do { \
  if(!(expr)) { \
    _fail_unless(expr, test_name, __FILE__, __LINE__,"Assertion '"#expr"' 
failed" , ## __VA_ARGS__, NULL); \
    return; \
  } \
} while(0)

#define fail_if(expr, ...) do { \
  if((expr)) { \
    _fail_unless(!(expr), test_name, __FILE__, __LINE__,"Failure '"#expr"' 
occured" , ## __VA_ARGS__, NULL); \
    return; \
  } \
} while(0)

#endif /* !_CHECK_H */

/* End of check.h */
/* -*- mode: C -*- Time-stamp: ""
 *
 *       File:         check.c
 *       Date:         Fri Apr 18 20:29:04 2008
 *
 *       GNU PDF Library - Simple way to run unit tests without Check...
 *
 */

/* Copyright (C) 2008 Free Software Foundation, Inc. */

/* 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/>.
 */

#include <check.h>


FILE *pf_log;
char *suite_running;
char *tc_running;


Suite *suite_create (const char *name)
{
  Suite *newelem = (Suite *)calloc(1,sizeof(Suite));
  if(newelem != NULL)
    {
      newelem->name = (name != NULL) ? strdup(name) : NULL;
      newelem->n = 0;
      newelem->size = INITIAL_SIZE;
      newelem->elements = (TCase **)calloc(newelem->size, sizeof(TCase *));
    }
  return newelem;
}

void suite_add_tcase (Suite *s, TCase *tc)
{
  if(s->n == s->size)
    {
      s->size *= 2;
      s->elements = (TCase **)realloc(s->elements, sizeof(TCase *)*s->size);
    }
  s->elements[s->n++] = tc;
}

TCase *tcase_create (const char *name)
{
  TCase *newelem = (TCase *)calloc(1,sizeof(TCase));
  if(newelem != NULL)
    {
      newelem->name = (name != NULL) ? strdup(name) : NULL;
      newelem->n = 0;
      newelem->size = INITIAL_SIZE;
      newelem->elements = (TFun *)calloc(newelem->size, sizeof(TFun));
    }
  return newelem;
}

void tcase_add_test (TCase *tc, TFun tf)
{
  if(tc->n == tc->size)
    {
      tc->size *= 2;
      tc->elements = (TFun *)realloc(tc->elements, sizeof(TFun)*tc->size);
    }
  tc->elements[tc->n++] = tf;
}

SRunner *srunner_create (Suite *s)
{
  SRunner *newelem = (SRunner *)calloc(1,sizeof(SRunner));
  if(newelem != NULL)
    {
      newelem->n = 0;
      newelem->size = INITIAL_SIZE;
      newelem->elements = (Suite **)calloc(newelem->size, sizeof(Suite *));
    }
  if(s != NULL)
    {
      srunner_add_suite(newelem, s);
    }
  return newelem;
}

void srunner_add_suite (SRunner *sr, Suite *s)
{
  if(sr->n == sr->size)
    {
      sr->size *= 2;
      sr->elements = (Suite **)realloc(sr->elements, sizeof(Suite *)*sr->size);
    }
  sr->elements[sr->n++] = s;
}

void srunner_free (SRunner *sr)
{
  extern FILE *pf_log;
  long i;
  /* Walk test suites in suite runner */
  for(i = 0; i < sr->n; i++)
    {
      Suite *suite = sr->elements[i];
      long j;
      /* Walk test cases in suite */
      for(j=0; j < suite->n; j++)
        {
          TCase *tc = suite->elements[j];
          if(tc->name != NULL)
            free(tc->name);
          if(tc->elements != NULL)
            free(tc->elements);
          free(tc);
        }
      if(suite->name != NULL)
        free(suite->name);
      if(suite->elements != NULL)
        free(suite->elements);
      free(suite);
    }
  if(sr->elements != NULL)
    free(sr->elements);
  free(sr);
  
  /* Close log file if it was open */
  if(pf_log != NULL)
    {
      fclose(pf_log);
    }
}

void srunner_run_all (SRunner *sr, enum print_output print_mode)
{
  extern char *tc_running;
  extern FILE *pf_log;
  long i;
  fprintf(stdout,"[No-Check] Running all suites...\n\n\n");
  /* Walk test suites in suite runner */
  for(i = 0; i < sr->n; i++)
    {
      long j;
      Suite *suite = sr->elements[i];
      if(pf_log != NULL)
        {
          fprintf(pf_log,"Running suite %s\n", suite->name);
        }
      /* Walk test cases in suite */
      for(j=0; j < suite->n; j++)
        {
          long k;
          TCase *tc = suite->elements[j];
          tc_running = tc->name;
          /* Walk tests in test case... */
          for(k=0; k < tc->n; k++)
            {
              TFun function = tc->elements[k];
              /* Execute TEST */
              function(0);
            }
        }
    }
}
                


void _fail_unless (int result,
                   const char *test,
                   const char *file,
                   int line,
                   const char *expr,
                   ...)
{
  extern char *tc_running;
  extern FILE *pf_log;
  va_list args;
  FILE *pfs[2];
  short i;
  
  pfs[0] = stdout;
  pfs[1] = pf_log;
  
  va_start (args, expr);
  for(i=0; i <=1; i++)
    {
      if(pfs[i] != NULL)
        {
          fprintf(pfs[i], "%s:%d:%c:%s:%s: ",
                  file, line,
                  (result ? 'P' : 'F'),
                  tc_running, test);
          vfprintf (pfs[i], expr, args);
          fprintf(pfs[i], "\n");
        }
    }
  va_end (args);
}

void tcase_fn_start (const char *fname, const char *file, int line)
{
  /* Do nothing */
}


void srunner_set_log (SRunner *sr, const char *fname)
{
  extern FILE *pf_log;

  /* Open log file */
  pf_log = fopen(fname, "w");
}

int srunner_ntests_failed (SRunner *sr)
{
  /* Do nothing */
  return 0;
}

/* End of check.c */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]