crypt32: Make sure we show Unicode characters (Dutch translation).
[wine] / dlls / msxml3 / tests / saxreader.c
1 /*
2  * XML test
3  *
4  * Copyright 2008 Piotr Caban
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23
24 #include <stdio.h>
25 #include "windows.h"
26 #include "ole2.h"
27 #include "msxml2.h"
28 #include "ocidl.h"
29
30 #include "wine/test.h"
31
32 typedef enum _CH {
33     CH_ENDTEST,
34     CH_PUTDOCUMENTLOCATOR,
35     CH_STARTDOCUMENT,
36     CH_ENDDOCUMENT,
37     CH_STARTPREFIXMAPPING,
38     CH_ENDPREFIXMAPPING,
39     CH_STARTELEMENT,
40     CH_ENDELEMENT,
41     CH_CHARACTERS,
42     CH_IGNORABLEWHITESPACE,
43     CH_PROCESSINGINSTRUCTION,
44     CH_SKIPPEDENTITY
45 } CH;
46
47 static const WCHAR szSimpleXML[] = {
48 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
49 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
50 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
51 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
52 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
53 };
54
55 static const WCHAR szCarriageRetTest[] = {
56 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
57 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
58 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
59 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
60 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\0'
61 };
62
63 static const CHAR szTestXML[] =
64 "<?xml version=\"1.0\" ?>\n"
65 "<BankAccount>\n"
66 "   <Number>1234</Number>\n"
67 "   <Name>Captain Ahab</Name>\n"
68 "</BankAccount>\n";
69
70 typedef struct _contenthandlercheck {
71     CH id;
72     int line;
73     int column;
74     const char *arg1;
75     const char *arg2;
76     const char *arg3;
77 } content_handler_test;
78
79 static content_handler_test contentHandlerTest1[] = {
80     { CH_PUTDOCUMENTLOCATOR, 0, 0 },
81     { CH_STARTDOCUMENT, 0, 0 },
82     { CH_STARTELEMENT, 2, 14, "", "BankAccount", "BankAccount" },
83     { CH_CHARACTERS, 2, 14, "\n   " },
84     { CH_STARTELEMENT, 3, 12, "", "Number", "Number" },
85     { CH_CHARACTERS, 3, 12, "1234" },
86     { CH_ENDELEMENT, 3, 18, "", "Number", "Number" },
87     { CH_CHARACTERS, 3, 25, "\n   " },
88     { CH_STARTELEMENT, 4, 10, "", "Name", "Name" },
89     { CH_CHARACTERS, 4, 10, "Captain Ahab" },
90     { CH_ENDELEMENT, 4, 24, "", "Name", "Name" },
91     { CH_CHARACTERS, 4, 29, "\n" },
92     { CH_ENDELEMENT, 5, 3, "", "BankAccount", "BankAccount" },
93     { CH_ENDDOCUMENT, 0, 0 },
94     { CH_ENDTEST }
95 };
96
97 static content_handler_test contentHandlerTest2[] = {
98     { CH_PUTDOCUMENTLOCATOR, 0, 0 },
99     { CH_STARTDOCUMENT, 0, 0 },
100     { CH_STARTELEMENT, 2, 14, "", "BankAccount", "BankAccount" },
101     { CH_CHARACTERS, 2, 14, "\n" },
102     { CH_CHARACTERS, 2, 16, "\t" },
103     { CH_STARTELEMENT, 3, 10, "", "Number", "Number" },
104     { CH_CHARACTERS, 3, 10, "1234" },
105     { CH_ENDELEMENT, 3, 16, "", "Number", "Number" },
106     { CH_CHARACTERS, 3, 23, "\n" },
107     { CH_CHARACTERS, 3, 25, "\t" },
108     { CH_STARTELEMENT, 4, 8, "", "Name", "Name" },
109     { CH_CHARACTERS, 4, 8, "Captain Ahab" },
110     { CH_ENDELEMENT, 4, 22, "", "Name", "Name" },
111     { CH_CHARACTERS, 4, 27, "\n" },
112     { CH_ENDELEMENT, 5, 3, "", "BankAccount", "BankAccount" },
113     { CH_ENDDOCUMENT, 0, 0 },
114     { CH_ENDTEST }
115 };
116
117 static content_handler_test *expectCall;
118 static ISAXLocator *locator;
119
120 static const char *debugstr_wn(const WCHAR *szStr, int len)
121 {
122     static char buf[1024];
123     WideCharToMultiByte(CP_ACP, 0, szStr, len, buf, sizeof(buf), NULL, NULL);
124     return buf;
125 }
126
127 static void test_saxstr(unsigned line, const WCHAR *szStr, int nStr, const char *szTest)
128 {
129     WCHAR buf[1024];
130     int len;
131
132     if(!szTest) {
133         ok_(__FILE__,line) (szStr == NULL, "szStr != NULL\n");
134         ok_(__FILE__,line) (nStr == 0, "nStr = %d, expected 0\n", nStr);
135         return;
136     }
137
138     len = strlen(szTest);
139     ok_(__FILE__,line) (len == nStr, "nStr = %d, expected %d (%s)\n", nStr, len, szTest);
140     if(len != nStr)
141         return;
142
143     MultiByteToWideChar(CP_ACP, 0, szTest, -1, buf, sizeof(buf)/sizeof(WCHAR));
144     ok_(__FILE__,line) (!memcmp(szStr, buf, len*sizeof(WCHAR)), "unexpected szStr %s, expected %s\n",
145                         debugstr_wn(szStr, nStr), szTest);
146 }
147
148 static BOOL test_expect_call(CH id)
149 {
150     ok(expectCall->id == id, "unexpected call %d, expected %d\n", id, expectCall->id);
151     return expectCall->id == id;
152 }
153
154 static void test_locator(unsigned line, int loc_line, int loc_column)
155 {
156     int rcolumn, rline;
157     ISAXLocator_getLineNumber(locator, &rline);
158     ISAXLocator_getColumnNumber(locator, &rcolumn);
159
160     ok_(__FILE__,line) (rline == loc_line,
161             "unexpected line %d, expected %d\n", rline, loc_line);
162     ok_(__FILE__,line) (rcolumn == loc_column,
163             "unexpected column %d, expected %d\n", rcolumn, loc_column);
164 }
165
166 static HRESULT WINAPI contentHandler_QueryInterface(
167         ISAXContentHandler* iface,
168         REFIID riid,
169         void **ppvObject)
170 {
171     *ppvObject = NULL;
172
173     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISAXContentHandler))
174     {
175         *ppvObject = iface;
176     }
177     else
178     {
179         return E_NOINTERFACE;
180     }
181
182     return S_OK;
183 }
184
185 static ULONG WINAPI contentHandler_AddRef(
186         ISAXContentHandler* iface)
187 {
188     return 2;
189 }
190
191 static ULONG WINAPI contentHandler_Release(
192         ISAXContentHandler* iface)
193 {
194     return 1;
195 }
196
197 static HRESULT WINAPI contentHandler_putDocumentLocator(
198         ISAXContentHandler* iface,
199         ISAXLocator *pLocator)
200 {
201     if(!test_expect_call(CH_PUTDOCUMENTLOCATOR))
202         return E_FAIL;
203
204     locator = pLocator;
205     test_locator(__LINE__, expectCall->line, expectCall->column);
206
207     expectCall++;
208     return S_OK;
209 }
210
211 static HRESULT WINAPI contentHandler_startDocument(
212         ISAXContentHandler* iface)
213 {
214     if(!test_expect_call(CH_STARTDOCUMENT))
215         return E_FAIL;
216
217     test_locator(__LINE__, expectCall->line, expectCall->column);
218
219     expectCall++;
220     return S_OK;
221 }
222
223 static HRESULT WINAPI contentHandler_endDocument(
224         ISAXContentHandler* iface)
225 {
226     if(!test_expect_call(CH_ENDDOCUMENT))
227         return E_FAIL;
228
229     test_locator(__LINE__, expectCall->line, expectCall->column);
230
231     expectCall++;
232     return S_OK;
233 }
234
235 static HRESULT WINAPI contentHandler_startPrefixMapping(
236         ISAXContentHandler* iface,
237         const WCHAR *pPrefix,
238         int nPrefix,
239         const WCHAR *pUri,
240         int nUri)
241 {
242     if(!test_expect_call(CH_ENDDOCUMENT))
243         return E_FAIL;
244
245     test_saxstr(__LINE__, pPrefix, nPrefix, expectCall->arg1);
246     test_saxstr(__LINE__, pUri, nUri, expectCall->arg2);
247     test_locator(__LINE__, expectCall->line, expectCall->column);
248
249     expectCall++;
250     return S_OK;
251 }
252
253 static HRESULT WINAPI contentHandler_endPrefixMapping(
254         ISAXContentHandler* iface,
255         const WCHAR *pPrefix,
256         int nPrefix)
257 {
258     if(!test_expect_call(CH_ENDPREFIXMAPPING))
259         return E_FAIL;
260
261     test_saxstr(__LINE__, pPrefix, nPrefix, expectCall->arg1);
262     test_locator(__LINE__, expectCall->line, expectCall->column);
263
264     expectCall++;
265     return S_OK;
266 }
267
268 static HRESULT WINAPI contentHandler_startElement(
269         ISAXContentHandler* iface,
270         const WCHAR *pNamespaceUri,
271         int nNamespaceUri,
272         const WCHAR *pLocalName,
273         int nLocalName,
274         const WCHAR *pQName,
275         int nQName,
276         ISAXAttributes *pAttr)
277 {
278     if(!test_expect_call(CH_STARTELEMENT))
279         return E_FAIL;
280
281     test_saxstr(__LINE__, pNamespaceUri, nNamespaceUri, expectCall->arg1);
282     test_saxstr(__LINE__, pLocalName, nLocalName, expectCall->arg2);
283     test_saxstr(__LINE__, pQName, nQName, expectCall->arg3);
284     test_locator(__LINE__, expectCall->line, expectCall->column);
285
286     expectCall++;
287     return S_OK;
288 }
289
290 static HRESULT WINAPI contentHandler_endElement(
291         ISAXContentHandler* iface,
292         const WCHAR *pNamespaceUri,
293         int nNamespaceUri,
294         const WCHAR *pLocalName,
295         int nLocalName,
296         const WCHAR *pQName,
297         int nQName)
298 {
299     if(!test_expect_call(CH_ENDELEMENT))
300         return E_FAIL;
301
302     test_saxstr(__LINE__, pNamespaceUri, nNamespaceUri, expectCall->arg1);
303     test_saxstr(__LINE__, pLocalName, nLocalName, expectCall->arg2);
304     test_saxstr(__LINE__, pQName, nQName, expectCall->arg3);
305     test_locator(__LINE__, expectCall->line, expectCall->column);
306
307     expectCall++;
308     return S_OK;
309 }
310
311 static HRESULT WINAPI contentHandler_characters(
312         ISAXContentHandler* iface,
313         const WCHAR *pChars,
314         int nChars)
315 {
316     if(!test_expect_call(CH_CHARACTERS))
317         return E_FAIL;
318
319     test_saxstr(__LINE__, pChars, nChars, expectCall->arg1);
320     test_locator(__LINE__, expectCall->line, expectCall->column);
321
322     expectCall++;
323     return S_OK;
324 }
325
326 static HRESULT WINAPI contentHandler_ignorableWhitespace(
327         ISAXContentHandler* iface,
328         const WCHAR *pChars,
329         int nChars)
330 {
331     if(!test_expect_call(CH_IGNORABLEWHITESPACE))
332         return E_FAIL;
333
334     test_saxstr(__LINE__, pChars, nChars, expectCall->arg1);
335     test_locator(__LINE__, expectCall->line, expectCall->column);
336
337     expectCall++;
338     return S_OK;
339 }
340
341 static HRESULT WINAPI contentHandler_processingInstruction(
342         ISAXContentHandler* iface,
343         const WCHAR *pTarget,
344         int nTarget,
345         const WCHAR *pData,
346         int nData)
347 {
348     if(!test_expect_call(CH_PROCESSINGINSTRUCTION))
349         return E_FAIL;
350
351     test_saxstr(__LINE__, pTarget, nTarget, expectCall->arg1);
352     test_saxstr(__LINE__, pData, nData, expectCall->arg2);
353     test_locator(__LINE__, expectCall->line, expectCall->column);
354
355     expectCall++;
356     return S_OK;
357 }
358
359 static HRESULT WINAPI contentHandler_skippedEntity(
360         ISAXContentHandler* iface,
361         const WCHAR *pName,
362         int nName)
363 {
364     if(!test_expect_call(CH_SKIPPEDENTITY))
365         return E_FAIL;
366
367     test_saxstr(__LINE__, pName, nName, expectCall->arg1);
368     test_locator(__LINE__, expectCall->line, expectCall->column);
369
370     expectCall++;
371     return S_OK;
372 }
373
374
375 static const ISAXContentHandlerVtbl contentHandlerVtbl =
376 {
377     contentHandler_QueryInterface,
378     contentHandler_AddRef,
379     contentHandler_Release,
380     contentHandler_putDocumentLocator,
381     contentHandler_startDocument,
382     contentHandler_endDocument,
383     contentHandler_startPrefixMapping,
384     contentHandler_endPrefixMapping,
385     contentHandler_startElement,
386     contentHandler_endElement,
387     contentHandler_characters,
388     contentHandler_ignorableWhitespace,
389     contentHandler_processingInstruction,
390     contentHandler_skippedEntity
391 };
392
393 static ISAXContentHandler contentHandler = { &contentHandlerVtbl };
394
395 static HRESULT WINAPI isaxerrorHandler_QueryInterface(
396         ISAXErrorHandler* iface,
397         REFIID riid,
398         void **ppvObject)
399 {
400     *ppvObject = NULL;
401
402     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISAXErrorHandler))
403     {
404         *ppvObject = iface;
405     }
406     else
407     {
408         return E_NOINTERFACE;
409     }
410
411     return S_OK;
412 }
413
414 static ULONG WINAPI isaxerrorHandler_AddRef(
415         ISAXErrorHandler* iface)
416 {
417     return 2;
418 }
419
420 static ULONG WINAPI isaxerrorHandler_Release(
421         ISAXErrorHandler* iface)
422 {
423     return 1;
424 }
425
426 static HRESULT WINAPI isaxerrorHandler_error(
427         ISAXErrorHandler* iface,
428         ISAXLocator *pLocator,
429         const WCHAR *pErrorMessage,
430         HRESULT hrErrorCode)
431 {
432     return S_OK;
433 }
434
435 static HRESULT WINAPI isaxerrorHandler_fatalError(
436         ISAXErrorHandler* iface,
437         ISAXLocator *pLocator,
438         const WCHAR *pErrorMessage,
439         HRESULT hrErrorCode)
440 {
441     return S_OK;
442 }
443
444 static HRESULT WINAPI isaxerrorHanddler_ignorableWarning(
445         ISAXErrorHandler* iface,
446         ISAXLocator *pLocator,
447         const WCHAR *pErrorMessage,
448         HRESULT hrErrorCode)
449 {
450     return S_OK;
451 }
452
453 static const ISAXErrorHandlerVtbl errorHandlerVtbl =
454 {
455     isaxerrorHandler_QueryInterface,
456     isaxerrorHandler_AddRef,
457     isaxerrorHandler_Release,
458     isaxerrorHandler_error,
459     isaxerrorHandler_fatalError,
460     isaxerrorHanddler_ignorableWarning
461 };
462
463 static ISAXErrorHandler errorHandler = { &errorHandlerVtbl };
464
465 static void test_saxreader(void)
466 {
467     HRESULT hr;
468     ISAXXMLReader *reader = NULL;
469     VARIANT var;
470     ISAXContentHandler *lpContentHandler;
471     ISAXErrorHandler *lpErrorHandler;
472     SAFEARRAY *pSA;
473     SAFEARRAYBOUND SADim[1];
474     char *pSAData = NULL;
475     IStream *iStream;
476     ULARGE_INTEGER liSize;
477     LARGE_INTEGER liPos;
478     ULONG bytesWritten;
479     HANDLE file;
480     static const CHAR testXmlA[] = "test.xml";
481     static const WCHAR testXmlW[] = {'t','e','s','t','.','x','m','l',0};
482     IXMLDOMDocument *domDocument;
483     BSTR bstrData;
484     VARIANT_BOOL vBool;
485
486     hr = CoCreateInstance(&CLSID_SAXXMLReader, NULL, CLSCTX_INPROC_SERVER,
487             &IID_ISAXXMLReader, (LPVOID*)&reader);
488
489     if(FAILED(hr))
490     {
491         skip("Failed to create SAXXMLReader instance\n");
492         return;
493     }
494
495     hr = ISAXXMLReader_getContentHandler(reader, NULL);
496     ok(hr == E_POINTER, "Expected E_POINTER, got %08x\n", hr);
497
498     hr = ISAXXMLReader_getErrorHandler(reader, NULL);
499     ok(hr == E_POINTER, "Expected E_POINTER, got %08x\n", hr);
500
501     hr = ISAXXMLReader_getContentHandler(reader, &lpContentHandler);
502     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
503     ok(lpContentHandler == NULL, "Expected %p, got %p\n", NULL, lpContentHandler);
504
505     hr = ISAXXMLReader_getErrorHandler(reader, &lpErrorHandler);
506     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
507     ok(lpErrorHandler == NULL, "Expected %p, got %p\n", NULL, lpErrorHandler);
508
509     hr = ISAXXMLReader_putContentHandler(reader, NULL);
510     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
511
512     hr = ISAXXMLReader_putContentHandler(reader, &contentHandler);
513     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
514
515     hr = ISAXXMLReader_putErrorHandler(reader, &errorHandler);
516     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
517
518     hr = ISAXXMLReader_getContentHandler(reader, &lpContentHandler);
519     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
520     ok(lpContentHandler == &contentHandler, "Expected %p, got %p\n", &contentHandler, lpContentHandler);
521
522     V_VT(&var) = VT_BSTR;
523     V_BSTR(&var) = SysAllocString(szSimpleXML);
524
525     expectCall = contentHandlerTest1;
526     hr = ISAXXMLReader_parse(reader, var);
527     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
528     test_expect_call(CH_ENDTEST);
529
530     SADim[0].lLbound= 0;
531     SADim[0].cElements= sizeof(szTestXML)-1;
532     pSA = SafeArrayCreate(VT_UI1, 1, SADim);
533     SafeArrayAccessData(pSA, (void**)&pSAData);
534     memcpy(pSAData, szTestXML, sizeof(szTestXML)-1);
535     SafeArrayUnaccessData(pSA);
536     V_VT(&var) = VT_ARRAY|VT_UI1;
537     V_ARRAY(&var) = pSA;
538
539     expectCall = contentHandlerTest1;
540     hr = ISAXXMLReader_parse(reader, var);
541     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
542     test_expect_call(CH_ENDTEST);
543
544     SafeArrayDestroy(pSA);
545
546     CreateStreamOnHGlobal(NULL, TRUE, &iStream);
547     liSize.QuadPart = strlen(szTestXML);
548     IStream_SetSize(iStream, liSize);
549     IStream_Write(iStream, szTestXML, strlen(szTestXML), &bytesWritten);
550     liPos.QuadPart = 0;
551     IStream_Seek(iStream, liPos, STREAM_SEEK_SET, NULL);
552     V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
553     V_UNKNOWN(&var) = (IUnknown*)iStream;
554
555     expectCall = contentHandlerTest1;
556     hr = ISAXXMLReader_parse(reader, var);
557     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
558     test_expect_call(CH_ENDTEST);
559
560     IStream_Release(iStream);
561
562     V_VT(&var) = VT_BSTR;
563     V_BSTR(&var) = SysAllocString(szCarriageRetTest);
564
565     expectCall = contentHandlerTest2;
566     hr = ISAXXMLReader_parse(reader, var);
567     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
568     test_expect_call(CH_ENDTEST);
569
570     file = CreateFileA(testXmlA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
571     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
572     WriteFile(file, szTestXML, sizeof(szTestXML)-1, &bytesWritten, NULL);
573     CloseHandle(file);
574
575     expectCall = contentHandlerTest1;
576     hr = ISAXXMLReader_parseURL(reader, testXmlW);
577     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
578     test_expect_call(CH_ENDTEST);
579
580     DeleteFileA(testXmlA);
581
582     hr = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
583             &IID_IXMLDOMDocument, (LPVOID*)&domDocument);
584     if(FAILED(hr))
585     {
586         skip("Failed to create DOMDocument instance\n");
587         return;
588     }
589     bstrData = SysAllocString(szSimpleXML);
590     hr = IXMLDOMDocument_loadXML(domDocument, bstrData, &vBool);
591     V_VT(&var) = VT_UNKNOWN;
592     V_UNKNOWN(&var) = (IUnknown*)domDocument;
593
594     expectCall = contentHandlerTest2;
595     hr = ISAXXMLReader_parse(reader, var);
596     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
597     test_expect_call(CH_ENDTEST);
598     IXMLDOMDocument_Release(domDocument);
599
600     ISAXXMLReader_Release(reader);
601 }
602
603 START_TEST(saxreader)
604 {
605     HRESULT hr;
606
607     hr = CoInitialize(NULL);
608     ok(hr == S_OK, "failed to init com\n");
609
610     test_saxreader();
611
612     CoUninitialize();
613 }