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
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
37 #include <wine/test.h>
39 DEFINE_GUID(IID_IXmlReaderInput
, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
41 static HRESULT (WINAPI
*pCreateXmlReader
)(REFIID riid
, void **ppvObject
, IMalloc
*pMalloc
);
42 static HRESULT (WINAPI
*pCreateXmlReaderInputWithEncodingName
)(IUnknown
*stream
,
47 IXmlReaderInput
**ppInput
);
49 static WCHAR
*a2w(const char *str
)
51 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
52 WCHAR
*ret
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
53 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
57 static void free_str(WCHAR
*str
)
59 HeapFree(GetProcessHeap(), 0, str
);
62 static const char xmldecl_full
[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
63 static const char xmldecl_short
[] = "<?xml version=\"1.0\"?><RegistrationInfo/>";
65 static IStream
*create_stream_on_data(const char *data
, int size
)
67 IStream
*stream
= NULL
;
72 hglobal
= GlobalAlloc(GHND
, size
);
73 ptr
= GlobalLock(hglobal
);
75 memcpy(ptr
, data
, size
);
77 hr
= CreateStreamOnHGlobal(hglobal
, TRUE
, &stream
);
78 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
79 ok(stream
!= NULL
, "Expected non-NULL stream\n");
81 GlobalUnlock(hglobal
);
86 static void ok_pos_(IXmlReader
*reader
, int line
, int pos
, int line_broken
,
87 int pos_broken
, BOOL todo
, int _line_
)
93 hr
= IXmlReader_GetLineNumber(reader
, &l
);
94 ok_(__FILE__
, _line_
)(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
95 hr
= IXmlReader_GetLinePosition(reader
, &p
);
96 ok_(__FILE__
, _line_
)(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
98 if (line_broken
== -1 && pos_broken
== -1)
101 broken_state
= broken((line_broken
== -1 ? line
: line_broken
) == l
&&
102 (pos_broken
== -1 ? pos
: pos_broken
) == p
);
106 ok_(__FILE__
, _line_
)((l
== line
&& pos
== p
) || broken_state
,
107 "Expected (%d,%d), got (%d,%d)\n", line
, pos
, l
, p
);
110 ok_(__FILE__
, _line_
)((l
== line
&& pos
== p
) || broken_state
,
111 "Expected (%d,%d), got (%d,%d)\n", line
, pos
, l
, p
);
114 #define ok_pos(reader, l, p, l_brk, p_brk, todo) ok_pos_(reader, l, p, l_brk, p_brk, todo, __LINE__)
116 typedef struct input_iids_t
{
121 static const IID
*setinput_full
[] = {
122 &IID_IXmlReaderInput
,
124 &IID_ISequentialStream
,
128 /* this applies to early xmllite versions */
129 static const IID
*setinput_full_old
[] = {
130 &IID_IXmlReaderInput
,
131 &IID_ISequentialStream
,
136 /* after ::SetInput(IXmlReaderInput*) */
137 static const IID
*setinput_readerinput
[] = {
139 &IID_ISequentialStream
,
143 static const IID
*empty_seq
[] = {
147 static input_iids_t input_iids
;
149 static void ok_iids_(const input_iids_t
*iids
, const IID
**expected
, const IID
**exp_broken
, BOOL todo
, int line
)
153 while (expected
[i
++]) size
++;
157 ok_(__FILE__
, line
)(iids
->count
== size
, "Sequence size mismatch (%d), got (%d)\n", size
, iids
->count
);
160 ok_(__FILE__
, line
)(iids
->count
== size
, "Sequence size mismatch (%d), got (%d)\n", size
, iids
->count
);
162 if (iids
->count
!= size
) return;
164 for (i
= 0; i
< size
; i
++) {
165 ok_(__FILE__
, line
)(IsEqualGUID(&iids
->iids
[i
], expected
[i
]) ||
166 (exp_broken
? broken(IsEqualGUID(&iids
->iids
[i
], exp_broken
[i
])) : FALSE
),
167 "Wrong IID(%d), got %s\n", i
, wine_dbgstr_guid(&iids
->iids
[i
]));
170 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
172 static const char *state_to_str(XmlReadState state
)
174 static const char* state_names
[] = {
175 "XmlReadState_Initial",
176 "XmlReadState_Interactive",
177 "XmlReadState_Error",
178 "XmlReadState_EndOfFile",
179 "XmlReadState_Closed"
182 static const char unknown
[] = "unknown";
186 case XmlReadState_Initial
:
187 case XmlReadState_Interactive
:
188 case XmlReadState_Error
:
189 case XmlReadState_EndOfFile
:
190 case XmlReadState_Closed
:
191 return state_names
[state
];
197 static const char *type_to_str(XmlNodeType type
)
199 static const char* type_names
[] = {
201 "XmlNodeType_Element",
202 "XmlNodeType_Attribute",
206 "XmlNodeType_ProcessingInstruction",
207 "XmlNodeType_Comment",
209 "XmlNodeType_DocumentType",
211 "XmlNodeType_Whitespace",
213 "XmlNodeType_EndElement",
215 "XmlNodeType_XmlDeclaration"
218 static const char unknown
[] = "unknown";
222 case XmlNodeType_None
:
223 case XmlNodeType_Element
:
224 case XmlNodeType_Attribute
:
225 case XmlNodeType_Text
:
226 case XmlNodeType_CDATA
:
227 case XmlNodeType_ProcessingInstruction
:
228 case XmlNodeType_Comment
:
229 case XmlNodeType_DocumentType
:
230 case XmlNodeType_Whitespace
:
231 case XmlNodeType_EndElement
:
232 case XmlNodeType_XmlDeclaration
:
233 return type_names
[type
];
239 static void test_read_state_(IXmlReader
*reader
, XmlReadState expected
,
240 XmlReadState exp_broken
, BOOL todo
, int line
)
246 state
= -1; /* invalid value */
247 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_ReadState
, &state
);
248 ok_(__FILE__
, line
)(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
250 if (exp_broken
== -1)
251 broken_state
= FALSE
;
253 broken_state
= broken(exp_broken
== state
);
258 ok_(__FILE__
, line
)(state
== expected
|| broken_state
, "Expected (%s), got (%s)\n",
259 state_to_str(expected
), state_to_str(state
));
262 ok_(__FILE__
, line
)(state
== expected
|| broken_state
, "Expected (%s), got (%s)\n",
263 state_to_str(expected
), state_to_str(state
));
266 #define test_read_state(reader, exp, brk, todo) test_read_state_(reader, exp, brk, todo, __LINE__)
268 typedef struct _testinput
270 IUnknown IUnknown_iface
;
274 static inline testinput
*impl_from_IUnknown(IUnknown
*iface
)
276 return CONTAINING_RECORD(iface
, testinput
, IUnknown_iface
);
279 static HRESULT WINAPI
testinput_QueryInterface(IUnknown
*iface
, REFIID riid
, void** ppvObj
)
281 if (IsEqualGUID( riid
, &IID_IUnknown
))
284 IUnknown_AddRef(iface
);
288 input_iids
.iids
[input_iids
.count
++] = *riid
;
292 return E_NOINTERFACE
;
295 static ULONG WINAPI
testinput_AddRef(IUnknown
*iface
)
297 testinput
*This
= impl_from_IUnknown(iface
);
298 return InterlockedIncrement(&This
->ref
);
301 static ULONG WINAPI
testinput_Release(IUnknown
*iface
)
303 testinput
*This
= impl_from_IUnknown(iface
);
306 ref
= InterlockedDecrement(&This
->ref
);
309 HeapFree(GetProcessHeap(), 0, This
);
315 static const struct IUnknownVtbl testinput_vtbl
=
317 testinput_QueryInterface
,
322 static HRESULT
testinput_createinstance(void **ppObj
)
326 input
= HeapAlloc(GetProcessHeap(), 0, sizeof (*input
));
327 if(!input
) return E_OUTOFMEMORY
;
329 input
->IUnknown_iface
.lpVtbl
= &testinput_vtbl
;
332 *ppObj
= &input
->IUnknown_iface
;
337 static HRESULT WINAPI
teststream_QueryInterface(ISequentialStream
*iface
, REFIID riid
, void **obj
)
339 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_ISequentialStream
))
346 return E_NOINTERFACE
;
349 static ULONG WINAPI
teststream_AddRef(ISequentialStream
*iface
)
354 static ULONG WINAPI
teststream_Release(ISequentialStream
*iface
)
359 static int stream_readcall
;
361 static HRESULT WINAPI
teststream_Read(ISequentialStream
*iface
, void *pv
, ULONG cb
, ULONG
*pread
)
363 static const char xml
[] = "<!-- comment -->";
365 if (stream_readcall
++)
371 *pread
= sizeof(xml
) / 2;
372 memcpy(pv
, xml
, *pread
);
376 static HRESULT WINAPI
teststream_Write(ISequentialStream
*iface
, const void *pv
, ULONG cb
, ULONG
*written
)
378 ok(0, "unexpected call\n");
382 static const ISequentialStreamVtbl teststreamvtbl
=
384 teststream_QueryInterface
,
391 static BOOL
init_pointers(void)
393 /* don't free module here, it's to be unloaded on exit */
394 HMODULE mod
= LoadLibraryA("xmllite.dll");
398 win_skip("xmllite library not available\n");
402 #define MAKEFUNC(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return FALSE;
403 MAKEFUNC(CreateXmlReader
);
404 MAKEFUNC(CreateXmlReaderInputWithEncodingName
);
410 static void test_reader_create(void)
416 XmlNodeType nodetype
;
421 pCreateXmlReader(&IID_IXmlReader
, NULL
, NULL
);
422 pCreateXmlReader(NULL
, (void**)&reader
, NULL
);
425 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
426 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
428 test_read_state(reader
, XmlReadState_Closed
, -1, FALSE
);
430 nodetype
= XmlNodeType_Element
;
431 hr
= IXmlReader_GetNodeType(reader
, &nodetype
);
432 ok(hr
== S_FALSE
, "got %08x\n", hr
);
433 ok(nodetype
== XmlNodeType_None
, "got %d\n", nodetype
);
436 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_DtdProcessing
, (LONG_PTR
*)&dtd
);
437 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
438 ok(dtd
== DtdProcessing_Prohibit
, "got %d\n", dtd
);
441 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, dtd
);
442 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
444 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, -1);
445 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
447 /* Null input pointer, releases previous input */
448 hr
= IXmlReader_SetInput(reader
, NULL
);
449 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
451 test_read_state(reader
, XmlReadState_Initial
, XmlReadState_Closed
, FALSE
);
453 /* test input interface selection sequence */
454 hr
= testinput_createinstance((void**)&input
);
455 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
459 input_iids
.count
= 0;
460 hr
= IXmlReader_SetInput(reader
, input
);
461 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
462 ok_iids(&input_iids
, setinput_full
, setinput_full_old
, FALSE
);
463 IUnknown_Release(input
);
465 IXmlReader_Release(reader
);
468 static void test_readerinput(void)
470 IXmlReaderInput
*reader_input
;
471 IXmlReader
*reader
, *reader2
;
472 IUnknown
*obj
, *input
;
473 IStream
*stream
, *stream2
;
474 XmlNodeType nodetype
;
478 hr
= pCreateXmlReaderInputWithEncodingName(NULL
, NULL
, NULL
, FALSE
, NULL
, NULL
);
479 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
480 hr
= pCreateXmlReaderInputWithEncodingName(NULL
, NULL
, NULL
, FALSE
, NULL
, &reader_input
);
481 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
483 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
484 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
486 ref
= IStream_AddRef(stream
);
487 ok(ref
== 2, "Expected 2, got %d\n", ref
);
488 IStream_Release(stream
);
489 hr
= pCreateXmlReaderInputWithEncodingName((IUnknown
*)stream
, NULL
, NULL
, FALSE
, NULL
, &reader_input
);
490 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
492 hr
= IUnknown_QueryInterface(reader_input
, &IID_IStream
, (void**)&stream2
);
493 ok(hr
== E_NOINTERFACE
, "Expected S_OK, got %08x\n", hr
);
495 hr
= IUnknown_QueryInterface(reader_input
, &IID_ISequentialStream
, (void**)&stream2
);
496 ok(hr
== E_NOINTERFACE
, "Expected S_OK, got %08x\n", hr
);
498 /* IXmlReaderInput grabs a stream reference */
499 ref
= IStream_AddRef(stream
);
500 ok(ref
== 3, "Expected 3, got %d\n", ref
);
501 IStream_Release(stream
);
503 /* try ::SetInput() with valid IXmlReaderInput */
504 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
505 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
507 ref
= IUnknown_AddRef(reader_input
);
508 ok(ref
== 2, "Expected 2, got %d\n", ref
);
509 IUnknown_Release(reader_input
);
511 hr
= IXmlReader_SetInput(reader
, reader_input
);
512 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
514 test_read_state(reader
, XmlReadState_Initial
, -1, FALSE
);
516 nodetype
= XmlNodeType_Element
;
517 hr
= IXmlReader_GetNodeType(reader
, &nodetype
);
518 ok(hr
== S_OK
, "got %08x\n", hr
);
519 ok(nodetype
== XmlNodeType_None
, "got %d\n", nodetype
);
521 /* IXmlReader grabs a IXmlReaderInput reference */
522 ref
= IUnknown_AddRef(reader_input
);
523 ok(ref
== 3, "Expected 3, got %d\n", ref
);
524 IUnknown_Release(reader_input
);
526 ref
= IStream_AddRef(stream
);
527 ok(ref
== 4, "Expected 4, got %d\n", ref
);
528 IStream_Release(stream
);
530 /* reset input and check state */
531 hr
= IXmlReader_SetInput(reader
, NULL
);
532 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
534 test_read_state(reader
, XmlReadState_Initial
, XmlReadState_Closed
, FALSE
);
536 IXmlReader_Release(reader
);
538 ref
= IStream_AddRef(stream
);
539 ok(ref
== 3, "Expected 3, got %d\n", ref
);
540 IStream_Release(stream
);
542 ref
= IUnknown_AddRef(reader_input
);
543 ok(ref
== 2, "Expected 2, got %d\n", ref
);
544 IUnknown_Release(reader_input
);
546 /* IID_IXmlReaderInput */
547 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
548 so it's not a COM interface actually.
549 Such query will be used only to check if input is really IXmlReaderInput */
550 obj
= (IUnknown
*)0xdeadbeef;
551 hr
= IUnknown_QueryInterface(reader_input
, &IID_IXmlReaderInput
, (void**)&obj
);
552 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
553 ref
= IUnknown_AddRef(reader_input
);
554 ok(ref
== 3, "Expected 3, got %d\n", ref
);
555 IUnknown_Release(reader_input
);
557 IUnknown_Release(reader_input
);
558 IUnknown_Release(reader_input
);
559 IStream_Release(stream
);
561 /* test input interface selection sequence */
563 hr
= testinput_createinstance((void**)&input
);
564 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
566 input_iids
.count
= 0;
567 ref
= IUnknown_AddRef(input
);
568 ok(ref
== 2, "Expected 2, got %d\n", ref
);
569 IUnknown_Release(input
);
570 hr
= pCreateXmlReaderInputWithEncodingName(input
, NULL
, NULL
, FALSE
, NULL
, &reader_input
);
571 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
572 ok_iids(&input_iids
, empty_seq
, NULL
, FALSE
);
573 /* IXmlReaderInput stores stream interface as IUnknown */
574 ref
= IUnknown_AddRef(input
);
575 ok(ref
== 3, "Expected 3, got %d\n", ref
);
576 IUnknown_Release(input
);
578 hr
= pCreateXmlReader(&IID_IXmlReader
, (LPVOID
*)&reader
, NULL
);
579 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
581 input_iids
.count
= 0;
582 ref
= IUnknown_AddRef(reader_input
);
583 ok(ref
== 2, "Expected 2, got %d\n", ref
);
584 IUnknown_Release(reader_input
);
585 ref
= IUnknown_AddRef(input
);
586 ok(ref
== 3, "Expected 3, got %d\n", ref
);
587 IUnknown_Release(input
);
588 hr
= IXmlReader_SetInput(reader
, reader_input
);
589 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
590 ok_iids(&input_iids
, setinput_readerinput
, NULL
, FALSE
);
592 test_read_state(reader
, XmlReadState_Closed
, -1, FALSE
);
594 ref
= IUnknown_AddRef(input
);
595 ok(ref
== 3, "Expected 3, got %d\n", ref
);
596 IUnknown_Release(input
);
598 ref
= IUnknown_AddRef(reader_input
);
599 ok(ref
== 3 || broken(ref
== 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
600 "Expected 3, got %d\n", ref
);
601 IUnknown_Release(reader_input
);
602 /* repeat another time, no check or caching here */
603 input_iids
.count
= 0;
604 hr
= IXmlReader_SetInput(reader
, reader_input
);
605 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
606 ok_iids(&input_iids
, setinput_readerinput
, NULL
, FALSE
);
609 hr
= pCreateXmlReader(&IID_IXmlReader
, (LPVOID
*)&reader2
, NULL
);
610 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
612 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
613 ::SetInput() level, each time it's called */
614 input_iids
.count
= 0;
615 hr
= IXmlReader_SetInput(reader2
, reader_input
);
616 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
617 ok_iids(&input_iids
, setinput_readerinput
, NULL
, FALSE
);
619 IXmlReader_Release(reader2
);
620 IXmlReader_Release(reader
);
622 IUnknown_Release(reader_input
);
623 IUnknown_Release(input
);
626 static void test_reader_state(void)
629 XmlNodeType nodetype
;
632 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
633 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
635 /* invalid arguments */
636 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_ReadState
, NULL
);
637 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
639 /* attempt to read on closed reader */
640 test_read_state(reader
, XmlReadState_Closed
, -1, FALSE
);
643 /* newer versions crash here, probably cause no input was set */
644 hr
= IXmlReader_Read(reader
, &nodetype
);
645 ok(hr
== S_FALSE
, "got %08x\n", hr
);
647 IXmlReader_Release(reader
);
650 static void test_read_xmldeclaration(void)
652 static const WCHAR xmlW
[] = {'x','m','l',0};
653 static const WCHAR RegistrationInfoW
[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0};
660 { {'v','e','r','s','i','o','n',0}, {'1','.','0',0} },
661 { {'e','n','c','o','d','i','n','g',0}, {'U','T','F','-','8',0} },
662 { {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
668 UINT count
= 0, len
, i
;
672 hr
= pCreateXmlReader(&IID_IXmlReader
, (LPVOID
*)&reader
, NULL
);
673 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
675 /* position methods with Null args */
676 hr
= IXmlReader_GetLineNumber(reader
, NULL
);
677 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
679 hr
= IXmlReader_GetLinePosition(reader
, NULL
);
680 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
682 stream
= create_stream_on_data(xmldecl_full
, sizeof(xmldecl_full
));
684 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
685 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
687 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
688 ok(hr
== S_OK
, "got %08x\n", hr
);
689 ok(count
== 0, "got %d\n", count
);
691 /* try to move without attributes */
692 hr
= IXmlReader_MoveToElement(reader
);
693 ok(hr
== S_FALSE
, "got %08x\n", hr
);
695 hr
= IXmlReader_MoveToNextAttribute(reader
);
696 ok(hr
== S_FALSE
, "got %08x\n", hr
);
698 hr
= IXmlReader_MoveToFirstAttribute(reader
);
699 ok(hr
== S_FALSE
, "got %08x\n", hr
);
701 ok_pos(reader
, 0, 0, -1, -1, FALSE
);
704 hr
= IXmlReader_Read(reader
, &type
);
705 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
706 ok(type
== XmlNodeType_XmlDeclaration
,
707 "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type
));
708 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
709 ok_pos(reader
, 1, 3, -1, 55, TRUE
);
710 test_read_state(reader
, XmlReadState_Interactive
, -1, FALSE
);
712 hr
= IXmlReader_GetValue(reader
, &val
, NULL
);
713 ok(hr
== S_OK
, "got %08x\n", hr
);
714 ok(*val
== 0, "got %s\n", wine_dbgstr_w(val
));
716 /* check attributes */
717 hr
= IXmlReader_MoveToNextAttribute(reader
);
718 ok(hr
== S_OK
, "got %08x\n", hr
);
720 type
= XmlNodeType_None
;
721 hr
= IXmlReader_GetNodeType(reader
, &type
);
722 ok(hr
== S_OK
, "got %08x\n", hr
);
723 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
725 ok_pos(reader
, 1, 7, -1, 55, TRUE
);
727 /* try to move from last attribute */
728 hr
= IXmlReader_MoveToNextAttribute(reader
);
729 ok(hr
== S_OK
, "got %08x\n", hr
);
730 hr
= IXmlReader_MoveToNextAttribute(reader
);
731 ok(hr
== S_OK
, "got %08x\n", hr
);
732 hr
= IXmlReader_MoveToNextAttribute(reader
);
733 ok(hr
== S_FALSE
, "got %08x\n", hr
);
735 type
= XmlNodeType_None
;
736 hr
= IXmlReader_GetNodeType(reader
, &type
);
737 ok(hr
== S_OK
, "got %08x\n", hr
);
738 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
740 hr
= IXmlReader_MoveToFirstAttribute(reader
);
741 ok(hr
== S_OK
, "got %08x\n", hr
);
742 ok_pos(reader
, 1, 7, -1, 55, TRUE
);
744 hr
= IXmlReader_GetAttributeCount(reader
, NULL
);
745 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
747 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
748 ok(hr
== S_OK
, "got %08x\n", hr
);
749 ok(count
== 3, "Expected 3, got %d\n", count
);
751 for (i
= 0; i
< count
; i
++)
754 hr
= IXmlReader_GetLocalName(reader
, &val
, &len
);
755 ok(hr
== S_OK
, "got %08x\n", hr
);
756 ok(len
== lstrlenW(name_val
[i
].name
), "expected %u, got %u\n", lstrlenW(name_val
[i
].name
), len
);
757 ok(!lstrcmpW(name_val
[i
].name
, val
), "expected %s, got %s\n", wine_dbgstr_w(name_val
[i
].name
), wine_dbgstr_w(val
));
760 hr
= IXmlReader_GetValue(reader
, &val
, &len
);
761 ok(hr
== S_OK
, "got %08x\n", hr
);
762 ok(len
== lstrlenW(name_val
[i
].val
), "expected %u, got %u\n", lstrlenW(name_val
[i
].val
), len
);
763 ok(!lstrcmpW(name_val
[i
].val
, val
), "expected %s, got %s\n", wine_dbgstr_w(name_val
[i
].val
), wine_dbgstr_w(val
));
765 hr
= IXmlReader_MoveToNextAttribute(reader
);
766 ok(hr
== ((i
< count
- 1) ? S_OK
: S_FALSE
), "got %08x\n", hr
);
769 hr
= IXmlReader_GetDepth(reader
, &count
);
770 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
771 ok(count
== 1, "Expected 1, got %d\n", count
);
773 hr
= IXmlReader_MoveToElement(reader
);
774 ok(hr
== S_OK
, "got %08x\n", hr
);
776 type
= XmlNodeType_None
;
777 hr
= IXmlReader_GetNodeType(reader
, &type
);
778 ok(hr
== S_OK
, "got %08x\n", hr
);
779 ok(type
== XmlNodeType_XmlDeclaration
, "got %d\n", type
);
781 type
= XmlNodeType_XmlDeclaration
;
782 hr
= IXmlReader_Read(reader
, &type
);
783 /* newer versions return syntax error here cause document is incomplete,
784 it makes more sense than invalid char error */
786 ok(hr
== WC_E_SYNTAX
|| broken(hr
== WC_E_XMLCHARACTER
), "got 0x%08x\n", hr
);
787 ok(type
== XmlNodeType_None
, "got %d\n", type
);
789 IStream_Release(stream
);
791 /* test short variant */
792 stream
= create_stream_on_data(xmldecl_short
, sizeof(xmldecl_short
));
794 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
795 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
798 hr
= IXmlReader_Read(reader
, &type
);
799 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
800 ok(type
== XmlNodeType_XmlDeclaration
, "expected XmlDeclaration, got %s\n", type_to_str(type
));
801 ok_pos(reader
, 1, 3, 1, 21, TRUE
);
802 test_read_state(reader
, XmlReadState_Interactive
, -1, TRUE
);
804 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
805 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
806 ok(count
== 1, "expected 1, got %d\n", count
);
808 ret
= IXmlReader_IsEmptyElement(reader
);
809 ok(!ret
, "element should not be empty\n");
811 hr
= IXmlReader_GetValue(reader
, &val
, NULL
);
812 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
813 ok(*val
== 0, "got %s\n", wine_dbgstr_w(val
));
815 hr
= IXmlReader_GetLocalName(reader
, &val
, NULL
);
816 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
818 ok(!lstrcmpW(val
, xmlW
), "got %s\n", wine_dbgstr_w(val
));
820 /* check attributes */
821 hr
= IXmlReader_MoveToNextAttribute(reader
);
822 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
825 hr
= IXmlReader_GetNodeType(reader
, &type
);
826 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
827 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
828 ok_pos(reader
, 1, 7, 1, 21, TRUE
);
830 /* try to move from last attribute */
831 hr
= IXmlReader_MoveToNextAttribute(reader
);
832 ok(hr
== S_FALSE
, "expected S_FALSE, got %08x\n", hr
);
835 hr
= IXmlReader_Read(reader
, &type
);
836 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
837 ok(type
== XmlNodeType_Element
, "expected Element, got %s\n", type_to_str(type
));
838 ok_pos(reader
, 1, 23, 1, 40, TRUE
);
839 test_read_state(reader
, XmlReadState_Interactive
, -1, TRUE
);
841 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
842 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
843 ok(count
== 0, "expected 0, got %d\n", count
);
845 ret
= IXmlReader_IsEmptyElement(reader
);
846 ok(ret
, "element should be empty\n");
848 hr
= IXmlReader_GetValue(reader
, &val
, NULL
);
849 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
851 ok(*val
== 0, "got %s\n", wine_dbgstr_w(val
));
853 hr
= IXmlReader_GetLocalName(reader
, &val
, NULL
);
854 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
855 ok(!lstrcmpW(val
, RegistrationInfoW
), "got %s\n", wine_dbgstr_w(val
));
858 hr
= IXmlReader_Read(reader
, &type
);
860 ok(hr
== WC_E_SYNTAX
|| hr
== WC_E_XMLCHARACTER
/* XP */, "expected WC_E_SYNTAX, got %08x\n", hr
);
862 ok(type
== XmlNodeType_None
, "expected None, got %s\n", type_to_str(type
));
863 ok_pos(reader
, 1, 41, -1, -1, TRUE
);
864 test_read_state(reader
, XmlReadState_Error
, -1, TRUE
);
866 IStream_Release(stream
);
867 IXmlReader_Release(reader
);
875 HRESULT hr_broken
; /* this is set to older version results */
879 static struct test_entry comment_tests
[] = {
880 { "<!-- comment -->", "", " comment ", S_OK
},
881 { "<!-- - comment-->", "", " - comment", S_OK
},
882 { "<!-- -- comment-->", NULL
, NULL
, WC_E_COMMENT
, WC_E_GREATERTHAN
},
883 { "<!-- -- comment--->", NULL
, NULL
, WC_E_COMMENT
, WC_E_GREATERTHAN
},
887 static void test_read_comment(void)
889 struct test_entry
*test
= comment_tests
;
893 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
894 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
901 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
902 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
903 ok(hr
== S_OK
, "got %08x\n", hr
);
905 type
= XmlNodeType_None
;
906 hr
= IXmlReader_Read(reader
, &type
);
908 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
910 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
917 ok(type
== XmlNodeType_Comment
, "got %d for %s\n", type
, test
->xml
);
921 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
923 ok(len
== strlen(test
->name
), "got %u\n", len
);
924 str_exp
= a2w(test
->name
);
925 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
930 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
932 ok(len
== strlen(test
->name
), "got %u\n", len
);
933 str_exp
= a2w(test
->name
);
934 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
940 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
941 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
942 ok(len
== strlen(test
->value
), "got %u\n", len
);
943 str_exp
= a2w(test
->value
);
944 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
948 IStream_Release(stream
);
952 IXmlReader_Release(reader
);
955 static struct test_entry pi_tests
[] = {
956 { "<?pi?>", "pi", "", S_OK
},
957 { "<?pi ?>", "pi", "", S_OK
},
958 { "<?pi ?>", "pi", "", S_OK
},
959 { "<?pi pi data?>", "pi", "pi data", S_OK
},
960 { "<?pi pi data ?>", "pi", "pi data ", S_OK
},
961 { "<?pi data ?>", "pi", "data ", S_OK
},
962 { "<?pi:pi?>", NULL
, NULL
, NC_E_NAMECOLON
, WC_E_NAMECHARACTER
},
963 { "<?:pi ?>", NULL
, NULL
, WC_E_PI
, WC_E_NAMECHARACTER
},
964 { "<?-pi ?>", NULL
, NULL
, WC_E_PI
, WC_E_NAMECHARACTER
},
965 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK
},
969 static void test_read_pi(void)
971 struct test_entry
*test
= pi_tests
;
975 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
976 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
983 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
984 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
985 ok(hr
== S_OK
, "got %08x\n", hr
);
987 type
= XmlNodeType_None
;
988 hr
= IXmlReader_Read(reader
, &type
);
990 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
992 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
999 ok(type
== XmlNodeType_ProcessingInstruction
, "got %d for %s\n", type
, test
->xml
);
1003 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
1004 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1005 ok(len
== strlen(test
->name
), "got %u\n", len
);
1006 str_exp
= a2w(test
->name
);
1007 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1012 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1013 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1014 ok(len
== strlen(test
->name
), "got %u\n", len
);
1015 str_exp
= a2w(test
->name
);
1016 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1020 len
= !strlen(test
->value
);
1022 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
1023 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1024 ok(len
== strlen(test
->value
), "got %u\n", len
);
1025 str_exp
= a2w(test
->value
);
1026 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1030 IStream_Release(stream
);
1034 IXmlReader_Release(reader
);
1039 XmlNodeType types
[20];
1042 static const char misc_test_xml
[] =
1060 static struct nodes_test misc_test
= {
1063 XmlNodeType_Comment
,
1064 XmlNodeType_Comment
,
1065 XmlNodeType_ProcessingInstruction
,
1066 XmlNodeType_Comment
,
1067 XmlNodeType_Whitespace
,
1068 XmlNodeType_Comment
,
1069 XmlNodeType_Element
,
1070 XmlNodeType_Whitespace
,
1071 XmlNodeType_Element
,
1073 XmlNodeType_Comment
,
1075 XmlNodeType_ProcessingInstruction
,
1076 XmlNodeType_Whitespace
,
1077 XmlNodeType_EndElement
,
1082 static void test_read_full(void)
1084 struct nodes_test
*test
= &misc_test
;
1091 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1092 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1094 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
1095 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1096 ok(hr
== S_OK
, "got %08x\n", hr
);
1099 type
= XmlNodeType_None
;
1100 hr
= IXmlReader_Read(reader
, &type
);
1103 ok(test
->types
[i
] != XmlNodeType_None
, "%d: unexpected end of test data\n", i
);
1104 if (test
->types
[i
] == XmlNodeType_None
) break;
1105 ok(type
== test
->types
[i
], "%d: got wrong type %d, expected %d\n", i
, type
, test
->types
[i
]);
1106 if (type
== XmlNodeType_Whitespace
)
1111 hr
= IXmlReader_GetValue(reader
, &ptr
, &len
);
1112 ok(hr
== S_OK
, "%d: GetValue failed 0x%08x\n", i
, hr
);
1113 ok(len
> 0, "%d: wrong value length %d\n", i
, len
);
1115 hr
= IXmlReader_Read(reader
, &type
);
1118 ok(test
->types
[i
] == XmlNodeType_None
, "incomplete sequence, got %d\n", test
->types
[i
]);
1120 IStream_Release(stream
);
1121 IXmlReader_Release(reader
);
1124 static const char test_dtd
[] =
1125 "<!DOCTYPE testdtd SYSTEM \"externalid uri\" >"
1128 static void test_read_dtd(void)
1130 static const WCHAR sysvalW
[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0};
1131 static const WCHAR dtdnameW
[] = {'t','e','s','t','d','t','d',0};
1132 static const WCHAR sysW
[] = {'S','Y','S','T','E','M',0};
1140 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1141 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1143 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, DtdProcessing_Parse
);
1144 ok(hr
== S_OK
, "got 0x%8x\n", hr
);
1146 stream
= create_stream_on_data(test_dtd
, sizeof(test_dtd
));
1147 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1148 ok(hr
== S_OK
, "got %08x\n", hr
);
1150 type
= XmlNodeType_None
;
1151 hr
= IXmlReader_Read(reader
, &type
);
1152 ok(hr
== S_OK
, "got 0x%8x\n", hr
);
1153 ok(type
== XmlNodeType_DocumentType
, "got type %d\n", type
);
1156 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
1157 ok(hr
== S_OK
, "got %08x\n", hr
);
1158 ok(count
== 1, "got %d\n", count
);
1160 hr
= IXmlReader_MoveToFirstAttribute(reader
);
1161 ok(hr
== S_OK
, "got %08x\n", hr
);
1163 type
= XmlNodeType_None
;
1164 hr
= IXmlReader_GetNodeType(reader
, &type
);
1165 ok(hr
== S_OK
, "got %08x\n", hr
);
1166 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
1170 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
1171 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1172 ok(len
== lstrlenW(sysW
), "got %u\n", len
);
1173 ok(!lstrcmpW(str
, sysW
), "got %s\n", wine_dbgstr_w(str
));
1177 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
1178 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1179 ok(len
== lstrlenW(sysvalW
), "got %u\n", len
);
1180 ok(!lstrcmpW(str
, sysvalW
), "got %s\n", wine_dbgstr_w(str
));
1182 hr
= IXmlReader_MoveToElement(reader
);
1183 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1187 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
1188 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1190 ok(len
== lstrlenW(dtdnameW
), "got %u\n", len
);
1191 ok(!lstrcmpW(str
, dtdnameW
), "got %s\n", wine_dbgstr_w(str
));
1195 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1196 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1197 ok(len
== lstrlenW(dtdnameW
), "got %u\n", len
);
1198 ok(!lstrcmpW(str
, dtdnameW
), "got %s\n", wine_dbgstr_w(str
));
1200 type
= XmlNodeType_None
;
1201 hr
= IXmlReader_Read(reader
, &type
);
1202 ok(hr
== S_OK
, "got 0x%8x\n", hr
);
1203 ok(type
== XmlNodeType_Comment
, "got type %d\n", type
);
1205 IStream_Release(stream
);
1206 IXmlReader_Release(reader
);
1209 static struct test_entry element_tests
[] = {
1210 { "<a/>", "a", "", S_OK
},
1211 { "<a />", "a", "", S_OK
},
1212 { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX
},
1213 { "<:a/>", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1214 { "< a/>", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1215 { "<a>", "a", "", S_OK
},
1216 { "<a >", "a", "", S_OK
},
1217 { "<a \r \t\n>", "a", "", S_OK
},
1218 { "</a>", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1222 static void test_read_element(void)
1224 struct test_entry
*test
= element_tests
;
1225 static const char stag
[] = "<a><b></b></a>";
1226 static const char mismatch
[] = "<a></b>";
1233 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1234 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1238 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
1239 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1240 ok(hr
== S_OK
, "got %08x\n", hr
);
1242 type
= XmlNodeType_None
;
1243 hr
= IXmlReader_Read(reader
, &type
);
1244 if (test
->hr_broken
)
1245 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1247 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1254 ok(type
== XmlNodeType_Element
, "got %d for %s\n", type
, test
->xml
);
1258 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1259 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1260 ok(len
== strlen(test
->name
), "got %u\n", len
);
1261 str_exp
= a2w(test
->name
);
1262 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1268 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
1269 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1270 ok(len
== 0, "got %u\n", len
);
1271 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1274 IStream_Release(stream
);
1278 /* test reader depth increment */
1279 stream
= create_stream_on_data(stag
, sizeof(stag
));
1280 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1281 ok(hr
== S_OK
, "got %08x\n", hr
);
1284 hr
= IXmlReader_GetDepth(reader
, &depth
);
1285 ok(hr
== S_OK
, "got %08x\n", hr
);
1286 ok(depth
== 0, "got %d\n", depth
);
1288 type
= XmlNodeType_None
;
1289 hr
= IXmlReader_Read(reader
, &type
);
1290 ok(hr
== S_OK
, "got %08x\n", hr
);
1291 ok(type
== XmlNodeType_Element
, "got %d\n", type
);
1294 hr
= IXmlReader_GetDepth(reader
, &depth
);
1295 ok(hr
== S_OK
, "got %08x\n", hr
);
1296 ok(depth
== 0, "got %d\n", depth
);
1298 type
= XmlNodeType_None
;
1299 hr
= IXmlReader_Read(reader
, &type
);
1300 ok(hr
== S_OK
, "got %08x\n", hr
);
1301 ok(type
== XmlNodeType_Element
, "got %d\n", type
);
1304 hr
= IXmlReader_GetDepth(reader
, &depth
);
1305 ok(hr
== S_OK
, "got %08x\n", hr
);
1306 ok(depth
== 1, "got %d\n", depth
);
1308 /* read end tag for inner element */
1309 type
= XmlNodeType_None
;
1310 hr
= IXmlReader_Read(reader
, &type
);
1311 ok(hr
== S_OK
, "got %08x\n", hr
);
1312 ok(type
== XmlNodeType_EndElement
, "got %d\n", type
);
1315 hr
= IXmlReader_GetDepth(reader
, &depth
);
1316 ok(hr
== S_OK
, "got %08x\n", hr
);
1318 ok(depth
== 2, "got %d\n", depth
);
1320 /* read end tag for container element */
1321 type
= XmlNodeType_None
;
1322 hr
= IXmlReader_Read(reader
, &type
);
1323 ok(hr
== S_OK
, "got %08x\n", hr
);
1324 ok(type
== XmlNodeType_EndElement
, "got %d\n", type
);
1327 hr
= IXmlReader_GetDepth(reader
, &depth
);
1328 ok(hr
== S_OK
, "got %08x\n", hr
);
1329 ok(depth
== 1, "got %d\n", depth
);
1331 IStream_Release(stream
);
1333 /* start/end tag mismatch */
1334 stream
= create_stream_on_data(mismatch
, sizeof(mismatch
));
1335 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1336 ok(hr
== S_OK
, "got %08x\n", hr
);
1338 type
= XmlNodeType_None
;
1339 hr
= IXmlReader_Read(reader
, &type
);
1340 ok(hr
== S_OK
, "got %08x\n", hr
);
1341 ok(type
== XmlNodeType_Element
, "got %d\n", type
);
1343 type
= XmlNodeType_Element
;
1344 hr
= IXmlReader_Read(reader
, &type
);
1345 ok(hr
== WC_E_ELEMENTMATCH
, "got %08x\n", hr
);
1347 ok(type
== XmlNodeType_None
, "got %d\n", type
);
1349 IStream_Release(stream
);
1351 IXmlReader_Release(reader
);
1354 static ISequentialStream teststream
= { &teststreamvtbl
};
1356 static void test_read_pending(void)
1364 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1365 ok(hr
== S_OK
, "S_OK, got 0x%08x\n", hr
);
1367 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)&teststream
);
1368 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1370 /* first read call returns incomplete node, second attempt fails with E_PENDING */
1371 stream_readcall
= 0;
1372 type
= XmlNodeType_Element
;
1373 hr
= IXmlReader_Read(reader
, &type
);
1374 ok(hr
== S_OK
|| broken(hr
== E_PENDING
), "got 0x%08x\n", hr
);
1375 /* newer versions are happy when it's enough data to detect node type,
1376 older versions keep reading until it fails to read more */
1377 ok(stream_readcall
== 1 || broken(stream_readcall
> 1), "got %d\n", stream_readcall
);
1378 ok(type
== XmlNodeType_Comment
|| broken(type
== XmlNodeType_None
), "got %d\n", type
);
1380 /* newer versions' GetValue() makes an attempt to read more */
1381 c
= stream_readcall
;
1382 value
= (void*)0xdeadbeef;
1383 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
1384 ok(hr
== E_PENDING
, "got 0x%08x\n", hr
);
1385 ok(value
== NULL
|| broken(value
== (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value
);
1386 ok(c
< stream_readcall
|| broken(c
== stream_readcall
), "got %d, expected %d\n", stream_readcall
, c
+1);
1388 IXmlReader_Release(reader
);
1391 static void test_readvaluechunk(void)
1393 static const char testA
[] = "<!-- comment1 -->";
1402 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1403 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1405 stream
= create_stream_on_data(testA
, sizeof(testA
));
1406 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1407 ok(hr
== S_OK
, "got %08x\n", hr
);
1409 hr
= IXmlReader_Read(reader
, &type
);
1410 ok(hr
== S_OK
, "got %08x\n", hr
);
1414 hr
= IXmlReader_ReadValueChunk(reader
, &b
, 1, &c
);
1415 ok(hr
== S_OK
, "got %08x\n", hr
);
1416 ok(c
== 1, "got %u\n", c
);
1417 ok(b
== ' ', "got %x\n", b
);
1419 /* portion read as chunk is skipped from resulting node value */
1421 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
1422 ok(hr
== S_OK
, "got %08x\n", hr
);
1423 ok(value
[0] == 'c', "got %s\n", wine_dbgstr_w(value
));
1425 /* once value is returned/allocated it's not possible to read by chunk */
1428 hr
= IXmlReader_ReadValueChunk(reader
, &b
, 1, &c
);
1429 ok(hr
== S_FALSE
, "got %08x\n", hr
);
1430 ok(c
== 0, "got %u\n", c
);
1431 ok(b
== 0, "got %x\n", b
);
1434 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
1435 ok(hr
== S_OK
, "got %08x\n", hr
);
1436 ok(value
[0] == 'c', "got %s\n", wine_dbgstr_w(value
));
1438 IXmlReader_Release(reader
);
1441 static struct test_entry cdata_tests
[] = {
1442 { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK
},
1443 { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK
},
1444 { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK
, S_OK
, TRUE
},
1445 { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK
, S_OK
, TRUE
},
1446 { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK
},
1450 static void test_read_cdata(void)
1452 struct test_entry
*test
= cdata_tests
;
1456 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1457 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1464 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
1465 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1466 ok(hr
== S_OK
, "got %08x\n", hr
);
1468 type
= XmlNodeType_None
;
1469 hr
= IXmlReader_Read(reader
, &type
);
1471 /* read one more to get to CDATA */
1472 if (type
== XmlNodeType_Element
)
1474 type
= XmlNodeType_None
;
1475 hr
= IXmlReader_Read(reader
, &type
);
1478 if (test
->hr_broken
)
1479 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1481 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1488 ok(type
== XmlNodeType_CDATA
, "got %d for %s\n", type
, test
->xml
);
1490 str_exp
= a2w(test
->name
);
1494 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
1495 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1496 ok(len
== strlen(test
->name
), "got %u\n", len
);
1497 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1500 hr
= IXmlReader_GetLocalName(reader
, &str
, NULL
);
1501 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1502 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1508 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1509 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1510 ok(len
== strlen(test
->name
), "got %u\n", len
);
1511 str_exp
= a2w(test
->name
);
1512 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1518 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
1519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1521 str_exp
= a2w(test
->value
);
1525 ok(len
== strlen(test
->value
), "got %u\n", len
);
1526 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1531 ok(len
== strlen(test
->value
), "got %u\n", len
);
1532 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1537 IStream_Release(stream
);
1541 IXmlReader_Release(reader
);
1544 static struct test_entry text_tests
[] = {
1545 { "<a>simple text</a>", "", "simple text", S_OK
},
1546 { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND
},
1550 static void test_read_text(void)
1552 struct test_entry
*test
= text_tests
;
1556 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1557 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1564 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
1565 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1566 ok(hr
== S_OK
, "got %08x\n", hr
);
1568 type
= XmlNodeType_None
;
1569 hr
= IXmlReader_Read(reader
, &type
);
1571 /* read one more to get to CDATA */
1572 if (type
== XmlNodeType_Element
)
1574 type
= XmlNodeType_None
;
1575 hr
= IXmlReader_Read(reader
, &type
);
1578 if (test
->hr_broken
)
1579 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1581 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1588 ok(type
== XmlNodeType_Text
, "got %d for %s\n", type
, test
->xml
);
1590 str_exp
= a2w(test
->name
);
1594 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
1595 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1596 ok(len
== strlen(test
->name
), "got %u\n", len
);
1597 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1600 hr
= IXmlReader_GetLocalName(reader
, &str
, NULL
);
1601 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1602 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1608 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1609 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1610 ok(len
== strlen(test
->name
), "got %u\n", len
);
1611 str_exp
= a2w(test
->name
);
1612 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1618 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
1619 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1621 str_exp
= a2w(test
->value
);
1625 ok(len
== strlen(test
->value
), "got %u\n", len
);
1626 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1631 ok(len
== strlen(test
->value
), "got %u\n", len
);
1632 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1637 IStream_Release(stream
);
1641 IXmlReader_Release(reader
);
1644 struct test_entry_empty
{
1649 static struct test_entry_empty empty_element_tests
[] = {
1650 { "<a></a>", FALSE
},
1655 static void test_isemptyelement(void)
1657 struct test_entry_empty
*test
= empty_element_tests
;
1661 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1662 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1670 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
1671 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1672 ok(hr
== S_OK
, "got %08x\n", hr
);
1674 type
= XmlNodeType_None
;
1675 hr
= IXmlReader_Read(reader
, &type
);
1676 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1677 ok(type
== XmlNodeType_Element
, "got %d\n", type
);
1679 ret
= IXmlReader_IsEmptyElement(reader
);
1680 ok(ret
== test
->empty
, "got %d, expected %d. xml=%s\n", ret
, test
->empty
, test
->xml
);
1682 IStream_Release(stream
);
1686 IXmlReader_Release(reader
);
1689 static struct test_entry attributes_tests
[] = {
1690 { "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK
},
1691 { "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK
},
1692 { "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK
},
1693 { "<a attr1=\' \'/>", "attr1", " ", S_OK
},
1694 { "<a attr1=\" \"/>", "attr1", " ", S_OK
},
1695 { "<a attr1=\"\r\n \r \n \t\n\r\"/>", "attr1", " ", S_OK
},
1696 { "<a attr1=\" val \"/>", "attr1", " val ", S_OK
},
1697 { "<a attr1=\"\r\n\tval\n\"/>", "attr1", " val ", S_OK
},
1698 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK
},
1699 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK
},
1700 { "<a attr1=\"<>&'"\"/>", "attr1", "<>&\'\"", S_OK
},
1701 { "<a attr1=\"&entname;\"/>", NULL
, NULL
, WC_E_UNDECLAREDENTITY
},
1702 { "<a attr1=\"val\"/>", NULL
, NULL
, WC_E_XMLCHARACTER
},
1703 { "<a attr1=\"val &#a;\"/>", NULL
, NULL
, WC_E_DIGIT
, WC_E_SEMICOLON
},
1704 { "<a attr1=\"val a;\"/>", NULL
, NULL
, WC_E_SEMICOLON
},
1705 { "<a attr1=\"val g;\"/>", NULL
, NULL
, WC_E_SEMICOLON
},
1706 { "<a attr1=\"val &#xg;\"/>", NULL
, NULL
, WC_E_HEXDIGIT
, WC_E_SEMICOLON
},
1707 { "<a attr1=attrvalue/>", NULL
, NULL
, WC_E_QUOTE
},
1708 { "<a attr1=\"attr<value\"/>", NULL
, NULL
, WC_E_LESSTHAN
},
1709 { "<a attr1=\"&entname\"/>", NULL
, NULL
, WC_E_SEMICOLON
},
1713 static void test_read_attribute(void)
1715 struct test_entry
*test
= attributes_tests
;
1719 hr
= pCreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1720 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1727 stream
= create_stream_on_data(test
->xml
, strlen(test
->xml
)+1);
1728 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
1729 ok(hr
== S_OK
, "got %08x\n", hr
);
1731 type
= XmlNodeType_None
;
1732 hr
= IXmlReader_Read(reader
, &type
);
1734 if (test
->hr_broken
)
1735 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1737 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1744 ok(type
== XmlNodeType_Element
, "got %d for %s\n", type
, test
->xml
);
1746 hr
= IXmlReader_MoveToFirstAttribute(reader
);
1747 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1751 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
1752 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1753 ok(len
== strlen(test
->name
), "got %u\n", len
);
1754 str_exp
= a2w(test
->name
);
1755 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1760 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1761 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1763 ok(len
== strlen(test
->name
), "got %u\n", len
);
1764 str_exp
= a2w(test
->name
);
1765 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1771 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
1772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1773 ok(len
== strlen(test
->value
), "got %u\n", len
);
1774 str_exp
= a2w(test
->value
);
1775 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1779 IStream_Release(stream
);
1783 IXmlReader_Release(reader
);
1788 if (!init_pointers())
1791 test_reader_create();
1793 test_reader_state();
1794 test_read_attribute();
1796 test_read_comment();
1799 test_read_element();
1800 test_isemptyelement();
1803 test_read_pending();
1804 test_readvaluechunk();
1805 test_read_xmldeclaration();