Portability fix for testThreads.c
[platform/upstream/libxslt.git] / xsltproc / testThreads.c
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