1 #include "config.h"
2 #include <stdlib.h>
3 #include <stdio.h>
4
5 #include <libxml/parser.h>
6 #include <libxml/threads.h>
7
8 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
9 #include <libxml/catalog.h>
10 #ifdef HAVE_PTHREAD_H
11 #include <pthread.h>
12 #elif defined(_WIN32)
13 #include <windows.h>
14 #endif
15 #include <string.h>
16 #include <assert.h>
17
18 #define MAX_ARGC 20
19 #define TEST_REPEAT_COUNT 500
20 #ifdef HAVE_PTHREAD_H
21 static pthread_t tid[MAX_ARGC];
22 #elif defined(_WIN32)
23 static HANDLE tid[MAX_ARGC];
24 #endif
25
26 typedef struct {
27 const char *filename;
28 int okay;
29 } xmlThreadParams;
30
31 static const char *catalog = "test/threads/complex.xml";
32 static xmlThreadParams threadParams[] = {
33 { "test/threads/abc.xml", 0 },
34 { "test/threads/acb.xml", 0 },
35 { "test/threads/bac.xml", 0 },
36 { "test/threads/bca.xml", 0 },
37 { "test/threads/cab.xml", 0 },
38 { "test/threads/cba.xml", 0 },
39 { "test/threads/invalid.xml", 0 }
40 };
41 static const unsigned int num_threads = sizeof(threadParams) /
42 sizeof(threadParams[0]);
43
44 static void *
thread_specific_data(void * private_data)45 thread_specific_data(void *private_data)
46 {
47 xmlDocPtr myDoc;
48 xmlThreadParams *params = (xmlThreadParams *) private_data;
49 const char *filename = params->filename;
50 int okay = 1;
51 int options = 0;
52
53 if (xmlCheckThreadLocalStorage() != 0) {
54 printf("xmlCheckThreadLocalStorage failed\n");
55 params->okay = 0;
56 return(NULL);
57 }
58
59 if (strcmp(filename, "test/threads/invalid.xml") != 0) {
60 options |= XML_PARSE_DTDVALID;
61 }
62 myDoc = xmlReadFile(filename, NULL, options);
63 if (myDoc) {
64 xmlFreeDoc(myDoc);
65 } else {
66 printf("parse failed\n");
67 okay = 0;
68 }
69 params->okay = okay;
70 return(NULL);
71 }
72
73 #ifdef _WIN32
74 static DWORD WINAPI
win32_thread_specific_data(void * private_data)75 win32_thread_specific_data(void *private_data)
76 {
77 thread_specific_data(private_data);
78 return(0);
79 }
80 #endif
81 #endif /* LIBXML_THREADS_ENABLED */
82
83 int
main(void)84 main(void)
85 {
86 unsigned int repeat;
87 int status = 0;
88
89 (void) repeat;
90
91 xmlInitParser();
92
93 if (xmlCheckThreadLocalStorage() != 0) {
94 printf("xmlCheckThreadLocalStorage failed for main thread\n");
95 return(1);
96 }
97
98 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
99 for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++) {
100 unsigned int i;
101 int ret;
102
103 xmlLoadCatalog(catalog);
104
105 #ifdef HAVE_PTHREAD_H
106 memset(tid, 0xff, sizeof(*tid)*num_threads);
107
108 for (i = 0; i < num_threads; i++) {
109 ret = pthread_create(&tid[i], NULL, thread_specific_data,
110 (void *) &threadParams[i]);
111 if (ret != 0) {
112 perror("pthread_create");
113 exit(1);
114 }
115 }
116 for (i = 0; i < num_threads; i++) {
117 void *result;
118 ret = pthread_join(tid[i], &result);
119 if (ret != 0) {
120 perror("pthread_join");
121 exit(1);
122 }
123 }
124 #elif defined(_WIN32)
125 for (i = 0; i < num_threads; i++)
126 {
127 tid[i] = (HANDLE) -1;
128 }
129
130 for (i = 0; i < num_threads; i++)
131 {
132 DWORD useless;
133 tid[i] = CreateThread(NULL, 0,
134 win32_thread_specific_data, &threadParams[i], 0, &useless);
135 if (tid[i] == NULL)
136 {
137 perror("CreateThread");
138 exit(1);
139 }
140 }
141
142 if (WaitForMultipleObjects (num_threads, tid, TRUE, INFINITE) == WAIT_FAILED)
143 perror ("WaitForMultipleObjects failed");
144
145 for (i = 0; i < num_threads; i++)
146 {
147 DWORD exitCode;
148 ret = GetExitCodeThread (tid[i], &exitCode);
149 if (ret == 0)
150 {
151 perror("GetExitCodeThread");
152 exit(1);
153 }
154 CloseHandle (tid[i]);
155 }
156 #endif /* pthreads */
157
158 xmlCatalogCleanup();
159
160 for (i = 0; i < num_threads; i++) {
161 if (threadParams[i].okay == 0) {
162 printf("Thread %d handling %s failed\n", i,
163 threadParams[i].filename);
164 status = 1;
165 }
166 }
167 }
168 #endif /* LIBXML_THREADS_ENABLED */
169
170 xmlCleanupParser();
171
172 return (status);
173 }
174
175