xmllite/tests: Some tests for reader position.
[wine.git] / dlls / xmllite / tests / reader.c
blobb0713a6616b95a36cffd303e7d00f124bbb67161
1 /*
2 * IXmlReader tests
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
21 #define COBJMACROS
22 #define CONST_VTABLE
24 #include <stdarg.h>
25 #include <stdio.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "initguid.h"
30 #include "ole2.h"
31 #include "xmllite.h"
32 #include "wine/test.h"
34 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
36 static WCHAR *a2w(const char *str)
38 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
39 WCHAR *ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
40 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
41 return ret;
44 static void free_str(WCHAR *str)
46 HeapFree(GetProcessHeap(), 0, str);
49 static const char xmldecl_full[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
50 static const char xmldecl_short[] = "<?xml version=\"1.0\"?><RegistrationInfo/>";
52 static IStream *create_stream_on_data(const void *data, unsigned int size)
54 IStream *stream = NULL;
55 HGLOBAL hglobal;
56 void *ptr;
57 HRESULT hr;
59 hglobal = GlobalAlloc(GHND, size);
60 ptr = GlobalLock(hglobal);
62 memcpy(ptr, data, size);
64 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
65 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
66 ok(stream != NULL, "Expected non-NULL stream\n");
68 GlobalUnlock(hglobal);
70 return stream;
73 static void test_reader_pos(IXmlReader *reader, UINT line, UINT pos, UINT line_broken,
74 UINT pos_broken, int _line_)
76 UINT l = ~0u, p = ~0u;
77 BOOL broken_state;
79 IXmlReader_GetLineNumber(reader, &l);
80 IXmlReader_GetLinePosition(reader, &p);
82 if (line_broken == ~0u && pos_broken == ~0u)
83 broken_state = FALSE;
84 else
85 broken_state = broken((line_broken == ~0u ? line : line_broken) == l &&
86 (pos_broken == ~0u ? pos : pos_broken) == p);
88 ok_(__FILE__, _line_)((l == line && pos == p) || broken_state,
89 "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p);
91 #define TEST_READER_POSITION(reader, line, pos) \
92 test_reader_pos(reader, line, pos, ~0u, ~0u, __LINE__)
93 #define TEST_READER_POSITION2(reader, line, pos, line_broken, pos_broken) \
94 test_reader_pos(reader, line, pos, line_broken, pos_broken, __LINE__)
96 typedef struct input_iids_t {
97 IID iids[10];
98 int count;
99 } input_iids_t;
101 static const IID *setinput_full[] = {
102 &IID_IXmlReaderInput,
103 &IID_IStream,
104 &IID_ISequentialStream,
105 NULL
108 /* this applies to early xmllite versions */
109 static const IID *setinput_full_old[] = {
110 &IID_IXmlReaderInput,
111 &IID_ISequentialStream,
112 &IID_IStream,
113 NULL
116 /* after ::SetInput(IXmlReaderInput*) */
117 static const IID *setinput_readerinput[] = {
118 &IID_IStream,
119 &IID_ISequentialStream,
120 NULL
123 static const IID *empty_seq[] = {
124 NULL
127 static input_iids_t input_iids;
129 static void ok_iids_(const input_iids_t *iids, const IID **expected, const IID **exp_broken, BOOL todo, int line)
131 int i = 0, size = 0;
133 while (expected[i++]) size++;
135 todo_wine_if (todo)
136 ok_(__FILE__, line)(iids->count == size, "Sequence size mismatch (%d), got (%d)\n", size, iids->count);
138 if (iids->count != size) return;
140 for (i = 0; i < size; i++) {
141 ok_(__FILE__, line)(IsEqualGUID(&iids->iids[i], expected[i]) ||
142 (exp_broken ? broken(IsEqualGUID(&iids->iids[i], exp_broken[i])) : FALSE),
143 "Wrong IID(%d), got %s\n", i, wine_dbgstr_guid(&iids->iids[i]));
146 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
148 static const char *state_to_str(XmlReadState state)
150 static const char* state_names[] = {
151 "XmlReadState_Initial",
152 "XmlReadState_Interactive",
153 "XmlReadState_Error",
154 "XmlReadState_EndOfFile",
155 "XmlReadState_Closed"
158 static const char unknown[] = "unknown";
160 switch (state)
162 case XmlReadState_Initial:
163 case XmlReadState_Interactive:
164 case XmlReadState_Error:
165 case XmlReadState_EndOfFile:
166 case XmlReadState_Closed:
167 return state_names[state];
168 default:
169 return unknown;
173 static const char *type_to_str(XmlNodeType type)
175 static const char* type_names[] = {
176 "XmlNodeType_None",
177 "XmlNodeType_Element",
178 "XmlNodeType_Attribute",
179 "XmlNodeType_Text",
180 "XmlNodeType_CDATA",
181 "", "",
182 "XmlNodeType_ProcessingInstruction",
183 "XmlNodeType_Comment",
185 "XmlNodeType_DocumentType",
186 "", "",
187 "XmlNodeType_Whitespace",
189 "XmlNodeType_EndElement",
191 "XmlNodeType_XmlDeclaration"
194 static const char unknown[] = "unknown";
196 switch (type)
198 case XmlNodeType_None:
199 case XmlNodeType_Element:
200 case XmlNodeType_Attribute:
201 case XmlNodeType_Text:
202 case XmlNodeType_CDATA:
203 case XmlNodeType_ProcessingInstruction:
204 case XmlNodeType_Comment:
205 case XmlNodeType_DocumentType:
206 case XmlNodeType_Whitespace:
207 case XmlNodeType_EndElement:
208 case XmlNodeType_XmlDeclaration:
209 return type_names[type];
210 default:
211 return unknown;
215 static void test_read_state(IXmlReader *reader, XmlReadState expected,
216 XmlReadState exp_broken, int line)
218 BOOL broken_state;
219 LONG_PTR state;
221 state = -1; /* invalid state value */
222 IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
224 if (exp_broken == -1)
225 broken_state = FALSE;
226 else
227 broken_state = broken(exp_broken == state);
229 ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n",
230 state_to_str(expected), state_to_str(state));
233 #define TEST_READER_STATE(reader, state) test_read_state(reader, state, -1, __LINE__)
234 #define TEST_READER_STATE2(reader, state, brk) test_read_state(reader, state, brk, __LINE__)
236 typedef struct _testinput
238 IUnknown IUnknown_iface;
239 LONG ref;
240 } testinput;
242 static inline testinput *impl_from_IUnknown(IUnknown *iface)
244 return CONTAINING_RECORD(iface, testinput, IUnknown_iface);
247 static HRESULT WINAPI testinput_QueryInterface(IUnknown *iface, REFIID riid, void** ppvObj)
249 if (IsEqualGUID( riid, &IID_IUnknown ))
251 *ppvObj = iface;
252 IUnknown_AddRef(iface);
253 return S_OK;
256 input_iids.iids[input_iids.count++] = *riid;
258 *ppvObj = NULL;
260 return E_NOINTERFACE;
263 static ULONG WINAPI testinput_AddRef(IUnknown *iface)
265 testinput *This = impl_from_IUnknown(iface);
266 return InterlockedIncrement(&This->ref);
269 static ULONG WINAPI testinput_Release(IUnknown *iface)
271 testinput *This = impl_from_IUnknown(iface);
272 LONG ref;
274 ref = InterlockedDecrement(&This->ref);
275 if (ref == 0)
277 HeapFree(GetProcessHeap(), 0, This);
280 return ref;
283 static const struct IUnknownVtbl testinput_vtbl =
285 testinput_QueryInterface,
286 testinput_AddRef,
287 testinput_Release
290 static HRESULT testinput_createinstance(void **ppObj)
292 testinput *input;
294 input = HeapAlloc(GetProcessHeap(), 0, sizeof (*input));
295 if(!input) return E_OUTOFMEMORY;
297 input->IUnknown_iface.lpVtbl = &testinput_vtbl;
298 input->ref = 1;
300 *ppObj = &input->IUnknown_iface;
302 return S_OK;
305 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
307 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
309 *obj = iface;
310 return S_OK;
313 *obj = NULL;
314 return E_NOINTERFACE;
317 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
319 return 2;
322 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
324 return 1;
327 static int stream_readcall;
329 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
331 static const char xml[] = "<!-- comment -->";
333 if (stream_readcall++)
335 *pread = 0;
336 return E_PENDING;
339 *pread = sizeof(xml) / 2;
340 memcpy(pv, xml, *pread);
341 return S_OK;
344 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
346 ok(0, "unexpected call\n");
347 return E_NOTIMPL;
350 static const ISequentialStreamVtbl teststreamvtbl =
352 teststream_QueryInterface,
353 teststream_AddRef,
354 teststream_Release,
355 teststream_Read,
356 teststream_Write
359 static HRESULT WINAPI resolver_QI(IXmlResolver *iface, REFIID riid, void **obj)
361 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
363 if (IsEqualIID(riid, &IID_IXmlResolver) || IsEqualIID(riid, &IID_IUnknown))
365 *obj = iface;
366 IXmlResolver_AddRef(iface);
367 return S_OK;
370 *obj = NULL;
371 return E_NOINTERFACE;
374 static ULONG WINAPI resolver_AddRef(IXmlResolver *iface)
376 return 2;
379 static ULONG WINAPI resolver_Release(IXmlResolver *iface)
381 return 1;
384 static HRESULT WINAPI resolver_ResolveUri(IXmlResolver *iface, const WCHAR *base_uri,
385 const WCHAR *public_id, const WCHAR *system_id, IUnknown **input)
387 ok(0, "unexpected call\n");
388 return E_NOTIMPL;
391 static const IXmlResolverVtbl resolvervtbl =
393 resolver_QI,
394 resolver_AddRef,
395 resolver_Release,
396 resolver_ResolveUri
399 static IXmlResolver testresolver = { &resolvervtbl };
401 static void test_reader_create(void)
403 IXmlResolver *resolver;
404 HRESULT hr;
405 IXmlReader *reader;
406 IUnknown *input;
407 DtdProcessing dtd;
408 XmlNodeType nodetype;
410 /* crashes native */
411 if (0)
413 CreateXmlReader(&IID_IXmlReader, NULL, NULL);
414 CreateXmlReader(NULL, (void**)&reader, NULL);
417 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
418 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
420 TEST_READER_STATE(reader, XmlReadState_Closed);
422 nodetype = XmlNodeType_Element;
423 hr = IXmlReader_GetNodeType(reader, &nodetype);
424 ok(hr == S_FALSE, "got %08x\n", hr);
425 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
427 /* crashes on XP, 2k3, works on newer versions */
428 if (0)
430 hr = IXmlReader_GetNodeType(reader, NULL);
431 ok(hr == E_INVALIDARG, "got %08x\n", hr);
434 resolver = (void*)0xdeadbeef;
435 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
436 ok(hr == S_OK, "got 0x%08x\n", hr);
437 ok(resolver == NULL, "got %p\n", resolver);
439 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
440 ok(hr == S_OK, "got 0x%08x\n", hr);
442 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR)&testresolver);
443 ok(hr == S_OK, "got 0x%08x\n", hr);
445 resolver = NULL;
446 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
447 ok(hr == S_OK, "got 0x%08x\n", hr);
448 ok(resolver == &testresolver, "got %p\n", resolver);
449 IXmlResolver_Release(resolver);
451 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
452 ok(hr == S_OK, "got 0x%08x\n", hr);
454 dtd = 2;
455 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_DtdProcessing, (LONG_PTR*)&dtd);
456 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
457 ok(dtd == DtdProcessing_Prohibit, "got %d\n", dtd);
459 dtd = 2;
460 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, dtd);
461 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
463 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, -1);
464 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
466 /* Null input pointer, releases previous input */
467 hr = IXmlReader_SetInput(reader, NULL);
468 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
470 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
472 /* test input interface selection sequence */
473 hr = testinput_createinstance((void**)&input);
474 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
476 if (hr == S_OK)
478 input_iids.count = 0;
479 hr = IXmlReader_SetInput(reader, input);
480 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
481 ok_iids(&input_iids, setinput_full, setinput_full_old, FALSE);
482 IUnknown_Release(input);
484 IXmlReader_Release(reader);
487 static void test_readerinput(void)
489 IXmlReaderInput *reader_input;
490 IXmlReader *reader, *reader2;
491 IUnknown *obj, *input;
492 IStream *stream, *stream2;
493 XmlNodeType nodetype;
494 HRESULT hr;
495 LONG ref;
497 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, NULL);
498 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
499 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, &reader_input);
500 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
502 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
503 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
505 ref = IStream_AddRef(stream);
506 ok(ref == 2, "Expected 2, got %d\n", ref);
507 IStream_Release(stream);
508 hr = CreateXmlReaderInputWithEncodingName((IUnknown*)stream, NULL, NULL, FALSE, NULL, &reader_input);
509 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
511 hr = IUnknown_QueryInterface(reader_input, &IID_IStream, (void**)&stream2);
512 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
514 hr = IUnknown_QueryInterface(reader_input, &IID_ISequentialStream, (void**)&stream2);
515 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
517 /* IXmlReaderInput grabs a stream reference */
518 ref = IStream_AddRef(stream);
519 ok(ref == 3, "Expected 3, got %d\n", ref);
520 IStream_Release(stream);
522 /* try ::SetInput() with valid IXmlReaderInput */
523 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
524 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
526 ref = IUnknown_AddRef(reader_input);
527 ok(ref == 2, "Expected 2, got %d\n", ref);
528 IUnknown_Release(reader_input);
530 hr = IXmlReader_SetInput(reader, reader_input);
531 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
533 TEST_READER_STATE(reader, XmlReadState_Initial);
535 nodetype = XmlNodeType_Element;
536 hr = IXmlReader_GetNodeType(reader, &nodetype);
537 ok(hr == S_OK, "got %08x\n", hr);
538 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
540 /* IXmlReader grabs a IXmlReaderInput reference */
541 ref = IUnknown_AddRef(reader_input);
542 ok(ref == 3, "Expected 3, got %d\n", ref);
543 IUnknown_Release(reader_input);
545 ref = IStream_AddRef(stream);
546 ok(ref == 4, "Expected 4, got %d\n", ref);
547 IStream_Release(stream);
549 /* reset input and check state */
550 hr = IXmlReader_SetInput(reader, NULL);
551 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
553 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
555 IXmlReader_Release(reader);
557 ref = IStream_AddRef(stream);
558 ok(ref == 3, "Expected 3, got %d\n", ref);
559 IStream_Release(stream);
561 ref = IUnknown_AddRef(reader_input);
562 ok(ref == 2, "Expected 2, got %d\n", ref);
563 IUnknown_Release(reader_input);
565 /* IID_IXmlReaderInput */
566 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
567 so it's not a COM interface actually.
568 Such query will be used only to check if input is really IXmlReaderInput */
569 obj = (IUnknown*)0xdeadbeef;
570 hr = IUnknown_QueryInterface(reader_input, &IID_IXmlReaderInput, (void**)&obj);
571 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
572 ref = IUnknown_AddRef(reader_input);
573 ok(ref == 3, "Expected 3, got %d\n", ref);
574 IUnknown_Release(reader_input);
576 IUnknown_Release(reader_input);
577 IUnknown_Release(reader_input);
578 IStream_Release(stream);
580 /* test input interface selection sequence */
581 input = NULL;
582 hr = testinput_createinstance((void**)&input);
583 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
585 input_iids.count = 0;
586 ref = IUnknown_AddRef(input);
587 ok(ref == 2, "Expected 2, got %d\n", ref);
588 IUnknown_Release(input);
589 hr = CreateXmlReaderInputWithEncodingName(input, NULL, NULL, FALSE, NULL, &reader_input);
590 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
591 ok_iids(&input_iids, empty_seq, NULL, FALSE);
592 /* IXmlReaderInput stores stream interface as IUnknown */
593 ref = IUnknown_AddRef(input);
594 ok(ref == 3, "Expected 3, got %d\n", ref);
595 IUnknown_Release(input);
597 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
598 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
600 input_iids.count = 0;
601 ref = IUnknown_AddRef(reader_input);
602 ok(ref == 2, "Expected 2, got %d\n", ref);
603 IUnknown_Release(reader_input);
604 ref = IUnknown_AddRef(input);
605 ok(ref == 3, "Expected 3, got %d\n", ref);
606 IUnknown_Release(input);
607 hr = IXmlReader_SetInput(reader, reader_input);
608 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
609 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
611 TEST_READER_STATE(reader, XmlReadState_Closed);
613 ref = IUnknown_AddRef(input);
614 ok(ref == 3, "Expected 3, got %d\n", ref);
615 IUnknown_Release(input);
617 ref = IUnknown_AddRef(reader_input);
618 ok(ref == 3 || broken(ref == 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
619 "Expected 3, got %d\n", ref);
620 IUnknown_Release(reader_input);
621 /* repeat another time, no check or caching here */
622 input_iids.count = 0;
623 hr = IXmlReader_SetInput(reader, reader_input);
624 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
625 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
627 /* another reader */
628 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader2, NULL);
629 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
631 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
632 ::SetInput() level, each time it's called */
633 input_iids.count = 0;
634 hr = IXmlReader_SetInput(reader2, reader_input);
635 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
636 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
638 IXmlReader_Release(reader2);
639 IXmlReader_Release(reader);
641 IUnknown_Release(reader_input);
642 IUnknown_Release(input);
645 static void test_reader_state(void)
647 XmlNodeType nodetype;
648 IXmlReader *reader;
649 IStream *stream;
650 HRESULT hr;
652 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
653 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
655 /* invalid arguments */
656 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, NULL);
657 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
659 /* attempt to read on closed reader */
660 TEST_READER_STATE(reader, XmlReadState_Closed);
662 if (0)
664 /* newer versions crash here, probably because no input was set */
665 hr = IXmlReader_Read(reader, &nodetype);
666 ok(hr == S_FALSE, "got %08x\n", hr);
669 stream = create_stream_on_data("xml", sizeof("xml"));
671 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
672 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
674 TEST_READER_STATE(reader, XmlReadState_Initial);
676 nodetype = XmlNodeType_Element;
677 hr = IXmlReader_Read(reader, &nodetype);
678 todo_wine
679 ok(FAILED(hr), "got %08x\n", hr);
680 ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype);
682 todo_wine
683 TEST_READER_STATE(reader, XmlReadState_Error);
685 nodetype = XmlNodeType_Element;
686 hr = IXmlReader_Read(reader, &nodetype);
687 todo_wine
688 ok(FAILED(hr), "got %08x\n", hr);
689 ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype);
691 IStream_Release(stream);
692 IXmlReader_Release(reader);
695 static void test_reader_depth(IXmlReader *reader, UINT depth, UINT brk, int line)
697 BOOL condition;
698 UINT d = ~0u;
700 IXmlReader_GetDepth(reader, &d);
702 condition = d == depth;
703 if (brk != ~0u)
704 condition |= broken(d == brk);
705 ok_(__FILE__, line)(condition, "Unexpected nesting depth %u, expected %u\n", d, depth);
708 #define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__)
709 #define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__)
711 static void test_read_xmldeclaration(void)
713 static const WCHAR xmlW[] = {'x','m','l',0};
714 static const WCHAR RegistrationInfoW[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0};
715 static const struct
717 WCHAR name[12];
718 WCHAR val[12];
719 } name_val[] =
721 { {'v','e','r','s','i','o','n',0}, {'1','.','0',0} },
722 { {'e','n','c','o','d','i','n','g',0}, {'U','T','F','-','8',0} },
723 { {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
725 IXmlReader *reader;
726 IStream *stream;
727 HRESULT hr;
728 XmlNodeType type;
729 UINT count = 0, len, i;
730 BOOL ret;
731 const WCHAR *val;
733 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
734 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
736 stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
738 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
739 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
741 hr = IXmlReader_GetAttributeCount(reader, &count);
742 ok(hr == S_OK, "got %08x\n", hr);
743 ok(count == 0, "got %d\n", count);
745 /* try to move without attributes */
746 hr = IXmlReader_MoveToElement(reader);
747 ok(hr == S_FALSE, "got %08x\n", hr);
749 hr = IXmlReader_MoveToNextAttribute(reader);
750 ok(hr == S_FALSE, "got %08x\n", hr);
752 hr = IXmlReader_MoveToFirstAttribute(reader);
753 ok(hr == S_FALSE, "got %08x\n", hr);
755 TEST_READER_POSITION(reader, 0, 0);
757 type = -1;
758 hr = IXmlReader_Read(reader, &type);
759 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
760 ok(type == XmlNodeType_XmlDeclaration,
761 "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type));
762 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
763 todo_wine
764 TEST_READER_POSITION2(reader, 1, 3, ~0u, 55);
766 TEST_DEPTH(reader, 0);
767 TEST_READER_STATE(reader, XmlReadState_Interactive);
769 hr = IXmlReader_GetValue(reader, &val, NULL);
770 ok(hr == S_OK, "got %08x\n", hr);
771 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
773 /* check attributes */
774 hr = IXmlReader_MoveToNextAttribute(reader);
775 ok(hr == S_OK, "got %08x\n", hr);
777 TEST_DEPTH(reader, 1);
779 type = XmlNodeType_None;
780 hr = IXmlReader_GetNodeType(reader, &type);
781 ok(hr == S_OK, "got %08x\n", hr);
782 ok(type == XmlNodeType_Attribute, "got %d\n", type);
784 todo_wine
785 TEST_READER_POSITION2(reader, 1, 7, ~0u, 55);
787 /* try to move from last attribute */
788 hr = IXmlReader_MoveToNextAttribute(reader);
789 ok(hr == S_OK, "got %08x\n", hr);
790 hr = IXmlReader_MoveToNextAttribute(reader);
791 ok(hr == S_OK, "got %08x\n", hr);
792 hr = IXmlReader_MoveToNextAttribute(reader);
793 ok(hr == S_FALSE, "got %08x\n", hr);
795 type = XmlNodeType_None;
796 hr = IXmlReader_GetNodeType(reader, &type);
797 ok(hr == S_OK, "got %08x\n", hr);
798 ok(type == XmlNodeType_Attribute, "got %d\n", type);
800 hr = IXmlReader_MoveToFirstAttribute(reader);
801 ok(hr == S_OK, "got %08x\n", hr);
802 todo_wine
803 TEST_READER_POSITION2(reader, 1, 7, ~0u, 55);
805 hr = IXmlReader_GetAttributeCount(reader, NULL);
806 ok(hr == E_INVALIDARG, "got %08x\n", hr);
808 hr = IXmlReader_GetAttributeCount(reader, &count);
809 ok(hr == S_OK, "got %08x\n", hr);
810 ok(count == 3, "Expected 3, got %d\n", count);
812 for (i = 0; i < count; i++)
814 len = 0;
815 hr = IXmlReader_GetLocalName(reader, &val, &len);
816 ok(hr == S_OK, "got %08x\n", hr);
817 ok(len == lstrlenW(name_val[i].name), "expected %u, got %u\n", lstrlenW(name_val[i].name), len);
818 ok(!lstrcmpW(name_val[i].name, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].name), wine_dbgstr_w(val));
820 len = 0;
821 hr = IXmlReader_GetValue(reader, &val, &len);
822 ok(hr == S_OK, "got %08x\n", hr);
823 ok(len == lstrlenW(name_val[i].val), "expected %u, got %u\n", lstrlenW(name_val[i].val), len);
824 ok(!lstrcmpW(name_val[i].val, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].val), wine_dbgstr_w(val));
826 hr = IXmlReader_MoveToNextAttribute(reader);
827 ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr);
830 TEST_DEPTH(reader, 1);
832 hr = IXmlReader_MoveToElement(reader);
833 ok(hr == S_OK, "got %08x\n", hr);
835 type = XmlNodeType_None;
836 hr = IXmlReader_GetNodeType(reader, &type);
837 ok(hr == S_OK, "got %08x\n", hr);
838 ok(type == XmlNodeType_XmlDeclaration, "got %d\n", type);
840 type = XmlNodeType_XmlDeclaration;
841 hr = IXmlReader_Read(reader, &type);
842 /* newer versions return syntax error here cause document is incomplete,
843 it makes more sense than invalid char error */
844 todo_wine {
845 ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
846 ok(type == XmlNodeType_None, "got %d\n", type);
848 IStream_Release(stream);
850 /* test short variant */
851 stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
853 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
854 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
856 type = -1;
857 hr = IXmlReader_Read(reader, &type);
858 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
859 ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type));
860 todo_wine
861 TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
862 TEST_READER_STATE(reader, XmlReadState_Interactive);
864 hr = IXmlReader_GetAttributeCount(reader, &count);
865 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
866 ok(count == 1, "expected 1, got %d\n", count);
868 ret = IXmlReader_IsEmptyElement(reader);
869 ok(!ret, "element should not be empty\n");
871 hr = IXmlReader_GetValue(reader, &val, NULL);
872 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
873 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
875 val = NULL;
876 hr = IXmlReader_GetLocalName(reader, &val, NULL);
877 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
878 ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val));
880 val = NULL;
881 hr = IXmlReader_GetQualifiedName(reader, &val, NULL);
882 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
883 ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val));
885 /* check attributes */
886 hr = IXmlReader_MoveToNextAttribute(reader);
887 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
889 type = -1;
890 hr = IXmlReader_GetNodeType(reader, &type);
891 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
892 ok(type == XmlNodeType_Attribute, "got %d\n", type);
893 todo_wine
894 TEST_READER_POSITION2(reader, 1, 7, ~0u, 21);
896 /* try to move from last attribute */
897 hr = IXmlReader_MoveToNextAttribute(reader);
898 ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
900 type = -1;
901 hr = IXmlReader_Read(reader, &type);
902 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
903 ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type));
904 todo_wine
905 TEST_READER_POSITION2(reader, 1, 23, ~0u, 40);
906 TEST_READER_STATE(reader, XmlReadState_Interactive);
908 hr = IXmlReader_GetAttributeCount(reader, &count);
909 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
910 ok(count == 0, "expected 0, got %d\n", count);
912 ret = IXmlReader_IsEmptyElement(reader);
913 ok(ret, "element should be empty\n");
915 hr = IXmlReader_GetValue(reader, &val, NULL);
916 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
917 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
919 hr = IXmlReader_GetLocalName(reader, &val, NULL);
920 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
921 ok(!lstrcmpW(val, RegistrationInfoW), "got %s\n", wine_dbgstr_w(val));
923 type = -1;
924 hr = IXmlReader_Read(reader, &type);
925 todo_wine
926 ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
927 ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
928 todo_wine {
929 TEST_READER_POSITION(reader, 1, 41);
930 TEST_READER_STATE(reader, XmlReadState_Error);
932 IStream_Release(stream);
933 IXmlReader_Release(reader);
936 struct test_entry {
937 const char *xml;
938 const char *name;
939 const char *value;
940 HRESULT hr;
941 HRESULT hr_broken; /* this is set to older version results */
942 BOOL todo;
945 static struct test_entry comment_tests[] = {
946 { "<!-- comment -->", "", " comment ", S_OK },
947 { "<!-- - comment-->", "", " - comment", S_OK },
948 { "<!-- -- comment-->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
949 { "<!-- -- comment--->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
950 { NULL }
953 static void test_read_comment(void)
955 static const char *teststr = "<a>text<!-- comment --></a>";
956 struct test_entry *test = comment_tests;
957 static const XmlNodeType types[] =
959 XmlNodeType_Element,
960 XmlNodeType_Text,
961 XmlNodeType_Comment,
962 XmlNodeType_EndElement,
964 unsigned int i = 0;
965 IXmlReader *reader;
966 XmlNodeType type;
967 IStream *stream;
968 HRESULT hr;
970 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
971 ok(hr == S_OK, "S_OK, got %08x\n", hr);
973 stream = create_stream_on_data(teststr, strlen(teststr));
974 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
975 ok(hr == S_OK, "got %08x\n", hr);
977 while (IXmlReader_Read(reader, &type) == S_OK)
979 const WCHAR *value;
981 ok(type == types[i], "%d: unexpected node type %d\n", i, type);
983 if (type == XmlNodeType_Text || type == XmlNodeType_Comment)
985 hr = IXmlReader_GetValue(reader, &value, NULL);
986 ok(hr == S_OK, "got %08x\n", hr);
987 ok(*value != 0, "Expected node value\n");
989 i++;
992 IStream_Release(stream);
994 while (test->xml)
996 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
997 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
998 ok(hr == S_OK, "got %08x\n", hr);
1000 type = XmlNodeType_None;
1001 hr = IXmlReader_Read(reader, &type);
1002 if (test->hr_broken)
1003 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1004 else
1005 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1006 if (hr == S_OK)
1008 const WCHAR *str;
1009 WCHAR *str_exp;
1010 UINT len;
1012 ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml);
1014 len = 1;
1015 str = NULL;
1016 hr = IXmlReader_GetLocalName(reader, &str, &len);
1017 ok(hr == S_OK, "got 0x%08x\n", hr);
1018 ok(len == strlen(test->name), "got %u\n", len);
1019 str_exp = a2w(test->name);
1020 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1021 free_str(str_exp);
1023 len = 1;
1024 str = NULL;
1025 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1026 ok(hr == S_OK, "got 0x%08x\n", hr);
1027 ok(len == strlen(test->name), "got %u\n", len);
1028 str_exp = a2w(test->name);
1029 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1030 free_str(str_exp);
1032 /* value */
1033 len = 1;
1034 str = NULL;
1035 hr = IXmlReader_GetValue(reader, &str, &len);
1036 ok(hr == S_OK, "got 0x%08x\n", hr);
1037 ok(len == strlen(test->value), "got %u\n", len);
1038 str_exp = a2w(test->value);
1039 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1040 free_str(str_exp);
1043 IStream_Release(stream);
1044 test++;
1047 IXmlReader_Release(reader);
1050 static struct test_entry pi_tests[] = {
1051 { "<?pi?>", "pi", "", S_OK },
1052 { "<?pi ?>", "pi", "", S_OK },
1053 { "<?pi ?>", "pi", "", S_OK },
1054 { "<?pi pi data?>", "pi", "pi data", S_OK },
1055 { "<?pi pi data ?>", "pi", "pi data ", S_OK },
1056 { "<?pi data ?>", "pi", "data ", S_OK },
1057 { "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
1058 { "<?:pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
1059 { "<?-pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
1060 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK },
1061 { NULL }
1064 static void test_read_pi(void)
1066 struct test_entry *test = pi_tests;
1067 IXmlReader *reader;
1068 HRESULT hr;
1070 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1071 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1073 while (test->xml)
1075 XmlNodeType type;
1076 IStream *stream;
1078 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1079 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1080 ok(hr == S_OK, "got %08x\n", hr);
1082 type = XmlNodeType_None;
1083 hr = IXmlReader_Read(reader, &type);
1084 if (test->hr_broken)
1085 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1086 else
1087 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1088 if (hr == S_OK)
1090 const WCHAR *str;
1091 WCHAR *str_exp;
1092 UINT len;
1094 ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml);
1096 len = 0;
1097 str = NULL;
1098 hr = IXmlReader_GetLocalName(reader, &str, &len);
1099 ok(hr == S_OK, "got 0x%08x\n", hr);
1100 ok(len == strlen(test->name), "got %u\n", len);
1101 str_exp = a2w(test->name);
1102 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1103 free_str(str_exp);
1105 len = 0;
1106 str = NULL;
1107 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1108 ok(hr == S_OK, "got 0x%08x\n", hr);
1109 ok(len == strlen(test->name), "got %u\n", len);
1110 str_exp = a2w(test->name);
1111 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1112 free_str(str_exp);
1114 /* value */
1115 len = !strlen(test->value);
1116 str = NULL;
1117 hr = IXmlReader_GetValue(reader, &str, &len);
1118 ok(hr == S_OK, "got 0x%08x\n", hr);
1119 ok(len == strlen(test->value), "got %u\n", len);
1120 str_exp = a2w(test->value);
1121 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1122 free_str(str_exp);
1125 IStream_Release(stream);
1126 test++;
1129 IXmlReader_Release(reader);
1132 struct nodes_test {
1133 const char *xml;
1134 XmlNodeType types[20];
1137 static const char misc_test_xml[] =
1138 "<!-- comment1 -->"
1139 "<!-- comment2 -->"
1140 "<?pi1 pi1body ?>"
1141 "<!-- comment3 -->"
1142 " \t \r \n"
1143 "<!-- comment4 -->"
1144 "<a>"
1145 "\r\n\t"
1146 "<b/>"
1147 "text"
1148 "<!-- comment -->"
1149 "text2"
1150 "<?pi pibody ?>"
1151 "\r\n"
1152 "</a>"
1155 static struct nodes_test misc_test = {
1156 misc_test_xml,
1158 XmlNodeType_Comment,
1159 XmlNodeType_Comment,
1160 XmlNodeType_ProcessingInstruction,
1161 XmlNodeType_Comment,
1162 XmlNodeType_Whitespace,
1163 XmlNodeType_Comment,
1164 XmlNodeType_Element,
1165 XmlNodeType_Whitespace,
1166 XmlNodeType_Element,
1167 XmlNodeType_Text,
1168 XmlNodeType_Comment,
1169 XmlNodeType_Text,
1170 XmlNodeType_ProcessingInstruction,
1171 XmlNodeType_Whitespace,
1172 XmlNodeType_EndElement,
1173 XmlNodeType_None
1177 static void test_read_full(void)
1179 struct nodes_test *test = &misc_test;
1180 IXmlReader *reader;
1181 XmlNodeType type;
1182 IStream *stream;
1183 HRESULT hr;
1184 int i;
1186 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1187 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1189 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1190 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1191 ok(hr == S_OK, "got %08x\n", hr);
1193 i = 0;
1194 type = ~0u;
1195 while (IXmlReader_Read(reader, &type) == S_OK)
1197 ok(test->types[i] != XmlNodeType_None, "%d: unexpected end of test data\n", i);
1198 if (test->types[i] == XmlNodeType_None) break;
1199 ok(type == test->types[i], "%d: got wrong type %d, expected %d\n", i, type, test->types[i]);
1200 if (type == XmlNodeType_Whitespace)
1202 const WCHAR *ptr;
1203 UINT len = 0;
1205 hr = IXmlReader_GetValue(reader, &ptr, &len);
1206 ok(hr == S_OK, "%d: GetValue failed 0x%08x\n", i, hr);
1207 ok(len > 0, "%d: wrong value length %d\n", i, len);
1209 i++;
1211 ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]);
1213 IStream_Release(stream);
1214 IXmlReader_Release(reader);
1217 static const char test_public_dtd[] =
1218 "<!DOCTYPE testdtd PUBLIC \"pubid\" \"externalid uri\" >";
1220 static void test_read_public_dtd(void)
1222 static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0};
1223 static const WCHAR pubvalW[] = {'p','u','b','i','d',0};
1224 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1225 static const WCHAR sysW[] = {'S','Y','S','T','E','M',0};
1226 static const WCHAR pubW[] = {'P','U','B','L','I','C',0};
1227 IXmlReader *reader;
1228 const WCHAR *str;
1229 XmlNodeType type;
1230 IStream *stream;
1231 UINT len, count;
1232 HRESULT hr;
1234 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1235 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1237 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1238 ok(hr == S_OK, "got 0x%8x\n", hr);
1240 stream = create_stream_on_data(test_public_dtd, sizeof(test_public_dtd));
1241 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1242 ok(hr == S_OK, "got %08x\n", hr);
1244 type = XmlNodeType_None;
1245 hr = IXmlReader_Read(reader, &type);
1246 ok(hr == S_OK, "got 0x%8x\n", hr);
1247 ok(type == XmlNodeType_DocumentType, "got type %d\n", type);
1249 count = 0;
1250 hr = IXmlReader_GetAttributeCount(reader, &count);
1251 ok(hr == S_OK, "got %08x\n", hr);
1252 ok(count == 2, "got %d\n", count);
1254 hr = IXmlReader_MoveToFirstAttribute(reader);
1255 ok(hr == S_OK, "got %08x\n", hr);
1257 type = XmlNodeType_None;
1258 hr = IXmlReader_GetNodeType(reader, &type);
1259 ok(hr == S_OK, "got %08x\n", hr);
1260 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1262 len = 0;
1263 str = NULL;
1264 hr = IXmlReader_GetLocalName(reader, &str, &len);
1265 ok(hr == S_OK, "got 0x%08x\n", hr);
1266 ok(len == lstrlenW(pubW), "got %u\n", len);
1267 ok(!lstrcmpW(str, pubW), "got %s\n", wine_dbgstr_w(str));
1269 len = 0;
1270 str = NULL;
1271 hr = IXmlReader_GetValue(reader, &str, &len);
1272 ok(hr == S_OK, "got 0x%08x\n", hr);
1273 ok(len == lstrlenW(pubvalW), "got %u\n", len);
1274 ok(!lstrcmpW(str, pubvalW), "got %s\n", wine_dbgstr_w(str));
1276 hr = IXmlReader_MoveToNextAttribute(reader);
1277 ok(hr == S_OK, "got %08x\n", hr);
1279 type = XmlNodeType_None;
1280 hr = IXmlReader_GetNodeType(reader, &type);
1281 ok(hr == S_OK, "got %08x\n", hr);
1282 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1284 len = 0;
1285 str = NULL;
1286 hr = IXmlReader_GetLocalName(reader, &str, &len);
1287 ok(hr == S_OK, "got 0x%08x\n", hr);
1288 ok(len == lstrlenW(sysW), "got %u\n", len);
1289 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
1291 len = 0;
1292 str = NULL;
1293 hr = IXmlReader_GetValue(reader, &str, &len);
1294 ok(hr == S_OK, "got 0x%08x\n", hr);
1295 ok(len == lstrlenW(sysvalW), "got %u\n", len);
1296 ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str));
1298 hr = IXmlReader_MoveToElement(reader);
1299 ok(hr == S_OK, "got 0x%08x\n", hr);
1301 len = 0;
1302 str = NULL;
1303 hr = IXmlReader_GetLocalName(reader, &str, &len);
1304 ok(hr == S_OK, "got 0x%08x\n", hr);
1305 todo_wine {
1306 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1307 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1309 len = 0;
1310 str = NULL;
1311 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1312 ok(hr == S_OK, "got 0x%08x\n", hr);
1313 todo_wine {
1314 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1315 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1317 IStream_Release(stream);
1318 IXmlReader_Release(reader);
1321 static const char test_system_dtd[] =
1322 "<!DOCTYPE testdtd SYSTEM \"externalid uri\" >"
1323 "<!-- comment -->";
1325 static void test_read_system_dtd(void)
1327 static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0};
1328 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1329 static const WCHAR sysW[] = {'S','Y','S','T','E','M',0};
1330 IXmlReader *reader;
1331 const WCHAR *str;
1332 XmlNodeType type;
1333 IStream *stream;
1334 UINT len, count;
1335 HRESULT hr;
1337 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1338 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1340 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1341 ok(hr == S_OK, "got 0x%8x\n", hr);
1343 stream = create_stream_on_data(test_system_dtd, sizeof(test_system_dtd));
1344 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1345 ok(hr == S_OK, "got %08x\n", hr);
1347 type = XmlNodeType_None;
1348 hr = IXmlReader_Read(reader, &type);
1349 ok(hr == S_OK, "got 0x%8x\n", hr);
1350 ok(type == XmlNodeType_DocumentType, "got type %d\n", type);
1352 count = 0;
1353 hr = IXmlReader_GetAttributeCount(reader, &count);
1354 ok(hr == S_OK, "got %08x\n", hr);
1355 ok(count == 1, "got %d\n", count);
1357 hr = IXmlReader_MoveToFirstAttribute(reader);
1358 ok(hr == S_OK, "got %08x\n", hr);
1360 type = XmlNodeType_None;
1361 hr = IXmlReader_GetNodeType(reader, &type);
1362 ok(hr == S_OK, "got %08x\n", hr);
1363 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1365 len = 0;
1366 str = NULL;
1367 hr = IXmlReader_GetLocalName(reader, &str, &len);
1368 ok(hr == S_OK, "got 0x%08x\n", hr);
1369 ok(len == lstrlenW(sysW), "got %u\n", len);
1370 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
1372 len = 0;
1373 str = NULL;
1374 hr = IXmlReader_GetValue(reader, &str, &len);
1375 ok(hr == S_OK, "got 0x%08x\n", hr);
1376 ok(len == lstrlenW(sysvalW), "got %u\n", len);
1377 ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str));
1379 hr = IXmlReader_MoveToElement(reader);
1380 ok(hr == S_OK, "got 0x%08x\n", hr);
1382 len = 0;
1383 str = NULL;
1384 hr = IXmlReader_GetLocalName(reader, &str, &len);
1385 ok(hr == S_OK, "got 0x%08x\n", hr);
1386 todo_wine {
1387 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1388 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1390 len = 0;
1391 str = NULL;
1392 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1393 ok(hr == S_OK, "got 0x%08x\n", hr);
1394 todo_wine {
1395 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1396 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1398 type = XmlNodeType_None;
1399 hr = IXmlReader_Read(reader, &type);
1400 ok(hr == S_OK, "got 0x%8x\n", hr);
1401 ok(type == XmlNodeType_Comment, "got type %d\n", type);
1403 IStream_Release(stream);
1404 IXmlReader_Release(reader);
1407 static struct test_entry element_tests[] = {
1408 { "<a/>", "a", "", S_OK },
1409 { "<a />", "a", "", S_OK },
1410 { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX },
1411 { "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1412 { "< a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1413 { "<a>", "a", "", S_OK },
1414 { "<a >", "a", "", S_OK },
1415 { "<a \r \t\n>", "a", "", S_OK },
1416 { "</a>", NULL, NULL, NC_E_QNAMECHARACTER },
1417 { NULL }
1420 static void test_read_element(void)
1422 struct test_entry *test = element_tests;
1423 static const char stag[] =
1424 "<a attr1=\"_a\">"
1425 "<b attr2=\"_b\">"
1426 "text"
1427 "<c attr3=\"_c\"/>"
1428 "<d attr4=\"_d\"></d>"
1429 "</b>"
1430 "</a>";
1431 static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 };
1432 static const char mismatch[] = "<a></b>";
1433 IXmlReader *reader;
1434 XmlNodeType type;
1435 IStream *stream;
1436 unsigned int i;
1437 UINT depth;
1438 HRESULT hr;
1440 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1441 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1443 while (test->xml)
1445 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1446 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1447 ok(hr == S_OK, "got %08x\n", hr);
1449 type = XmlNodeType_None;
1450 hr = IXmlReader_Read(reader, &type);
1451 if (test->hr_broken)
1452 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1453 else
1454 todo_wine_if(test->hr == NC_E_UNDECLAREDPREFIX)
1455 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1456 if (hr == S_OK)
1458 const WCHAR *str;
1459 WCHAR *str_exp;
1460 UINT len;
1462 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1464 len = 0;
1465 str = NULL;
1466 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1467 ok(hr == S_OK, "got 0x%08x\n", hr);
1468 ok(len == strlen(test->name), "got %u\n", len);
1469 str_exp = a2w(test->name);
1470 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1471 free_str(str_exp);
1473 /* value */
1474 len = 1;
1475 str = NULL;
1476 hr = IXmlReader_GetValue(reader, &str, &len);
1477 ok(hr == S_OK, "got 0x%08x\n", hr);
1478 ok(len == 0, "got %u\n", len);
1479 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1482 IStream_Release(stream);
1483 test++;
1486 /* test reader depth increment */
1487 stream = create_stream_on_data(stag, sizeof(stag));
1488 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
1489 ok(hr == S_OK, "got %08x\n", hr);
1491 i = 0;
1492 while (IXmlReader_Read(reader, &type) == S_OK)
1494 ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement ||
1495 type == XmlNodeType_Text, "Unexpected node type %d\n", type);
1497 depth = 123;
1498 hr = IXmlReader_GetDepth(reader, &depth);
1499 ok(hr == S_OK, "got %08x\n", hr);
1500 ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
1502 if (type == XmlNodeType_Element)
1504 UINT count = 0;
1506 hr = IXmlReader_GetAttributeCount(reader, &count);
1507 ok(hr == S_OK, "got %08x\n", hr);
1509 /* moving to attributes increases depth */
1510 if (count)
1512 const WCHAR *value;
1514 hr = IXmlReader_GetValue(reader, &value, NULL);
1515 ok(*value == 0, "Unexpected value %s\n", wine_dbgstr_w(value));
1517 hr = IXmlReader_MoveToFirstAttribute(reader);
1518 ok(hr == S_OK, "got %08x\n", hr);
1520 hr = IXmlReader_GetValue(reader, &value, NULL);
1521 ok(*value != 0, "Unexpected value %s\n", wine_dbgstr_w(value));
1523 depth = 123;
1524 hr = IXmlReader_GetDepth(reader, &depth);
1525 ok(hr == S_OK, "got %08x\n", hr);
1526 ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1);
1528 hr = IXmlReader_MoveToElement(reader);
1529 ok(hr == S_OK, "got %08x\n", hr);
1531 hr = IXmlReader_GetValue(reader, &value, NULL);
1532 ok(*value == 0, "Unexpected value %s\n", wine_dbgstr_w(value));
1534 depth = 123;
1535 hr = IXmlReader_GetDepth(reader, &depth);
1536 ok(hr == S_OK, "got %08x\n", hr);
1537 ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
1541 i++;
1544 IStream_Release(stream);
1546 /* start/end tag mismatch */
1547 stream = create_stream_on_data(mismatch, sizeof(mismatch));
1548 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1549 ok(hr == S_OK, "got %08x\n", hr);
1551 type = XmlNodeType_None;
1552 hr = IXmlReader_Read(reader, &type);
1553 ok(hr == S_OK, "got %08x\n", hr);
1554 ok(type == XmlNodeType_Element, "got %d\n", type);
1556 type = XmlNodeType_Element;
1557 hr = IXmlReader_Read(reader, &type);
1558 ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr);
1559 todo_wine
1560 ok(type == XmlNodeType_None, "got %d\n", type);
1562 IStream_Release(stream);
1564 IXmlReader_Release(reader);
1567 static ISequentialStream teststream = { &teststreamvtbl };
1569 static void test_read_pending(void)
1571 IXmlReader *reader;
1572 const WCHAR *value;
1573 XmlNodeType type;
1574 HRESULT hr;
1575 int c;
1577 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1578 ok(hr == S_OK, "S_OK, got 0x%08x\n", hr);
1580 hr = IXmlReader_SetInput(reader, (IUnknown*)&teststream);
1581 ok(hr == S_OK, "got 0x%08x\n", hr);
1583 /* first read call returns incomplete node, second attempt fails with E_PENDING */
1584 stream_readcall = 0;
1585 type = XmlNodeType_Element;
1586 hr = IXmlReader_Read(reader, &type);
1587 ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr);
1588 /* newer versions are happy when it's enough data to detect node type,
1589 older versions keep reading until it fails to read more */
1590 ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall);
1591 ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type);
1593 /* newer versions' GetValue() makes an attempt to read more */
1594 c = stream_readcall;
1595 value = (void*)0xdeadbeef;
1596 hr = IXmlReader_GetValue(reader, &value, NULL);
1597 ok(hr == E_PENDING, "got 0x%08x\n", hr);
1598 ok(value == NULL || broken(value == (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value);
1599 ok(c < stream_readcall || broken(c == stream_readcall), "got %d, expected %d\n", stream_readcall, c+1);
1601 IXmlReader_Release(reader);
1604 static void test_readvaluechunk(void)
1606 static const char testA[] = "<!-- comment1 -->";
1607 IXmlReader *reader;
1608 XmlNodeType type;
1609 IStream *stream;
1610 const WCHAR *value;
1611 WCHAR b;
1612 HRESULT hr;
1613 UINT c;
1615 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1616 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1618 stream = create_stream_on_data(testA, sizeof(testA));
1619 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1620 ok(hr == S_OK, "got %08x\n", hr);
1622 hr = IXmlReader_Read(reader, &type);
1623 ok(hr == S_OK, "got %08x\n", hr);
1625 c = 0;
1626 b = 0;
1627 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1628 ok(hr == S_OK, "got %08x\n", hr);
1629 ok(c == 1, "got %u\n", c);
1630 ok(b == ' ', "got %x\n", b);
1632 /* portion read as chunk is skipped from resulting node value */
1633 value = NULL;
1634 hr = IXmlReader_GetValue(reader, &value, NULL);
1635 ok(hr == S_OK, "got %08x\n", hr);
1636 ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value));
1638 /* once value is returned/allocated it's not possible to read by chunk */
1639 c = 0;
1640 b = 0;
1641 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1642 ok(hr == S_FALSE, "got %08x\n", hr);
1643 ok(c == 0, "got %u\n", c);
1644 ok(b == 0, "got %x\n", b);
1646 value = NULL;
1647 hr = IXmlReader_GetValue(reader, &value, NULL);
1648 ok(hr == S_OK, "got %08x\n", hr);
1649 ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value));
1651 IXmlReader_Release(reader);
1652 IStream_Release(stream);
1655 static struct test_entry cdata_tests[] = {
1656 { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK },
1657 { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK },
1658 { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK, S_OK, TRUE },
1659 { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK, S_OK, TRUE },
1660 { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK },
1661 { NULL }
1664 static void test_read_cdata(void)
1666 struct test_entry *test = cdata_tests;
1667 IXmlReader *reader;
1668 HRESULT hr;
1670 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1671 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1673 while (test->xml)
1675 XmlNodeType type;
1676 IStream *stream;
1678 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1679 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1680 ok(hr == S_OK, "got %08x\n", hr);
1682 type = XmlNodeType_None;
1683 hr = IXmlReader_Read(reader, &type);
1685 /* read one more to get to CDATA */
1686 if (type == XmlNodeType_Element)
1688 type = XmlNodeType_None;
1689 hr = IXmlReader_Read(reader, &type);
1692 if (test->hr_broken)
1693 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1694 else
1695 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1696 if (hr == S_OK)
1698 const WCHAR *str;
1699 WCHAR *str_exp;
1700 UINT len;
1702 ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml);
1704 str_exp = a2w(test->name);
1706 len = 1;
1707 str = NULL;
1708 hr = IXmlReader_GetLocalName(reader, &str, &len);
1709 ok(hr == S_OK, "got 0x%08x\n", hr);
1710 ok(len == strlen(test->name), "got %u\n", len);
1711 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1713 str = NULL;
1714 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1715 ok(hr == S_OK, "got 0x%08x\n", hr);
1716 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1718 free_str(str_exp);
1720 len = 1;
1721 str = NULL;
1722 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1723 ok(hr == S_OK, "got 0x%08x\n", hr);
1724 ok(len == strlen(test->name), "got %u\n", len);
1725 str_exp = a2w(test->name);
1726 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1727 free_str(str_exp);
1729 /* value */
1730 len = 1;
1731 str = NULL;
1732 hr = IXmlReader_GetValue(reader, &str, &len);
1733 ok(hr == S_OK, "got 0x%08x\n", hr);
1735 str_exp = a2w(test->value);
1736 todo_wine_if (test->todo)
1738 ok(len == strlen(test->value), "got %u\n", len);
1739 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1741 free_str(str_exp);
1744 IStream_Release(stream);
1745 test++;
1748 IXmlReader_Release(reader);
1751 static struct test_entry text_tests[] = {
1752 { "<a>simple text</a>", "", "simple text", S_OK },
1753 { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND },
1754 { "<a>\n \r\n \n\n text</a>", "", "\n \n \n\n text", S_OK, S_OK, TRUE },
1755 { "<a>\r \r\r\n \n\n text</a>", "", "\n \n\n \n\n text", S_OK, S_OK, TRUE },
1756 { NULL }
1759 static void test_read_text(void)
1761 struct test_entry *test = text_tests;
1762 IXmlReader *reader;
1763 HRESULT hr;
1765 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1766 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1768 while (test->xml)
1770 XmlNodeType type;
1771 IStream *stream;
1773 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1774 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1775 ok(hr == S_OK, "got %08x\n", hr);
1777 type = XmlNodeType_None;
1778 hr = IXmlReader_Read(reader, &type);
1780 /* read one more to get to text node */
1781 if (type == XmlNodeType_Element)
1783 type = XmlNodeType_None;
1784 hr = IXmlReader_Read(reader, &type);
1786 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1787 if (hr == S_OK)
1789 const WCHAR *str;
1790 WCHAR *str_exp;
1791 UINT len;
1793 ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml);
1795 str_exp = a2w(test->name);
1797 len = 1;
1798 str = NULL;
1799 hr = IXmlReader_GetLocalName(reader, &str, &len);
1800 ok(hr == S_OK, "got 0x%08x\n", hr);
1801 ok(len == strlen(test->name), "got %u\n", len);
1802 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1804 str = NULL;
1805 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1806 ok(hr == S_OK, "got 0x%08x\n", hr);
1807 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1809 free_str(str_exp);
1811 len = 1;
1812 str = NULL;
1813 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1814 ok(hr == S_OK, "got 0x%08x\n", hr);
1815 ok(len == strlen(test->name), "got %u\n", len);
1816 str_exp = a2w(test->name);
1817 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1818 free_str(str_exp);
1820 /* value */
1821 len = 1;
1822 str = NULL;
1823 hr = IXmlReader_GetValue(reader, &str, &len);
1824 ok(hr == S_OK, "got 0x%08x\n", hr);
1826 str_exp = a2w(test->value);
1827 todo_wine_if (test->todo)
1829 ok(len == strlen(test->value), "got %u\n", len);
1830 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1832 free_str(str_exp);
1835 IStream_Release(stream);
1836 test++;
1839 IXmlReader_Release(reader);
1842 struct test_entry_empty {
1843 const char *xml;
1844 BOOL empty;
1847 static struct test_entry_empty empty_element_tests[] = {
1848 { "<a></a>", FALSE },
1849 { "<a/>", TRUE },
1850 { NULL }
1853 static void test_isemptyelement(void)
1855 struct test_entry_empty *test = empty_element_tests;
1856 IXmlReader *reader;
1857 HRESULT hr;
1859 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1860 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1862 while (test->xml)
1864 XmlNodeType type;
1865 IStream *stream;
1866 BOOL ret;
1868 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1869 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1870 ok(hr == S_OK, "got %08x\n", hr);
1872 type = XmlNodeType_None;
1873 hr = IXmlReader_Read(reader, &type);
1874 ok(hr == S_OK, "got 0x%08x\n", hr);
1875 ok(type == XmlNodeType_Element, "got %d\n", type);
1877 ret = IXmlReader_IsEmptyElement(reader);
1878 ok(ret == test->empty, "got %d, expected %d. xml=%s\n", ret, test->empty, test->xml);
1880 IStream_Release(stream);
1881 test++;
1884 IXmlReader_Release(reader);
1887 static struct test_entry attributes_tests[] = {
1888 { "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK },
1889 { "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK },
1890 { "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK },
1891 { "<a attr1=\' \'/>", "attr1", " ", S_OK },
1892 { "<a attr1=\" \"/>", "attr1", " ", S_OK },
1893 { "<a attr1=\"\r\n \r \n \t\n\r\"/>", "attr1", " ", S_OK },
1894 { "<a attr1=\" val \"/>", "attr1", " val ", S_OK },
1895 { "<a attr1=\"\r\n\tval\n\"/>", "attr1", " val ", S_OK },
1896 { "<a attr1=\"val&#32;\"/>", "attr1", "val ", S_OK },
1897 { "<a attr1=\"val&#x20;\"/>", "attr1", "val ", S_OK },
1898 { "<a attr1=\"&lt;&gt;&amp;&apos;&quot;\"/>", "attr1", "<>&\'\"", S_OK },
1899 { "<a attr1=\"&entname;\"/>", NULL, NULL, WC_E_UNDECLAREDENTITY },
1900 { "<a attr1=\"val&#xfffe;\"/>", NULL, NULL, WC_E_XMLCHARACTER },
1901 { "<a attr1=\"val &#a;\"/>", NULL, NULL, WC_E_DIGIT, WC_E_SEMICOLON },
1902 { "<a attr1=\"val &#12a;\"/>", NULL, NULL, WC_E_SEMICOLON },
1903 { "<a attr1=\"val &#x12g;\"/>", NULL, NULL, WC_E_SEMICOLON },
1904 { "<a attr1=\"val &#xg;\"/>", NULL, NULL, WC_E_HEXDIGIT, WC_E_SEMICOLON },
1905 { "<a attr1=attrvalue/>", NULL, NULL, WC_E_QUOTE },
1906 { "<a attr1=\"attr<value\"/>", NULL, NULL, WC_E_LESSTHAN },
1907 { "<a attr1=\"&entname\"/>", NULL, NULL, WC_E_SEMICOLON },
1908 { NULL }
1911 static void test_read_attribute(void)
1913 struct test_entry *test = attributes_tests;
1914 IXmlReader *reader;
1915 HRESULT hr;
1917 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1918 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1920 while (test->xml)
1922 XmlNodeType type;
1923 IStream *stream;
1925 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1926 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1927 ok(hr == S_OK, "got %08x\n", hr);
1929 hr = IXmlReader_Read(reader, NULL);
1931 if (test->hr_broken)
1932 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1933 else
1934 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1935 if (hr == S_OK)
1937 const WCHAR *str;
1938 WCHAR *str_exp;
1939 UINT len;
1941 type = XmlNodeType_None;
1942 hr = IXmlReader_GetNodeType(reader, &type);
1943 ok(hr == S_OK, "Failed to get node type, %#x\n", hr);
1945 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1947 hr = IXmlReader_MoveToFirstAttribute(reader);
1948 ok(hr == S_OK, "got 0x%08x\n", hr);
1950 len = 1;
1951 str = NULL;
1952 hr = IXmlReader_GetLocalName(reader, &str, &len);
1953 ok(hr == S_OK, "got 0x%08x\n", hr);
1954 ok(len == strlen(test->name), "got %u\n", len);
1955 str_exp = a2w(test->name);
1956 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1957 free_str(str_exp);
1959 len = 1;
1960 str = NULL;
1961 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1962 ok(hr == S_OK, "got 0x%08x\n", hr);
1963 ok(len == strlen(test->name), "got %u\n", len);
1964 str_exp = a2w(test->name);
1965 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1966 free_str(str_exp);
1968 /* value */
1969 len = 1;
1970 str = NULL;
1971 hr = IXmlReader_GetValue(reader, &str, &len);
1972 ok(hr == S_OK, "got 0x%08x\n", hr);
1973 ok(len == strlen(test->value), "got %u\n", len);
1974 str_exp = a2w(test->value);
1975 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1976 free_str(str_exp);
1979 IStream_Release(stream);
1980 test++;
1983 IXmlReader_Release(reader);
1986 static void test_reader_properties(void)
1988 IXmlReader *reader;
1989 LONG_PTR value;
1990 HRESULT hr;
1992 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1993 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1995 value = 0;
1996 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value);
1997 ok(hr == S_OK, "GetProperty failed: %08x\n", hr);
1998 ok(value == 256, "Unexpected default max depth value %ld\n", value);
2000 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0);
2001 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
2003 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
2004 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
2006 value = 256;
2007 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value);
2008 ok(hr == S_OK, "GetProperty failed: %08x\n", hr);
2009 ok(value == 0, "Unexpected max depth value %ld\n", value);
2011 IXmlReader_Release(reader);
2014 static void test_prefix(void)
2016 static const struct
2018 const char *xml;
2019 const char *prefix1;
2020 const char *prefix2;
2021 const char *prefix3;
2022 } prefix_tests[] =
2024 { "<b xmlns=\"defns\" xml:a=\"a ns\"/>", "", "", "xml" },
2025 { "<c:b xmlns:c=\"c ns\" xml:a=\"a ns\"/>", "c", "xmlns", "xml" },
2027 IXmlReader *reader;
2028 unsigned int i;
2029 HRESULT hr;
2031 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
2032 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2034 for (i = 0; i < sizeof(prefix_tests)/sizeof(prefix_tests[0]); i++) {
2035 const WCHAR *prefix;
2036 XmlNodeType type;
2037 WCHAR *expected;
2038 IStream *stream;
2040 stream = create_stream_on_data(prefix_tests[i].xml, strlen(prefix_tests[i].xml) + 1);
2041 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2042 ok(hr == S_OK, "got %08x\n", hr);
2044 hr = IXmlReader_Read(reader, &type);
2045 ok(hr == S_OK, "Read() failed, %#x\n", hr);
2046 ok(type == XmlNodeType_Element, "Unexpected node type %d.\n", type);
2048 expected = a2w(prefix_tests[i].prefix1);
2049 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
2050 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
2051 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
2052 wine_dbgstr_w(expected));
2053 free_str(expected);
2055 hr = IXmlReader_MoveToFirstAttribute(reader);
2056 ok(hr == S_OK, "MoveToFirstAttribute() failed, %#x.\n", hr);
2058 hr = IXmlReader_GetNodeType(reader, &type);
2059 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
2060 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
2062 expected = a2w(prefix_tests[i].prefix2);
2063 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
2064 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
2065 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
2066 wine_dbgstr_w(expected));
2067 free_str(expected);
2069 hr = IXmlReader_MoveToNextAttribute(reader);
2070 ok(hr == S_OK, "MoveToNextAttribute() failed, %#x.\n", hr);
2072 hr = IXmlReader_GetNodeType(reader, &type);
2073 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
2074 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
2076 expected = a2w(prefix_tests[i].prefix3);
2077 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
2078 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
2079 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
2080 wine_dbgstr_w(expected));
2081 free_str(expected);
2083 /* back to the element, check prefix */
2084 hr = IXmlReader_MoveToElement(reader);
2085 ok(hr == S_OK, "MoveToElement() failed, %#x.\n", hr);
2087 expected = a2w(prefix_tests[i].prefix1);
2088 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
2089 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
2090 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
2091 wine_dbgstr_w(expected));
2092 free_str(expected);
2094 IStream_Release(stream);
2097 IXmlReader_Release(reader);
2100 static void test_namespaceuri(void)
2102 struct uri_test
2104 const char *xml;
2105 const char *uri[5];
2106 } uri_tests[] =
2108 { "<a xmlns=\"defns a\"><b xmlns=\"defns b\"><c xmlns=\"defns c\"/></b></a>",
2109 { "defns a", "defns b", "defns c", "defns b", "defns a" }},
2110 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"/>",
2111 { "ns r" }},
2112 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"><b/></r:a>",
2113 { "ns r", "defns a", "ns r" }},
2114 { "<a xmlns=\"defns a\" xmlns:r=\"ns r\"><r:b/></a>",
2115 { "defns a", "ns r", "defns a" }},
2116 { "<a><b><c/></b></a>",
2117 { "", "", "", "", "" }},
2118 { "<a>text</a>",
2119 { "", "", "" }},
2120 { "<a>\r\n</a>",
2121 { "", "", "" }},
2122 { "<a><![CDATA[data]]></a>",
2123 { "", "", "" }},
2124 { "<?xml version=\"1.0\" ?><a/>",
2125 { "", "" }},
2126 { "<a><?pi ?></a>",
2127 { "", "", "" }},
2128 { "<a><!-- comment --></a>",
2129 { "", "", "" }},
2131 IXmlReader *reader;
2132 XmlNodeType type;
2133 unsigned int i;
2134 HRESULT hr;
2136 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
2137 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2139 for (i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); i++) {
2140 IStream *stream = create_stream_on_data(uri_tests[i].xml, strlen(uri_tests[i].xml) + 1);
2141 unsigned int j = 0;
2143 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2144 ok(hr == S_OK, "got %08x\n", hr);
2146 type = ~0u;
2147 while (IXmlReader_Read(reader, &type) == S_OK) {
2148 const WCHAR *uri, *local, *qname;
2149 UINT length, length2;
2150 WCHAR *uriW;
2152 ok(type == XmlNodeType_Element ||
2153 type == XmlNodeType_Text ||
2154 type == XmlNodeType_CDATA ||
2155 type == XmlNodeType_ProcessingInstruction ||
2156 type == XmlNodeType_Comment ||
2157 type == XmlNodeType_Whitespace ||
2158 type == XmlNodeType_EndElement ||
2159 type == XmlNodeType_XmlDeclaration, "Unexpected node type %d.\n", type);
2161 local = NULL;
2162 length = 0;
2163 hr = IXmlReader_GetLocalName(reader, &local, &length);
2164 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2165 ok(local != NULL, "Unexpected NULL local name pointer\n");
2167 qname = NULL;
2168 length2 = 0;
2169 hr = IXmlReader_GetQualifiedName(reader, &qname, &length2);
2170 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2171 ok(qname != NULL, "Unexpected NULL qualified name pointer\n");
2173 if (type == XmlNodeType_Element ||
2174 type == XmlNodeType_EndElement ||
2175 type == XmlNodeType_ProcessingInstruction ||
2176 type == XmlNodeType_XmlDeclaration)
2178 ok(*local != 0, "Unexpected empty local name\n");
2179 ok(length > 0, "Unexpected local name length\n");
2181 ok(*qname != 0, "Unexpected empty qualified name\n");
2182 ok(length2 > 0, "Unexpected qualified name length\n");
2185 uri = NULL;
2186 hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL);
2187 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2188 ok(uri != NULL, "Unexpected NULL uri pointer\n");
2190 uriW = a2w(uri_tests[i].uri[j]);
2191 ok(!lstrcmpW(uriW, uri), "%s: uri %s\n", wine_dbgstr_w(local), wine_dbgstr_w(uri));
2192 free_str(uriW);
2194 j++;
2196 ok(type == XmlNodeType_None, "Unexpected node type %d\n", type);
2198 IStream_Release(stream);
2201 IXmlReader_Release(reader);
2204 static void test_read_charref(void)
2206 static const char testA[] = "<a b=\"c\">&#x1f3;&#x103;</a>";
2207 static const WCHAR chardataW[] = {0x01f3,0x0103,0};
2208 const WCHAR *value;
2209 IXmlReader *reader;
2210 XmlNodeType type;
2211 IStream *stream;
2212 HRESULT hr;
2214 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2215 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2217 stream = create_stream_on_data(testA, sizeof(testA));
2218 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2219 ok(hr == S_OK, "got %08x\n", hr);
2221 hr = IXmlReader_Read(reader, &type);
2222 ok(hr == S_OK, "got %08x\n", hr);
2223 ok(type == XmlNodeType_Element, "Unexpected node type %d\n", type);
2225 hr = IXmlReader_Read(reader, &type);
2226 ok(hr == S_OK, "got %08x\n", hr);
2227 ok(type == XmlNodeType_Text, "Unexpected node type %d\n", type);
2229 hr = IXmlReader_GetValue(reader, &value, NULL);
2230 ok(hr == S_OK, "got %08x\n", hr);
2231 ok(!lstrcmpW(value, chardataW), "Text value : %s\n", wine_dbgstr_w(value));
2233 hr = IXmlReader_Read(reader, &type);
2234 ok(hr == S_OK, "got %08x\n", hr);
2235 ok(type == XmlNodeType_EndElement, "Unexpected node type %d\n", type);
2237 IXmlReader_Release(reader);
2238 IStream_Release(stream);
2241 static void test_encoding_detection(void)
2243 static const struct encoding_testW
2245 WCHAR text[16];
2247 encoding_testsW[] =
2249 { { '<','?','p','i',' ','?','>',0 } },
2250 { { '<','!','-','-',' ','c','-','-','>',0 } },
2251 { { 0xfeff,'<','a','/','>',0 } },
2252 { { '<','a','/','>',0 } },
2254 static const char *encoding_testsA[] =
2256 "<?pi ?>",
2257 "<!-- comment -->",
2258 "\xef\xbb\xbf<a/>", /* UTF-8 BOM */
2259 "<a/>",
2261 IXmlReader *reader;
2262 XmlNodeType type;
2263 IStream *stream;
2264 unsigned int i;
2265 HRESULT hr;
2267 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2268 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2270 /* there's no way to query detected encoding back, so just verify that document is browsable */
2272 for (i = 0; i < sizeof(encoding_testsA)/sizeof(encoding_testsA[0]); i++)
2274 stream = create_stream_on_data(encoding_testsA[i], strlen(encoding_testsA[i]));
2276 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2277 ok(hr == S_OK, "got %08x\n", hr);
2279 type = XmlNodeType_None;
2280 hr = IXmlReader_Read(reader, &type);
2281 ok(hr == S_OK, "got %08x\n", hr);
2282 ok(type != XmlNodeType_None, "Unexpected node type %d\n", type);
2284 IStream_Release(stream);
2287 for (i = 0; i < sizeof(encoding_testsW)/sizeof(encoding_testsW[0]); i++)
2289 stream = create_stream_on_data(encoding_testsW[i].text, lstrlenW(encoding_testsW[i].text) * sizeof(WCHAR));
2291 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2292 ok(hr == S_OK, "got %08x\n", hr);
2294 type = XmlNodeType_None;
2295 hr = IXmlReader_Read(reader, &type);
2296 ok(hr == S_OK, "%u: got %08x\n", i, hr);
2297 ok(type != XmlNodeType_None, "%u: unexpected node type %d\n", i, type);
2299 IStream_Release(stream);
2302 IXmlReader_Release(reader);
2305 static void test_eof_state(IXmlReader *reader, BOOL eof)
2307 LONG_PTR state;
2308 HRESULT hr;
2310 ok(IXmlReader_IsEOF(reader) == eof, "Unexpected IsEOF() result\n");
2311 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
2312 ok(hr == S_OK, "GetProperty() failed, %#x\n", hr);
2313 ok((state == XmlReadState_EndOfFile) == eof, "Unexpected EndOfFile state %ld\n", state);
2316 static void test_endoffile(void)
2318 static const char *xml = "<a/>";
2319 IXmlReader *reader;
2320 XmlNodeType type;
2321 IStream *stream;
2322 HRESULT hr;
2324 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2325 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2327 test_eof_state(reader, FALSE);
2329 stream = create_stream_on_data(xml, strlen(xml));
2331 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2332 ok(hr == S_OK, "got %08x\n", hr);
2334 test_eof_state(reader, FALSE);
2336 type = XmlNodeType_None;
2337 hr = IXmlReader_Read(reader, &type);
2338 ok(hr == S_OK, "got %#x\n", hr);
2339 ok(type == XmlNodeType_Element, "Unexpected type %d\n", type);
2341 test_eof_state(reader, FALSE);
2343 type = XmlNodeType_Element;
2344 hr = IXmlReader_Read(reader, &type);
2345 ok(hr == S_FALSE, "got %#x\n", hr);
2346 ok(type == XmlNodeType_None, "Unexpected type %d\n", type);
2348 test_eof_state(reader, TRUE);
2350 hr = IXmlReader_SetInput(reader, NULL);
2351 ok(hr == S_OK, "got %08x\n", hr);
2353 test_eof_state(reader, FALSE);
2355 IStream_Release(stream);
2357 IXmlReader_Release(reader);
2360 static void test_max_element_depth(void)
2362 static const char *xml =
2363 "<a>"
2364 "<b attrb=\"_b\">"
2365 "<c>"
2366 "<d></d>"
2367 "</c>"
2368 "</b>"
2369 "</a>";
2370 unsigned int count;
2371 IXmlReader *reader;
2372 IStream *stream;
2373 HRESULT hr;
2375 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2376 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2378 stream = create_stream_on_data(xml, strlen(xml));
2380 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2381 ok(hr == S_OK, "got %08x\n", hr);
2383 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2);
2384 ok(hr == S_OK, "got %08x\n", hr);
2386 TEST_DEPTH(reader, 0);
2388 hr = IXmlReader_Read(reader, NULL);
2389 ok(hr == S_OK, "got %08x\n", hr);
2391 TEST_DEPTH(reader, 0);
2393 hr = IXmlReader_Read(reader, NULL);
2394 ok(hr == S_OK, "got %08x\n", hr);
2396 TEST_DEPTH(reader, 1);
2397 TEST_READER_STATE(reader, XmlReadState_Interactive);
2399 hr = IXmlReader_Read(reader, NULL);
2400 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2402 todo_wine {
2403 TEST_DEPTH2(reader, 0, 2);
2404 TEST_READER_STATE(reader, XmlReadState_Error);
2406 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 10);
2407 ok(hr == S_OK, "got %08x\n", hr);
2409 hr = IXmlReader_Read(reader, NULL);
2410 todo_wine {
2411 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2413 TEST_DEPTH2(reader, 0, 2);
2414 TEST_READER_STATE(reader, XmlReadState_Error);
2416 IStream_Release(stream);
2418 /* test if stepping into attributes enforces depth limit too */
2419 stream = create_stream_on_data(xml, strlen(xml));
2421 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2422 ok(hr == S_OK, "got %08x\n", hr);
2424 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2);
2425 ok(hr == S_OK, "got %08x\n", hr);
2427 TEST_DEPTH(reader, 0);
2429 hr = IXmlReader_Read(reader, NULL);
2430 ok(hr == S_OK, "got %08x\n", hr);
2432 TEST_DEPTH(reader, 0);
2434 hr = IXmlReader_Read(reader, NULL);
2435 ok(hr == S_OK, "got %08x\n", hr);
2437 TEST_DEPTH(reader, 1);
2439 hr = IXmlReader_MoveToFirstAttribute(reader);
2440 ok(hr == S_OK, "got %08x\n", hr);
2442 TEST_DEPTH(reader, 2);
2443 TEST_READER_STATE(reader, XmlReadState_Interactive);
2445 hr = IXmlReader_Read(reader, NULL);
2446 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2448 todo_wine {
2449 TEST_DEPTH2(reader, 0, 2);
2450 TEST_READER_STATE(reader, XmlReadState_Error);
2452 IStream_Release(stream);
2454 /* set max depth to 0, this disables depth limit */
2455 stream = create_stream_on_data(xml, strlen(xml));
2457 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2458 ok(hr == S_OK, "got %08x\n", hr);
2460 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
2461 ok(hr == S_OK, "got %08x\n", hr);
2463 count = 0;
2464 while (IXmlReader_Read(reader, NULL) == S_OK)
2465 count++;
2466 ok(count == 8, "Unexpected node number %u\n", count);
2467 TEST_READER_STATE(reader, XmlReadState_EndOfFile);
2469 IStream_Release(stream);
2471 IXmlReader_Release(reader);
2474 static void test_reader_position(void)
2476 static const char *xml = "<c:a xmlns:c=\"nsdef c\" b=\"attr b\" />";
2477 IXmlReader *reader;
2478 XmlNodeType type;
2479 IStream *stream;
2480 HRESULT hr;
2481 UINT position;
2483 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2484 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2486 /* position methods with Null args */
2487 hr = IXmlReader_GetLineNumber(reader, NULL);
2488 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
2490 hr = IXmlReader_GetLinePosition(reader, NULL);
2491 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
2493 position = 123;
2494 hr = IXmlReader_GetLinePosition(reader, &position);
2495 todo_wine
2496 ok(hr == S_FALSE, "got %#x\n", hr);
2497 ok(position == 0, "got %u\n", position);
2499 position = 123;
2500 hr = IXmlReader_GetLineNumber(reader, &position);
2501 todo_wine
2502 ok(hr == S_FALSE, "got %#x\n", hr);
2503 ok(position == 0, "got %u\n", position);
2505 stream = create_stream_on_data(xml, strlen(xml));
2507 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2508 ok(hr == S_OK, "got %08x\n", hr);
2510 TEST_READER_POSITION(reader, 0, 0);
2511 hr = IXmlReader_Read(reader, &type);
2512 ok(hr == S_OK, "got %08x\n", hr);
2513 ok(type == XmlNodeType_Element, "got type %d\n", type);
2514 todo_wine
2515 TEST_READER_POSITION2(reader, 1, 2, ~0u, 36);
2517 hr = IXmlReader_MoveToNextAttribute(reader);
2518 ok(hr == S_OK, "got %08x\n", hr);
2519 todo_wine
2520 TEST_READER_POSITION2(reader, 1, 6, ~0u, 36);
2522 hr = IXmlReader_MoveToNextAttribute(reader);
2523 ok(hr == S_OK, "got %08x\n", hr);
2524 todo_wine
2525 TEST_READER_POSITION2(reader, 1, 24, ~0u, 36);
2527 hr = IXmlReader_MoveToElement(reader);
2528 ok(hr == S_OK, "got %08x\n", hr);
2529 todo_wine
2530 TEST_READER_POSITION2(reader, 1, 2, ~0u, 36);
2532 IXmlReader_SetInput(reader, NULL);
2533 TEST_READER_POSITION(reader, 0, 0);
2535 IStream_Release(stream);
2536 IXmlReader_Release(reader);
2539 START_TEST(reader)
2541 test_reader_create();
2542 test_readerinput();
2543 test_reader_state();
2544 test_read_attribute();
2545 test_read_cdata();
2546 test_read_comment();
2547 test_read_pi();
2548 test_read_system_dtd();
2549 test_read_public_dtd();
2550 test_read_element();
2551 test_isemptyelement();
2552 test_read_text();
2553 test_read_full();
2554 test_read_pending();
2555 test_readvaluechunk();
2556 test_read_xmldeclaration();
2557 test_reader_properties();
2558 test_prefix();
2559 test_namespaceuri();
2560 test_read_charref();
2561 test_encoding_detection();
2562 test_endoffile();
2563 test_max_element_depth();
2564 test_reader_position();