1 #include "libxml.h"
2 #include <stdlib.h>
3 #include <stdio.h>
4 
5 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
6 #include <libxml/globals.h>
7 #include <libxml/threads.h>
8 #include <libxml/parser.h>
9 #include <libxml/catalog.h>
10 #include <windows.h>
11 #include <string.h>
12 #include <assert.h>
13 
14 #define	MAX_ARGC	20
15 #define TEST_REPEAT_COUNT 500
16 
17 static HANDLE tid[MAX_ARGC];
18 
19 static const char *catalog = "test/threads/complex.xml";
20 static char *testfiles[] = {
21     "test/threads/abc.xml",
22     "test/threads/acb.xml",
23     "test/threads/bac.xml",
24     "test/threads/bca.xml",
25     "test/threads/cab.xml",
26     "test/threads/cba.xml",
27     "test/threads/invalid.xml",
28 };
29 
30 const char *Okay = "OK";
31 const char *Failed = "Failed";
32 
33 #ifndef xmlDoValidityCheckingDefaultValue
34 #error xmlDoValidityCheckingDefaultValue is not a macro
35 #endif
36 #ifndef xmlGenericErrorContext
37 #error xmlGenericErrorContext is not a macro
38 #endif
39 
40 static DWORD WINAPI
thread_specific_data(void * private_data)41 thread_specific_data(void *private_data)
42 {
43     xmlDocPtr myDoc;
44     const char *filename = (const char *) private_data;
45     int okay = 1;
46 
47     if (!strcmp(filename, "test/threads/invalid.xml")) {
48         xmlDoValidityCheckingDefaultValue = 0;
49         xmlGenericErrorContext = stdout;
50     } else {
51         xmlDoValidityCheckingDefaultValue = 1;
52         xmlGenericErrorContext = stderr;
53     }
54     myDoc = xmlParseFile(filename);
55     if (myDoc) {
56         xmlFreeDoc(myDoc);
57     } else {
58         printf("parse failed\n");
59 	okay = 0;
60     }
61     if (!strcmp(filename, "test/threads/invalid.xml")) {
62         if (xmlDoValidityCheckingDefaultValue != 0) {
63 	    printf("ValidityCheckingDefaultValue override failed\n");
64 	    okay = 0;
65 	}
66         if (xmlGenericErrorContext != stdout) {
67 	    printf("xmlGenericErrorContext override failed\n");
68 	    okay = 0;
69 	}
70     } else {
71         if (xmlDoValidityCheckingDefaultValue != 1) {
72 	    printf("ValidityCheckingDefaultValue override failed\n");
73 	    okay = 0;
74 	}
75         if (xmlGenericErrorContext != stderr) {
76 	    printf("xmlGenericErrorContext override failed\n");
77 	    okay = 0;
78 	}
79     }
80     if (okay == 0)
81 	return ((DWORD) Failed);
82     return ((DWORD) Okay);
83 }
84 
85 int
main()86 main()
87 {
88 	unsigned int i, repeat;
89 	unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
90 	DWORD results[MAX_ARGC];
91 	BOOL ret;
92 
93 	xmlInitParser();
94 	for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++)
95 	{
96 		xmlLoadCatalog(catalog);
97 
98 		for (i = 0; i < num_threads; i++)
99 		{
100 			results[i] = 0;
101 			tid[i] = (HANDLE) -1;
102 		}
103 
104 		for (i = 0; i < num_threads; i++)
105 		{
106 			DWORD useless;
107 			tid[i] = CreateThread(NULL, 0,
108 				thread_specific_data, testfiles[i], 0, &useless);
109 			if (tid[i] == NULL)
110 			{
111 				perror("CreateThread");
112 				exit(1);
113 			}
114 		}
115 
116 		if (WaitForMultipleObjects (num_threads, tid, TRUE, INFINITE) == WAIT_FAILED)
117 			perror ("WaitForMultipleObjects failed");
118 
119 		for (i = 0; i < num_threads; i++)
120 		{
121 			ret = GetExitCodeThread (tid[i], &results[i]);
122 			if (ret == 0)
123 			{
124 				perror("GetExitCodeThread");
125 				exit(1);
126 			}
127 			CloseHandle (tid[i]);
128 		}
129 
130 		xmlCatalogCleanup();
131 		for (i = 0; i < num_threads; i++) {
132 		    if (results[i] != (DWORD) Okay)
133 			printf("Thread %d handling %s failed\n", i, testfiles[i]);
134 		}
135 	}
136 
137 	xmlCleanupParser();
138 	xmlMemoryDump();
139 
140 	return (0);
141 }
142 
143 #else /* !LIBXML_THREADS_ENABLED */
144 int
main()145 main()
146 {
147     fprintf(stderr, "libxml was not compiled with thread or catalog support\n");
148     return (0);
149 }
150 #endif
151