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 44static pthread_t tid[MAX_ARGC]; 45 46#define EXT_NS BAD_CAST "http://foo.org" 47#define EXT_DATA "bar" 48 49const char *stylesheet = "<xsl:stylesheet version='1.0' \ 50xmlns:xsl='http://www.w3.org/1999/XSL/Transform' \ 51xmlns:foo='http://foo.org' \ 52extension-element-prefixes='foo'>\ 53<xsl:template match='text()'>\ 54Success <xsl:value-of select='foo:foo()'/>\ 55</xsl:template>\ 56</xsl:stylesheet>\ 57"; 58 59int init = 0; 60 61const char *doc = "<doc>Failed</doc>"; 62const char *expect = "<?xml version=\"1.0\"?>\nSuccess foo\n"; 63 64static void fooFunction(xmlXPathParserContextPtr ctxt, 65 int nargs ATTRIBUTE_UNUSED) { 66 xmlXPathReturnString(ctxt, xmlStrdup(BAD_CAST "foo")); 67} 68 69static 70void * 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 76static 77void 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 88static void registerFooModule(void) { 89 xsltRegisterExtModule(EXT_NS, registerFooExtensions, shutdownFooExtensions); 90} 91 92static void * 93threadRoutine1(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 138static void * 139threadRoutine2(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} 174int 175main(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 */ 267int 268main(void) 269{ 270 fprintf(stderr, "libxml was not compiled with thread\n"); 271 return (0); 272} 273#endif 274