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");