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