2 * testThreads.c: testing of heavilly multithreaded concurrent accesses
4 * See Copyright for the status of this software.
10 * TODO: extend it to allow giving the stylesheets/input as filenames on the
11 * command line to test specifics, also add exslt
15 #include "libexslt/exslt.h"
20 #include <libxml/xmlversion.h>
22 #if defined(LIBXML_THREAD_ENABLED) && defined(HAVE_PTHREAD_H)
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>
37 #if !defined(_MSC_VER)
44 static pthread_t tid
[MAX_ARGC
];
46 #define EXT_NS BAD_CAST "http://foo.org"
47 #define EXT_DATA "bar"
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()'/>\
61 const char *doc
= "<doc>Failed</doc>";
62 const char *expect
= "<?xml version=\"1.0\"?>\nSuccess foo\n";
64 static void fooFunction(xmlXPathParserContextPtr ctxt
,
65 int nargs ATTRIBUTE_UNUSED
) {
66 xmlXPathReturnString(ctxt
, xmlStrdup(BAD_CAST
"foo"));
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
);
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");
83 if (!xmlStrEqual(BAD_CAST str
, BAD_CAST EXT_DATA
)) {
84 fprintf(stderr
, "Mismatch in extensions shutdown DATA");
88 static void registerFooModule(void) {
89 xsltRegisterExtModule(EXT_NS
, registerFooExtensions
, shutdownFooExtensions
);
93 threadRoutine1(void *data
)
100 xsltStylesheetPtr cur
;
101 int id
= (int)(unsigned long) data
;
103 input
= xmlReadMemory(doc
, strlen(doc
), "doc.xml", NULL
, 0);
105 fprintf(stderr
, "Thread id %d failed to parse input\n", id
);
108 style
= xmlReadMemory(stylesheet
, strlen(stylesheet
), "doc.xsl", NULL
, 0);
110 fprintf(stderr
, "Thread id %d failed to parse stylesheet\n", id
);
113 cur
= xsltParseStylesheetDoc(style
);
115 fprintf(stderr
, "Thread id %d failed to compile stylesheet\n", id
);
118 res
= xsltApplyStylesheet(cur
, input
, NULL
);
120 fprintf(stderr
, "Thread id %d failed to apply stylesheet\n", id
);
123 if (xsltSaveResultToString(&result
, &len
, res
, cur
) < 0) {
124 fprintf(stderr
, "Thread id %d failed to output result\n", id
);
127 if (!xmlStrEqual(BAD_CAST expect
, result
)) {
128 fprintf(stderr
, "Thread id %d output not conform\n", id
);
131 xsltFreeStylesheet(cur
);
139 threadRoutine2(void *data
)
145 xsltStylesheetPtr cur
= (xsltStylesheetPtr
) data
;
148 fprintf(stderr
, "Thread failed to get the stylesheet\n");
151 input
= xmlReadMemory(doc
, strlen(doc
), "doc.xml", NULL
, 0);
153 fprintf(stderr
, "Thread failed to parse input\n");
156 res
= xsltApplyStylesheet(cur
, input
, NULL
);
158 fprintf(stderr
, "Thread failed to apply stylesheet\n");
161 if (xsltSaveResultToString(&result
, &len
, res
, cur
) < 0) {
162 fprintf(stderr
, "Thread failed to output result\n");
165 if (!xmlStrEqual(BAD_CAST expect
, result
)) {
166 fprintf(stderr
, "Thread output not conform\n");
177 unsigned int i
, repeat
;
178 unsigned int num_threads
= 8;
179 void *results
[MAX_ARGC
];
185 * Register the EXSLT extensions and the test module
188 xsltRegisterTestModule();
191 * Register our own extension module
196 * First pass each thread has its own version of the stylesheet
197 * each of them will initialize and shutdown the extension
200 for (repeat
= 0;repeat
< 500;repeat
++) {
201 memset(results
, 0, sizeof(*results
)*num_threads
);
202 memset(tid
, 0xff, sizeof(*tid
)*num_threads
);
204 for (i
= 0; i
< num_threads
; i
++) {
205 ret
= pthread_create(&tid
[i
], NULL
, threadRoutine1
,
206 (void *) (unsigned long) i
);
208 perror("pthread_create");
212 for (i
= 0; i
< num_threads
; i
++) {
213 ret
= pthread_join(tid
[i
], &results
[i
]);
215 perror("pthread_join");
222 * Second pass all threads share the same stylesheet instance
223 * look for transformation clashes
226 for (repeat
= 0;repeat
< 500;repeat
++) {
228 xsltStylesheetPtr cur
;
230 style
= xmlReadMemory(stylesheet
, strlen(stylesheet
), "doc.xsl",
233 fprintf(stderr
, "Main failed to parse stylesheet\n");
236 cur
= xsltParseStylesheetDoc(style
);
238 fprintf(stderr
, "Main failed to compile stylesheet\n");
241 memset(results
, 0, sizeof(*results
)*num_threads
);
242 memset(tid
, 0xff, sizeof(*tid
)*num_threads
);
244 for (i
= 0; i
< num_threads
; i
++) {
245 ret
= pthread_create(&tid
[i
], NULL
, threadRoutine2
, (void *) cur
);
247 perror("pthread_create");
251 for (i
= 0; i
< num_threads
; i
++) {
252 ret
= pthread_join(tid
[i
], &results
[i
]);
254 perror("pthread_join");
258 xsltFreeStylesheet(cur
);
260 xsltCleanupGlobals();
266 #else /* !LIBXML_THREADS_ENABLED | !HAVE_PTHREAD_H */
270 fprintf(stderr
, "libxml was not compiled with thread\n");