libextractor

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

test_lib.c (7010B)


      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     if ( (NULL != sd[i].validate) &&
    117          (0 == sd[i].validate (data,
    118                                data_len)) )
    119       continue;
    120     sd[i].solved = 1;
    121     return 0;
    122   }
    123   fprintf (stderr,
    124            "Got additional meta data of type %d and format %d with value `%.*s' from plugin `%s'\n",
    125            type,
    126            format,
    127            (int) data_len,
    128            data,
    129            plugin_name);
    130   return 0;
    131 }
    132 
    133 
    134 /**
    135  * Run a test for the given plugin, problem set and options.
    136  *
    137  * @param plugin_name name of the plugin to load
    138  * @param ps array of problems the plugin should solve;
    139  *        NULL in filename terminates the array.
    140  * @param opt options to use for loading the plugin
    141  * @return 0 on success, 1 on failure
    142  */
    143 static int
    144 run (const char *plugin_name,
    145      struct ProblemSet *ps,
    146      enum EXTRACTOR_Options opt)
    147 {
    148   struct EXTRACTOR_PluginList *pl;
    149   unsigned int i;
    150   unsigned int j;
    151   int ret;
    152   bool skipped = false;
    153 
    154   pl = EXTRACTOR_plugin_add_config (NULL,
    155                                     plugin_name,
    156                                     opt);
    157   for (i = 0; NULL != ps[i].filename; i++)
    158   {
    159     if (0 != access (ps[i].filename,
    160                      R_OK))
    161     {
    162       fprintf (stderr,
    163                "Failed to access %s, skipping test\n",
    164                ps[i].filename);
    165       skipped = true;
    166       continue;
    167     }
    168     EXTRACTOR_extract (pl,
    169                        ps[i].filename,
    170                        NULL, 0,
    171                        &process_replies,
    172                        ps[i].solution);
    173   }
    174   EXTRACTOR_plugin_remove_all (pl);
    175   if (skipped)
    176     return 0;
    177   ret = 0;
    178   for (i = 0; NULL != ps[i].filename; i++)
    179     for (j = 0; -1 != ps[i].solution[j].solved; j++)
    180       if (0 == ps[i].solution[j].solved)
    181       {
    182         ret = 1;
    183         fprintf (stderr,
    184                  "Did not get expected meta data of type %d and format %d with value `%.*s' from plugin `%s'\n",
    185                  ps[i].solution[j].type,
    186                  ps[i].solution[j].format,
    187                  (int) ps[i].solution[j].data_len,
    188                  ps[i].solution[j].data,
    189                  plugin_name);
    190       }
    191       else
    192         ps[i].solution[j].solved = 0;
    193   /* reset for next round */
    194   return ret;
    195 }
    196 
    197 
    198 #ifndef WINDOWS
    199 /**
    200  * Install a signal handler to ignore SIGPIPE.
    201  */
    202 static void
    203 ignore_sigpipe ()
    204 {
    205   struct sigaction oldsig;
    206   struct sigaction sig;
    207 
    208   memset (&sig, 0, sizeof (struct sigaction));
    209   sig.sa_handler = SIG_IGN;
    210   sigemptyset (&sig.sa_mask);
    211 #ifdef SA_INTERRUPT
    212   sig.sa_flags = SA_INTERRUPT;  /* SunOS */
    213 #else
    214   sig.sa_flags = SA_RESTART;
    215 #endif
    216   if (0 != sigaction (SIGPIPE, &sig, &oldsig))
    217     fprintf (stderr,
    218              "Failed to install SIGPIPE handler: %s\n", strerror (errno));
    219 }
    220 
    221 
    222 #endif
    223 
    224 
    225 /**
    226  * Main function to be called to test a plugin.
    227  *
    228  * @param plugin_name name of the plugin to load
    229  * @param ps array of problems the plugin should solve;
    230  *        NULL in filename terminates the array.
    231  * @return 0 on success, 1 on failure
    232  */
    233 int
    234 ET_main (const char *plugin_name,
    235          struct ProblemSet *ps)
    236 {
    237   int ret;
    238 
    239   /* change environment to find plugins which may not yet be
    240      not installed but should be in the current directory (or .libs)
    241      on 'make check' */
    242 #ifndef WINDOWS
    243   ignore_sigpipe ();
    244 #endif
    245   if (0 != putenv ("LIBEXTRACTOR_PREFIX=./.libs/"))
    246     fprintf (stderr,
    247              "Failed to update my environment, plugin loading may fail: %s\n",
    248              strerror (errno));
    249   ret = run (plugin_name, ps, EXTRACTOR_OPTION_DEFAULT_POLICY);
    250   if (0 != ret)
    251     return ret;
    252   ret = run (plugin_name, ps, EXTRACTOR_OPTION_IN_PROCESS);
    253   if (0 != ret)
    254     return ret;
    255   return 0;
    256 }
    257 
    258 
    259 /* end of test_lib.c */