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