4 * Copyright 2010, 2012-2013 Nikolay Sivov
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.
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.
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
32 #include "wine/test.h"
34 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
36 static HRESULT (WINAPI *pCreateXmlReader)(REFIID riid, void **ppvObject, IMalloc *pMalloc);
37 static HRESULT (WINAPI *pCreateXmlReaderInputWithEncodingName)(IUnknown *stream,
42 IXmlReaderInput **ppInput);
43 static const char *debugstr_guid(REFIID riid)
47 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
48 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
49 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
50 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
55 static WCHAR *a2w(const char *str)
57 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
58 WCHAR *ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
59 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
63 static void free_str(WCHAR *str)
65 HeapFree(GetProcessHeap(), 0, str);
68 static const char xmldecl_full[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
70 static IStream *create_stream_on_data(const char *data, int size)
72 IStream *stream = NULL;
77 hglobal = GlobalAlloc(GHND, size);
78 ptr = GlobalLock(hglobal);
80 memcpy(ptr, data, size);
82 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
83 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
84 ok(stream != NULL, "Expected non-NULL stream\n");
86 GlobalUnlock(hglobal);
91 static void ok_pos_(IXmlReader *reader, int line, int pos, int line_broken,
92 int pos_broken, int todo, int _line_)
98 hr = IXmlReader_GetLineNumber(reader, &l);
99 ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr);
100 hr = IXmlReader_GetLinePosition(reader, &p);
101 ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr);
103 if (line_broken == -1 && pos_broken == -1)
106 broken_state = broken((line_broken == -1 ? line : line_broken) == l &&
107 (pos_broken == -1 ? pos : pos_broken) == p);
111 ok_(__FILE__, _line_)((l == line && pos == p) || broken_state,
112 "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p);
115 ok_(__FILE__, _line_)((l == line && pos == p) || broken_state,
116 "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p);
119 #define ok_pos(reader, l, p, l_brk, p_brk, todo) ok_pos_(reader, l, p, l_brk, p_brk, todo, __LINE__)
121 typedef struct input_iids_t {
126 static const IID *setinput_full[] = {
127 &IID_IXmlReaderInput,
129 &IID_ISequentialStream,
133 /* this applies to early xmllite versions */
134 static const IID *setinput_full_old[] = {
135 &IID_IXmlReaderInput,
136 &IID_ISequentialStream,
141 /* after ::SetInput(IXmlReaderInput*) */
142 static const IID *setinput_readerinput[] = {
144 &IID_ISequentialStream,
148 static const IID *empty_seq[] = {
152 static input_iids_t input_iids;
154 static void ok_iids_(const input_iids_t *iids, const IID **expected, const IID **exp_broken, int todo, int line)
158 while (expected[i++]) size++;
162 ok_(__FILE__, line)(iids->count == size, "Sequence size mismatch (%d), got (%d)\n", size, iids->count);
165 ok_(__FILE__, line)(iids->count == size, "Sequence size mismatch (%d), got (%d)\n", size, iids->count);
167 if (iids->count != size) return;
169 for (i = 0; i < size; i++) {
170 ok_(__FILE__, line)(IsEqualGUID(&iids->iids[i], expected[i]) ||
171 (exp_broken ? broken(IsEqualGUID(&iids->iids[i], exp_broken[i])) : FALSE),
172 "Wrong IID(%d), got (%s)\n", i, debugstr_guid(&iids->iids[i]));
175 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
177 static const char *state_to_str(XmlReadState state)
179 static const char* state_names[] = {
180 "XmlReadState_Initial",
181 "XmlReadState_Interactive",
182 "XmlReadState_Error",
183 "XmlReadState_EndOfFile",
184 "XmlReadState_Closed"
187 static const char unknown[] = "unknown";
191 case XmlReadState_Initial:
192 case XmlReadState_Interactive:
193 case XmlReadState_Error:
194 case XmlReadState_EndOfFile:
195 case XmlReadState_Closed:
196 return state_names[state];
202 static const char *type_to_str(XmlNodeType type)
204 static const char* type_names[] = {
206 "XmlNodeType_Element",
207 "XmlNodeType_Attribute",
211 "XmlNodeType_ProcessingInstruction",
212 "XmlNodeType_Comment",
214 "XmlNodeType_DocumentType",
216 "XmlNodeType_Whitespace",
218 "XmlNodeType_EndElement",
220 "XmlNodeType_XmlDeclaration"
223 static const char unknown[] = "unknown";
227 case XmlNodeType_None:
228 case XmlNodeType_Element:
229 case XmlNodeType_Attribute:
230 case XmlNodeType_Text:
231 case XmlNodeType_CDATA:
232 case XmlNodeType_ProcessingInstruction:
233 case XmlNodeType_Comment:
234 case XmlNodeType_DocumentType:
235 case XmlNodeType_Whitespace:
236 case XmlNodeType_EndElement:
237 case XmlNodeType_XmlDeclaration:
238 return type_names[type];
244 static void test_read_state_(IXmlReader *reader, XmlReadState expected,
245 XmlReadState exp_broken, int todo, int line)
251 state = -1; /* invalid value */
252 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, (LONG_PTR*)&state);
253 ok_(__FILE__, line)(hr == S_OK, "Expected S_OK, got %08x\n", hr);
255 if (exp_broken == -1)
258 broken_state = broken(exp_broken == state);
263 ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n",
264 state_to_str(expected), state_to_str(state));
267 ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n",
268 state_to_str(expected), state_to_str(state));
271 #define test_read_state(reader, exp, brk, todo) test_read_state_(reader, exp, brk, todo, __LINE__)
273 typedef struct _testinput
275 IUnknown IUnknown_iface;
279 static inline testinput *impl_from_IUnknown(IUnknown *iface)
281 return CONTAINING_RECORD(iface, testinput, IUnknown_iface);
284 static HRESULT WINAPI testinput_QueryInterface(IUnknown *iface, REFIID riid, void** ppvObj)
286 if (IsEqualGUID( riid, &IID_IUnknown ))
289 IUnknown_AddRef(iface);
293 input_iids.iids[input_iids.count++] = *riid;
297 return E_NOINTERFACE;
300 static ULONG WINAPI testinput_AddRef(IUnknown *iface)
302 testinput *This = impl_from_IUnknown(iface);
303 return InterlockedIncrement(&This->ref);
306 static ULONG WINAPI testinput_Release(IUnknown *iface)
308 testinput *This = impl_from_IUnknown(iface);
311 ref = InterlockedDecrement(&This->ref);
314 HeapFree(GetProcessHeap(), 0, This);
320 static const struct IUnknownVtbl testinput_vtbl =
322 testinput_QueryInterface,
327 static HRESULT testinput_createinstance(void **ppObj)
331 input = HeapAlloc(GetProcessHeap(), 0, sizeof (*input));
332 if(!input) return E_OUTOFMEMORY;
334 input->IUnknown_iface.lpVtbl = &testinput_vtbl;
337 *ppObj = &input->IUnknown_iface;
342 static BOOL init_pointers(void)
344 /* don't free module here, it's to be unloaded on exit */
345 HMODULE mod = LoadLibraryA("xmllite.dll");
349 win_skip("xmllite library not available\n");
353 #define MAKEFUNC(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return FALSE;
354 MAKEFUNC(CreateXmlReader);
355 MAKEFUNC(CreateXmlReaderInputWithEncodingName);
361 static void test_reader_create(void)
367 XmlNodeType nodetype;
372 pCreateXmlReader(&IID_IXmlReader, NULL, NULL);
373 pCreateXmlReader(NULL, (void**)&reader, NULL);
376 hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
377 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
379 test_read_state(reader, XmlReadState_Closed, -1, FALSE);
381 nodetype = XmlNodeType_Element;
382 hr = IXmlReader_GetNodeType(reader, &nodetype);
383 ok(hr == S_FALSE, "got %08x\n", hr);
384 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
387 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_DtdProcessing, (LONG_PTR*)&dtd);
388 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
389 ok(dtd == DtdProcessing_Prohibit, "got %d\n", dtd);
392 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, dtd);
393 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
395 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, -1);
396 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
398 /* Null input pointer, releases previous input */
399 hr = IXmlReader_SetInput(reader, NULL);
400 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
402 test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE);
404 /* test input interface selection sequence */
405 hr = testinput_createinstance((void**)&input);
406 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
410 input_iids.count = 0;
411 hr = IXmlReader_SetInput(reader, input);
412 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
413 ok_iids(&input_iids, setinput_full, setinput_full_old, FALSE);
414 IUnknown_Release(input);
416 IXmlReader_Release(reader);
419 static void test_readerinput(void)
421 IXmlReaderInput *reader_input;
422 IXmlReader *reader, *reader2;
423 IUnknown *obj, *input;
424 IStream *stream, *stream2;
425 XmlNodeType nodetype;
429 hr = pCreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, NULL);
430 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
431 hr = pCreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, &reader_input);
432 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
434 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
435 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
437 ref = IStream_AddRef(stream);
438 ok(ref == 2, "Expected 2, got %d\n", ref);
439 IStream_Release(stream);
440 hr = pCreateXmlReaderInputWithEncodingName((IUnknown*)stream, NULL, NULL, FALSE, NULL, &reader_input);
441 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
443 hr = IUnknown_QueryInterface(reader_input, &IID_IStream, (void**)&stream2);
444 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
446 hr = IUnknown_QueryInterface(reader_input, &IID_ISequentialStream, (void**)&stream2);
447 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
449 /* IXmlReaderInput grabs a stream reference */
450 ref = IStream_AddRef(stream);
451 ok(ref == 3, "Expected 3, got %d\n", ref);
452 IStream_Release(stream);
454 /* try ::SetInput() with valid IXmlReaderInput */
455 hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
456 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
458 ref = IUnknown_AddRef(reader_input);
459 ok(ref == 2, "Expected 2, got %d\n", ref);
460 IUnknown_Release(reader_input);
462 hr = IXmlReader_SetInput(reader, reader_input);
463 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
465 test_read_state(reader, XmlReadState_Initial, -1, FALSE);
467 nodetype = XmlNodeType_Element;
468 hr = IXmlReader_GetNodeType(reader, &nodetype);
469 ok(hr == S_OK, "got %08x\n", hr);
470 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
472 /* IXmlReader grabs a IXmlReaderInput reference */
473 ref = IUnknown_AddRef(reader_input);
474 ok(ref == 3, "Expected 3, got %d\n", ref);
475 IUnknown_Release(reader_input);
477 ref = IStream_AddRef(stream);
478 ok(ref == 4, "Expected 4, got %d\n", ref);
479 IStream_Release(stream);
481 /* reset input and check state */
482 hr = IXmlReader_SetInput(reader, NULL);
483 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
485 test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE);
487 IXmlReader_Release(reader);
489 ref = IStream_AddRef(stream);
490 ok(ref == 3, "Expected 3, got %d\n", ref);
491 IStream_Release(stream);
493 ref = IUnknown_AddRef(reader_input);
494 ok(ref == 2, "Expected 2, got %d\n", ref);
495 IUnknown_Release(reader_input);
497 /* IID_IXmlReaderInput */
498 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
499 so it's not a COM interface actually.
500 Such query will be used only to check if input is really IXmlReaderInput */
501 obj = (IUnknown*)0xdeadbeef;
502 hr = IUnknown_QueryInterface(reader_input, &IID_IXmlReaderInput, (void**)&obj);
503 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
504 ref = IUnknown_AddRef(reader_input);
505 ok(ref == 3, "Expected 3, got %d\n", ref);
506 IUnknown_Release(reader_input);
508 IUnknown_Release(reader_input);
509 IUnknown_Release(reader_input);
510 IStream_Release(stream);
512 /* test input interface selection sequence */
514 hr = testinput_createinstance((void**)&input);
515 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
517 input_iids.count = 0;
518 ref = IUnknown_AddRef(input);
519 ok(ref == 2, "Expected 2, got %d\n", ref);
520 IUnknown_Release(input);
521 hr = pCreateXmlReaderInputWithEncodingName(input, NULL, NULL, FALSE, NULL, &reader_input);
522 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
523 ok_iids(&input_iids, empty_seq, NULL, FALSE);
524 /* IXmlReaderInput stores stream interface as IUnknown */
525 ref = IUnknown_AddRef(input);
526 ok(ref == 3, "Expected 3, got %d\n", ref);
527 IUnknown_Release(input);
529 hr = pCreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
530 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
532 input_iids.count = 0;
533 ref = IUnknown_AddRef(reader_input);
534 ok(ref == 2, "Expected 2, got %d\n", ref);
535 IUnknown_Release(reader_input);
536 ref = IUnknown_AddRef(input);
537 ok(ref == 3, "Expected 3, got %d\n", ref);
538 IUnknown_Release(input);
539 hr = IXmlReader_SetInput(reader, reader_input);
540 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
541 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
543 test_read_state(reader, XmlReadState_Closed, -1, FALSE);
545 ref = IUnknown_AddRef(input);
546 ok(ref == 3, "Expected 3, got %d\n", ref);
547 IUnknown_Release(input);
549 ref = IUnknown_AddRef(reader_input);
550 ok(ref == 3 || broken(ref == 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
551 "Expected 3, got %d\n", ref);
552 IUnknown_Release(reader_input);
553 /* repeat another time, no check or caching here */
554 input_iids.count = 0;
555 hr = IXmlReader_SetInput(reader, reader_input);
556 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
557 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
560 hr = pCreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader2, NULL);
561 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
563 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
564 ::SetInput() level, each time it's called */
565 input_iids.count = 0;
566 hr = IXmlReader_SetInput(reader2, reader_input);
567 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
568 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
570 IXmlReader_Release(reader2);
571 IXmlReader_Release(reader);
573 IUnknown_Release(reader_input);
574 IUnknown_Release(input);
577 static void test_reader_state(void)
580 XmlNodeType nodetype;
583 hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
584 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
586 /* invalid arguments */
587 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, NULL);
588 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
590 /* attempt to read on closed reader */
591 test_read_state(reader, XmlReadState_Closed, -1, 0);
594 /* newer versions crash here, probably cause no input was set */
595 hr = IXmlReader_Read(reader, &nodetype);
596 ok(hr == S_FALSE, "got %08x\n", hr);
598 IXmlReader_Release(reader);
601 static void test_read_xmldeclaration(void)
610 hr = pCreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
611 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
613 /* position methods with Null args */
614 hr = IXmlReader_GetLineNumber(reader, NULL);
615 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
617 hr = IXmlReader_GetLinePosition(reader, NULL);
618 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
620 stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
622 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
623 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
625 hr = IXmlReader_GetAttributeCount(reader, &count);
626 ok(hr == S_OK, "got %08x\n", hr);
627 ok(count == 0, "got %d\n", count);
629 /* try to move without attributes */
630 hr = IXmlReader_MoveToElement(reader);
631 ok(hr == S_FALSE, "got %08x\n", hr);
633 hr = IXmlReader_MoveToNextAttribute(reader);
634 ok(hr == S_FALSE, "got %08x\n", hr);
636 hr = IXmlReader_MoveToFirstAttribute(reader);
637 ok(hr == S_FALSE, "got %08x\n", hr);
639 ok_pos(reader, 0, 0, -1, -1, FALSE);
642 hr = IXmlReader_Read(reader, &type);
643 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
644 ok(type == XmlNodeType_XmlDeclaration,
645 "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type));
646 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
647 ok_pos(reader, 1, 3, -1, 55, TRUE);
648 test_read_state(reader, XmlReadState_Interactive, -1, 0);
650 hr = IXmlReader_GetValue(reader, &val, NULL);
651 ok(hr == S_OK, "got %08x\n", hr);
652 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
654 /* check attributes */
655 hr = IXmlReader_MoveToNextAttribute(reader);
656 ok(hr == S_OK, "got %08x\n", hr);
658 type = XmlNodeType_None;
659 hr = IXmlReader_GetNodeType(reader, &type);
660 ok(hr == S_OK, "got %08x\n", hr);
661 ok(type == XmlNodeType_Attribute, "got %d\n", type);
663 ok_pos(reader, 1, 7, -1, 55, TRUE);
665 /* try to move from last attribute */
666 hr = IXmlReader_MoveToNextAttribute(reader);
667 ok(hr == S_OK, "got %08x\n", hr);
668 hr = IXmlReader_MoveToNextAttribute(reader);
669 ok(hr == S_OK, "got %08x\n", hr);
670 hr = IXmlReader_MoveToNextAttribute(reader);
671 ok(hr == S_FALSE, "got %08x\n", hr);
673 type = XmlNodeType_None;
674 hr = IXmlReader_GetNodeType(reader, &type);
675 ok(hr == S_OK, "got %08x\n", hr);
676 ok(type == XmlNodeType_Attribute, "got %d\n", type);
678 hr = IXmlReader_MoveToFirstAttribute(reader);
679 ok(hr == S_OK, "got %08x\n", hr);
680 ok_pos(reader, 1, 7, -1, 55, TRUE);
682 hr = IXmlReader_GetAttributeCount(reader, NULL);
683 ok(hr == E_INVALIDARG, "got %08x\n", hr);
685 hr = IXmlReader_GetAttributeCount(reader, &count);
686 ok(hr == S_OK, "got %08x\n", hr);
687 ok(count == 3, "Expected 3, got %d\n", count);
689 hr = IXmlReader_GetDepth(reader, &count);
691 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
692 ok(count == 1, "Expected 1, got %d\n", count);
695 hr = IXmlReader_MoveToElement(reader);
696 ok(hr == S_OK, "got %08x\n", hr);
698 type = XmlNodeType_None;
699 hr = IXmlReader_GetNodeType(reader, &type);
700 ok(hr == S_OK, "got %08x\n", hr);
701 ok(type == XmlNodeType_XmlDeclaration, "got %d\n", type);
703 type = XmlNodeType_XmlDeclaration;
704 hr = IXmlReader_Read(reader, &type);
705 /* newer versions return syntax error here cause document is incomplete,
706 it makes more sense than invalid char error */
708 ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
709 ok(type == XmlNodeType_None, "got %d\n", type);
711 IStream_Release(stream);
712 IXmlReader_Release(reader);
720 HRESULT hr_broken; /* this is set to older version results */
723 static struct test_entry comment_tests[] = {
724 { "<!-- comment -->", "", " comment ", S_OK },
725 { "<!-- - comment-->", "", " - comment", S_OK },
726 { "<!-- -- comment-->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
727 { "<!-- -- comment--->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
731 static void test_read_comment(void)
733 struct test_entry *test = comment_tests;
737 hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
738 ok(hr == S_OK, "S_OK, got %08x\n", hr);
745 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
746 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
747 ok(hr == S_OK, "got %08x\n", hr);
749 type = XmlNodeType_None;
750 hr = IXmlReader_Read(reader, &type);
752 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
754 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
761 ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml);
765 hr = IXmlReader_GetLocalName(reader, &str, &len);
766 ok(hr == S_OK, "got 0x%08x\n", hr);
767 ok(len == strlen(test->name), "got %u\n", len);
768 str_exp = a2w(test->name);
769 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
774 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
775 ok(hr == S_OK, "got 0x%08x\n", hr);
776 ok(len == strlen(test->name), "got %u\n", len);
777 str_exp = a2w(test->name);
778 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
784 hr = IXmlReader_GetValue(reader, &str, &len);
785 ok(hr == S_OK, "got 0x%08x\n", hr);
786 ok(len == strlen(test->value), "got %u\n", len);
787 str_exp = a2w(test->value);
788 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
792 IStream_Release(stream);
796 IXmlReader_Release(reader);
799 static struct test_entry pi_tests[] = {
800 { "<?pi?>", "pi", "", S_OK },
801 { "<?pi ?>", "pi", "", S_OK },
802 { "<?pi pi data?>", "pi", "pi data", S_OK },
803 { "<?pi pi data ?>", "pi", "pi data ", S_OK },
804 { "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
805 { "<?:pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
806 { "<?-pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
807 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK },
811 static void test_read_pi(void)
813 struct test_entry *test = pi_tests;
817 hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
818 ok(hr == S_OK, "S_OK, got %08x\n", hr);
825 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
826 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
827 ok(hr == S_OK, "got %08x\n", hr);
829 type = XmlNodeType_None;
830 hr = IXmlReader_Read(reader, &type);
832 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
834 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
841 ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml);
845 hr = IXmlReader_GetLocalName(reader, &str, &len);
846 ok(hr == S_OK, "got 0x%08x\n", hr);
847 ok(len == strlen(test->name), "got %u\n", len);
848 str_exp = a2w(test->name);
849 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
854 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
855 ok(hr == S_OK, "got 0x%08x\n", hr);
856 ok(len == strlen(test->name), "got %u\n", len);
857 str_exp = a2w(test->name);
858 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
862 len = !strlen(test->value);
864 hr = IXmlReader_GetValue(reader, &str, &len);
865 ok(hr == S_OK, "got 0x%08x\n", hr);
866 ok(len == strlen(test->value), "got %u\n", len);
867 str_exp = a2w(test->value);
868 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
872 IStream_Release(stream);
876 IXmlReader_Release(reader);
883 r = CoInitialize( NULL );
884 ok( r == S_OK, "failed to init com\n");
886 if (!init_pointers())
892 test_reader_create();
897 test_read_xmldeclaration();