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
31 /**
32 * Function that libextractor calls for each
33 * meta data item found.
34 *
35 * @param cls closure the 'struct SolutionData' we are currently working on
36 * @param plugin_name should be "test"
37 * @param type should be "COMMENT"
38 * @param format should be "UTF8"
39 * @param data_mime_type should be "<no mime>"
40 * @param data hello world or good bye
41 * @param data_len number of bytes in data
42 * @return 0 (always)
43 */
44 static int
process_replies(void * cls,const char * plugin_name,enum EXTRACTOR_MetaType type,enum EXTRACTOR_MetaFormat format,const char * data_mime_type,const char * data,size_t data_len)45 process_replies (void *cls,
46 const char *plugin_name,
47 enum EXTRACTOR_MetaType type,
48 enum EXTRACTOR_MetaFormat format,
49 const char *data_mime_type,
50 const char *data,
51 size_t data_len)
52 {
53 struct SolutionData *sd = cls;
54 unsigned int i;
55
56 for (i = 0; -1 != sd[i].solved; i++)
57 {
58 if ( (0 != sd[i].solved) ||
59 (sd[i].type != type) ||
60 (sd[i].format != format) )
61 continue;
62 if ( (sd[i].regex) &&
63 (EXTRACTOR_METAFORMAT_BINARY != format) )
64 {
65 regex_t re;
66 regmatch_t match;
67
68 if (0 !=
69 regcomp (&re,
70 sd[i].data,
71 REG_EXTENDED))
72 {
73 fprintf (stderr,
74 "Not a valid regex: %s\n",
75 sd[i].data);
76 abort ();
77 }
78 if ( ('\0' != data[data_len - 1]) ||
79 (0 != regexec (&re,
80 data,
81 1,
82 &match,
83 0)) )
84 {
85 regfree (&re);
86 continue;
87 }
88 regfree (&re);
89 }
90 else
91 {
92 if ( (EXTRACTOR_METAFORMAT_BINARY != format) &&
93 ( (sd[i].data_len != data_len) ||
94 (0 != memcmp (sd[i].data, data, data_len)) ) )
95 continue;
96 if ( (EXTRACTOR_METAFORMAT_BINARY == format) &&
97 ( (sd[i].data_len > data_len) ||
98 (0 != memcmp (sd[i].data, data, sd[i].data_len)) ) )
99 continue;
100 }
101
102 if (NULL != sd[i].data_mime_type)
103 {
104 if (NULL == data_mime_type)
105 continue;
106 if (0 != strcmp (sd[i].data_mime_type, data_mime_type))
107 continue;
108 }
109 else
110 {
111 if (NULL != data_mime_type)
112 continue;
113 }
114 sd[i].solved = 1;
115 return 0;
116 }
117 fprintf (stderr,
118 "Got additional meta data of type %d and format %d with value `%.*s' from plugin `%s'\n",
119 type,
120 format,
121 (int) data_len,
122 data,
123 plugin_name);
124 return 0;
125 }
126
127
128 /**
129 * Run a test for the given plugin, problem set and options.
130 *
131 * @param plugin_name name of the plugin to load
132 * @param ps array of problems the plugin should solve;
133 * NULL in filename terminates the array.
134 * @param opt options to use for loading the plugin
135 * @return 0 on success, 1 on failure
136 */
137 static int
run(const char * plugin_name,struct ProblemSet * ps,enum EXTRACTOR_Options opt)138 run (const char *plugin_name,
139 struct ProblemSet *ps,
140 enum EXTRACTOR_Options opt)
141 {
142 struct EXTRACTOR_PluginList *pl;
143 unsigned int i;
144 unsigned int j;
145 int ret;
146
147 pl = EXTRACTOR_plugin_add_config (NULL,
148 plugin_name,
149 opt);
150 for (i = 0; NULL != ps[i].filename; i++)
151 EXTRACTOR_extract (pl,
152 ps[i].filename,
153 NULL, 0,
154 &process_replies,
155 ps[i].solution);
156 EXTRACTOR_plugin_remove_all (pl);
157 ret = 0;
158 for (i = 0; NULL != ps[i].filename; i++)
159 for (j = 0; -1 != ps[i].solution[j].solved; j++)
160 if (0 == ps[i].solution[j].solved)
161 {
162 ret = 1;
163 fprintf (stderr,
164 "Did not get expected meta data of type %d and format %d with value `%.*s' from plugin `%s'\n",
165 ps[i].solution[j].type,
166 ps[i].solution[j].format,
167 (int) ps[i].solution[j].data_len,
168 ps[i].solution[j].data,
169 plugin_name);
170 }
171 else
172 ps[i].solution[j].solved = 0;
173 /* reset for next round */
174 return ret;
175 }
176
177
178 #ifndef WINDOWS
179 /**
180 * Install a signal handler to ignore SIGPIPE.
181 */
182 static void
ignore_sigpipe()183 ignore_sigpipe ()
184 {
185 struct sigaction oldsig;
186 struct sigaction sig;
187
188 memset (&sig, 0, sizeof (struct sigaction));
189 sig.sa_handler = SIG_IGN;
190 sigemptyset (&sig.sa_mask);
191 #ifdef SA_INTERRUPT
192 sig.sa_flags = SA_INTERRUPT; /* SunOS */
193 #else
194 sig.sa_flags = SA_RESTART;
195 #endif
196 if (0 != sigaction (SIGPIPE, &sig, &oldsig))
197 fprintf (stderr,
198 "Failed to install SIGPIPE handler: %s\n", strerror (errno));
199 }
200
201
202 #endif
203
204
205 /**
206 * Main function to be called to test a plugin.
207 *
208 * @param plugin_name name of the plugin to load
209 * @param ps array of problems the plugin should solve;
210 * NULL in filename terminates the array.
211 * @return 0 on success, 1 on failure
212 */
213 int
ET_main(const char * plugin_name,struct ProblemSet * ps)214 ET_main (const char *plugin_name,
215 struct ProblemSet *ps)
216 {
217 int ret;
218
219 /* change environment to find plugins which may not yet be
220 not installed but should be in the current directory (or .libs)
221 on 'make check' */
222 #ifndef WINDOWS
223 ignore_sigpipe ();
224 #endif
225 if (0 != putenv ("LIBEXTRACTOR_PREFIX=./.libs/"))
226 fprintf (stderr,
227 "Failed to update my environment, plugin loading may fail: %s\n",
228 strerror (errno));
229 ret = run (plugin_name, ps, EXTRACTOR_OPTION_DEFAULT_POLICY);
230 if (0 != ret)
231 return ret;
232 ret = run (plugin_name, ps, EXTRACTOR_OPTION_IN_PROCESS);
233 if (0 != ret)
234 return ret;
235 return 0;
236 }
237
238
239 /* end of test_lib.c */
240