libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

test_lib.c (6876B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2012 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 */
     20 /**
     21  * @file plugins/test_lib.c
     22  * @brief helper library for writing testcases
     23  * @author Christian Grothoff
     24  */
     25 #include "platform.h"
     26 #include "test_lib.h"
     27 #include <sys/types.h>
     28 #include <regex.h>
     29 #include <signal.h>
     30 #include <stdbool.h>
     31 #include <unistd.h>
     32 
     33 /**
     34  * Function that libextractor calls for each
     35  * meta data item found.
     36  *
     37  * @param cls closure the 'struct SolutionData' we are currently working on
     38  * @param plugin_name should be "test"
     39  * @param type should be "COMMENT"
     40  * @param format should be "UTF8"
     41  * @param data_mime_type should be "<no mime>"
     42  * @param data hello world or good bye
     43  * @param data_len number of bytes in data
     44  * @return 0 (always)
     45  */
     46 static int
     47 process_replies (void *cls,
     48                  const char *plugin_name,
     49                  enum EXTRACTOR_MetaType type,
     50                  enum EXTRACTOR_MetaFormat format,
     51                  const char *data_mime_type,
     52                  const char *data,
     53                  size_t data_len)
     54 {
     55   struct SolutionData *sd = cls;
     56   unsigned int i;
     57 
     58   for (i = 0; -1 != sd[i].solved; i++)
     59   {
     60     if ( (0 != sd[i].solved) ||
     61          (sd[i].type != type) ||
     62          (sd[i].format != format) )
     63       continue;
     64     if ( (sd[i].regex) &&
     65          (EXTRACTOR_METAFORMAT_BINARY != format) )
     66     {
     67       regex_t re;
     68       regmatch_t match;
     69 
     70       if (0 !=
     71           regcomp (&re,
     72                    sd[i].data,
     73                    REG_EXTENDED))
     74       {
     75         fprintf (stderr,
     76                  "Not a valid regex: %s\n",
     77                  sd[i].data);
     78         abort ();
     79       }
     80       if ( ('\0' != data[data_len - 1]) ||
     81            (0 != regexec (&re,
     82                           data,
     83                           1,
     84                           &match,
     85                           0)) )
     86       {
     87         regfree (&re);
     88         continue;
     89       }
     90       regfree (&re);
     91     }
     92     else
     93     {
     94       if ( (EXTRACTOR_METAFORMAT_BINARY != format) &&
     95            ( (sd[i].data_len != data_len) ||
     96              (0 != memcmp (sd[i].data, data, data_len)) ) )
     97         continue;
     98       if ( (EXTRACTOR_METAFORMAT_BINARY == format) &&
     99            ( (sd[i].data_len > data_len) ||
    100              (0 != memcmp (sd[i].data, data, sd[i].data_len)) ) )
    101         continue;
    102     }
    103 
    104     if (NULL != sd[i].data_mime_type)
    105     {
    106       if (NULL == data_mime_type)
    107         continue;
    108       if (0 != strcmp (sd[i].data_mime_type, data_mime_type))
    109         continue;
    110     }
    111     else
    112     {
    113       if (NULL != data_mime_type)
    114         continue;
    115     }
    116     sd[i].solved = 1;
    117     return 0;
    118   }
    119   fprintf (stderr,
    120            "Got additional meta data of type %d and format %d with value `%.*s' from plugin `%s'\n",
    121            type,
    122            format,
    123            (int) data_len,
    124            data,
    125            plugin_name);
    126   return 0;
    127 }
    128 
    129 
    130 /**
    131  * Run a test for the given plugin, problem set and options.
    132  *
    133  * @param plugin_name name of the plugin to load
    134  * @param ps array of problems the plugin should solve;
    135  *        NULL in filename terminates the array.
    136  * @param opt options to use for loading the plugin
    137  * @return 0 on success, 1 on failure
    138  */
    139 static int
    140 run (const char *plugin_name,
    141      struct ProblemSet *ps,
    142      enum EXTRACTOR_Options opt)
    143 {
    144   struct EXTRACTOR_PluginList *pl;
    145   unsigned int i;
    146   unsigned int j;
    147   int ret;
    148   bool skipped = false;
    149 
    150   pl = EXTRACTOR_plugin_add_config (NULL,
    151                                     plugin_name,
    152                                     opt);
    153   for (i = 0; NULL != ps[i].filename; i++)
    154   {
    155     if (0 != access (ps[i].filename,
    156                      R_OK))
    157     {
    158       fprintf (stderr,
    159                "Failed to access %s, skipping test\n",
    160                ps[i].filename);
    161       skipped = true;
    162       continue;
    163     }
    164     EXTRACTOR_extract (pl,
    165                        ps[i].filename,
    166                        NULL, 0,
    167                        &process_replies,
    168                        ps[i].solution);
    169   }
    170   EXTRACTOR_plugin_remove_all (pl);
    171   if (skipped)
    172     return 0;
    173   ret = 0;
    174   for (i = 0; NULL != ps[i].filename; i++)
    175     for (j = 0; -1 != ps[i].solution[j].solved; j++)
    176       if (0 == ps[i].solution[j].solved)
    177       {
    178         ret = 1;
    179         fprintf (stderr,
    180                  "Did not get expected meta data of type %d and format %d with value `%.*s' from plugin `%s'\n",
    181                  ps[i].solution[j].type,
    182                  ps[i].solution[j].format,
    183                  (int) ps[i].solution[j].data_len,
    184                  ps[i].solution[j].data,
    185                  plugin_name);
    186       }
    187       else
    188         ps[i].solution[j].solved = 0;
    189   /* reset for next round */
    190   return ret;
    191 }
    192 
    193 
    194 #ifndef WINDOWS
    195 /**
    196  * Install a signal handler to ignore SIGPIPE.
    197  */
    198 static void
    199 ignore_sigpipe ()
    200 {
    201   struct sigaction oldsig;
    202   struct sigaction sig;
    203 
    204   memset (&sig, 0, sizeof (struct sigaction));
    205   sig.sa_handler = SIG_IGN;
    206   sigemptyset (&sig.sa_mask);
    207 #ifdef SA_INTERRUPT
    208   sig.sa_flags = SA_INTERRUPT;  /* SunOS */
    209 #else
    210   sig.sa_flags = SA_RESTART;
    211 #endif
    212   if (0 != sigaction (SIGPIPE, &sig, &oldsig))
    213     fprintf (stderr,
    214              "Failed to install SIGPIPE handler: %s\n", strerror (errno));
    215 }
    216 
    217 
    218 #endif
    219 
    220 
    221 /**
    222  * Main function to be called to test a plugin.
    223  *
    224  * @param plugin_name name of the plugin to load
    225  * @param ps array of problems the plugin should solve;
    226  *        NULL in filename terminates the array.
    227  * @return 0 on success, 1 on failure
    228  */
    229 int
    230 ET_main (const char *plugin_name,
    231          struct ProblemSet *ps)
    232 {
    233   int ret;
    234 
    235   /* change environment to find plugins which may not yet be
    236      not installed but should be in the current directory (or .libs)
    237      on 'make check' */
    238 #ifndef WINDOWS
    239   ignore_sigpipe ();
    240 #endif
    241   if (0 != putenv ("LIBEXTRACTOR_PREFIX=./.libs/"))
    242     fprintf (stderr,
    243              "Failed to update my environment, plugin loading may fail: %s\n",
    244              strerror (errno));
    245   ret = run (plugin_name, ps, EXTRACTOR_OPTION_DEFAULT_POLICY);
    246   if (0 != ret)
    247     return ret;
    248   ret = run (plugin_name, ps, EXTRACTOR_OPTION_IN_PROCESS);
    249   if (0 != ret)
    250     return ret;
    251   return 0;
    252 }
    253 
    254 
    255 /* end of test_lib.c */