OLD | NEW |
| (Empty) |
1 /** | |
2 * testThreads.c: testing of heavilly multithreaded concurrent accesses | |
3 * | |
4 * See Copyright for the status of this software. | |
5 * | |
6 * daniel@veillard.com | |
7 */ | |
8 | |
9 /* | |
10 * TODO: extend it to allow giving the stylesheets/input as filenames on the | |
11 * command line to test specifics, also add exslt | |
12 */ | |
13 | |
14 #include "config.h" | |
15 #include "libexslt/exslt.h" | |
16 #include <stdlib.h> | |
17 #include <stdio.h> | |
18 | |
19 #define _REENTRANT | |
20 #include <libxml/xmlversion.h> | |
21 | |
22 #if defined(LIBXML_THREAD_ENABLED) && defined(HAVE_PTHREAD_H) | |
23 | |
24 #include <libxml/globals.h> | |
25 #include <libxml/threads.h> | |
26 #include <libxml/parser.h> | |
27 #include <libxml/catalog.h> | |
28 #include <libxml/xpathInternals.h> | |
29 #include <libxslt/xslt.h> | |
30 #include <libxslt/xsltInternals.h> | |
31 #include <libxslt/transform.h> | |
32 #include <libxslt/xsltutils.h> | |
33 #include <libxslt/extensions.h> | |
34 #include <libexslt/exsltconfig.h> | |
35 #include <pthread.h> | |
36 #include <string.h> | |
37 #if !defined(_MSC_VER) | |
38 #include <unistd.h> | |
39 #endif | |
40 #include <assert.h> | |
41 | |
42 #define MAX_ARGC 20 | |
43 | |
44 static pthread_t tid[MAX_ARGC]; | |
45 | |
46 #define EXT_NS BAD_CAST "http://foo.org" | |
47 #define EXT_DATA "bar" | |
48 | |
49 const char *stylesheet = "<xsl:stylesheet version='1.0' \ | |
50 xmlns:xsl='http://www.w3.org/1999/XSL/Transform' \ | |
51 xmlns:foo='http://foo.org' \ | |
52 extension-element-prefixes='foo'>\ | |
53 <xsl:template match='text()'>\ | |
54 Success <xsl:value-of select='foo:foo()'/>\ | |
55 </xsl:template>\ | |
56 </xsl:stylesheet>\ | |
57 "; | |
58 | |
59 int init = 0; | |
60 | |
61 const char *doc = "<doc>Failed</doc>"; | |
62 const char *expect = "<?xml version=\"1.0\"?>\nSuccess foo\n"; | |
63 | |
64 static void fooFunction(xmlXPathParserContextPtr ctxt, | |
65 int nargs ATTRIBUTE_UNUSED) { | |
66 xmlXPathReturnString(ctxt, xmlStrdup(BAD_CAST "foo")); | |
67 } | |
68 | |
69 static | |
70 void * registerFooExtensions(ATTRIBUTE_UNUSED xsltTransformContextPtr ctxt, | |
71 ATTRIBUTE_UNUSED const xmlChar *URI) { | |
72 xsltRegisterExtModuleFunction(BAD_CAST "foo", EXT_NS, fooFunction); | |
73 return((void *)EXT_DATA); | |
74 } | |
75 | |
76 static | |
77 void shutdownFooExtensions(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, | |
78 const xmlChar *URI, void *data) { | |
79 const char *str = (const char *) data; | |
80 if (!xmlStrEqual(URI, EXT_NS)) { | |
81 fprintf(stderr, "Mismatch in extensions shutdown URI"); | |
82 } | |
83 if (!xmlStrEqual(BAD_CAST str, BAD_CAST EXT_DATA)) { | |
84 fprintf(stderr, "Mismatch in extensions shutdown DATA"); | |
85 } | |
86 } | |
87 | |
88 static void registerFooModule(void) { | |
89 xsltRegisterExtModule(EXT_NS, registerFooExtensions, shutdownFooExtensions); | |
90 } | |
91 | |
92 static void * | |
93 threadRoutine1(void *data) | |
94 { | |
95 xmlDocPtr input; | |
96 xmlDocPtr style; | |
97 xmlDocPtr res; | |
98 xmlChar *result; | |
99 int len; | |
100 xsltStylesheetPtr cur; | |
101 int id = (int)(unsigned long) data; | |
102 | |
103 input = xmlReadMemory(doc, strlen(doc), "doc.xml", NULL, 0); | |
104 if (input == NULL) { | |
105 fprintf(stderr, "Thread id %d failed to parse input\n", id); | |
106 exit(1); | |
107 } | |
108 style = xmlReadMemory(stylesheet, strlen(stylesheet), "doc.xsl", NULL, 0); | |
109 if (style == NULL) { | |
110 fprintf(stderr, "Thread id %d failed to parse stylesheet\n", id); | |
111 exit(1); | |
112 } | |
113 cur = xsltParseStylesheetDoc(style); | |
114 if (cur == NULL) { | |
115 fprintf(stderr, "Thread id %d failed to compile stylesheet\n", id); | |
116 exit(1); | |
117 } | |
118 res = xsltApplyStylesheet(cur, input, NULL); | |
119 if (res == NULL) { | |
120 fprintf(stderr, "Thread id %d failed to apply stylesheet\n", id); | |
121 exit(1); | |
122 } | |
123 if (xsltSaveResultToString(&result, &len, res, cur) < 0) { | |
124 fprintf(stderr, "Thread id %d failed to output result\n", id); | |
125 exit(1); | |
126 } | |
127 if (!xmlStrEqual(BAD_CAST expect, result)) { | |
128 fprintf(stderr, "Thread id %d output not conform\n", id); | |
129 exit(1); | |
130 } | |
131 xsltFreeStylesheet(cur); | |
132 xmlFreeDoc(input); | |
133 xmlFreeDoc(res); | |
134 xmlFree(result); | |
135 return(0); | |
136 } | |
137 | |
138 static void * | |
139 threadRoutine2(void *data) | |
140 { | |
141 xmlDocPtr input; | |
142 xmlDocPtr res; | |
143 xmlChar *result; | |
144 int len; | |
145 xsltStylesheetPtr cur = (xsltStylesheetPtr) data; | |
146 | |
147 if (cur == NULL) { | |
148 fprintf(stderr, "Thread failed to get the stylesheet\n"); | |
149 exit(1); | |
150 } | |
151 input = xmlReadMemory(doc, strlen(doc), "doc.xml", NULL, 0); | |
152 if (input == NULL) { | |
153 fprintf(stderr, "Thread failed to parse input\n"); | |
154 exit(1); | |
155 } | |
156 res = xsltApplyStylesheet(cur, input, NULL); | |
157 if (res == NULL) { | |
158 fprintf(stderr, "Thread failed to apply stylesheet\n"); | |
159 exit(1); | |
160 } | |
161 if (xsltSaveResultToString(&result, &len, res, cur) < 0) { | |
162 fprintf(stderr, "Thread failed to output result\n"); | |
163 exit(1); | |
164 } | |
165 if (!xmlStrEqual(BAD_CAST expect, result)) { | |
166 fprintf(stderr, "Thread output not conform\n"); | |
167 exit(1); | |
168 } | |
169 xmlFreeDoc(input); | |
170 xmlFreeDoc(res); | |
171 xmlFree(result); | |
172 return(0); | |
173 } | |
174 int | |
175 main(void) | |
176 { | |
177 unsigned int i, repeat; | |
178 unsigned int num_threads = 8; | |
179 void *results[MAX_ARGC]; | |
180 int ret; | |
181 | |
182 xmlInitParser(); | |
183 | |
184 /* | |
185 * Register the EXSLT extensions and the test module | |
186 */ | |
187 exsltRegisterAll(); | |
188 xsltRegisterTestModule(); | |
189 | |
190 /* | |
191 * Register our own extension module | |
192 */ | |
193 registerFooModule(); | |
194 | |
195 /* | |
196 * First pass each thread has its own version of the stylesheet | |
197 * each of them will initialize and shutdown the extension | |
198 */ | |
199 printf("Pass 1\n"); | |
200 for (repeat = 0;repeat < 500;repeat++) { | |
201 memset(results, 0, sizeof(*results)*num_threads); | |
202 memset(tid, 0xff, sizeof(*tid)*num_threads); | |
203 | |
204 for (i = 0; i < num_threads; i++) { | |
205 ret = pthread_create(&tid[i], NULL, threadRoutine1, | |
206 (void *) (unsigned long) i); | |
207 if (ret != 0) { | |
208 perror("pthread_create"); | |
209 exit(1); | |
210 } | |
211 } | |
212 for (i = 0; i < num_threads; i++) { | |
213 ret = pthread_join(tid[i], &results[i]); | |
214 if (ret != 0) { | |
215 perror("pthread_join"); | |
216 exit(1); | |
217 } | |
218 } | |
219 } | |
220 | |
221 /* | |
222 * Second pass all threads share the same stylesheet instance | |
223 * look for transformation clashes | |
224 */ | |
225 printf("Pass 2\n"); | |
226 for (repeat = 0;repeat < 500;repeat++) { | |
227 xmlDocPtr style; | |
228 xsltStylesheetPtr cur; | |
229 | |
230 style = xmlReadMemory(stylesheet, strlen(stylesheet), "doc.xsl", | |
231 NULL, 0); | |
232 if (style == NULL) { | |
233 fprintf(stderr, "Main failed to parse stylesheet\n"); | |
234 exit(1); | |
235 } | |
236 cur = xsltParseStylesheetDoc(style); | |
237 if (cur == NULL) { | |
238 fprintf(stderr, "Main failed to compile stylesheet\n"); | |
239 exit(1); | |
240 } | |
241 memset(results, 0, sizeof(*results)*num_threads); | |
242 memset(tid, 0xff, sizeof(*tid)*num_threads); | |
243 | |
244 for (i = 0; i < num_threads; i++) { | |
245 ret = pthread_create(&tid[i], NULL, threadRoutine2, (void *) cur); | |
246 if (ret != 0) { | |
247 perror("pthread_create"); | |
248 exit(1); | |
249 } | |
250 } | |
251 for (i = 0; i < num_threads; i++) { | |
252 ret = pthread_join(tid[i], &results[i]); | |
253 if (ret != 0) { | |
254 perror("pthread_join"); | |
255 exit(1); | |
256 } | |
257 } | |
258 xsltFreeStylesheet(cur); | |
259 } | |
260 xsltCleanupGlobals(); | |
261 xmlCleanupParser(); | |
262 xmlMemoryDump(); | |
263 printf("Ok\n"); | |
264 return (0); | |
265 } | |
266 #else /* !LIBXML_THREADS_ENABLED | !HAVE_PTHREAD_H */ | |
267 int | |
268 main(void) | |
269 { | |
270 fprintf(stderr, "libxml was not compiled with thread\n"); | |
271 return (0); | |
272 } | |
273 #endif | |
OLD | NEW |