Index: third_party/libxslt/xsltproc/testThreads.c |
diff --git a/third_party/libxslt/xsltproc/testThreads.c b/third_party/libxslt/xsltproc/testThreads.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..05f0039c350be058d856bf83a53c8d27db97b040 |
--- /dev/null |
+++ b/third_party/libxslt/xsltproc/testThreads.c |
@@ -0,0 +1,273 @@ |
+/** |
+ * testThreads.c: testing of heavilly multithreaded concurrent accesses |
+ * |
+ * See Copyright for the status of this software. |
+ * |
+ * daniel@veillard.com |
+ */ |
+ |
+/* |
+ * TODO: extend it to allow giving the stylesheets/input as filenames on the |
+ * command line to test specifics, also add exslt |
+ */ |
+ |
+#include "config.h" |
+#include "libexslt/exslt.h" |
+#include <stdlib.h> |
+#include <stdio.h> |
+ |
+#define _REENTRANT |
+#include <libxml/xmlversion.h> |
+ |
+#if defined(LIBXML_THREAD_ENABLED) && defined(HAVE_PTHREAD_H) |
+ |
+#include <libxml/globals.h> |
+#include <libxml/threads.h> |
+#include <libxml/parser.h> |
+#include <libxml/catalog.h> |
+#include <libxml/xpathInternals.h> |
+#include <libxslt/xslt.h> |
+#include <libxslt/xsltInternals.h> |
+#include <libxslt/transform.h> |
+#include <libxslt/xsltutils.h> |
+#include <libxslt/extensions.h> |
+#include <libexslt/exsltconfig.h> |
+#include <pthread.h> |
+#include <string.h> |
+#if !defined(_MSC_VER) |
+#include <unistd.h> |
+#endif |
+#include <assert.h> |
+ |
+#define MAX_ARGC 20 |
+ |
+static pthread_t tid[MAX_ARGC]; |
+ |
+#define EXT_NS BAD_CAST "http://foo.org" |
+#define EXT_DATA "bar" |
+ |
+const char *stylesheet = "<xsl:stylesheet version='1.0' \ |
+xmlns:xsl='http://www.w3.org/1999/XSL/Transform' \ |
+xmlns:foo='http://foo.org' \ |
+extension-element-prefixes='foo'>\ |
+<xsl:template match='text()'>\ |
+Success <xsl:value-of select='foo:foo()'/>\ |
+</xsl:template>\ |
+</xsl:stylesheet>\ |
+"; |
+ |
+int init = 0; |
+ |
+const char *doc = "<doc>Failed</doc>"; |
+const char *expect = "<?xml version=\"1.0\"?>\nSuccess foo\n"; |
+ |
+static void fooFunction(xmlXPathParserContextPtr ctxt, |
+ int nargs ATTRIBUTE_UNUSED) { |
+ xmlXPathReturnString(ctxt, xmlStrdup(BAD_CAST "foo")); |
+} |
+ |
+static |
+void * registerFooExtensions(ATTRIBUTE_UNUSED xsltTransformContextPtr ctxt, |
+ ATTRIBUTE_UNUSED const xmlChar *URI) { |
+ xsltRegisterExtModuleFunction(BAD_CAST "foo", EXT_NS, fooFunction); |
+ return((void *)EXT_DATA); |
+} |
+ |
+static |
+void shutdownFooExtensions(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, |
+ const xmlChar *URI, void *data) { |
+ const char *str = (const char *) data; |
+ if (!xmlStrEqual(URI, EXT_NS)) { |
+ fprintf(stderr, "Mismatch in extensions shutdown URI"); |
+ } |
+ if (!xmlStrEqual(BAD_CAST str, BAD_CAST EXT_DATA)) { |
+ fprintf(stderr, "Mismatch in extensions shutdown DATA"); |
+ } |
+} |
+ |
+static void registerFooModule(void) { |
+ xsltRegisterExtModule(EXT_NS, registerFooExtensions, shutdownFooExtensions); |
+} |
+ |
+static void * |
+threadRoutine1(void *data) |
+{ |
+ xmlDocPtr input; |
+ xmlDocPtr style; |
+ xmlDocPtr res; |
+ xmlChar *result; |
+ int len; |
+ xsltStylesheetPtr cur; |
+ int id = (int)(unsigned long) data; |
+ |
+ input = xmlReadMemory(doc, strlen(doc), "doc.xml", NULL, 0); |
+ if (input == NULL) { |
+ fprintf(stderr, "Thread id %d failed to parse input\n", id); |
+ exit(1); |
+ } |
+ style = xmlReadMemory(stylesheet, strlen(stylesheet), "doc.xsl", NULL, 0); |
+ if (style == NULL) { |
+ fprintf(stderr, "Thread id %d failed to parse stylesheet\n", id); |
+ exit(1); |
+ } |
+ cur = xsltParseStylesheetDoc(style); |
+ if (cur == NULL) { |
+ fprintf(stderr, "Thread id %d failed to compile stylesheet\n", id); |
+ exit(1); |
+ } |
+ res = xsltApplyStylesheet(cur, input, NULL); |
+ if (res == NULL) { |
+ fprintf(stderr, "Thread id %d failed to apply stylesheet\n", id); |
+ exit(1); |
+ } |
+ if (xsltSaveResultToString(&result, &len, res, cur) < 0) { |
+ fprintf(stderr, "Thread id %d failed to output result\n", id); |
+ exit(1); |
+ } |
+ if (!xmlStrEqual(BAD_CAST expect, result)) { |
+ fprintf(stderr, "Thread id %d output not conform\n", id); |
+ exit(1); |
+ } |
+ xsltFreeStylesheet(cur); |
+ xmlFreeDoc(input); |
+ xmlFreeDoc(res); |
+ xmlFree(result); |
+ return(0); |
+} |
+ |
+static void * |
+threadRoutine2(void *data) |
+{ |
+ xmlDocPtr input; |
+ xmlDocPtr res; |
+ xmlChar *result; |
+ int len; |
+ xsltStylesheetPtr cur = (xsltStylesheetPtr) data; |
+ |
+ if (cur == NULL) { |
+ fprintf(stderr, "Thread failed to get the stylesheet\n"); |
+ exit(1); |
+ } |
+ input = xmlReadMemory(doc, strlen(doc), "doc.xml", NULL, 0); |
+ if (input == NULL) { |
+ fprintf(stderr, "Thread failed to parse input\n"); |
+ exit(1); |
+ } |
+ res = xsltApplyStylesheet(cur, input, NULL); |
+ if (res == NULL) { |
+ fprintf(stderr, "Thread failed to apply stylesheet\n"); |
+ exit(1); |
+ } |
+ if (xsltSaveResultToString(&result, &len, res, cur) < 0) { |
+ fprintf(stderr, "Thread failed to output result\n"); |
+ exit(1); |
+ } |
+ if (!xmlStrEqual(BAD_CAST expect, result)) { |
+ fprintf(stderr, "Thread output not conform\n"); |
+ exit(1); |
+ } |
+ xmlFreeDoc(input); |
+ xmlFreeDoc(res); |
+ xmlFree(result); |
+ return(0); |
+} |
+int |
+main(void) |
+{ |
+ unsigned int i, repeat; |
+ unsigned int num_threads = 8; |
+ void *results[MAX_ARGC]; |
+ int ret; |
+ |
+ xmlInitParser(); |
+ |
+ /* |
+ * Register the EXSLT extensions and the test module |
+ */ |
+ exsltRegisterAll(); |
+ xsltRegisterTestModule(); |
+ |
+ /* |
+ * Register our own extension module |
+ */ |
+ registerFooModule(); |
+ |
+ /* |
+ * First pass each thread has its own version of the stylesheet |
+ * each of them will initialize and shutdown the extension |
+ */ |
+ printf("Pass 1\n"); |
+ for (repeat = 0;repeat < 500;repeat++) { |
+ memset(results, 0, sizeof(*results)*num_threads); |
+ memset(tid, 0xff, sizeof(*tid)*num_threads); |
+ |
+ for (i = 0; i < num_threads; i++) { |
+ ret = pthread_create(&tid[i], NULL, threadRoutine1, |
+ (void *) (unsigned long) i); |
+ if (ret != 0) { |
+ perror("pthread_create"); |
+ exit(1); |
+ } |
+ } |
+ for (i = 0; i < num_threads; i++) { |
+ ret = pthread_join(tid[i], &results[i]); |
+ if (ret != 0) { |
+ perror("pthread_join"); |
+ exit(1); |
+ } |
+ } |
+ } |
+ |
+ /* |
+ * Second pass all threads share the same stylesheet instance |
+ * look for transformation clashes |
+ */ |
+ printf("Pass 2\n"); |
+ for (repeat = 0;repeat < 500;repeat++) { |
+ xmlDocPtr style; |
+ xsltStylesheetPtr cur; |
+ |
+ style = xmlReadMemory(stylesheet, strlen(stylesheet), "doc.xsl", |
+ NULL, 0); |
+ if (style == NULL) { |
+ fprintf(stderr, "Main failed to parse stylesheet\n"); |
+ exit(1); |
+ } |
+ cur = xsltParseStylesheetDoc(style); |
+ if (cur == NULL) { |
+ fprintf(stderr, "Main failed to compile stylesheet\n"); |
+ exit(1); |
+ } |
+ memset(results, 0, sizeof(*results)*num_threads); |
+ memset(tid, 0xff, sizeof(*tid)*num_threads); |
+ |
+ for (i = 0; i < num_threads; i++) { |
+ ret = pthread_create(&tid[i], NULL, threadRoutine2, (void *) cur); |
+ if (ret != 0) { |
+ perror("pthread_create"); |
+ exit(1); |
+ } |
+ } |
+ for (i = 0; i < num_threads; i++) { |
+ ret = pthread_join(tid[i], &results[i]); |
+ if (ret != 0) { |
+ perror("pthread_join"); |
+ exit(1); |
+ } |
+ } |
+ xsltFreeStylesheet(cur); |
+ } |
+ xsltCleanupGlobals(); |
+ xmlCleanupParser(); |
+ xmlMemoryDump(); |
+ printf("Ok\n"); |
+ return (0); |
+} |
+#else /* !LIBXML_THREADS_ENABLED | !HAVE_PTHREAD_H */ |
+int |
+main(void) |
+{ |
+ fprintf(stderr, "libxml was not compiled with thread\n"); |
+ return (0); |
+} |
+#endif |