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 |