| 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 |