4 * Copyright 2010, 2012-2013, 2016-2017 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"
33 #include "wine/heap.h"
35 DEFINE_GUID(IID_IXmlReaderInput
, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
37 static WCHAR
*a2w(const char *str
)
39 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
40 WCHAR
*ret
= heap_alloc(len
* sizeof(WCHAR
));
41 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
45 static void free_str(WCHAR
*str
)
50 static int strcmp_wa(const WCHAR
*str1
, const char *stra
)
52 WCHAR
*str2
= a2w(stra
);
53 int r
= lstrcmpW(str1
, str2
);
58 static const char xmldecl_full
[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
59 static const char xmldecl_short
[] = "<?xml version=\"1.0\"?><RegistrationInfo/>";
61 static IStream
*create_stream_on_data(const void *data
, unsigned int size
)
63 IStream
*stream
= NULL
;
68 hglobal
= GlobalAlloc(GHND
, size
);
69 ptr
= GlobalLock(hglobal
);
71 memcpy(ptr
, data
, size
);
73 hr
= CreateStreamOnHGlobal(hglobal
, TRUE
, &stream
);
74 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
75 ok(stream
!= NULL
, "Expected non-NULL stream\n");
77 GlobalUnlock(hglobal
);
82 static void test_reader_pos(IXmlReader
*reader
, UINT line
, UINT pos
, UINT line_broken
,
83 UINT pos_broken
, int _line_
)
85 UINT l
= ~0u, p
= ~0u;
88 IXmlReader_GetLineNumber(reader
, &l
);
89 IXmlReader_GetLinePosition(reader
, &p
);
91 if (line_broken
== ~0u && pos_broken
== ~0u)
94 broken_state
= broken((line_broken
== ~0u ? line
: line_broken
) == l
&&
95 (pos_broken
== ~0u ? pos
: pos_broken
) == p
);
97 ok_(__FILE__
, _line_
)((l
== line
&& pos
== p
) || broken_state
,
98 "Expected (%d,%d), got (%d,%d)\n", line
, pos
, l
, p
);
100 #define TEST_READER_POSITION(reader, line, pos) \
101 test_reader_pos(reader, line, pos, ~0u, ~0u, __LINE__)
102 #define TEST_READER_POSITION2(reader, line, pos, line_broken, pos_broken) \
103 test_reader_pos(reader, line, pos, line_broken, pos_broken, __LINE__)
105 typedef struct input_iids_t
{
110 static const IID
*setinput_full
[] = {
111 &IID_IXmlReaderInput
,
113 &IID_ISequentialStream
,
117 /* this applies to early xmllite versions */
118 static const IID
*setinput_full_old
[] = {
119 &IID_IXmlReaderInput
,
120 &IID_ISequentialStream
,
125 /* after ::SetInput(IXmlReaderInput*) */
126 static const IID
*setinput_readerinput
[] = {
128 &IID_ISequentialStream
,
132 static const IID
*empty_seq
[] = {
136 static input_iids_t input_iids
;
138 static void ok_iids_(const input_iids_t
*iids
, const IID
**expected
, const IID
**exp_broken
, BOOL todo
, int line
)
142 while (expected
[i
++]) size
++;
145 ok_(__FILE__
, line
)(iids
->count
== size
, "Sequence size mismatch (%d), got (%d)\n", size
, iids
->count
);
147 if (iids
->count
!= size
) return;
149 for (i
= 0; i
< size
; i
++) {
150 ok_(__FILE__
, line
)(IsEqualGUID(&iids
->iids
[i
], expected
[i
]) ||
151 (exp_broken
? broken(IsEqualGUID(&iids
->iids
[i
], exp_broken
[i
])) : FALSE
),
152 "Wrong IID(%d), got %s\n", i
, wine_dbgstr_guid(&iids
->iids
[i
]));
155 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
157 static const char *state_to_str(XmlReadState state
)
159 static const char* state_names
[] = {
160 "XmlReadState_Initial",
161 "XmlReadState_Interactive",
162 "XmlReadState_Error",
163 "XmlReadState_EndOfFile",
164 "XmlReadState_Closed"
167 static const char unknown
[] = "unknown";
171 case XmlReadState_Initial
:
172 case XmlReadState_Interactive
:
173 case XmlReadState_Error
:
174 case XmlReadState_EndOfFile
:
175 case XmlReadState_Closed
:
176 return state_names
[state
];
182 static const char *type_to_str(XmlNodeType type
)
184 static const char* type_names
[] = {
186 "XmlNodeType_Element",
187 "XmlNodeType_Attribute",
191 "XmlNodeType_ProcessingInstruction",
192 "XmlNodeType_Comment",
194 "XmlNodeType_DocumentType",
196 "XmlNodeType_Whitespace",
198 "XmlNodeType_EndElement",
200 "XmlNodeType_XmlDeclaration"
203 static const char unknown
[] = "unknown";
207 case XmlNodeType_None
:
208 case XmlNodeType_Element
:
209 case XmlNodeType_Attribute
:
210 case XmlNodeType_Text
:
211 case XmlNodeType_CDATA
:
212 case XmlNodeType_ProcessingInstruction
:
213 case XmlNodeType_Comment
:
214 case XmlNodeType_DocumentType
:
215 case XmlNodeType_Whitespace
:
216 case XmlNodeType_EndElement
:
217 case XmlNodeType_XmlDeclaration
:
218 return type_names
[type
];
224 #define set_input_string(a,b) _set_input_string(__LINE__,a,b);
225 static void _set_input_string(unsigned line
, IXmlReader
*reader
, const char *xml
)
230 stream
= create_stream_on_data(xml
, strlen(xml
));
232 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
233 ok_(__FILE__
,line
)(hr
== S_OK
, "got %08x\n", hr
);
235 IStream_Release(stream
);
238 #define read_node(a,b) _read_node(__LINE__,a,b)
239 static void _read_node(unsigned line
, IXmlReader
*reader
, XmlNodeType expected_type
)
244 hr
= IXmlReader_Read(reader
, &type
);
245 if (expected_type
== XmlNodeType_None
)
246 ok_(__FILE__
,line
)(hr
== S_FALSE
, "Read returned %08x, expected S_FALSE\n", hr
);
248 ok_(__FILE__
,line
)(hr
== S_OK
, "Read returned %08x\n", hr
);
249 ok_(__FILE__
,line
)(type
== expected_type
, "read type %d, expected %d\n", type
, expected_type
);
252 #define next_attribute(a) _next_attribute(__LINE__,a)
253 static void _next_attribute(unsigned line
, IXmlReader
*reader
)
256 hr
= IXmlReader_MoveToNextAttribute(reader
);
257 ok_(__FILE__
,line
)(hr
== S_OK
, "MoveToNextAttribute returned %08x\n", hr
);
260 #define move_to_element(a) _move_to_element(__LINE__,a)
261 static void _move_to_element(unsigned line
, IXmlReader
*reader
)
264 hr
= IXmlReader_MoveToElement(reader
);
265 ok_(__FILE__
,line
)(hr
== S_OK
, "MoveToElement failed: %08x\n", hr
);
268 static void test_read_state(IXmlReader
*reader
, XmlReadState expected
,
269 XmlReadState exp_broken
, int line
)
274 state
= -1; /* invalid state value */
275 IXmlReader_GetProperty(reader
, XmlReaderProperty_ReadState
, &state
);
277 if (exp_broken
== expected
)
278 broken_state
= FALSE
;
280 broken_state
= broken(exp_broken
== state
);
282 ok_(__FILE__
, line
)(state
== expected
|| broken_state
, "Expected (%s), got (%s)\n",
283 state_to_str(expected
), state_to_str(state
));
286 #define TEST_READER_STATE(reader, state) test_read_state(reader, state, state, __LINE__)
287 #define TEST_READER_STATE2(reader, state, brk) test_read_state(reader, state, brk, __LINE__)
289 #define reader_value(a,b) _reader_value(__LINE__,a,b)
290 static const WCHAR
*_reader_value(unsigned line
, IXmlReader
*reader
, const char *expect
)
292 const WCHAR
*str
= (void*)0xdeadbeef;
293 ULONG len
= 0xdeadbeef;
296 hr
= IXmlReader_GetValue(reader
, &str
, &len
);
297 ok_(__FILE__
,line
)(hr
== S_OK
, "GetValue returned %08x\n", hr
);
298 ok_(__FILE__
,line
)(len
== lstrlenW(str
), "len = %u\n", len
);
299 ok_(__FILE__
,line
)(!strcmp_wa(str
, expect
), "value = %s\n", wine_dbgstr_w(str
));
303 #define reader_name(a,b) _reader_name(__LINE__,a,b)
304 static const WCHAR
*_reader_name(unsigned line
, IXmlReader
*reader
, const char *expect
)
306 const WCHAR
*str
= (void*)0xdeadbeef;
307 ULONG len
= 0xdeadbeef;
310 hr
= IXmlReader_GetLocalName(reader
, &str
, &len
);
311 ok_(__FILE__
,line
)(hr
== S_OK
, "GetLocalName returned %08x\n", hr
);
312 ok_(__FILE__
,line
)(len
== lstrlenW(str
), "len = %u\n", len
);
313 ok_(__FILE__
,line
)(!strcmp_wa(str
, expect
), "name = %s\n", wine_dbgstr_w(str
));
317 #define reader_prefix(a,b) _reader_prefix(__LINE__,a,b)
318 static const WCHAR
*_reader_prefix(unsigned line
, IXmlReader
*reader
, const char *expect
)
320 const WCHAR
*str
= (void*)0xdeadbeef;
321 ULONG len
= 0xdeadbeef;
324 hr
= IXmlReader_GetPrefix(reader
, &str
, &len
);
325 ok_(__FILE__
,line
)(hr
== S_OK
, "GetPrefix returned %08x\n", hr
);
326 ok_(__FILE__
,line
)(len
== lstrlenW(str
), "len = %u\n", len
);
327 ok_(__FILE__
,line
)(!strcmp_wa(str
, expect
), "prefix = %s\n", wine_dbgstr_w(str
));
331 #define reader_namespace(a,b) _reader_namespace(__LINE__,a,b)
332 static const WCHAR
*_reader_namespace(unsigned line
, IXmlReader
*reader
, const char *expect
)
334 const WCHAR
*str
= (void*)0xdeadbeef;
335 ULONG len
= 0xdeadbeef;
338 hr
= IXmlReader_GetNamespaceUri(reader
, &str
, &len
);
339 ok_(__FILE__
,line
)(hr
== S_OK
, "GetNamespaceUri returned %08x\n", hr
);
340 ok_(__FILE__
,line
)(len
== lstrlenW(str
), "len = %u\n", len
);
341 ok_(__FILE__
,line
)(!strcmp_wa(str
, expect
), "namespace = %s\n", wine_dbgstr_w(str
));
345 #define reader_qname(a,b) _reader_qname(a,b,__LINE__)
346 static const WCHAR
*_reader_qname(IXmlReader
*reader
, const char *expect
, unsigned line
)
348 const WCHAR
*str
= (void*)0xdeadbeef;
349 ULONG len
= 0xdeadbeef;
352 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
353 ok_(__FILE__
,line
)(hr
== S_OK
, "GetQualifiedName returned %08x\n", hr
);
354 ok_(__FILE__
,line
)(len
== lstrlenW(str
), "len = %u\n", len
);
355 ok_(__FILE__
,line
)(!strcmp_wa(str
, expect
), "name = %s\n", wine_dbgstr_w(str
));
359 #define read_value_char(a,b) _read_value_char(a,b,__LINE__)
360 static void _read_value_char(IXmlReader
*reader
, WCHAR expected_char
, unsigned line
)
366 hr
= IXmlReader_ReadValueChunk(reader
, &c
, 1, &count
);
367 ok_(__FILE__
,line
)(hr
== S_OK
, "got %08x\n", hr
);
368 ok_(__FILE__
,line
)(count
== 1, "got %u\n", c
);
369 ok_(__FILE__
,line
)(c
== expected_char
, "got %x\n", c
);
372 typedef struct _testinput
374 IUnknown IUnknown_iface
;
378 static inline testinput
*impl_from_IUnknown(IUnknown
*iface
)
380 return CONTAINING_RECORD(iface
, testinput
, IUnknown_iface
);
383 static HRESULT WINAPI
testinput_QueryInterface(IUnknown
*iface
, REFIID riid
, void** ppvObj
)
385 if (IsEqualGUID( riid
, &IID_IUnknown
))
388 IUnknown_AddRef(iface
);
392 input_iids
.iids
[input_iids
.count
++] = *riid
;
396 return E_NOINTERFACE
;
399 static ULONG WINAPI
testinput_AddRef(IUnknown
*iface
)
401 testinput
*This
= impl_from_IUnknown(iface
);
402 return InterlockedIncrement(&This
->ref
);
405 static ULONG WINAPI
testinput_Release(IUnknown
*iface
)
407 testinput
*This
= impl_from_IUnknown(iface
);
410 ref
= InterlockedDecrement(&This
->ref
);
417 static const struct IUnknownVtbl testinput_vtbl
=
419 testinput_QueryInterface
,
424 static HRESULT
testinput_createinstance(void **ppObj
)
428 input
= heap_alloc(sizeof(*input
));
429 if(!input
) return E_OUTOFMEMORY
;
431 input
->IUnknown_iface
.lpVtbl
= &testinput_vtbl
;
434 *ppObj
= &input
->IUnknown_iface
;
439 static HRESULT WINAPI
teststream_QueryInterface(ISequentialStream
*iface
, REFIID riid
, void **obj
)
441 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_ISequentialStream
))
448 return E_NOINTERFACE
;
451 static ULONG WINAPI
teststream_AddRef(ISequentialStream
*iface
)
456 static ULONG WINAPI
teststream_Release(ISequentialStream
*iface
)
461 static int stream_readcall
;
463 static HRESULT WINAPI
teststream_Read(ISequentialStream
*iface
, void *pv
, ULONG cb
, ULONG
*pread
)
465 static const char xml
[] = "<!-- comment -->";
467 if (stream_readcall
++)
473 *pread
= sizeof(xml
) / 2;
474 memcpy(pv
, xml
, *pread
);
478 static HRESULT WINAPI
teststream_Write(ISequentialStream
*iface
, const void *pv
, ULONG cb
, ULONG
*written
)
480 ok(0, "unexpected call\n");
484 static const ISequentialStreamVtbl teststreamvtbl
=
486 teststream_QueryInterface
,
493 static HRESULT WINAPI
resolver_QI(IXmlResolver
*iface
, REFIID riid
, void **obj
)
495 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid
));
497 if (IsEqualIID(riid
, &IID_IXmlResolver
) || IsEqualIID(riid
, &IID_IUnknown
))
500 IXmlResolver_AddRef(iface
);
505 return E_NOINTERFACE
;
508 static ULONG WINAPI
resolver_AddRef(IXmlResolver
*iface
)
513 static ULONG WINAPI
resolver_Release(IXmlResolver
*iface
)
518 static HRESULT WINAPI
resolver_ResolveUri(IXmlResolver
*iface
, const WCHAR
*base_uri
,
519 const WCHAR
*public_id
, const WCHAR
*system_id
, IUnknown
**input
)
521 ok(0, "unexpected call\n");
525 static const IXmlResolverVtbl resolvervtbl
=
533 static IXmlResolver testresolver
= { &resolvervtbl
};
535 static void test_reader_create(void)
537 IXmlResolver
*resolver
;
538 IUnknown
*input
, *unk
;
541 XmlNodeType nodetype
;
547 CreateXmlReader(&IID_IXmlReader
, NULL
, NULL
);
548 CreateXmlReader(NULL
, (void**)&reader
, NULL
);
551 hr
= CreateXmlReader(&IID_IStream
, (void **)&unk
, NULL
);
552 ok(hr
== E_NOINTERFACE
, "got %08x\n", hr
);
554 hr
= CreateXmlReader(&IID_IUnknown
, (void **)&unk
, NULL
);
555 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
556 hr
= IUnknown_QueryInterface(unk
, &IID_IXmlReader
, (void **)&reader
);
557 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
558 ok(unk
== (IUnknown
*)reader
, "unexpected interface\n");
559 IXmlReader_Release(reader
);
560 IUnknown_Release(unk
);
562 hr
= CreateXmlReader(&IID_IUnknown
, (void **)&reader
, NULL
);
563 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
564 IXmlReader_Release(reader
);
566 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
567 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
569 TEST_READER_STATE(reader
, XmlReadState_Closed
);
571 nodetype
= XmlNodeType_Element
;
572 hr
= IXmlReader_GetNodeType(reader
, &nodetype
);
573 ok(hr
== S_FALSE
, "got %08x\n", hr
);
574 ok(nodetype
== XmlNodeType_None
, "got %d\n", nodetype
);
576 /* crashes on XP, 2k3, works on newer versions */
579 hr
= IXmlReader_GetNodeType(reader
, NULL
);
580 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
583 resolver
= (void*)0xdeadbeef;
584 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_XmlResolver
, (LONG_PTR
*)&resolver
);
585 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
586 ok(resolver
== NULL
, "got %p\n", resolver
);
588 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_XmlResolver
, 0);
589 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
591 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_XmlResolver
, (LONG_PTR
)&testresolver
);
592 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
595 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_XmlResolver
, (LONG_PTR
*)&resolver
);
596 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
597 ok(resolver
== &testresolver
, "got %p\n", resolver
);
598 IXmlResolver_Release(resolver
);
600 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_XmlResolver
, 0);
601 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
604 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_DtdProcessing
, (LONG_PTR
*)&dtd
);
605 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
606 ok(dtd
== DtdProcessing_Prohibit
, "got %d\n", dtd
);
609 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, dtd
);
610 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
612 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, -1);
613 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
615 /* Null input pointer, releases previous input */
616 hr
= IXmlReader_SetInput(reader
, NULL
);
617 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
619 TEST_READER_STATE2(reader
, XmlReadState_Initial
, XmlReadState_Closed
);
621 /* test input interface selection sequence */
622 hr
= testinput_createinstance((void**)&input
);
623 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
627 input_iids
.count
= 0;
628 hr
= IXmlReader_SetInput(reader
, input
);
629 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
630 ok_iids(&input_iids
, setinput_full
, setinput_full_old
, FALSE
);
631 IUnknown_Release(input
);
633 IXmlReader_Release(reader
);
636 static void test_readerinput(void)
638 IXmlReaderInput
*reader_input
;
639 IXmlReader
*reader
, *reader2
;
640 IUnknown
*obj
, *input
;
641 IStream
*stream
, *stream2
;
642 XmlNodeType nodetype
;
646 hr
= CreateXmlReaderInputWithEncodingName(NULL
, NULL
, NULL
, FALSE
, NULL
, NULL
);
647 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
648 hr
= CreateXmlReaderInputWithEncodingName(NULL
, NULL
, NULL
, FALSE
, NULL
, &reader_input
);
649 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
651 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
652 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
654 ref
= IStream_AddRef(stream
);
655 ok(ref
== 2, "Expected 2, got %d\n", ref
);
656 IStream_Release(stream
);
657 hr
= CreateXmlReaderInputWithEncodingName((IUnknown
*)stream
, NULL
, NULL
, FALSE
, NULL
, &reader_input
);
658 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
660 hr
= IUnknown_QueryInterface(reader_input
, &IID_IStream
, (void**)&stream2
);
661 ok(hr
== E_NOINTERFACE
, "Expected S_OK, got %08x\n", hr
);
663 hr
= IUnknown_QueryInterface(reader_input
, &IID_ISequentialStream
, (void**)&stream2
);
664 ok(hr
== E_NOINTERFACE
, "Expected S_OK, got %08x\n", hr
);
666 /* IXmlReaderInput grabs a stream reference */
667 ref
= IStream_AddRef(stream
);
668 ok(ref
== 3, "Expected 3, got %d\n", ref
);
669 IStream_Release(stream
);
671 /* try ::SetInput() with valid IXmlReaderInput */
672 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
673 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
675 ref
= IUnknown_AddRef(reader_input
);
676 ok(ref
== 2, "Expected 2, got %d\n", ref
);
677 IUnknown_Release(reader_input
);
679 hr
= IXmlReader_SetInput(reader
, reader_input
);
680 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
682 TEST_READER_STATE(reader
, XmlReadState_Initial
);
684 nodetype
= XmlNodeType_Element
;
685 hr
= IXmlReader_GetNodeType(reader
, &nodetype
);
686 ok(hr
== S_OK
, "got %08x\n", hr
);
687 ok(nodetype
== XmlNodeType_None
, "got %d\n", nodetype
);
689 /* IXmlReader grabs a IXmlReaderInput reference */
690 ref
= IUnknown_AddRef(reader_input
);
691 ok(ref
== 3, "Expected 3, got %d\n", ref
);
692 IUnknown_Release(reader_input
);
694 ref
= IStream_AddRef(stream
);
695 ok(ref
== 4, "Expected 4, got %d\n", ref
);
696 IStream_Release(stream
);
698 /* reset input and check state */
699 hr
= IXmlReader_SetInput(reader
, NULL
);
700 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
702 TEST_READER_STATE2(reader
, XmlReadState_Initial
, XmlReadState_Closed
);
704 IXmlReader_Release(reader
);
706 ref
= IStream_AddRef(stream
);
707 ok(ref
== 3, "Expected 3, got %d\n", ref
);
708 IStream_Release(stream
);
710 ref
= IUnknown_AddRef(reader_input
);
711 ok(ref
== 2, "Expected 2, got %d\n", ref
);
712 IUnknown_Release(reader_input
);
714 /* IID_IXmlReaderInput */
715 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
716 so it's not a COM interface actually.
717 Such query will be used only to check if input is really IXmlReaderInput */
718 obj
= (IUnknown
*)0xdeadbeef;
719 hr
= IUnknown_QueryInterface(reader_input
, &IID_IXmlReaderInput
, (void**)&obj
);
720 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
721 ref
= IUnknown_AddRef(reader_input
);
722 ok(ref
== 3, "Expected 3, got %d\n", ref
);
723 IUnknown_Release(reader_input
);
725 IUnknown_Release(reader_input
);
726 IUnknown_Release(reader_input
);
727 IStream_Release(stream
);
729 /* test input interface selection sequence */
731 hr
= testinput_createinstance((void**)&input
);
732 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
734 input_iids
.count
= 0;
735 ref
= IUnknown_AddRef(input
);
736 ok(ref
== 2, "Expected 2, got %d\n", ref
);
737 IUnknown_Release(input
);
738 hr
= CreateXmlReaderInputWithEncodingName(input
, NULL
, NULL
, FALSE
, NULL
, &reader_input
);
739 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
740 ok_iids(&input_iids
, empty_seq
, NULL
, FALSE
);
741 /* IXmlReaderInput stores stream interface as IUnknown */
742 ref
= IUnknown_AddRef(input
);
743 ok(ref
== 3, "Expected 3, got %d\n", ref
);
744 IUnknown_Release(input
);
746 hr
= CreateXmlReader(&IID_IXmlReader
, (LPVOID
*)&reader
, NULL
);
747 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
749 input_iids
.count
= 0;
750 ref
= IUnknown_AddRef(reader_input
);
751 ok(ref
== 2, "Expected 2, got %d\n", ref
);
752 IUnknown_Release(reader_input
);
753 ref
= IUnknown_AddRef(input
);
754 ok(ref
== 3, "Expected 3, got %d\n", ref
);
755 IUnknown_Release(input
);
756 hr
= IXmlReader_SetInput(reader
, reader_input
);
757 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
758 ok_iids(&input_iids
, setinput_readerinput
, NULL
, FALSE
);
760 TEST_READER_STATE(reader
, XmlReadState_Closed
);
762 ref
= IUnknown_AddRef(input
);
763 ok(ref
== 3, "Expected 3, got %d\n", ref
);
764 IUnknown_Release(input
);
766 ref
= IUnknown_AddRef(reader_input
);
767 ok(ref
== 3 || broken(ref
== 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
768 "Expected 3, got %d\n", ref
);
769 IUnknown_Release(reader_input
);
770 /* repeat another time, no check or caching here */
771 input_iids
.count
= 0;
772 hr
= IXmlReader_SetInput(reader
, reader_input
);
773 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
774 ok_iids(&input_iids
, setinput_readerinput
, NULL
, FALSE
);
777 hr
= CreateXmlReader(&IID_IXmlReader
, (LPVOID
*)&reader2
, NULL
);
778 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
780 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
781 ::SetInput() level, each time it's called */
782 input_iids
.count
= 0;
783 hr
= IXmlReader_SetInput(reader2
, reader_input
);
784 ok(hr
== E_NOINTERFACE
, "Expected E_NOINTERFACE, got %08x\n", hr
);
785 ok_iids(&input_iids
, setinput_readerinput
, NULL
, FALSE
);
787 IXmlReader_Release(reader2
);
788 IXmlReader_Release(reader
);
790 IUnknown_Release(reader_input
);
791 IUnknown_Release(input
);
794 static void test_reader_state(void)
796 XmlNodeType nodetype
;
800 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
801 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
803 /* invalid arguments */
804 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_ReadState
, NULL
);
805 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
807 /* attempt to read on closed reader */
808 TEST_READER_STATE(reader
, XmlReadState_Closed
);
812 /* newer versions crash here, probably because no input was set */
813 hr
= IXmlReader_Read(reader
, &nodetype
);
814 ok(hr
== S_FALSE
, "got %08x\n", hr
);
816 set_input_string(reader
, "xml");
817 TEST_READER_STATE(reader
, XmlReadState_Initial
);
819 nodetype
= XmlNodeType_Element
;
820 hr
= IXmlReader_Read(reader
, &nodetype
);
822 ok(FAILED(hr
), "got %08x\n", hr
);
823 ok(nodetype
== XmlNodeType_None
, "Unexpected node type %d\n", nodetype
);
826 TEST_READER_STATE(reader
, XmlReadState_Error
);
828 nodetype
= XmlNodeType_Element
;
829 hr
= IXmlReader_Read(reader
, &nodetype
);
831 ok(FAILED(hr
), "got %08x\n", hr
);
832 ok(nodetype
== XmlNodeType_None
, "Unexpected node type %d\n", nodetype
);
834 IXmlReader_Release(reader
);
837 static void test_reader_depth(IXmlReader
*reader
, UINT depth
, UINT brk
, int line
)
842 IXmlReader_GetDepth(reader
, &d
);
844 condition
= d
== depth
;
846 condition
|= broken(d
== brk
);
847 ok_(__FILE__
, line
)(condition
, "Unexpected nesting depth %u, expected %u\n", d
, depth
);
850 #define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__)
851 #define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__)
853 static void test_read_xmldeclaration(void)
861 { {'v','e','r','s','i','o','n',0}, {'1','.','0',0} },
862 { {'e','n','c','o','d','i','n','g',0}, {'U','T','F','-','8',0} },
863 { {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
869 UINT count
= 0, len
, i
;
873 hr
= CreateXmlReader(&IID_IXmlReader
, (LPVOID
*)&reader
, NULL
);
874 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
876 stream
= create_stream_on_data(xmldecl_full
, sizeof(xmldecl_full
));
878 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
879 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
881 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
882 ok(hr
== S_OK
, "got %08x\n", hr
);
883 ok(count
== 0, "got %d\n", count
);
885 /* try to move without attributes */
886 hr
= IXmlReader_MoveToElement(reader
);
887 ok(hr
== S_FALSE
, "got %08x\n", hr
);
889 hr
= IXmlReader_MoveToNextAttribute(reader
);
890 ok(hr
== S_FALSE
, "got %08x\n", hr
);
892 hr
= IXmlReader_MoveToFirstAttribute(reader
);
893 ok(hr
== S_FALSE
, "got %08x\n", hr
);
895 TEST_READER_POSITION(reader
, 0, 0);
897 read_node(reader
, XmlNodeType_XmlDeclaration
);
899 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
900 TEST_READER_POSITION2(reader
, 1, 3, ~0u, 55);
902 TEST_DEPTH(reader
, 0);
903 TEST_READER_STATE(reader
, XmlReadState_Interactive
);
905 reader_value(reader
, "");
907 /* check attributes */
908 next_attribute(reader
);
910 TEST_DEPTH(reader
, 1);
912 type
= XmlNodeType_None
;
913 hr
= IXmlReader_GetNodeType(reader
, &type
);
914 ok(hr
== S_OK
, "got %08x\n", hr
);
915 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
917 TEST_READER_POSITION2(reader
, 1, 7, ~0u, 55);
919 /* try to move from last attribute */
920 next_attribute(reader
);
921 next_attribute(reader
);
922 hr
= IXmlReader_MoveToNextAttribute(reader
);
923 ok(hr
== S_FALSE
, "got %08x\n", hr
);
925 type
= XmlNodeType_None
;
926 hr
= IXmlReader_GetNodeType(reader
, &type
);
927 ok(hr
== S_OK
, "got %08x\n", hr
);
928 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
930 hr
= IXmlReader_MoveToFirstAttribute(reader
);
931 ok(hr
== S_OK
, "got %08x\n", hr
);
932 TEST_READER_POSITION2(reader
, 1, 7, ~0u, 55);
934 hr
= IXmlReader_GetAttributeCount(reader
, NULL
);
935 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
937 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
938 ok(hr
== S_OK
, "got %08x\n", hr
);
939 ok(count
== 3, "Expected 3, got %d\n", count
);
941 for (i
= 0; i
< count
; i
++)
944 hr
= IXmlReader_GetLocalName(reader
, &val
, &len
);
945 ok(hr
== S_OK
, "got %08x\n", hr
);
946 ok(len
== lstrlenW(name_val
[i
].name
), "expected %u, got %u\n", lstrlenW(name_val
[i
].name
), len
);
947 ok(!lstrcmpW(name_val
[i
].name
, val
), "expected %s, got %s\n", wine_dbgstr_w(name_val
[i
].name
), wine_dbgstr_w(val
));
950 hr
= IXmlReader_GetValue(reader
, &val
, &len
);
951 ok(hr
== S_OK
, "got %08x\n", hr
);
952 ok(len
== lstrlenW(name_val
[i
].val
), "expected %u, got %u\n", lstrlenW(name_val
[i
].val
), len
);
953 ok(!lstrcmpW(name_val
[i
].val
, val
), "expected %s, got %s\n", wine_dbgstr_w(name_val
[i
].val
), wine_dbgstr_w(val
));
955 hr
= IXmlReader_MoveToNextAttribute(reader
);
956 ok(hr
== ((i
< count
- 1) ? S_OK
: S_FALSE
), "got %08x\n", hr
);
959 TEST_DEPTH(reader
, 1);
961 move_to_element(reader
);
962 TEST_READER_POSITION2(reader
, 1, 3, ~0u, 55);
964 type
= XmlNodeType_None
;
965 hr
= IXmlReader_GetNodeType(reader
, &type
);
966 ok(hr
== S_OK
, "got %08x\n", hr
);
967 ok(type
== XmlNodeType_XmlDeclaration
, "got %d\n", type
);
969 type
= XmlNodeType_XmlDeclaration
;
970 hr
= IXmlReader_Read(reader
, &type
);
971 /* newer versions return syntax error here cause document is incomplete,
972 it makes more sense than invalid char error */
974 ok(hr
== WC_E_SYNTAX
|| broken(hr
== WC_E_XMLCHARACTER
), "got 0x%08x\n", hr
);
975 ok(type
== XmlNodeType_None
, "got %d\n", type
);
977 IStream_Release(stream
);
979 /* test short variant */
980 stream
= create_stream_on_data(xmldecl_short
, sizeof(xmldecl_short
));
982 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
983 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
985 read_node(reader
, XmlNodeType_XmlDeclaration
);
986 TEST_READER_POSITION2(reader
, 1, 3, ~0u, 21);
987 TEST_READER_STATE(reader
, XmlReadState_Interactive
);
989 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
990 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
991 ok(count
== 1, "expected 1, got %d\n", count
);
993 ret
= IXmlReader_IsEmptyElement(reader
);
994 ok(!ret
, "element should not be empty\n");
996 reader_value(reader
, "");
997 reader_name(reader
, "xml");
999 reader_qname(reader
, "xml");
1001 /* check attributes */
1002 next_attribute(reader
);
1005 hr
= IXmlReader_GetNodeType(reader
, &type
);
1006 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
1007 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
1008 TEST_READER_POSITION2(reader
, 1, 7, ~0u, 21);
1010 /* try to move from last attribute */
1011 hr
= IXmlReader_MoveToNextAttribute(reader
);
1012 ok(hr
== S_FALSE
, "expected S_FALSE, got %08x\n", hr
);
1014 read_node(reader
, XmlNodeType_Element
);
1015 TEST_READER_POSITION2(reader
, 1, 23, ~0u, 40);
1016 TEST_READER_STATE(reader
, XmlReadState_Interactive
);
1018 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
1019 ok(hr
== S_OK
, "expected S_OK, got %08x\n", hr
);
1020 ok(count
== 0, "expected 0, got %d\n", count
);
1022 ret
= IXmlReader_IsEmptyElement(reader
);
1023 ok(ret
, "element should be empty\n");
1025 reader_value(reader
, "");
1026 reader_name(reader
, "RegistrationInfo");
1029 hr
= IXmlReader_Read(reader
, &type
);
1031 ok(hr
== WC_E_SYNTAX
|| hr
== WC_E_XMLCHARACTER
/* XP */, "expected WC_E_SYNTAX, got %08x\n", hr
);
1032 ok(type
== XmlNodeType_None
, "expected XmlNodeType_None, got %s\n", type_to_str(type
));
1033 TEST_READER_POSITION(reader
, 1, 41);
1035 TEST_READER_STATE(reader
, XmlReadState_Error
);
1037 IStream_Release(stream
);
1038 IXmlReader_Release(reader
);
1046 HRESULT hr_broken
; /* this is set to older version results */
1050 static struct test_entry comment_tests
[] = {
1051 { "<!-- comment -->", "", " comment ", S_OK
},
1052 { "<!-- - comment-->", "", " - comment", S_OK
},
1053 { "<!-- -- comment-->", NULL
, NULL
, WC_E_COMMENT
, WC_E_GREATERTHAN
},
1054 { "<!-- -- comment--->", NULL
, NULL
, WC_E_COMMENT
, WC_E_GREATERTHAN
},
1058 static void test_read_comment(void)
1060 static const char *teststr
= "<a>text<!-- comment --></a>";
1061 struct test_entry
*test
= comment_tests
;
1062 static const XmlNodeType types
[] =
1064 XmlNodeType_Element
,
1066 XmlNodeType_Comment
,
1067 XmlNodeType_EndElement
,
1074 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1075 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1077 set_input_string(reader
, teststr
);
1079 while (IXmlReader_Read(reader
, &type
) == S_OK
)
1083 ok(type
== types
[i
], "%d: unexpected node type %d\n", i
, type
);
1085 if (type
== XmlNodeType_Text
|| type
== XmlNodeType_Comment
)
1087 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
1088 ok(hr
== S_OK
, "got %08x\n", hr
);
1089 ok(*value
!= 0, "Expected node value\n");
1096 set_input_string(reader
, test
->xml
);
1098 type
= XmlNodeType_None
;
1099 hr
= IXmlReader_Read(reader
, &type
);
1100 if (test
->hr_broken
)
1101 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1103 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1108 ok(type
== XmlNodeType_Comment
, "got %d for %s\n", type
, test
->xml
);
1110 reader_name(reader
, "");
1113 hr
= IXmlReader_GetLocalName(reader
, &str
, NULL
);
1114 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1115 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1117 reader_qname(reader
, "");
1120 hr
= IXmlReader_GetQualifiedName(reader
, &str
, NULL
);
1121 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1122 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1125 reader_value(reader
, test
->value
);
1131 IXmlReader_Release(reader
);
1134 static struct test_entry pi_tests
[] = {
1135 { "<?pi?>", "pi", "", S_OK
},
1136 { "<?pi ?>", "pi", "", S_OK
},
1137 { "<?pi ?>", "pi", "", S_OK
},
1138 { "<?pi pi data?>", "pi", "pi data", S_OK
},
1139 { "<?pi pi data ?>", "pi", "pi data ", S_OK
},
1140 { "<?pi data ?>", "pi", "data ", S_OK
},
1141 { "<?pi:pi?>", NULL
, NULL
, NC_E_NAMECOLON
, WC_E_NAMECHARACTER
},
1142 { "<?:pi ?>", NULL
, NULL
, WC_E_PI
, WC_E_NAMECHARACTER
},
1143 { "<?-pi ?>", NULL
, NULL
, WC_E_PI
, WC_E_NAMECHARACTER
},
1144 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK
},
1148 static void test_read_pi(void)
1150 struct test_entry
*test
= pi_tests
;
1154 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1155 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1161 set_input_string(reader
, test
->xml
);
1163 type
= XmlNodeType_None
;
1164 hr
= IXmlReader_Read(reader
, &type
);
1165 if (test
->hr_broken
)
1166 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1168 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1175 ok(type
== XmlNodeType_ProcessingInstruction
, "got %d for %s\n", type
, test
->xml
);
1177 reader_name(reader
, test
->name
);
1181 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1182 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1183 ok(len
== strlen(test
->name
), "got %u\n", len
);
1184 str_exp
= a2w(test
->name
);
1185 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1189 reader_value(reader
, test
->value
);
1195 IXmlReader_Release(reader
);
1206 static const char misc_test_xml
[] =
1224 static struct nodes_test misc_test
= {
1227 {XmlNodeType_Comment
, " comment1 "},
1228 {XmlNodeType_Comment
, " comment2 "},
1229 {XmlNodeType_ProcessingInstruction
, "pi1body "},
1230 {XmlNodeType_Comment
, " comment3 "},
1231 {XmlNodeType_Whitespace
, " \t \n \n"},
1232 {XmlNodeType_Comment
, " comment4 "},
1233 {XmlNodeType_Element
, ""},
1234 {XmlNodeType_Whitespace
, "\n\t"},
1235 {XmlNodeType_Element
, ""},
1236 {XmlNodeType_Text
, "text"},
1237 {XmlNodeType_Comment
, " comment "},
1238 {XmlNodeType_Text
, "text2"},
1239 {XmlNodeType_ProcessingInstruction
, "pibody "},
1240 {XmlNodeType_Whitespace
, "\n"},
1241 {XmlNodeType_EndElement
, ""},
1242 {XmlNodeType_None
, ""}
1246 static void test_read_full(void)
1248 struct nodes_test
*test
= &misc_test
;
1253 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1254 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1256 set_input_string(reader
, test
->xml
);
1261 read_node(reader
, test
->nodes
[i
].type
);
1262 reader_value(reader
, test
->nodes
[i
].value
);
1263 } while(test
->nodes
[i
++].type
!= XmlNodeType_None
);
1265 IXmlReader_Release(reader
);
1268 static const char test_public_dtd
[] =
1269 "<!DOCTYPE testdtd PUBLIC \"pubid\" \"externalid uri\" >";
1271 static void test_read_public_dtd(void)
1273 static const WCHAR dtdnameW
[] = {'t','e','s','t','d','t','d',0};
1280 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1281 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1283 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, DtdProcessing_Parse
);
1284 ok(hr
== S_OK
, "got 0x%8x\n", hr
);
1286 set_input_string(reader
, test_public_dtd
);
1288 read_node(reader
, XmlNodeType_DocumentType
);
1291 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
1292 ok(hr
== S_OK
, "got %08x\n", hr
);
1293 ok(count
== 2, "got %d\n", count
);
1295 hr
= IXmlReader_MoveToFirstAttribute(reader
);
1296 ok(hr
== S_OK
, "got %08x\n", hr
);
1298 type
= XmlNodeType_None
;
1299 hr
= IXmlReader_GetNodeType(reader
, &type
);
1300 ok(hr
== S_OK
, "got %08x\n", hr
);
1301 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
1303 reader_name(reader
, "PUBLIC");
1304 reader_value(reader
, "pubid");
1306 next_attribute(reader
);
1308 type
= XmlNodeType_None
;
1309 hr
= IXmlReader_GetNodeType(reader
, &type
);
1310 ok(hr
== S_OK
, "got %08x\n", hr
);
1311 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
1313 reader_name(reader
, "SYSTEM");
1314 reader_value(reader
, "externalid uri");
1316 move_to_element(reader
);
1317 reader_name(reader
, "testdtd");
1321 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1322 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1324 ok(len
== lstrlenW(dtdnameW
), "got %u\n", len
);
1325 ok(!lstrcmpW(str
, dtdnameW
), "got %s\n", wine_dbgstr_w(str
));
1327 IXmlReader_Release(reader
);
1330 static const char test_system_dtd
[] =
1331 "<!DOCTYPE testdtd SYSTEM \"externalid uri\" >"
1334 static void test_read_system_dtd(void)
1336 static const WCHAR dtdnameW
[] = {'t','e','s','t','d','t','d',0};
1343 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1344 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1346 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_DtdProcessing
, DtdProcessing_Parse
);
1347 ok(hr
== S_OK
, "got 0x%8x\n", hr
);
1349 set_input_string(reader
, test_system_dtd
);
1351 read_node(reader
, XmlNodeType_DocumentType
);
1354 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
1355 ok(hr
== S_OK
, "got %08x\n", hr
);
1356 ok(count
== 1, "got %d\n", count
);
1358 hr
= IXmlReader_MoveToFirstAttribute(reader
);
1359 ok(hr
== S_OK
, "got %08x\n", hr
);
1361 type
= XmlNodeType_None
;
1362 hr
= IXmlReader_GetNodeType(reader
, &type
);
1363 ok(hr
== S_OK
, "got %08x\n", hr
);
1364 ok(type
== XmlNodeType_Attribute
, "got %d\n", type
);
1366 reader_name(reader
, "SYSTEM");
1367 reader_value(reader
, "externalid uri");
1369 move_to_element(reader
);
1370 reader_name(reader
, "testdtd");
1374 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1375 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1377 ok(len
== lstrlenW(dtdnameW
), "got %u\n", len
);
1378 ok(!lstrcmpW(str
, dtdnameW
), "got %s\n", wine_dbgstr_w(str
));
1381 read_node(reader
, XmlNodeType_Comment
);
1383 IXmlReader_Release(reader
);
1386 static struct test_entry element_tests
[] = {
1387 { "<a/>", "a", "", S_OK
},
1388 { "<a />", "a", "", S_OK
},
1389 { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX
},
1390 { "<:a/>", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1391 { "< a/>", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1392 { "<a>", "a", "", S_OK
},
1393 { "<a >", "a", "", S_OK
},
1394 { "<a \r \t\n>", "a", "", S_OK
},
1395 { "</a>", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1396 { "<a:b:c />", NULL
, NULL
, NC_E_QNAMECOLON
},
1397 { "<:b:c />", NULL
, NULL
, NC_E_QNAMECHARACTER
},
1401 static void test_read_element(void)
1403 struct test_entry
*test
= element_tests
;
1404 static const char stag
[] =
1409 "<d attr4=\"_d\"></d>"
1412 static const UINT depths
[] = { 0, 1, 2, 2, 2, 3, 2, 1 };
1419 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1420 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1424 set_input_string(reader
, test
->xml
);
1426 type
= XmlNodeType_None
;
1427 hr
= IXmlReader_Read(reader
, &type
);
1428 if (test
->hr_broken
)
1429 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1431 todo_wine_if(test
->hr
== NC_E_UNDECLAREDPREFIX
)
1432 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1439 ok(type
== XmlNodeType_Element
, "got %d for %s\n", type
, test
->xml
);
1443 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1444 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1445 ok(len
== strlen(test
->name
), "got %u\n", len
);
1446 str_exp
= a2w(test
->name
);
1447 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1451 reader_value(reader
, "");
1457 /* test reader depth increment */
1458 set_input_string(reader
, stag
);
1461 while (IXmlReader_Read(reader
, &type
) == S_OK
)
1465 ok(type
== XmlNodeType_Element
|| type
== XmlNodeType_EndElement
||
1466 type
== XmlNodeType_Text
, "Unexpected node type %d\n", type
);
1469 hr
= IXmlReader_GetDepth(reader
, &depth
);
1470 ok(hr
== S_OK
, "got %08x\n", hr
);
1471 ok(depth
== depths
[i
], "%u: got depth %u, expected %u\n", i
, depth
, depths
[i
]);
1473 if (type
== XmlNodeType_Element
|| type
== XmlNodeType_EndElement
)
1475 const WCHAR
*prefix
;
1478 hr
= IXmlReader_GetPrefix(reader
, &prefix
, NULL
);
1479 ok(hr
== S_OK
, "got %08x\n", hr
);
1480 ok(prefix
!= NULL
, "got %p\n", prefix
);
1484 const WCHAR
*local
, *qname
;
1487 hr
= IXmlReader_GetLocalName(reader
, &local
, NULL
);
1488 ok(hr
== S_OK
, "got %08x\n", hr
);
1489 ok(local
!= NULL
, "got %p\n", local
);
1492 hr
= IXmlReader_GetQualifiedName(reader
, &qname
, NULL
);
1493 ok(hr
== S_OK
, "got %08x\n", hr
);
1494 ok(qname
!= NULL
, "got %p\n", qname
);
1496 ok(local
== qname
, "expected same pointer\n");
1500 if (type
== XmlNodeType_EndElement
)
1503 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
1504 ok(hr
== S_OK
, "got %08x\n", hr
);
1505 ok(count
== 0, "got %u\n", count
);
1508 if (type
== XmlNodeType_Element
)
1511 hr
= IXmlReader_GetAttributeCount(reader
, &count
);
1512 ok(hr
== S_OK
, "got %08x\n", hr
);
1514 /* moving to attributes increases depth */
1519 reader_value(reader
, "");
1521 hr
= IXmlReader_MoveToFirstAttribute(reader
);
1522 ok(hr
== S_OK
, "got %08x\n", hr
);
1524 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
1525 ok(*value
!= 0, "Unexpected value %s\n", wine_dbgstr_w(value
));
1528 hr
= IXmlReader_GetDepth(reader
, &depth
);
1529 ok(hr
== S_OK
, "got %08x\n", hr
);
1530 ok(depth
== depths
[i
] + 1, "%u: got depth %u, expected %u\n", i
, depth
, depths
[i
] + 1);
1532 move_to_element(reader
);
1533 reader_value(reader
, "");
1536 hr
= IXmlReader_GetDepth(reader
, &depth
);
1537 ok(hr
== S_OK
, "got %08x\n", hr
);
1538 ok(depth
== depths
[i
], "%u: got depth %u, expected %u\n", i
, depth
, depths
[i
]);
1545 /* start/end tag mismatch */
1546 set_input_string(reader
, "<a></b>");
1548 read_node(reader
, XmlNodeType_Element
);
1550 type
= XmlNodeType_Element
;
1551 hr
= IXmlReader_Read(reader
, &type
);
1552 ok(hr
== WC_E_ELEMENTMATCH
, "got %08x\n", hr
);
1553 ok(type
== XmlNodeType_None
, "got %d\n", type
);
1554 TEST_READER_STATE(reader
, XmlReadState_Error
);
1556 IXmlReader_Release(reader
);
1559 static ISequentialStream teststream
= { &teststreamvtbl
};
1561 static void test_read_pending(void)
1569 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1570 ok(hr
== S_OK
, "S_OK, got 0x%08x\n", hr
);
1572 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)&teststream
);
1573 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1575 /* first read call returns incomplete node, second attempt fails with E_PENDING */
1576 stream_readcall
= 0;
1577 type
= XmlNodeType_Element
;
1578 hr
= IXmlReader_Read(reader
, &type
);
1579 ok(hr
== S_OK
|| broken(hr
== E_PENDING
), "got 0x%08x\n", hr
);
1580 /* newer versions are happy when it's enough data to detect node type,
1581 older versions keep reading until it fails to read more */
1583 ok(stream_readcall
== 1 || broken(stream_readcall
> 1), "got %d\n", stream_readcall
);
1584 ok(type
== XmlNodeType_Comment
|| broken(type
== XmlNodeType_None
), "got %d\n", type
);
1586 /* newer versions' GetValue() makes an attempt to read more */
1587 c
= stream_readcall
;
1588 value
= (void*)0xdeadbeef;
1589 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
1590 ok(hr
== E_PENDING
, "got 0x%08x\n", hr
);
1591 ok(value
== NULL
|| broken(value
== (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value
);
1592 ok(c
< stream_readcall
|| broken(c
== stream_readcall
), "got %d, expected %d\n", stream_readcall
, c
+1);
1594 IXmlReader_Release(reader
);
1597 static void test_readvaluechunk(void)
1606 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1607 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1609 set_input_string(reader
, "<!-- comment1 --><!-- comment2 -->");
1611 hr
= IXmlReader_Read(reader
, &type
);
1612 ok(hr
== S_OK
, "got %08x\n", hr
);
1613 ok(type
== XmlNodeType_Comment
, "type = %u\n", type
);
1615 read_value_char(reader
, ' ');
1616 read_value_char(reader
, 'c');
1618 /* portion read as chunk is skipped from resulting node value */
1619 reader_value(reader
, "omment1 ");
1621 /* once value is returned/allocated it's not possible to read by chunk */
1624 hr
= IXmlReader_ReadValueChunk(reader
, &b
, 1, &c
);
1625 ok(hr
== S_FALSE
, "got %08x\n", hr
);
1626 ok(c
== 0, "got %u\n", c
);
1627 ok(b
== 0, "got %x\n", b
);
1630 hr
= IXmlReader_ReadValueChunk(reader
, buf
, 0, &c
);
1631 ok(hr
== S_OK
, "got %08x\n", hr
);
1632 ok(!c
, "c = %u\n", c
);
1634 reader_value(reader
, "omment1 ");
1637 read_node(reader
, XmlNodeType_Comment
);
1640 hr
= IXmlReader_ReadValueChunk(reader
, buf
, 0, &c
);
1641 ok(hr
== S_OK
, "got %08x\n", hr
);
1642 ok(!c
, "c = %u\n", c
);
1645 memset(buf
, 0xcc, sizeof(buf
));
1646 hr
= IXmlReader_ReadValueChunk(reader
, buf
, ARRAY_SIZE(buf
), &c
);
1647 ok(hr
== S_OK
, "got %08x\n", hr
);
1648 ok(c
== 10, "got %u\n", c
);
1649 ok(buf
[c
] == 0xcccc, "buffer overflow\n");
1651 ok(!strcmp_wa(buf
, " comment2 "), "buf = %s\n", wine_dbgstr_w(buf
));
1654 memset(buf
, 0xcc, sizeof(buf
));
1655 hr
= IXmlReader_ReadValueChunk(reader
, buf
, ARRAY_SIZE(buf
), &c
);
1656 ok(hr
== S_FALSE
, "got %08x\n", hr
);
1657 ok(!c
, "got %u\n", c
);
1659 /* portion read as chunk is skipped from resulting node value */
1660 reader_value(reader
, "");
1662 /* once value is returned/allocated it's not possible to read by chunk */
1665 hr
= IXmlReader_ReadValueChunk(reader
, &b
, 1, &c
);
1666 ok(hr
== S_FALSE
, "got %08x\n", hr
);
1667 ok(c
== 0, "got %u\n", c
);
1668 ok(b
== 0xffff, "got %x\n", b
);
1670 reader_value(reader
, "");
1672 IXmlReader_Release(reader
);
1675 static struct test_entry cdata_tests
[] = {
1676 { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK
},
1677 { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK
},
1678 { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK
, S_OK
},
1679 { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK
, S_OK
},
1680 { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK
},
1684 static void test_read_cdata(void)
1686 struct test_entry
*test
= cdata_tests
;
1690 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1691 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1697 set_input_string(reader
, test
->xml
);
1699 type
= XmlNodeType_None
;
1700 hr
= IXmlReader_Read(reader
, &type
);
1702 /* read one more to get to CDATA */
1703 if (type
== XmlNodeType_Element
)
1705 type
= XmlNodeType_None
;
1706 hr
= IXmlReader_Read(reader
, &type
);
1709 if (test
->hr_broken
)
1710 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1712 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1718 ok(type
== XmlNodeType_CDATA
, "got %d for %s\n", type
, test
->xml
);
1720 reader_name(reader
, "");
1723 hr
= IXmlReader_GetLocalName(reader
, &str
, NULL
);
1724 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1725 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1729 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1730 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1731 ok(len
== 0, "got %u\n", len
);
1732 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1735 hr
= IXmlReader_GetQualifiedName(reader
, &str
, NULL
);
1736 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1737 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1740 reader_value(reader
, test
->value
);
1746 IXmlReader_Release(reader
);
1749 static struct test_entry text_tests
[] = {
1750 { "<a>simple text</a>", "", "simple text", S_OK
},
1751 { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND
},
1752 { "<a>\n \r\n \n\n text</a>", "", "\n \n \n\n text", S_OK
, S_OK
},
1753 { "<a>\r \r\r\n \n\n text</a>", "", "\n \n\n \n\n text", S_OK
, S_OK
},
1757 static void test_read_text(void)
1759 struct test_entry
*test
= text_tests
;
1763 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1764 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1770 set_input_string(reader
, test
->xml
);
1772 type
= XmlNodeType_None
;
1773 hr
= IXmlReader_Read(reader
, &type
);
1775 /* read one more to get to text node */
1776 if (type
== XmlNodeType_Element
)
1778 type
= XmlNodeType_None
;
1779 hr
= IXmlReader_Read(reader
, &type
);
1781 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1787 ok(type
== XmlNodeType_Text
, "got %d for %s\n", type
, test
->xml
);
1789 reader_name(reader
, "");
1792 hr
= IXmlReader_GetLocalName(reader
, &str
, NULL
);
1793 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1794 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1798 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1799 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1800 ok(len
== 0, "got %u\n", len
);
1801 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1804 hr
= IXmlReader_GetQualifiedName(reader
, &str
, NULL
);
1805 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1806 ok(*str
== 0, "got %s\n", wine_dbgstr_w(str
));
1809 reader_value(reader
, test
->value
);
1815 IXmlReader_Release(reader
);
1818 struct test_entry_empty
{
1823 static struct test_entry_empty empty_element_tests
[] = {
1824 { "<a></a>", FALSE
},
1829 static void test_isemptyelement(void)
1831 struct test_entry_empty
*test
= empty_element_tests
;
1835 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1836 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1843 set_input_string(reader
, test
->xml
);
1845 type
= XmlNodeType_None
;
1846 hr
= IXmlReader_Read(reader
, &type
);
1847 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1848 ok(type
== XmlNodeType_Element
, "got %d\n", type
);
1850 ret
= IXmlReader_IsEmptyElement(reader
);
1851 ok(ret
== test
->empty
, "got %d, expected %d. xml=%s\n", ret
, test
->empty
, test
->xml
);
1856 IXmlReader_Release(reader
);
1859 static struct test_entry attributes_tests
[] = {
1860 { "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK
},
1861 { "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK
},
1862 { "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK
},
1863 { "<a attr1=\' \'/>", "attr1", " ", S_OK
},
1864 { "<a attr1=\" \"/>", "attr1", " ", S_OK
},
1865 { "<a attr1=\"\r\n \r \n \t\n\r\"/>", "attr1", " ", S_OK
},
1866 { "<a attr1=\" val \"/>", "attr1", " val ", S_OK
},
1867 { "<a attr1=\"\r\n\tval\n\"/>", "attr1", " val ", S_OK
},
1868 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK
},
1869 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK
},
1870 { "<a attr1=\"<>&'"\"/>", "attr1", "<>&\'\"", S_OK
},
1871 { "<a attr1=\"&entname;\"/>", NULL
, NULL
, WC_E_UNDECLAREDENTITY
},
1872 { "<a attr1=\"val\"/>", NULL
, NULL
, WC_E_XMLCHARACTER
},
1873 { "<a attr1=\"val &#a;\"/>", NULL
, NULL
, WC_E_DIGIT
, WC_E_SEMICOLON
},
1874 { "<a attr1=\"val a;\"/>", NULL
, NULL
, WC_E_SEMICOLON
},
1875 { "<a attr1=\"val g;\"/>", NULL
, NULL
, WC_E_SEMICOLON
},
1876 { "<a attr1=\"val &#xg;\"/>", NULL
, NULL
, WC_E_HEXDIGIT
, WC_E_SEMICOLON
},
1877 { "<a attr1=attrvalue/>", NULL
, NULL
, WC_E_QUOTE
},
1878 { "<a attr1=\"attr<value\"/>", NULL
, NULL
, WC_E_LESSTHAN
},
1879 { "<a attr1=\"&entname\"/>", NULL
, NULL
, WC_E_SEMICOLON
},
1883 static void test_read_attribute(void)
1885 struct test_entry
*test
= attributes_tests
;
1889 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1890 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1896 set_input_string(reader
, test
->xml
);
1898 hr
= IXmlReader_Read(reader
, NULL
);
1900 if (test
->hr_broken
)
1901 ok(hr
== test
->hr
|| broken(hr
== test
->hr_broken
), "got %08x for %s\n", hr
, test
->xml
);
1903 ok(hr
== test
->hr
, "got %08x for %s\n", hr
, test
->xml
);
1910 type
= XmlNodeType_None
;
1911 hr
= IXmlReader_GetNodeType(reader
, &type
);
1912 ok(hr
== S_OK
, "Failed to get node type, %#x\n", hr
);
1914 ok(type
== XmlNodeType_Element
, "got %d for %s\n", type
, test
->xml
);
1916 hr
= IXmlReader_MoveToFirstAttribute(reader
);
1917 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1919 reader_name(reader
, test
->name
);
1923 hr
= IXmlReader_GetQualifiedName(reader
, &str
, &len
);
1924 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1925 ok(len
== strlen(test
->name
), "got %u\n", len
);
1926 str_exp
= a2w(test
->name
);
1927 ok(!lstrcmpW(str
, str_exp
), "got %s\n", wine_dbgstr_w(str
));
1931 reader_value(reader
, test
->value
);
1937 IXmlReader_Release(reader
);
1940 static void test_reader_properties(void)
1946 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1947 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1950 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_MaxElementDepth
, &value
);
1951 ok(hr
== S_OK
, "GetProperty failed: %08x\n", hr
);
1952 ok(value
== 256, "Unexpected default max depth value %ld\n", value
);
1954 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_MultiLanguage
, 0);
1955 ok(hr
== S_OK
, "SetProperty failed: %08x\n", hr
);
1957 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_MaxElementDepth
, 0);
1958 ok(hr
== S_OK
, "SetProperty failed: %08x\n", hr
);
1961 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_MaxElementDepth
, &value
);
1962 ok(hr
== S_OK
, "GetProperty failed: %08x\n", hr
);
1963 ok(value
== 0, "Unexpected max depth value %ld\n", value
);
1965 IXmlReader_Release(reader
);
1968 static void test_prefix(void)
1973 const char *prefix1
;
1974 const char *prefix2
;
1975 const char *prefix3
;
1978 { "<b xmlns=\"defns\" xml:a=\"a ns\"/>", "", "", "xml" },
1979 { "<c:b xmlns:c=\"c ns\" xml:a=\"a ns\"/>", "c", "xmlns", "xml" },
1985 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
1986 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
1988 for (i
= 0; i
< ARRAY_SIZE(prefix_tests
); i
++) {
1991 set_input_string(reader
, prefix_tests
[i
].xml
);
1993 hr
= IXmlReader_Read(reader
, &type
);
1994 ok(hr
== S_OK
, "Read() failed, %#x\n", hr
);
1995 ok(type
== XmlNodeType_Element
, "Unexpected node type %d.\n", type
);
1997 reader_prefix(reader
, prefix_tests
[i
].prefix1
);
1999 hr
= IXmlReader_MoveToFirstAttribute(reader
);
2000 ok(hr
== S_OK
, "MoveToFirstAttribute() failed, %#x.\n", hr
);
2002 hr
= IXmlReader_GetNodeType(reader
, &type
);
2003 ok(hr
== S_OK
, "GetNodeType() failed, %#x.\n", hr
);
2004 ok(type
== XmlNodeType_Attribute
, "Unexpected node type %d.\n", type
);
2006 reader_prefix(reader
, prefix_tests
[i
].prefix2
);
2008 next_attribute(reader
);
2010 hr
= IXmlReader_GetNodeType(reader
, &type
);
2011 ok(hr
== S_OK
, "GetNodeType() failed, %#x.\n", hr
);
2012 ok(type
== XmlNodeType_Attribute
, "Unexpected node type %d.\n", type
);
2014 reader_prefix(reader
, prefix_tests
[i
].prefix3
);
2016 /* back to the element, check prefix */
2017 move_to_element(reader
);
2018 reader_prefix(reader
, prefix_tests
[i
].prefix1
);
2021 IXmlReader_Release(reader
);
2024 static void test_namespaceuri(void)
2032 { "<a xmlns=\"defns a\"><b xmlns=\"defns b\"><c xmlns=\"defns c\"/></b></a>",
2033 { "defns a", "defns b", "defns c", "defns b", "defns a" }},
2034 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"/>",
2036 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"><b/></r:a>",
2037 { "ns r", "defns a", "ns r" }},
2038 { "<a xmlns=\"defns a\" xmlns:r=\"ns r\"><r:b/></a>",
2039 { "defns a", "ns r", "defns a" }},
2040 { "<a><b><c/></b></a>",
2041 { "", "", "", "", "" }},
2046 { "<a><![CDATA[data]]></a>",
2048 { "<?xml version=\"1.0\" ?><a/>",
2052 { "<a><!-- comment --></a>",
2060 hr
= CreateXmlReader(&IID_IXmlReader
, (void**)&reader
, NULL
);
2061 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2063 for (i
= 0; i
< ARRAY_SIZE(uri_tests
); i
++) {
2066 set_input_string(reader
, uri_tests
[i
].xml
);
2069 while (IXmlReader_Read(reader
, &type
) == S_OK
) {
2070 const WCHAR
*local
, *qname
;
2071 UINT length
, length2
;
2073 ok(type
== XmlNodeType_Element
||
2074 type
== XmlNodeType_Text
||
2075 type
== XmlNodeType_CDATA
||
2076 type
== XmlNodeType_ProcessingInstruction
||
2077 type
== XmlNodeType_Comment
||
2078 type
== XmlNodeType_Whitespace
||
2079 type
== XmlNodeType_EndElement
||
2080 type
== XmlNodeType_XmlDeclaration
, "Unexpected node type %d.\n", type
);
2084 hr
= IXmlReader_GetLocalName(reader
, &local
, &length
);
2085 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2086 ok(local
!= NULL
, "Unexpected NULL local name pointer\n");
2090 hr
= IXmlReader_GetQualifiedName(reader
, &qname
, &length2
);
2091 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2092 ok(qname
!= NULL
, "Unexpected NULL qualified name pointer\n");
2094 if (type
== XmlNodeType_Element
||
2095 type
== XmlNodeType_EndElement
||
2096 type
== XmlNodeType_ProcessingInstruction
||
2097 type
== XmlNodeType_XmlDeclaration
)
2099 ok(*local
!= 0, "Unexpected empty local name\n");
2100 ok(length
> 0, "Unexpected local name length\n");
2102 ok(*qname
!= 0, "Unexpected empty qualified name\n");
2103 ok(length2
> 0, "Unexpected qualified name length\n");
2106 reader_namespace(reader
, uri_tests
[i
].uri
[j
]);
2110 ok(type
== XmlNodeType_None
, "Unexpected node type %d\n", type
);
2113 IXmlReader_Release(reader
);
2116 static void test_read_charref(void)
2118 static const char testA
[] = "<a b=\"c\">dză></a>";
2119 static const WCHAR chardataW
[] = {0x01f3,0x0103,'>',0};
2125 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2126 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2128 set_input_string(reader
, testA
);
2130 hr
= IXmlReader_Read(reader
, &type
);
2131 ok(hr
== S_OK
, "got %08x\n", hr
);
2132 ok(type
== XmlNodeType_Element
, "Unexpected node type %d\n", type
);
2134 hr
= IXmlReader_Read(reader
, &type
);
2135 ok(hr
== S_OK
, "got %08x\n", hr
);
2136 ok(type
== XmlNodeType_Text
, "Unexpected node type %d\n", type
);
2138 hr
= IXmlReader_GetValue(reader
, &value
, NULL
);
2139 ok(hr
== S_OK
, "got %08x\n", hr
);
2140 ok(!lstrcmpW(value
, chardataW
), "Text value : %s\n", wine_dbgstr_w(value
));
2142 hr
= IXmlReader_Read(reader
, &type
);
2143 ok(hr
== S_OK
, "got %08x\n", hr
);
2144 ok(type
== XmlNodeType_EndElement
, "Unexpected node type %d\n", type
);
2146 hr
= IXmlReader_Read(reader
, &type
);
2147 ok(hr
== S_FALSE
, "got %08x\n", hr
);
2148 ok(type
== XmlNodeType_None
, "Unexpected node type %d\n", type
);
2150 IXmlReader_Release(reader
);
2153 static void test_encoding_detection(void)
2155 static const struct encoding_testW
2161 { { '<','?','p','i',' ','?','>',0 } },
2162 { { '<','!','-','-',' ','c','-','-','>',0 } },
2163 { { 0xfeff,'<','a','/','>',0 } },
2164 { { '<','a','/','>',0 } },
2166 static const char *encoding_testsA
[] =
2170 "\xef\xbb\xbf<a/>", /* UTF-8 BOM */
2179 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2180 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2182 /* there's no way to query detected encoding back, so just verify that document is browsable */
2184 for (i
= 0; i
< ARRAY_SIZE(encoding_testsA
); i
++)
2186 set_input_string(reader
, encoding_testsA
[i
]);
2188 type
= XmlNodeType_None
;
2189 hr
= IXmlReader_Read(reader
, &type
);
2190 ok(hr
== S_OK
, "got %08x\n", hr
);
2191 ok(type
!= XmlNodeType_None
, "Unexpected node type %d\n", type
);
2194 for (i
= 0; i
< ARRAY_SIZE(encoding_testsW
); i
++)
2196 stream
= create_stream_on_data(encoding_testsW
[i
].text
, lstrlenW(encoding_testsW
[i
].text
) * sizeof(WCHAR
));
2198 hr
= IXmlReader_SetInput(reader
, (IUnknown
*)stream
);
2199 ok(hr
== S_OK
, "got %08x\n", hr
);
2201 type
= XmlNodeType_None
;
2202 hr
= IXmlReader_Read(reader
, &type
);
2203 ok(hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2204 ok(type
!= XmlNodeType_None
, "%u: unexpected node type %d\n", i
, type
);
2206 IStream_Release(stream
);
2209 IXmlReader_Release(reader
);
2212 static void test_eof_state(IXmlReader
*reader
, BOOL eof
)
2217 ok(IXmlReader_IsEOF(reader
) == eof
, "Unexpected IsEOF() result\n");
2218 hr
= IXmlReader_GetProperty(reader
, XmlReaderProperty_ReadState
, &state
);
2219 ok(hr
== S_OK
, "GetProperty() failed, %#x\n", hr
);
2220 ok((state
== XmlReadState_EndOfFile
) == eof
, "Unexpected EndOfFile state %ld\n", state
);
2223 static void test_endoffile(void)
2229 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2230 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2232 test_eof_state(reader
, FALSE
);
2234 set_input_string(reader
, "<a/>");
2236 test_eof_state(reader
, FALSE
);
2238 type
= XmlNodeType_None
;
2239 hr
= IXmlReader_Read(reader
, &type
);
2240 ok(hr
== S_OK
, "got %#x\n", hr
);
2241 ok(type
== XmlNodeType_Element
, "Unexpected type %d\n", type
);
2243 test_eof_state(reader
, FALSE
);
2245 type
= XmlNodeType_Element
;
2246 hr
= IXmlReader_Read(reader
, &type
);
2247 ok(hr
== S_FALSE
, "got %#x\n", hr
);
2248 ok(type
== XmlNodeType_None
, "Unexpected type %d\n", type
);
2250 test_eof_state(reader
, TRUE
);
2252 hr
= IXmlReader_SetInput(reader
, NULL
);
2253 ok(hr
== S_OK
, "got %08x\n", hr
);
2255 test_eof_state(reader
, FALSE
);
2257 IXmlReader_Release(reader
);
2259 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2260 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2262 set_input_string(reader
, "<a/>text");
2264 type
= XmlNodeType_None
;
2265 hr
= IXmlReader_Read(reader
, &type
);
2266 ok(hr
== S_OK
, "got %#x\n", hr
);
2267 ok(type
== XmlNodeType_Element
, "Unexpected type %d\n", type
);
2269 test_eof_state(reader
, FALSE
);
2271 type
= XmlNodeType_Element
;
2272 hr
= IXmlReader_Read(reader
, &type
);
2273 ok(hr
== WC_E_SYNTAX
, "got %#x\n", hr
);
2274 ok(type
== XmlNodeType_None
, "Unexpected type %d\n", type
);
2276 test_eof_state(reader
, FALSE
);
2278 hr
= IXmlReader_SetInput(reader
, NULL
);
2279 ok(hr
== S_OK
, "got %08x\n", hr
);
2281 IXmlReader_Release(reader
);
2284 static void test_max_element_depth(void)
2286 static const char *xml
=
2294 XmlNodeType nodetype
;
2299 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2300 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2302 set_input_string(reader
, xml
);
2304 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_MaxElementDepth
, 2);
2305 ok(hr
== S_OK
, "got %08x\n", hr
);
2307 TEST_DEPTH(reader
, 0);
2309 hr
= IXmlReader_Read(reader
, NULL
);
2310 ok(hr
== S_OK
, "got %08x\n", hr
);
2312 TEST_DEPTH(reader
, 0);
2314 hr
= IXmlReader_Read(reader
, NULL
);
2315 ok(hr
== S_OK
, "got %08x\n", hr
);
2317 TEST_DEPTH(reader
, 1);
2318 TEST_READER_STATE(reader
, XmlReadState_Interactive
);
2320 hr
= IXmlReader_Read(reader
, NULL
);
2321 ok(hr
== SC_E_MAXELEMENTDEPTH
, "got %08x\n", hr
);
2323 TEST_DEPTH2(reader
, 0, 2);
2324 TEST_READER_STATE(reader
, XmlReadState_Error
);
2326 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_MaxElementDepth
, 10);
2327 ok(hr
== S_OK
, "got %08x\n", hr
);
2329 hr
= IXmlReader_Read(reader
, NULL
);
2330 ok(hr
== SC_E_MAXELEMENTDEPTH
, "got %08x\n", hr
);
2332 TEST_DEPTH2(reader
, 0, 2);
2333 TEST_READER_STATE(reader
, XmlReadState_Error
);
2335 /* test if stepping into attributes enforces depth limit too */
2336 set_input_string(reader
, xml
);
2338 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_MaxElementDepth
, 2);
2339 ok(hr
== S_OK
, "got %08x\n", hr
);
2341 TEST_DEPTH(reader
, 0);
2343 hr
= IXmlReader_Read(reader
, NULL
);
2344 ok(hr
== S_OK
, "got %08x\n", hr
);
2346 TEST_DEPTH(reader
, 0);
2348 hr
= IXmlReader_Read(reader
, NULL
);
2349 ok(hr
== S_OK
, "got %08x\n", hr
);
2351 TEST_DEPTH(reader
, 1);
2353 hr
= IXmlReader_MoveToFirstAttribute(reader
);
2354 ok(hr
== S_OK
, "got %08x\n", hr
);
2356 TEST_DEPTH(reader
, 2);
2357 TEST_READER_STATE(reader
, XmlReadState_Interactive
);
2360 hr
= IXmlReader_Read(reader
, &nodetype
);
2361 ok(hr
== SC_E_MAXELEMENTDEPTH
, "got %08x\n", hr
);
2362 ok(nodetype
== XmlNodeType_None
, "got node type %d\n", nodetype
);
2365 hr
= IXmlReader_Read(reader
, &nodetype
);
2366 ok(hr
== SC_E_MAXELEMENTDEPTH
, "got %08x\n", hr
);
2367 ok(nodetype
== XmlNodeType_None
, "got node type %d\n", nodetype
);
2369 TEST_DEPTH2(reader
, 0, 2);
2370 TEST_READER_STATE(reader
, XmlReadState_Error
);
2372 /* set max depth to 0, this disables depth limit */
2373 set_input_string(reader
, xml
);
2375 hr
= IXmlReader_SetProperty(reader
, XmlReaderProperty_MaxElementDepth
, 0);
2376 ok(hr
== S_OK
, "got %08x\n", hr
);
2379 while (IXmlReader_Read(reader
, NULL
) == S_OK
)
2381 ok(count
== 8, "Unexpected node number %u\n", count
);
2382 TEST_READER_STATE(reader
, XmlReadState_EndOfFile
);
2384 IXmlReader_Release(reader
);
2387 static void test_reader_position(void)
2389 static const char *xml
= "<c:a xmlns:c=\"nsdef c\" b=\"attr b\">\n</c:a>";
2395 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2396 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2398 TEST_READER_STATE(reader
, XmlReadState_Closed
);
2400 /* position methods with Null args */
2401 hr
= IXmlReader_GetLineNumber(reader
, NULL
);
2402 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
2404 hr
= IXmlReader_GetLinePosition(reader
, NULL
);
2405 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
2408 hr
= IXmlReader_GetLinePosition(reader
, &position
);
2409 ok(hr
== S_FALSE
, "got %#x\n", hr
);
2410 ok(position
== 0, "got %u\n", position
);
2413 hr
= IXmlReader_GetLineNumber(reader
, &position
);
2414 ok(hr
== S_FALSE
, "got %#x\n", hr
);
2415 ok(position
== 0, "got %u\n", position
);
2417 set_input_string(reader
, xml
);
2419 TEST_READER_STATE(reader
, XmlReadState_Initial
);
2420 TEST_READER_POSITION(reader
, 0, 0);
2421 hr
= IXmlReader_Read(reader
, &type
);
2422 ok(hr
== S_OK
, "got %08x\n", hr
);
2423 ok(type
== XmlNodeType_Element
, "got type %d\n", type
);
2424 TEST_READER_POSITION2(reader
, 1, 2, ~0u, 34);
2426 next_attribute(reader
);
2427 TEST_READER_POSITION2(reader
, 1, 6, ~0u, 34);
2429 next_attribute(reader
);
2430 TEST_READER_POSITION2(reader
, 1, 24, ~0u, 34);
2432 move_to_element(reader
);
2433 TEST_READER_POSITION2(reader
, 1, 2, ~0u, 34);
2435 hr
= IXmlReader_Read(reader
, &type
);
2436 ok(hr
== S_OK
, "got %08x\n", hr
);
2437 ok(type
== XmlNodeType_Whitespace
, "got type %d\n", type
);
2438 TEST_READER_POSITION2(reader
, 1, 35, 2, 6);
2440 hr
= IXmlReader_Read(reader
, &type
);
2441 ok(hr
== S_OK
, "got %08x\n", hr
);
2442 ok(type
== XmlNodeType_EndElement
, "got type %d\n", type
);
2443 TEST_READER_POSITION2(reader
, 2, 3, 2, 6);
2445 hr
= IXmlReader_SetInput(reader
, NULL
);
2446 ok(hr
== S_OK
, "got %08x\n", hr
);
2447 TEST_READER_STATE2(reader
, XmlReadState_Initial
, XmlReadState_Closed
);
2448 TEST_READER_POSITION(reader
, 0, 0);
2450 IXmlReader_Release(reader
);
2453 static void test_string_pointers(void)
2455 const WCHAR
*ns
, *nsq
, *empty
, *xmlns_ns
, *xmlns_name
, *name
, *p
, *q
, *xml
, *ptr
, *value
;
2459 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2460 ok(hr
== S_OK
, "S_OK, got %08x\n", hr
);
2462 set_input_string(reader
, "<elem xmlns=\"myns\">myns<elem2 /></elem>");
2464 read_node(reader
, XmlNodeType_Element
);
2465 empty
= reader_value(reader
, "");
2466 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2467 name
= reader_name(reader
, "elem");
2468 ok(name
== reader_qname(reader
, "elem"), "name != qname\n");
2469 ns
= reader_namespace(reader
, "myns");
2471 next_attribute(reader
);
2472 ptr
= reader_value(reader
, "myns");
2475 win_skip("attr value is different than namespace pointer, assuming old xmllite\n");
2476 IXmlReader_Release(reader
);
2479 ok(ns
== ptr
, "ns != value\n");
2480 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2481 xmlns_ns
= reader_namespace(reader
, "http://www.w3.org/2000/xmlns/");
2482 xmlns_name
= reader_name(reader
, "xmlns");
2483 ok(xmlns_name
== reader_qname(reader
, "xmlns"), "xmlns_name != qname\n");
2485 read_node(reader
, XmlNodeType_Text
);
2486 ok(ns
!= reader_value(reader
, "myns"), "ns == value\n");
2487 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2488 ok(empty
== reader_namespace(reader
, ""), "empty != namespace\n");
2489 ok(empty
== reader_name(reader
, ""), "empty != name\n");
2490 ok(empty
== reader_qname(reader
, ""), "empty != qname\n");
2492 read_node(reader
, XmlNodeType_Element
);
2493 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2494 ok(ns
== reader_namespace(reader
, "myns"), "empty != namespace\n");
2496 read_node(reader
, XmlNodeType_EndElement
);
2497 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2498 ok(name
== reader_name(reader
, "elem"), "empty != name\n");
2499 ok(name
== reader_qname(reader
, "elem"), "empty != qname\n");
2500 ok(ns
== reader_namespace(reader
, "myns"), "empty != namespace\n");
2502 set_input_string(reader
, "<elem xmlns:p=\"myns\" xmlns:q=\"mynsq\"><p:elem2 q:attr=\"\"></p:elem2></elem>");
2504 read_node(reader
, XmlNodeType_Element
);
2505 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2506 name
= reader_name(reader
, "elem");
2507 ok(empty
== reader_namespace(reader
, ""), "empty != namespace\n");
2509 next_attribute(reader
);
2510 ns
= reader_value(reader
, "myns");
2511 ok(xmlns_name
== reader_prefix(reader
, "xmlns"), "xmlns_name != prefix\n");
2512 p
= reader_name(reader
, "p");
2513 ok(xmlns_ns
== reader_namespace(reader
, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n");
2515 next_attribute(reader
);
2516 nsq
= reader_value(reader
, "mynsq");
2517 ok(xmlns_name
== reader_prefix(reader
, "xmlns"), "xmlns_name != prefix\n");
2518 q
= reader_name(reader
, "q");
2519 ok(xmlns_ns
== reader_namespace(reader
, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n");
2521 read_node(reader
, XmlNodeType_Element
);
2522 ok(p
== reader_prefix(reader
, "p"), "p != prefix\n");
2523 ok(ns
== reader_namespace(reader
, "myns"), "empty != namespace\n");
2524 name
= reader_qname(reader
, "p:elem2");
2526 next_attribute(reader
);
2527 ok(empty
!= reader_value(reader
, ""), "empty == value\n");
2528 ok(q
== reader_prefix(reader
, "q"), "q != prefix\n");
2529 ok(nsq
== reader_namespace(reader
, "mynsq"), "nsq != namespace\n");
2531 read_node(reader
, XmlNodeType_EndElement
);
2532 ptr
= reader_qname(reader
, "p:elem2"); todo_wine
ok(name
!= ptr
, "q == qname\n");
2534 set_input_string(reader
, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
2536 read_node(reader
, XmlNodeType_XmlDeclaration
);
2537 ok(empty
== reader_value(reader
, ""), "empty != value\n");
2538 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2539 xml
= reader_name(reader
, "xml");
2540 ptr
= reader_qname(reader
, "xml"); todo_wine
ok(xml
== ptr
, "xml != qname\n");
2541 ok(empty
== reader_namespace(reader
, ""), "empty != namespace\n");
2543 next_attribute(reader
);
2544 ok(empty
== reader_prefix(reader
, ""), "empty != prefix\n");
2545 ok(empty
== reader_namespace(reader
, ""), "empty != namespace\n");
2547 set_input_string(reader
, "<elem xmlns:p=\"myns\"><p:elem2 attr=\"\" /></elem>");
2549 read_node(reader
, XmlNodeType_Element
);
2550 next_attribute(reader
);
2551 read_value_char(reader
, 'm');
2552 p
= reader_value(reader
, "yns");
2554 read_node(reader
, XmlNodeType_Element
);
2555 ns
= reader_namespace(reader
, "myns");
2556 ok(ns
+1 == p
, "ns+1 != p\n");
2558 set_input_string(reader
, "<elem attr=\"value\"></elem>");
2560 read_node(reader
, XmlNodeType_Element
);
2561 next_attribute(reader
);
2562 name
= reader_name(reader
, "attr");
2563 value
= reader_value(reader
, "value");
2565 move_to_element(reader
);
2566 next_attribute(reader
);
2567 ok(name
== reader_name(reader
, "attr"), "attr pointer changed\n");
2568 ok(value
== reader_value(reader
, "value"), "value pointer changed\n");
2570 IXmlReader_Release(reader
);
2573 static void test_attribute_by_name(void)
2575 static const char *xml
= "<a><elem xmlns=\"myns\" a=\"value a\" b=\"value b\" xmlns:ns=\"ns uri\" "
2576 "ns:c=\"value c\" c=\"value c2\"/></a>";
2577 static const WCHAR xmlns_uriW
[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
2578 '2','0','0','0','/','x','m','l','n','s','/',0};
2579 static const WCHAR nsuriW
[] = {'n','s',' ','u','r','i',0};
2580 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
2581 static const WCHAR mynsW
[] = {'m','y','n','s',0};
2582 static const WCHAR nsW
[] = {'n','s',0};
2583 static const WCHAR emptyW
[] = {0};
2584 static const WCHAR aW
[] = {'a',0};
2585 static const WCHAR bW
[] = {'b',0};
2586 static const WCHAR cW
[] = {'c',0};
2590 hr
= CreateXmlReader(&IID_IXmlReader
, (void **)&reader
, NULL
);
2591 ok(hr
== S_OK
, "Failed to create reader, hr %#x.\n", hr
);
2593 set_input_string(reader
, xml
);
2595 hr
= IXmlReader_MoveToAttributeByName(reader
, NULL
, NULL
);
2596 ok(hr
== E_INVALIDARG
|| broken(hr
== S_FALSE
) /* WinXP */, "Unexpected hr %#x.\n", hr
);
2598 hr
= IXmlReader_MoveToAttributeByName(reader
, emptyW
, NULL
);
2599 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
2601 read_node(reader
, XmlNodeType_Element
);
2603 hr
= IXmlReader_MoveToAttributeByName(reader
, emptyW
, NULL
);
2604 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
2606 read_node(reader
, XmlNodeType_Element
);
2608 hr
= IXmlReader_MoveToAttributeByName(reader
, NULL
, NULL
);
2609 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
2611 hr
= IXmlReader_MoveToAttributeByName(reader
, NULL
, xmlns_uriW
);
2612 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
2614 hr
= IXmlReader_MoveToAttributeByName(reader
, emptyW
, xmlns_uriW
);
2615 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
2617 hr
= IXmlReader_MoveToAttributeByName(reader
, xmlnsW
, NULL
);
2618 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
2620 hr
= IXmlReader_MoveToAttributeByName(reader
, xmlnsW
, xmlns_uriW
);
2621 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2622 reader_value(reader
, "myns");
2624 hr
= IXmlReader_MoveToAttributeByName(reader
, aW
, NULL
);
2625 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2626 reader_value(reader
, "value a");
2628 hr
= IXmlReader_MoveToAttributeByName(reader
, bW
, NULL
);
2629 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2630 reader_value(reader
, "value b");
2632 hr
= IXmlReader_MoveToAttributeByName(reader
, aW
, mynsW
);
2633 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
2635 hr
= IXmlReader_MoveToAttributeByName(reader
, nsW
, NULL
);
2636 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
2638 hr
= IXmlReader_MoveToAttributeByName(reader
, nsW
, xmlns_uriW
);
2639 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2640 reader_value(reader
, "ns uri");
2642 hr
= IXmlReader_MoveToAttributeByName(reader
, bW
, emptyW
);
2643 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2644 reader_value(reader
, "value b");
2646 hr
= IXmlReader_MoveToAttributeByName(reader
, cW
, NULL
);
2647 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2648 reader_value(reader
, "value c2");
2650 hr
= IXmlReader_MoveToAttributeByName(reader
, cW
, nsuriW
);
2651 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
2652 reader_value(reader
, "value c");
2654 IXmlReader_Release(reader
);
2659 test_reader_create();
2661 test_reader_state();
2662 test_read_attribute();
2664 test_read_comment();
2666 test_read_system_dtd();
2667 test_read_public_dtd();
2668 test_read_element();
2669 test_isemptyelement();
2672 test_read_pending();
2673 test_readvaluechunk();
2674 test_read_xmldeclaration();
2675 test_reader_properties();
2677 test_namespaceuri();
2678 test_read_charref();
2679 test_encoding_detection();
2681 test_max_element_depth();
2682 test_reader_position();
2683 test_string_pointers();
2684 test_attribute_by_name();