1 /*
2 * IXmlReader tests
3 *
4 * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23
24 #include <stdarg.h>
25 #include <stdio.h>
26
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"
33 #include "wine/heap.h"
34
35 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
36
a2w(const char * str)37 static WCHAR *a2w(const char *str)
38 {
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);
42 return ret;
43 }
44
free_str(WCHAR * str)45 static void free_str(WCHAR *str)
46 {
47 heap_free(str);
48 }
49
strcmp_wa(const WCHAR * str1,const char * stra)50 static int strcmp_wa(const WCHAR *str1, const char *stra)
51 {
52 WCHAR *str2 = a2w(stra);
53 int r = lstrcmpW(str1, str2);
54 free_str(str2);
55 return r;
56 }
57
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/>";
60
create_stream_on_data(const void * data,unsigned int size)61 static IStream *create_stream_on_data(const void *data, unsigned int size)
62 {
63 IStream *stream = NULL;
64 HGLOBAL hglobal;
65 void *ptr;
66 HRESULT hr;
67
68 hglobal = GlobalAlloc(GHND, size);
69 ptr = GlobalLock(hglobal);
70
71 memcpy(ptr, data, size);
72
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");
76
77 GlobalUnlock(hglobal);
78
79 return stream;
80 }
81
test_reader_pos(IXmlReader * reader,UINT line,UINT pos,UINT line_broken,UINT pos_broken,int _line_)82 static void test_reader_pos(IXmlReader *reader, UINT line, UINT pos, UINT line_broken,
83 UINT pos_broken, int _line_)
84 {
85 UINT l = ~0u, p = ~0u;
86 BOOL broken_state;
87
88 IXmlReader_GetLineNumber(reader, &l);
89 IXmlReader_GetLinePosition(reader, &p);
90
91 if (line_broken == ~0u && pos_broken == ~0u)
92 broken_state = FALSE;
93 else
94 broken_state = broken((line_broken == ~0u ? line : line_broken) == l &&
95 (pos_broken == ~0u ? pos : pos_broken) == p);
96
97 ok_(__FILE__, _line_)((l == line && pos == p) || broken_state,
98 "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p);
99 }
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__)
104
105 typedef struct input_iids_t {
106 IID iids[10];
107 int count;
108 } input_iids_t;
109
110 static const IID *setinput_full[] = {
111 &IID_IXmlReaderInput,
112 &IID_IStream,
113 &IID_ISequentialStream,
114 NULL
115 };
116
117 /* this applies to early xmllite versions */
118 static const IID *setinput_full_old[] = {
119 &IID_IXmlReaderInput,
120 &IID_ISequentialStream,
121 &IID_IStream,
122 NULL
123 };
124
125 /* after ::SetInput(IXmlReaderInput*) */
126 static const IID *setinput_readerinput[] = {
127 &IID_IStream,
128 &IID_ISequentialStream,
129 NULL
130 };
131
132 static const IID *empty_seq[] = {
133 NULL
134 };
135
136 static input_iids_t input_iids;
137
ok_iids_(const input_iids_t * iids,const IID ** expected,const IID ** exp_broken,BOOL todo,int line)138 static void ok_iids_(const input_iids_t *iids, const IID **expected, const IID **exp_broken, BOOL todo, int line)
139 {
140 int i = 0, size = 0;
141
142 while (expected[i++]) size++;
143
144 todo_wine_if (todo)
145 ok_(__FILE__, line)(iids->count == size, "Sequence size mismatch (%d), got (%d)\n", size, iids->count);
146
147 if (iids->count != size) return;
148
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]));
153 }
154 }
155 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
156
state_to_str(XmlReadState state)157 static const char *state_to_str(XmlReadState state)
158 {
159 static const char* state_names[] = {
160 "XmlReadState_Initial",
161 "XmlReadState_Interactive",
162 "XmlReadState_Error",
163 "XmlReadState_EndOfFile",
164 "XmlReadState_Closed"
165 };
166
167 static const char unknown[] = "unknown";
168
169 switch (state)
170 {
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];
177 default:
178 return unknown;
179 }
180 }
181
type_to_str(XmlNodeType type)182 static const char *type_to_str(XmlNodeType type)
183 {
184 static const char* type_names[] = {
185 "XmlNodeType_None",
186 "XmlNodeType_Element",
187 "XmlNodeType_Attribute",
188 "XmlNodeType_Text",
189 "XmlNodeType_CDATA",
190 "", "",
191 "XmlNodeType_ProcessingInstruction",
192 "XmlNodeType_Comment",
193 "",
194 "XmlNodeType_DocumentType",
195 "", "",
196 "XmlNodeType_Whitespace",
197 "",
198 "XmlNodeType_EndElement",
199 "",
200 "XmlNodeType_XmlDeclaration"
201 };
202
203 static const char unknown[] = "unknown";
204
205 switch (type)
206 {
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];
219 default:
220 return unknown;
221 }
222 }
223
224 #define set_input_string(a,b) _set_input_string(__LINE__,a,b);
_set_input_string(unsigned line,IXmlReader * reader,const char * xml)225 static void _set_input_string(unsigned line, IXmlReader *reader, const char *xml)
226 {
227 IStream *stream;
228 HRESULT hr;
229
230 stream = create_stream_on_data(xml, strlen(xml));
231
232 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
233 ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr);
234
235 IStream_Release(stream);
236 }
237
238 #define read_node(a,b) _read_node(__LINE__,a,b)
_read_node(unsigned line,IXmlReader * reader,XmlNodeType expected_type)239 static void _read_node(unsigned line, IXmlReader *reader, XmlNodeType expected_type)
240 {
241 XmlNodeType type;
242 HRESULT hr;
243
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);
247 else
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);
250 }
251
252 #define next_attribute(a) _next_attribute(__LINE__,a)
_next_attribute(unsigned line,IXmlReader * reader)253 static void _next_attribute(unsigned line, IXmlReader *reader)
254 {
255 HRESULT hr;
256 hr = IXmlReader_MoveToNextAttribute(reader);
257 ok_(__FILE__,line)(hr == S_OK, "MoveToNextAttribute returned %08x\n", hr);
258 }
259
260 #define move_to_element(a) _move_to_element(__LINE__,a)
_move_to_element(unsigned line,IXmlReader * reader)261 static void _move_to_element(unsigned line, IXmlReader *reader)
262 {
263 HRESULT hr;
264 hr = IXmlReader_MoveToElement(reader);
265 ok_(__FILE__,line)(hr == S_OK, "MoveToElement failed: %08x\n", hr);
266 }
267
test_read_state(IXmlReader * reader,XmlReadState expected,XmlReadState exp_broken,int line)268 static void test_read_state(IXmlReader *reader, XmlReadState expected,
269 XmlReadState exp_broken, int line)
270 {
271 BOOL broken_state;
272 LONG_PTR state;
273
274 state = -1; /* invalid state value */
275 IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
276
277 if (exp_broken == expected)
278 broken_state = FALSE;
279 else
280 broken_state = broken(exp_broken == state);
281
282 ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n",
283 state_to_str(expected), state_to_str(state));
284 }
285
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__)
288
289 #define reader_value(a,b) _reader_value(__LINE__,a,b)
_reader_value(unsigned line,IXmlReader * reader,const char * expect)290 static const WCHAR *_reader_value(unsigned line, IXmlReader *reader, const char *expect)
291 {
292 const WCHAR *str = (void*)0xdeadbeef;
293 ULONG len = 0xdeadbeef;
294 HRESULT hr;
295
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));
300 return str;
301 }
302
303 #define reader_name(a,b) _reader_name(__LINE__,a,b)
_reader_name(unsigned line,IXmlReader * reader,const char * expect)304 static const WCHAR *_reader_name(unsigned line, IXmlReader *reader, const char *expect)
305 {
306 const WCHAR *str = (void*)0xdeadbeef;
307 ULONG len = 0xdeadbeef;
308 HRESULT hr;
309
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));
314 return str;
315 }
316
317 #define reader_prefix(a,b) _reader_prefix(__LINE__,a,b)
_reader_prefix(unsigned line,IXmlReader * reader,const char * expect)318 static const WCHAR *_reader_prefix(unsigned line, IXmlReader *reader, const char *expect)
319 {
320 const WCHAR *str = (void*)0xdeadbeef;
321 ULONG len = 0xdeadbeef;
322 HRESULT hr;
323
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));
328 return str;
329 }
330
331 #define reader_namespace(a,b) _reader_namespace(__LINE__,a,b)
_reader_namespace(unsigned line,IXmlReader * reader,const char * expect)332 static const WCHAR *_reader_namespace(unsigned line, IXmlReader *reader, const char *expect)
333 {
334 const WCHAR *str = (void*)0xdeadbeef;
335 ULONG len = 0xdeadbeef;
336 HRESULT hr;
337
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));
342 return str;
343 }
344
345 #define reader_qname(a,b) _reader_qname(a,b,__LINE__)
_reader_qname(IXmlReader * reader,const char * expect,unsigned line)346 static const WCHAR *_reader_qname(IXmlReader *reader, const char *expect, unsigned line)
347 {
348 const WCHAR *str = (void*)0xdeadbeef;
349 ULONG len = 0xdeadbeef;
350 HRESULT hr;
351
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));
356 return str;
357 }
358
359 #define read_value_char(a,b) _read_value_char(a,b,__LINE__)
_read_value_char(IXmlReader * reader,WCHAR expected_char,unsigned line)360 static void _read_value_char(IXmlReader *reader, WCHAR expected_char, unsigned line)
361 {
362 WCHAR c = 0xffff;
363 UINT count = 0;
364 HRESULT hr;
365
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);
370 }
371
372 typedef struct _testinput
373 {
374 IUnknown IUnknown_iface;
375 LONG ref;
376 } testinput;
377
impl_from_IUnknown(IUnknown * iface)378 static inline testinput *impl_from_IUnknown(IUnknown *iface)
379 {
380 return CONTAINING_RECORD(iface, testinput, IUnknown_iface);
381 }
382
testinput_QueryInterface(IUnknown * iface,REFIID riid,void ** ppvObj)383 static HRESULT WINAPI testinput_QueryInterface(IUnknown *iface, REFIID riid, void** ppvObj)
384 {
385 if (IsEqualGUID( riid, &IID_IUnknown ))
386 {
387 *ppvObj = iface;
388 IUnknown_AddRef(iface);
389 return S_OK;
390 }
391
392 input_iids.iids[input_iids.count++] = *riid;
393
394 *ppvObj = NULL;
395
396 return E_NOINTERFACE;
397 }
398
testinput_AddRef(IUnknown * iface)399 static ULONG WINAPI testinput_AddRef(IUnknown *iface)
400 {
401 testinput *This = impl_from_IUnknown(iface);
402 return InterlockedIncrement(&This->ref);
403 }
404
testinput_Release(IUnknown * iface)405 static ULONG WINAPI testinput_Release(IUnknown *iface)
406 {
407 testinput *This = impl_from_IUnknown(iface);
408 LONG ref;
409
410 ref = InterlockedDecrement(&This->ref);
411 if (ref == 0)
412 heap_free(This);
413
414 return ref;
415 }
416
417 static const struct IUnknownVtbl testinput_vtbl =
418 {
419 testinput_QueryInterface,
420 testinput_AddRef,
421 testinput_Release
422 };
423
testinput_createinstance(void ** ppObj)424 static HRESULT testinput_createinstance(void **ppObj)
425 {
426 testinput *input;
427
428 input = heap_alloc(sizeof(*input));
429 if(!input) return E_OUTOFMEMORY;
430
431 input->IUnknown_iface.lpVtbl = &testinput_vtbl;
432 input->ref = 1;
433
434 *ppObj = &input->IUnknown_iface;
435
436 return S_OK;
437 }
438
teststream_QueryInterface(ISequentialStream * iface,REFIID riid,void ** obj)439 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
440 {
441 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
442 {
443 *obj = iface;
444 return S_OK;
445 }
446
447 *obj = NULL;
448 return E_NOINTERFACE;
449 }
450
teststream_AddRef(ISequentialStream * iface)451 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
452 {
453 return 2;
454 }
455
teststream_Release(ISequentialStream * iface)456 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
457 {
458 return 1;
459 }
460
461 static int stream_readcall;
462
teststream_Read(ISequentialStream * iface,void * pv,ULONG cb,ULONG * pread)463 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
464 {
465 static const char xml[] = "<!-- comment -->";
466
467 if (stream_readcall++)
468 {
469 *pread = 0;
470 return E_PENDING;
471 }
472
473 *pread = sizeof(xml) / 2;
474 memcpy(pv, xml, *pread);
475 return S_OK;
476 }
477
teststream_Write(ISequentialStream * iface,const void * pv,ULONG cb,ULONG * written)478 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
479 {
480 ok(0, "unexpected call\n");
481 return E_NOTIMPL;
482 }
483
484 static const ISequentialStreamVtbl teststreamvtbl =
485 {
486 teststream_QueryInterface,
487 teststream_AddRef,
488 teststream_Release,
489 teststream_Read,
490 teststream_Write
491 };
492
resolver_QI(IXmlResolver * iface,REFIID riid,void ** obj)493 static HRESULT WINAPI resolver_QI(IXmlResolver *iface, REFIID riid, void **obj)
494 {
495 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
496
497 if (IsEqualIID(riid, &IID_IXmlResolver) || IsEqualIID(riid, &IID_IUnknown))
498 {
499 *obj = iface;
500 IXmlResolver_AddRef(iface);
501 return S_OK;
502 }
503
504 *obj = NULL;
505 return E_NOINTERFACE;
506 }
507
resolver_AddRef(IXmlResolver * iface)508 static ULONG WINAPI resolver_AddRef(IXmlResolver *iface)
509 {
510 return 2;
511 }
512
resolver_Release(IXmlResolver * iface)513 static ULONG WINAPI resolver_Release(IXmlResolver *iface)
514 {
515 return 1;
516 }
517
resolver_ResolveUri(IXmlResolver * iface,const WCHAR * base_uri,const WCHAR * public_id,const WCHAR * system_id,IUnknown ** input)518 static HRESULT WINAPI resolver_ResolveUri(IXmlResolver *iface, const WCHAR *base_uri,
519 const WCHAR *public_id, const WCHAR *system_id, IUnknown **input)
520 {
521 ok(0, "unexpected call\n");
522 return E_NOTIMPL;
523 }
524
525 static const IXmlResolverVtbl resolvervtbl =
526 {
527 resolver_QI,
528 resolver_AddRef,
529 resolver_Release,
530 resolver_ResolveUri
531 };
532
533 static IXmlResolver testresolver = { &resolvervtbl };
534
test_reader_create(void)535 static void test_reader_create(void)
536 {
537 IXmlResolver *resolver;
538 IUnknown *input, *unk;
539 IXmlReader *reader;
540 #ifdef __REACTOS__
541 LONG_PTR dtd;
542 #else
543 DtdProcessing dtd;
544 #endif
545 XmlNodeType nodetype;
546 HRESULT hr;
547
548 /* crashes native */
549 if (0)
550 {
551 CreateXmlReader(&IID_IXmlReader, NULL, NULL);
552 CreateXmlReader(NULL, (void**)&reader, NULL);
553 }
554
555 hr = CreateXmlReader(&IID_IStream, (void **)&unk, NULL);
556 ok(hr == E_NOINTERFACE, "got %08x\n", hr);
557
558 hr = CreateXmlReader(&IID_IUnknown, (void **)&unk, NULL);
559 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
560 hr = IUnknown_QueryInterface(unk, &IID_IXmlReader, (void **)&reader);
561 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
562 ok(unk == (IUnknown *)reader, "unexpected interface\n");
563 IXmlReader_Release(reader);
564 IUnknown_Release(unk);
565
566 hr = CreateXmlReader(&IID_IUnknown, (void **)&reader, NULL);
567 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
568 IXmlReader_Release(reader);
569
570 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
571 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
572
573 TEST_READER_STATE(reader, XmlReadState_Closed);
574
575 nodetype = XmlNodeType_Element;
576 hr = IXmlReader_GetNodeType(reader, &nodetype);
577 ok(hr == S_FALSE, "got %08x\n", hr);
578 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
579
580 /* crashes on XP, 2k3, works on newer versions */
581 if (0)
582 {
583 hr = IXmlReader_GetNodeType(reader, NULL);
584 ok(hr == E_INVALIDARG, "got %08x\n", hr);
585 }
586
587 resolver = (void*)0xdeadbeef;
588 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
589 ok(hr == S_OK, "got 0x%08x\n", hr);
590 ok(resolver == NULL, "got %p\n", resolver);
591
592 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
593 ok(hr == S_OK, "got 0x%08x\n", hr);
594
595 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR)&testresolver);
596 ok(hr == S_OK, "got 0x%08x\n", hr);
597
598 resolver = NULL;
599 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
600 ok(hr == S_OK, "got 0x%08x\n", hr);
601 ok(resolver == &testresolver, "got %p\n", resolver);
602 IXmlResolver_Release(resolver);
603
604 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
605 ok(hr == S_OK, "got 0x%08x\n", hr);
606
607 dtd = 2;
608 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_DtdProcessing, (LONG_PTR*)&dtd);
609 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
610 #ifdef __REACTOS__
611 ok(dtd == DtdProcessing_Prohibit, "got %Id\n", dtd);
612 #else
613 ok(dtd == DtdProcessing_Prohibit, "got %d\n", dtd);
614 #endif
615
616 dtd = 2;
617 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, dtd);
618 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
619
620 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, -1);
621 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
622
623 /* Null input pointer, releases previous input */
624 hr = IXmlReader_SetInput(reader, NULL);
625 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
626
627 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
628
629 /* test input interface selection sequence */
630 hr = testinput_createinstance((void**)&input);
631 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
632
633 if (hr == S_OK)
634 {
635 input_iids.count = 0;
636 hr = IXmlReader_SetInput(reader, input);
637 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
638 ok_iids(&input_iids, setinput_full, setinput_full_old, FALSE);
639 IUnknown_Release(input);
640 }
641 IXmlReader_Release(reader);
642 }
643
test_readerinput(void)644 static void test_readerinput(void)
645 {
646 IXmlReaderInput *reader_input;
647 IXmlReader *reader, *reader2;
648 IUnknown *obj, *input;
649 IStream *stream, *stream2;
650 XmlNodeType nodetype;
651 HRESULT hr;
652 LONG ref;
653
654 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, NULL);
655 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
656 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, &reader_input);
657 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
658
659 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
660 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
661
662 ref = IStream_AddRef(stream);
663 ok(ref == 2, "Expected 2, got %d\n", ref);
664 IStream_Release(stream);
665 hr = CreateXmlReaderInputWithEncodingName((IUnknown*)stream, NULL, NULL, FALSE, NULL, &reader_input);
666 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
667
668 hr = IUnknown_QueryInterface(reader_input, &IID_IStream, (void**)&stream2);
669 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
670
671 hr = IUnknown_QueryInterface(reader_input, &IID_ISequentialStream, (void**)&stream2);
672 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
673
674 /* IXmlReaderInput grabs a stream reference */
675 ref = IStream_AddRef(stream);
676 ok(ref == 3, "Expected 3, got %d\n", ref);
677 IStream_Release(stream);
678
679 /* try ::SetInput() with valid IXmlReaderInput */
680 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
681 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
682
683 ref = IUnknown_AddRef(reader_input);
684 ok(ref == 2, "Expected 2, got %d\n", ref);
685 IUnknown_Release(reader_input);
686
687 hr = IXmlReader_SetInput(reader, reader_input);
688 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
689
690 TEST_READER_STATE(reader, XmlReadState_Initial);
691
692 nodetype = XmlNodeType_Element;
693 hr = IXmlReader_GetNodeType(reader, &nodetype);
694 ok(hr == S_OK, "got %08x\n", hr);
695 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
696
697 /* IXmlReader grabs a IXmlReaderInput reference */
698 ref = IUnknown_AddRef(reader_input);
699 ok(ref == 3, "Expected 3, got %d\n", ref);
700 IUnknown_Release(reader_input);
701
702 ref = IStream_AddRef(stream);
703 ok(ref == 4, "Expected 4, got %d\n", ref);
704 IStream_Release(stream);
705
706 /* reset input and check state */
707 hr = IXmlReader_SetInput(reader, NULL);
708 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
709
710 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
711
712 IXmlReader_Release(reader);
713
714 ref = IStream_AddRef(stream);
715 ok(ref == 3, "Expected 3, got %d\n", ref);
716 IStream_Release(stream);
717
718 ref = IUnknown_AddRef(reader_input);
719 ok(ref == 2, "Expected 2, got %d\n", ref);
720 IUnknown_Release(reader_input);
721
722 /* IID_IXmlReaderInput */
723 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
724 so it's not a COM interface actually.
725 Such query will be used only to check if input is really IXmlReaderInput */
726 obj = (IUnknown*)0xdeadbeef;
727 hr = IUnknown_QueryInterface(reader_input, &IID_IXmlReaderInput, (void**)&obj);
728 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
729 ref = IUnknown_AddRef(reader_input);
730 ok(ref == 3, "Expected 3, got %d\n", ref);
731 IUnknown_Release(reader_input);
732
733 IUnknown_Release(reader_input);
734 IUnknown_Release(reader_input);
735 IStream_Release(stream);
736
737 /* test input interface selection sequence */
738 input = NULL;
739 hr = testinput_createinstance((void**)&input);
740 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
741
742 input_iids.count = 0;
743 ref = IUnknown_AddRef(input);
744 ok(ref == 2, "Expected 2, got %d\n", ref);
745 IUnknown_Release(input);
746 hr = CreateXmlReaderInputWithEncodingName(input, NULL, NULL, FALSE, NULL, &reader_input);
747 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
748 ok_iids(&input_iids, empty_seq, NULL, FALSE);
749 /* IXmlReaderInput stores stream interface as IUnknown */
750 ref = IUnknown_AddRef(input);
751 ok(ref == 3, "Expected 3, got %d\n", ref);
752 IUnknown_Release(input);
753
754 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
755 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
756
757 input_iids.count = 0;
758 ref = IUnknown_AddRef(reader_input);
759 ok(ref == 2, "Expected 2, got %d\n", ref);
760 IUnknown_Release(reader_input);
761 ref = IUnknown_AddRef(input);
762 ok(ref == 3, "Expected 3, got %d\n", ref);
763 IUnknown_Release(input);
764 hr = IXmlReader_SetInput(reader, reader_input);
765 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
766 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
767
768 TEST_READER_STATE(reader, XmlReadState_Closed);
769
770 ref = IUnknown_AddRef(input);
771 ok(ref == 3, "Expected 3, got %d\n", ref);
772 IUnknown_Release(input);
773
774 ref = IUnknown_AddRef(reader_input);
775 ok(ref == 3 || broken(ref == 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
776 "Expected 3, got %d\n", ref);
777 IUnknown_Release(reader_input);
778 /* repeat another time, no check or caching here */
779 input_iids.count = 0;
780 hr = IXmlReader_SetInput(reader, reader_input);
781 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
782 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
783
784 /* another reader */
785 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader2, NULL);
786 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
787
788 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
789 ::SetInput() level, each time it's called */
790 input_iids.count = 0;
791 hr = IXmlReader_SetInput(reader2, reader_input);
792 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
793 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
794
795 IXmlReader_Release(reader2);
796 IXmlReader_Release(reader);
797
798 IUnknown_Release(reader_input);
799 IUnknown_Release(input);
800 }
801
test_reader_state(void)802 static void test_reader_state(void)
803 {
804 XmlNodeType nodetype;
805 IXmlReader *reader;
806 HRESULT hr;
807
808 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
809 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
810
811 /* invalid arguments */
812 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, NULL);
813 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
814
815 /* attempt to read on closed reader */
816 TEST_READER_STATE(reader, XmlReadState_Closed);
817
818 if (0)
819 {
820 /* newer versions crash here, probably because no input was set */
821 hr = IXmlReader_Read(reader, &nodetype);
822 ok(hr == S_FALSE, "got %08x\n", hr);
823 }
824 set_input_string(reader, "xml");
825 TEST_READER_STATE(reader, XmlReadState_Initial);
826
827 nodetype = XmlNodeType_Element;
828 hr = IXmlReader_Read(reader, &nodetype);
829 todo_wine
830 ok(FAILED(hr), "got %08x\n", hr);
831 ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype);
832
833 todo_wine
834 TEST_READER_STATE(reader, XmlReadState_Error);
835
836 nodetype = XmlNodeType_Element;
837 hr = IXmlReader_Read(reader, &nodetype);
838 todo_wine
839 ok(FAILED(hr), "got %08x\n", hr);
840 ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype);
841
842 IXmlReader_Release(reader);
843 }
844
test_reader_depth(IXmlReader * reader,UINT depth,UINT brk,int line)845 static void test_reader_depth(IXmlReader *reader, UINT depth, UINT brk, int line)
846 {
847 BOOL condition;
848 UINT d = ~0u;
849
850 IXmlReader_GetDepth(reader, &d);
851
852 condition = d == depth;
853 if (brk != ~0u)
854 condition |= broken(d == brk);
855 ok_(__FILE__, line)(condition, "Unexpected nesting depth %u, expected %u\n", d, depth);
856 }
857
858 #define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__)
859 #define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__)
860
test_read_xmldeclaration(void)861 static void test_read_xmldeclaration(void)
862 {
863 static const struct
864 {
865 WCHAR name[12];
866 WCHAR val[12];
867 } name_val[] =
868 {
869 { {'v','e','r','s','i','o','n',0}, {'1','.','0',0} },
870 { {'e','n','c','o','d','i','n','g',0}, {'U','T','F','-','8',0} },
871 { {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
872 };
873 IXmlReader *reader;
874 IStream *stream;
875 HRESULT hr;
876 XmlNodeType type;
877 UINT count = 0, len, i;
878 BOOL ret;
879 const WCHAR *val;
880
881 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
882 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
883
884 stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
885
886 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
887 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
888
889 hr = IXmlReader_GetAttributeCount(reader, &count);
890 ok(hr == S_OK, "got %08x\n", hr);
891 ok(count == 0, "got %d\n", count);
892
893 /* try to move without attributes */
894 hr = IXmlReader_MoveToElement(reader);
895 ok(hr == S_FALSE, "got %08x\n", hr);
896
897 hr = IXmlReader_MoveToNextAttribute(reader);
898 ok(hr == S_FALSE, "got %08x\n", hr);
899
900 hr = IXmlReader_MoveToFirstAttribute(reader);
901 ok(hr == S_FALSE, "got %08x\n", hr);
902
903 TEST_READER_POSITION(reader, 0, 0);
904
905 read_node(reader, XmlNodeType_XmlDeclaration);
906
907 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
908 TEST_READER_POSITION2(reader, 1, 3, ~0u, 55);
909
910 TEST_DEPTH(reader, 0);
911 TEST_READER_STATE(reader, XmlReadState_Interactive);
912
913 reader_value(reader, "");
914
915 /* check attributes */
916 next_attribute(reader);
917
918 TEST_DEPTH(reader, 1);
919
920 type = XmlNodeType_None;
921 hr = IXmlReader_GetNodeType(reader, &type);
922 ok(hr == S_OK, "got %08x\n", hr);
923 ok(type == XmlNodeType_Attribute, "got %d\n", type);
924
925 TEST_READER_POSITION2(reader, 1, 7, ~0u, 55);
926
927 /* try to move from last attribute */
928 next_attribute(reader);
929 next_attribute(reader);
930 hr = IXmlReader_MoveToNextAttribute(reader);
931 ok(hr == S_FALSE, "got %08x\n", hr);
932
933 type = XmlNodeType_None;
934 hr = IXmlReader_GetNodeType(reader, &type);
935 ok(hr == S_OK, "got %08x\n", hr);
936 ok(type == XmlNodeType_Attribute, "got %d\n", type);
937
938 hr = IXmlReader_MoveToFirstAttribute(reader);
939 ok(hr == S_OK, "got %08x\n", hr);
940 TEST_READER_POSITION2(reader, 1, 7, ~0u, 55);
941
942 hr = IXmlReader_GetAttributeCount(reader, NULL);
943 ok(hr == E_INVALIDARG, "got %08x\n", hr);
944
945 hr = IXmlReader_GetAttributeCount(reader, &count);
946 ok(hr == S_OK, "got %08x\n", hr);
947 ok(count == 3, "Expected 3, got %d\n", count);
948
949 for (i = 0; i < count; i++)
950 {
951 len = 0;
952 hr = IXmlReader_GetLocalName(reader, &val, &len);
953 ok(hr == S_OK, "got %08x\n", hr);
954 ok(len == lstrlenW(name_val[i].name), "expected %u, got %u\n", lstrlenW(name_val[i].name), len);
955 ok(!lstrcmpW(name_val[i].name, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].name), wine_dbgstr_w(val));
956
957 len = 0;
958 hr = IXmlReader_GetValue(reader, &val, &len);
959 ok(hr == S_OK, "got %08x\n", hr);
960 ok(len == lstrlenW(name_val[i].val), "expected %u, got %u\n", lstrlenW(name_val[i].val), len);
961 ok(!lstrcmpW(name_val[i].val, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].val), wine_dbgstr_w(val));
962
963 hr = IXmlReader_MoveToNextAttribute(reader);
964 ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr);
965 }
966
967 TEST_DEPTH(reader, 1);
968
969 move_to_element(reader);
970 TEST_READER_POSITION2(reader, 1, 3, ~0u, 55);
971
972 type = XmlNodeType_None;
973 hr = IXmlReader_GetNodeType(reader, &type);
974 ok(hr == S_OK, "got %08x\n", hr);
975 ok(type == XmlNodeType_XmlDeclaration, "got %d\n", type);
976
977 type = XmlNodeType_XmlDeclaration;
978 hr = IXmlReader_Read(reader, &type);
979 /* newer versions return syntax error here cause document is incomplete,
980 it makes more sense than invalid char error */
981 todo_wine {
982 ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
983 ok(type == XmlNodeType_None, "got %d\n", type);
984 }
985 IStream_Release(stream);
986
987 /* test short variant */
988 stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
989
990 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
991 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
992
993 read_node(reader, XmlNodeType_XmlDeclaration);
994 TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
995 TEST_READER_STATE(reader, XmlReadState_Interactive);
996
997 hr = IXmlReader_GetAttributeCount(reader, &count);
998 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
999 ok(count == 1, "expected 1, got %d\n", count);
1000
1001 ret = IXmlReader_IsEmptyElement(reader);
1002 ok(!ret, "element should not be empty\n");
1003
1004 reader_value(reader, "");
1005 reader_name(reader, "xml");
1006
1007 reader_qname(reader, "xml");
1008
1009 /* check attributes */
1010 next_attribute(reader);
1011
1012 type = -1;
1013 hr = IXmlReader_GetNodeType(reader, &type);
1014 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
1015 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1016 TEST_READER_POSITION2(reader, 1, 7, ~0u, 21);
1017
1018 /* try to move from last attribute */
1019 hr = IXmlReader_MoveToNextAttribute(reader);
1020 ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
1021
1022 read_node(reader, XmlNodeType_Element);
1023 TEST_READER_POSITION2(reader, 1, 23, ~0u, 40);
1024 TEST_READER_STATE(reader, XmlReadState_Interactive);
1025
1026 hr = IXmlReader_GetAttributeCount(reader, &count);
1027 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
1028 ok(count == 0, "expected 0, got %d\n", count);
1029
1030 ret = IXmlReader_IsEmptyElement(reader);
1031 ok(ret, "element should be empty\n");
1032
1033 reader_value(reader, "");
1034 reader_name(reader, "RegistrationInfo");
1035
1036 type = -1;
1037 hr = IXmlReader_Read(reader, &type);
1038 todo_wine
1039 ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
1040 ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
1041 TEST_READER_POSITION(reader, 1, 41);
1042 todo_wine
1043 TEST_READER_STATE(reader, XmlReadState_Error);
1044
1045 IStream_Release(stream);
1046 IXmlReader_Release(reader);
1047 }
1048
1049 struct test_entry {
1050 const char *xml;
1051 const char *name;
1052 const char *value;
1053 HRESULT hr;
1054 HRESULT hr_broken; /* this is set to older version results */
1055 BOOL todo;
1056 };
1057
1058 static struct test_entry comment_tests[] = {
1059 { "<!-- comment -->", "", " comment ", S_OK },
1060 { "<!-- - comment-->", "", " - comment", S_OK },
1061 { "<!-- -- comment-->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
1062 { "<!-- -- comment--->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
1063 { NULL }
1064 };
1065
test_read_comment(void)1066 static void test_read_comment(void)
1067 {
1068 static const char *teststr = "<a>text<!-- comment --></a>";
1069 struct test_entry *test = comment_tests;
1070 static const XmlNodeType types[] =
1071 {
1072 XmlNodeType_Element,
1073 XmlNodeType_Text,
1074 XmlNodeType_Comment,
1075 XmlNodeType_EndElement,
1076 };
1077 unsigned int i = 0;
1078 IXmlReader *reader;
1079 XmlNodeType type;
1080 HRESULT hr;
1081
1082 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1083 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1084
1085 set_input_string(reader, teststr);
1086
1087 while (IXmlReader_Read(reader, &type) == S_OK)
1088 {
1089 const WCHAR *value;
1090
1091 ok(type == types[i], "%d: unexpected node type %d\n", i, type);
1092
1093 if (type == XmlNodeType_Text || type == XmlNodeType_Comment)
1094 {
1095 hr = IXmlReader_GetValue(reader, &value, NULL);
1096 ok(hr == S_OK, "got %08x\n", hr);
1097 ok(*value != 0, "Expected node value\n");
1098 }
1099 i++;
1100 }
1101
1102 while (test->xml)
1103 {
1104 set_input_string(reader, test->xml);
1105
1106 type = XmlNodeType_None;
1107 hr = IXmlReader_Read(reader, &type);
1108 if (test->hr_broken)
1109 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1110 else
1111 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1112 if (hr == S_OK)
1113 {
1114 const WCHAR *str;
1115
1116 ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml);
1117
1118 reader_name(reader, "");
1119
1120 str = NULL;
1121 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1122 ok(hr == S_OK, "got 0x%08x\n", hr);
1123 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1124
1125 reader_qname(reader, "");
1126
1127 str = NULL;
1128 hr = IXmlReader_GetQualifiedName(reader, &str, NULL);
1129 ok(hr == S_OK, "got 0x%08x\n", hr);
1130 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1131
1132 /* value */
1133 reader_value(reader, test->value);
1134 }
1135
1136 test++;
1137 }
1138
1139 IXmlReader_Release(reader);
1140 }
1141
1142 static struct test_entry pi_tests[] = {
1143 { "<?pi?>", "pi", "", S_OK },
1144 { "<?pi ?>", "pi", "", S_OK },
1145 { "<?pi ?>", "pi", "", S_OK },
1146 { "<?pi pi data?>", "pi", "pi data", S_OK },
1147 { "<?pi pi data ?>", "pi", "pi data ", S_OK },
1148 { "<?pi data ?>", "pi", "data ", S_OK },
1149 { "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
1150 { "<?:pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
1151 { "<?-pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
1152 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK },
1153 { NULL }
1154 };
1155
test_read_pi(void)1156 static void test_read_pi(void)
1157 {
1158 struct test_entry *test = pi_tests;
1159 IXmlReader *reader;
1160 HRESULT hr;
1161
1162 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1163 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1164
1165 while (test->xml)
1166 {
1167 XmlNodeType type;
1168
1169 set_input_string(reader, test->xml);
1170
1171 type = XmlNodeType_None;
1172 hr = IXmlReader_Read(reader, &type);
1173 if (test->hr_broken)
1174 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1175 else
1176 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1177 if (hr == S_OK)
1178 {
1179 const WCHAR *str;
1180 WCHAR *str_exp;
1181 UINT len;
1182
1183 ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml);
1184
1185 reader_name(reader, test->name);
1186
1187 len = 0;
1188 str = NULL;
1189 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1190 ok(hr == S_OK, "got 0x%08x\n", hr);
1191 ok(len == strlen(test->name), "got %u\n", len);
1192 str_exp = a2w(test->name);
1193 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1194 free_str(str_exp);
1195
1196 /* value */
1197 reader_value(reader, test->value);
1198 }
1199
1200 test++;
1201 }
1202
1203 IXmlReader_Release(reader);
1204 }
1205
1206 struct nodes_test {
1207 const char *xml;
1208 struct {
1209 XmlNodeType type;
1210 const char *value;
1211 } nodes[20];
1212 };
1213
1214 static const char misc_test_xml[] =
1215 "<!-- comment1 -->"
1216 "<!-- comment2 -->"
1217 "<?pi1 pi1body ?>"
1218 "<!-- comment3 -->"
1219 " \t \r \n"
1220 "<!-- comment4 -->"
1221 "<a>"
1222 "\r\n\t"
1223 "<b/>"
1224 "text"
1225 "<!-- comment -->"
1226 "text2"
1227 "<?pi pibody ?>"
1228 "\r\n"
1229 "</a>"
1230 ;
1231
1232 static struct nodes_test misc_test = {
1233 misc_test_xml,
1234 {
1235 {XmlNodeType_Comment, " comment1 "},
1236 {XmlNodeType_Comment, " comment2 "},
1237 {XmlNodeType_ProcessingInstruction, "pi1body "},
1238 {XmlNodeType_Comment, " comment3 "},
1239 {XmlNodeType_Whitespace, " \t \n \n"},
1240 {XmlNodeType_Comment, " comment4 "},
1241 {XmlNodeType_Element, ""},
1242 {XmlNodeType_Whitespace, "\n\t"},
1243 {XmlNodeType_Element, ""},
1244 {XmlNodeType_Text, "text"},
1245 {XmlNodeType_Comment, " comment "},
1246 {XmlNodeType_Text, "text2"},
1247 {XmlNodeType_ProcessingInstruction, "pibody "},
1248 {XmlNodeType_Whitespace, "\n"},
1249 {XmlNodeType_EndElement, ""},
1250 {XmlNodeType_None, ""}
1251 }
1252 };
1253
test_read_full(void)1254 static void test_read_full(void)
1255 {
1256 struct nodes_test *test = &misc_test;
1257 IXmlReader *reader;
1258 HRESULT hr;
1259 int i;
1260
1261 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1262 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1263
1264 set_input_string(reader, test->xml);
1265
1266 i = 0;
1267 do
1268 {
1269 read_node(reader, test->nodes[i].type);
1270 reader_value(reader, test->nodes[i].value);
1271 } while(test->nodes[i++].type != XmlNodeType_None);
1272
1273 IXmlReader_Release(reader);
1274 }
1275
1276 static const char test_public_dtd[] =
1277 "<!DOCTYPE testdtd PUBLIC \"pubid\" \"externalid uri\" >";
1278
test_read_public_dtd(void)1279 static void test_read_public_dtd(void)
1280 {
1281 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1282 IXmlReader *reader;
1283 const WCHAR *str;
1284 XmlNodeType type;
1285 UINT len, count;
1286 HRESULT hr;
1287
1288 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1289 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1290
1291 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1292 ok(hr == S_OK, "got 0x%8x\n", hr);
1293
1294 set_input_string(reader, test_public_dtd);
1295
1296 read_node(reader, XmlNodeType_DocumentType);
1297
1298 count = 0;
1299 hr = IXmlReader_GetAttributeCount(reader, &count);
1300 ok(hr == S_OK, "got %08x\n", hr);
1301 ok(count == 2, "got %d\n", count);
1302
1303 hr = IXmlReader_MoveToFirstAttribute(reader);
1304 ok(hr == S_OK, "got %08x\n", hr);
1305
1306 type = XmlNodeType_None;
1307 hr = IXmlReader_GetNodeType(reader, &type);
1308 ok(hr == S_OK, "got %08x\n", hr);
1309 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1310
1311 reader_name(reader, "PUBLIC");
1312 reader_value(reader, "pubid");
1313
1314 next_attribute(reader);
1315
1316 type = XmlNodeType_None;
1317 hr = IXmlReader_GetNodeType(reader, &type);
1318 ok(hr == S_OK, "got %08x\n", hr);
1319 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1320
1321 reader_name(reader, "SYSTEM");
1322 reader_value(reader, "externalid uri");
1323
1324 move_to_element(reader);
1325 reader_name(reader, "testdtd");
1326
1327 len = 0;
1328 str = NULL;
1329 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1330 ok(hr == S_OK, "got 0x%08x\n", hr);
1331 todo_wine {
1332 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1333 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1334 }
1335 IXmlReader_Release(reader);
1336 }
1337
1338 static const char test_system_dtd[] =
1339 "<!DOCTYPE testdtd SYSTEM \"externalid uri\" >"
1340 "<!-- comment -->";
1341
test_read_system_dtd(void)1342 static void test_read_system_dtd(void)
1343 {
1344 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1345 IXmlReader *reader;
1346 const WCHAR *str;
1347 XmlNodeType type;
1348 UINT len, count;
1349 HRESULT hr;
1350
1351 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1352 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1353
1354 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1355 ok(hr == S_OK, "got 0x%8x\n", hr);
1356
1357 set_input_string(reader, test_system_dtd);
1358
1359 read_node(reader, XmlNodeType_DocumentType);
1360
1361 count = 0;
1362 hr = IXmlReader_GetAttributeCount(reader, &count);
1363 ok(hr == S_OK, "got %08x\n", hr);
1364 ok(count == 1, "got %d\n", count);
1365
1366 hr = IXmlReader_MoveToFirstAttribute(reader);
1367 ok(hr == S_OK, "got %08x\n", hr);
1368
1369 type = XmlNodeType_None;
1370 hr = IXmlReader_GetNodeType(reader, &type);
1371 ok(hr == S_OK, "got %08x\n", hr);
1372 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1373
1374 reader_name(reader, "SYSTEM");
1375 reader_value(reader, "externalid uri");
1376
1377 move_to_element(reader);
1378 reader_name(reader, "testdtd");
1379
1380 len = 0;
1381 str = NULL;
1382 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1383 ok(hr == S_OK, "got 0x%08x\n", hr);
1384 todo_wine {
1385 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1386 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1387 }
1388
1389 read_node(reader, XmlNodeType_Comment);
1390
1391 IXmlReader_Release(reader);
1392 }
1393
1394 static struct test_entry element_tests[] = {
1395 { "<a/>", "a", "", S_OK },
1396 { "<a />", "a", "", S_OK },
1397 { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX },
1398 { "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1399 { "< a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1400 { "<a>", "a", "", S_OK },
1401 { "<a >", "a", "", S_OK },
1402 { "<a \r \t\n>", "a", "", S_OK },
1403 { "</a>", NULL, NULL, NC_E_QNAMECHARACTER },
1404 { "<a:b:c />", NULL, NULL, NC_E_QNAMECOLON },
1405 { "<:b:c />", NULL, NULL, NC_E_QNAMECHARACTER },
1406 { NULL }
1407 };
1408
test_read_element(void)1409 static void test_read_element(void)
1410 {
1411 struct test_entry *test = element_tests;
1412 static const char stag[] =
1413 "<a attr1=\"_a\">"
1414 "<b attr2=\"_b\">"
1415 "text"
1416 "<c attr3=\"_c\"/>"
1417 "<d attr4=\"_d\"></d>"
1418 "</b>"
1419 "</a>";
1420 static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 };
1421 IXmlReader *reader;
1422 XmlNodeType type;
1423 unsigned int i;
1424 UINT depth;
1425 HRESULT hr;
1426
1427 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1428 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1429
1430 while (test->xml)
1431 {
1432 set_input_string(reader, test->xml);
1433
1434 type = XmlNodeType_None;
1435 hr = IXmlReader_Read(reader, &type);
1436 if (test->hr_broken)
1437 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1438 else
1439 todo_wine_if(test->hr == NC_E_UNDECLAREDPREFIX)
1440 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1441 if (hr == S_OK)
1442 {
1443 const WCHAR *str;
1444 WCHAR *str_exp;
1445 UINT len;
1446
1447 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1448
1449 len = 0;
1450 str = NULL;
1451 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1452 ok(hr == S_OK, "got 0x%08x\n", hr);
1453 ok(len == strlen(test->name), "got %u\n", len);
1454 str_exp = a2w(test->name);
1455 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1456 free_str(str_exp);
1457
1458 /* value */
1459 reader_value(reader, "");
1460 }
1461
1462 test++;
1463 }
1464
1465 /* test reader depth increment */
1466 set_input_string(reader, stag);
1467
1468 i = 0;
1469 while (IXmlReader_Read(reader, &type) == S_OK)
1470 {
1471 UINT count;
1472
1473 ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement ||
1474 type == XmlNodeType_Text, "Unexpected node type %d\n", type);
1475
1476 depth = 123;
1477 hr = IXmlReader_GetDepth(reader, &depth);
1478 ok(hr == S_OK, "got %08x\n", hr);
1479 ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
1480
1481 if (type == XmlNodeType_Element || type == XmlNodeType_EndElement)
1482 {
1483 const WCHAR *prefix;
1484
1485 prefix = NULL;
1486 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
1487 ok(hr == S_OK, "got %08x\n", hr);
1488 ok(prefix != NULL, "got %p\n", prefix);
1489
1490 if (!*prefix)
1491 {
1492 const WCHAR *local, *qname;
1493
1494 local = NULL;
1495 hr = IXmlReader_GetLocalName(reader, &local, NULL);
1496 ok(hr == S_OK, "got %08x\n", hr);
1497 ok(local != NULL, "got %p\n", local);
1498
1499 qname = NULL;
1500 hr = IXmlReader_GetQualifiedName(reader, &qname, NULL);
1501 ok(hr == S_OK, "got %08x\n", hr);
1502 ok(qname != NULL, "got %p\n", qname);
1503
1504 ok(local == qname, "expected same pointer\n");
1505 }
1506 }
1507
1508 if (type == XmlNodeType_EndElement)
1509 {
1510 count = 1;
1511 hr = IXmlReader_GetAttributeCount(reader, &count);
1512 ok(hr == S_OK, "got %08x\n", hr);
1513 ok(count == 0, "got %u\n", count);
1514 }
1515
1516 if (type == XmlNodeType_Element)
1517 {
1518 count = 0;
1519 hr = IXmlReader_GetAttributeCount(reader, &count);
1520 ok(hr == S_OK, "got %08x\n", hr);
1521
1522 /* moving to attributes increases depth */
1523 if (count)
1524 {
1525 const WCHAR *value;
1526
1527 reader_value(reader, "");
1528
1529 hr = IXmlReader_MoveToFirstAttribute(reader);
1530 ok(hr == S_OK, "got %08x\n", hr);
1531
1532 hr = IXmlReader_GetValue(reader, &value, NULL);
1533 ok(*value != 0, "Unexpected value %s\n", wine_dbgstr_w(value));
1534
1535 depth = 123;
1536 hr = IXmlReader_GetDepth(reader, &depth);
1537 ok(hr == S_OK, "got %08x\n", hr);
1538 ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1);
1539
1540 move_to_element(reader);
1541 reader_value(reader, "");
1542
1543 depth = 123;
1544 hr = IXmlReader_GetDepth(reader, &depth);
1545 ok(hr == S_OK, "got %08x\n", hr);
1546 ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
1547 }
1548 }
1549
1550 i++;
1551 }
1552
1553 /* start/end tag mismatch */
1554 set_input_string(reader, "<a></b>");
1555
1556 read_node(reader, XmlNodeType_Element);
1557
1558 type = XmlNodeType_Element;
1559 hr = IXmlReader_Read(reader, &type);
1560 ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr);
1561 ok(type == XmlNodeType_None, "got %d\n", type);
1562 TEST_READER_STATE(reader, XmlReadState_Error);
1563
1564 IXmlReader_Release(reader);
1565 }
1566
1567 static ISequentialStream teststream = { &teststreamvtbl };
1568
test_read_pending(void)1569 static void test_read_pending(void)
1570 {
1571 IXmlReader *reader;
1572 const WCHAR *value;
1573 XmlNodeType type;
1574 HRESULT hr;
1575 int c;
1576
1577 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1578 ok(hr == S_OK, "S_OK, got 0x%08x\n", hr);
1579
1580 hr = IXmlReader_SetInput(reader, (IUnknown*)&teststream);
1581 ok(hr == S_OK, "got 0x%08x\n", hr);
1582
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 todo_wine
1591 ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall);
1592 ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type);
1593
1594 /* newer versions' GetValue() makes an attempt to read more */
1595 c = stream_readcall;
1596 value = (void*)0xdeadbeef;
1597 hr = IXmlReader_GetValue(reader, &value, NULL);
1598 ok(hr == E_PENDING, "got 0x%08x\n", hr);
1599 ok(value == NULL || broken(value == (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value);
1600 ok(c < stream_readcall || broken(c == stream_readcall), "got %d, expected %d\n", stream_readcall, c+1);
1601
1602 IXmlReader_Release(reader);
1603 }
1604
test_readvaluechunk(void)1605 static void test_readvaluechunk(void)
1606 {
1607 IXmlReader *reader;
1608 XmlNodeType type;
1609 WCHAR buf[64];
1610 WCHAR b;
1611 HRESULT hr;
1612 UINT c;
1613
1614 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1615 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1616
1617 set_input_string(reader, "<!-- comment1 --><!-- comment2 -->");
1618
1619 hr = IXmlReader_Read(reader, &type);
1620 ok(hr == S_OK, "got %08x\n", hr);
1621 ok(type == XmlNodeType_Comment, "type = %u\n", type);
1622
1623 read_value_char(reader, ' ');
1624 read_value_char(reader, 'c');
1625
1626 /* portion read as chunk is skipped from resulting node value */
1627 reader_value(reader, "omment1 ");
1628
1629 /* once value is returned/allocated it's not possible to read by chunk */
1630 c = 0;
1631 b = 0;
1632 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1633 ok(hr == S_FALSE, "got %08x\n", hr);
1634 ok(c == 0, "got %u\n", c);
1635 ok(b == 0, "got %x\n", b);
1636
1637 c = 0xdeadbeef;
1638 hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c);
1639 ok(hr == S_OK, "got %08x\n", hr);
1640 ok(!c, "c = %u\n", c);
1641
1642 reader_value(reader, "omment1 ");
1643
1644 /* read comment2 */
1645 read_node(reader, XmlNodeType_Comment);
1646
1647 c = 0xdeadbeef;
1648 hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c);
1649 ok(hr == S_OK, "got %08x\n", hr);
1650 ok(!c, "c = %u\n", c);
1651
1652 c = 0xdeadbeef;
1653 memset(buf, 0xcc, sizeof(buf));
1654 hr = IXmlReader_ReadValueChunk(reader, buf, ARRAY_SIZE(buf), &c);
1655 ok(hr == S_OK, "got %08x\n", hr);
1656 ok(c == 10, "got %u\n", c);
1657 ok(buf[c] == 0xcccc, "buffer overflow\n");
1658 buf[c] = 0;
1659 ok(!strcmp_wa(buf, " comment2 "), "buf = %s\n", wine_dbgstr_w(buf));
1660
1661 c = 0xdeadbeef;
1662 memset(buf, 0xcc, sizeof(buf));
1663 hr = IXmlReader_ReadValueChunk(reader, buf, ARRAY_SIZE(buf), &c);
1664 ok(hr == S_FALSE, "got %08x\n", hr);
1665 ok(!c, "got %u\n", c);
1666
1667 /* portion read as chunk is skipped from resulting node value */
1668 reader_value(reader, "");
1669
1670 /* once value is returned/allocated it's not possible to read by chunk */
1671 c = 0xdeadbeef;
1672 b = 0xffff;
1673 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1674 ok(hr == S_FALSE, "got %08x\n", hr);
1675 ok(c == 0, "got %u\n", c);
1676 ok(b == 0xffff, "got %x\n", b);
1677
1678 reader_value(reader, "");
1679
1680 IXmlReader_Release(reader);
1681 }
1682
1683 static struct test_entry cdata_tests[] = {
1684 { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK },
1685 { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK },
1686 { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK, S_OK },
1687 { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK, S_OK },
1688 { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK },
1689 { NULL }
1690 };
1691
test_read_cdata(void)1692 static void test_read_cdata(void)
1693 {
1694 struct test_entry *test = cdata_tests;
1695 IXmlReader *reader;
1696 HRESULT hr;
1697
1698 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1699 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1700
1701 while (test->xml)
1702 {
1703 XmlNodeType type;
1704
1705 set_input_string(reader, test->xml);
1706
1707 type = XmlNodeType_None;
1708 hr = IXmlReader_Read(reader, &type);
1709
1710 /* read one more to get to CDATA */
1711 if (type == XmlNodeType_Element)
1712 {
1713 type = XmlNodeType_None;
1714 hr = IXmlReader_Read(reader, &type);
1715 }
1716
1717 if (test->hr_broken)
1718 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1719 else
1720 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1721 if (hr == S_OK)
1722 {
1723 const WCHAR *str;
1724 UINT len;
1725
1726 ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml);
1727
1728 reader_name(reader, "");
1729
1730 str = NULL;
1731 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1732 ok(hr == S_OK, "got 0x%08x\n", hr);
1733 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1734
1735 len = 1;
1736 str = NULL;
1737 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1738 ok(hr == S_OK, "got 0x%08x\n", hr);
1739 ok(len == 0, "got %u\n", len);
1740 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1741
1742 str = NULL;
1743 hr = IXmlReader_GetQualifiedName(reader, &str, NULL);
1744 ok(hr == S_OK, "got 0x%08x\n", hr);
1745 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1746
1747 /* value */
1748 reader_value(reader, test->value);
1749 }
1750
1751 test++;
1752 }
1753
1754 IXmlReader_Release(reader);
1755 }
1756
1757 static struct test_entry text_tests[] = {
1758 { "<a>simple text</a>", "", "simple text", S_OK },
1759 { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND },
1760 { "<a>\n \r\n \n\n text</a>", "", "\n \n \n\n text", S_OK, S_OK },
1761 { "<a>\r \r\r\n \n\n text</a>", "", "\n \n\n \n\n text", S_OK, S_OK },
1762 { NULL }
1763 };
1764
test_read_text(void)1765 static void test_read_text(void)
1766 {
1767 struct test_entry *test = text_tests;
1768 IXmlReader *reader;
1769 HRESULT hr;
1770
1771 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1772 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1773
1774 while (test->xml)
1775 {
1776 XmlNodeType type;
1777
1778 set_input_string(reader, test->xml);
1779
1780 type = XmlNodeType_None;
1781 hr = IXmlReader_Read(reader, &type);
1782
1783 /* read one more to get to text node */
1784 if (type == XmlNodeType_Element)
1785 {
1786 type = XmlNodeType_None;
1787 hr = IXmlReader_Read(reader, &type);
1788 }
1789 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1790 if (hr == S_OK)
1791 {
1792 const WCHAR *str;
1793 UINT len;
1794
1795 ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml);
1796
1797 reader_name(reader, "");
1798
1799 str = NULL;
1800 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1801 ok(hr == S_OK, "got 0x%08x\n", hr);
1802 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1803
1804 len = 1;
1805 str = NULL;
1806 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1807 ok(hr == S_OK, "got 0x%08x\n", hr);
1808 ok(len == 0, "got %u\n", len);
1809 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1810
1811 str = NULL;
1812 hr = IXmlReader_GetQualifiedName(reader, &str, NULL);
1813 ok(hr == S_OK, "got 0x%08x\n", hr);
1814 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1815
1816 /* value */
1817 reader_value(reader, test->value);
1818 }
1819
1820 test++;
1821 }
1822
1823 IXmlReader_Release(reader);
1824 }
1825
1826 struct test_entry_empty {
1827 const char *xml;
1828 BOOL empty;
1829 };
1830
1831 static struct test_entry_empty empty_element_tests[] = {
1832 { "<a></a>", FALSE },
1833 { "<a/>", TRUE },
1834 { NULL }
1835 };
1836
test_isemptyelement(void)1837 static void test_isemptyelement(void)
1838 {
1839 struct test_entry_empty *test = empty_element_tests;
1840 IXmlReader *reader;
1841 HRESULT hr;
1842
1843 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1844 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1845
1846 while (test->xml)
1847 {
1848 XmlNodeType type;
1849 BOOL ret;
1850
1851 set_input_string(reader, test->xml);
1852
1853 type = XmlNodeType_None;
1854 hr = IXmlReader_Read(reader, &type);
1855 ok(hr == S_OK, "got 0x%08x\n", hr);
1856 ok(type == XmlNodeType_Element, "got %d\n", type);
1857
1858 ret = IXmlReader_IsEmptyElement(reader);
1859 ok(ret == test->empty, "got %d, expected %d. xml=%s\n", ret, test->empty, test->xml);
1860
1861 test++;
1862 }
1863
1864 IXmlReader_Release(reader);
1865 }
1866
1867 static struct test_entry attributes_tests[] = {
1868 { "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK },
1869 { "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK },
1870 { "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK },
1871 { "<a attr1=\' \'/>", "attr1", " ", S_OK },
1872 { "<a attr1=\" \"/>", "attr1", " ", S_OK },
1873 { "<a attr1=\"\r\n \r \n \t\n\r\"/>", "attr1", " ", S_OK },
1874 { "<a attr1=\" val \"/>", "attr1", " val ", S_OK },
1875 { "<a attr1=\"\r\n\tval\n\"/>", "attr1", " val ", S_OK },
1876 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK },
1877 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK },
1878 { "<a attr1=\"<>&'"\"/>", "attr1", "<>&\'\"", S_OK },
1879 { "<a attr1=\"&entname;\"/>", NULL, NULL, WC_E_UNDECLAREDENTITY },
1880 { "<a attr1=\"val\"/>", NULL, NULL, WC_E_XMLCHARACTER },
1881 { "<a attr1=\"val &#a;\"/>", NULL, NULL, WC_E_DIGIT, WC_E_SEMICOLON },
1882 { "<a attr1=\"val a;\"/>", NULL, NULL, WC_E_SEMICOLON },
1883 { "<a attr1=\"val g;\"/>", NULL, NULL, WC_E_SEMICOLON },
1884 { "<a attr1=\"val &#xg;\"/>", NULL, NULL, WC_E_HEXDIGIT, WC_E_SEMICOLON },
1885 { "<a attr1=attrvalue/>", NULL, NULL, WC_E_QUOTE },
1886 { "<a attr1=\"attr<value\"/>", NULL, NULL, WC_E_LESSTHAN },
1887 { "<a attr1=\"&entname\"/>", NULL, NULL, WC_E_SEMICOLON },
1888 { NULL }
1889 };
1890
test_read_attribute(void)1891 static void test_read_attribute(void)
1892 {
1893 struct test_entry *test = attributes_tests;
1894 IXmlReader *reader;
1895 HRESULT hr;
1896
1897 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1898 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1899
1900 while (test->xml)
1901 {
1902 XmlNodeType type;
1903
1904 set_input_string(reader, test->xml);
1905
1906 hr = IXmlReader_Read(reader, NULL);
1907
1908 if (test->hr_broken)
1909 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1910 else
1911 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1912 if (hr == S_OK)
1913 {
1914 const WCHAR *str;
1915 WCHAR *str_exp;
1916 UINT len;
1917
1918 type = XmlNodeType_None;
1919 hr = IXmlReader_GetNodeType(reader, &type);
1920 ok(hr == S_OK, "Failed to get node type, %#x\n", hr);
1921
1922 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1923
1924 hr = IXmlReader_MoveToFirstAttribute(reader);
1925 ok(hr == S_OK, "got 0x%08x\n", hr);
1926
1927 reader_name(reader, test->name);
1928
1929 len = 1;
1930 str = NULL;
1931 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1932 ok(hr == S_OK, "got 0x%08x\n", hr);
1933 ok(len == strlen(test->name), "got %u\n", len);
1934 str_exp = a2w(test->name);
1935 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1936 free_str(str_exp);
1937
1938 /* value */
1939 reader_value(reader, test->value);
1940 }
1941
1942 test++;
1943 }
1944
1945 IXmlReader_Release(reader);
1946 }
1947
test_reader_properties(void)1948 static void test_reader_properties(void)
1949 {
1950 IXmlReader *reader;
1951 LONG_PTR value;
1952 HRESULT hr;
1953
1954 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1955 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1956
1957 value = 0;
1958 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value);
1959 ok(hr == S_OK, "GetProperty failed: %08x\n", hr);
1960 ok(value == 256, "Unexpected default max depth value %ld\n", value);
1961
1962 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0);
1963 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
1964
1965 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
1966 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
1967
1968 value = 256;
1969 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value);
1970 ok(hr == S_OK, "GetProperty failed: %08x\n", hr);
1971 ok(value == 0, "Unexpected max depth value %ld\n", value);
1972
1973 IXmlReader_Release(reader);
1974 }
1975
test_prefix(void)1976 static void test_prefix(void)
1977 {
1978 static const struct
1979 {
1980 const char *xml;
1981 const char *prefix1;
1982 const char *prefix2;
1983 const char *prefix3;
1984 } prefix_tests[] =
1985 {
1986 { "<b xmlns=\"defns\" xml:a=\"a ns\"/>", "", "", "xml" },
1987 { "<c:b xmlns:c=\"c ns\" xml:a=\"a ns\"/>", "c", "xmlns", "xml" },
1988 };
1989 IXmlReader *reader;
1990 unsigned int i;
1991 HRESULT hr;
1992
1993 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1994 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1995
1996 for (i = 0; i < ARRAY_SIZE(prefix_tests); i++) {
1997 XmlNodeType type;
1998
1999 set_input_string(reader, prefix_tests[i].xml);
2000
2001 hr = IXmlReader_Read(reader, &type);
2002 ok(hr == S_OK, "Read() failed, %#x\n", hr);
2003 ok(type == XmlNodeType_Element, "Unexpected node type %d.\n", type);
2004
2005 reader_prefix(reader, prefix_tests[i].prefix1);
2006
2007 hr = IXmlReader_MoveToFirstAttribute(reader);
2008 ok(hr == S_OK, "MoveToFirstAttribute() failed, %#x.\n", hr);
2009
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);
2013
2014 reader_prefix(reader, prefix_tests[i].prefix2);
2015
2016 next_attribute(reader);
2017
2018 hr = IXmlReader_GetNodeType(reader, &type);
2019 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
2020 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
2021
2022 reader_prefix(reader, prefix_tests[i].prefix3);
2023
2024 /* back to the element, check prefix */
2025 move_to_element(reader);
2026 reader_prefix(reader, prefix_tests[i].prefix1);
2027 }
2028
2029 IXmlReader_Release(reader);
2030 }
2031
test_namespaceuri(void)2032 static void test_namespaceuri(void)
2033 {
2034 struct uri_test
2035 {
2036 const char *xml;
2037 const char *uri[5];
2038 } uri_tests[] =
2039 {
2040 { "<a xmlns=\"defns a\"><b xmlns=\"defns b\"><c xmlns=\"defns c\"/></b></a>",
2041 { "defns a", "defns b", "defns c", "defns b", "defns a" }},
2042 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"/>",
2043 { "ns r" }},
2044 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"><b/></r:a>",
2045 { "ns r", "defns a", "ns r" }},
2046 { "<a xmlns=\"defns a\" xmlns:r=\"ns r\"><r:b/></a>",
2047 { "defns a", "ns r", "defns a" }},
2048 { "<a><b><c/></b></a>",
2049 { "", "", "", "", "" }},
2050 { "<a>text</a>",
2051 { "", "", "" }},
2052 { "<a>\r\n</a>",
2053 { "", "", "" }},
2054 { "<a><![CDATA[data]]></a>",
2055 { "", "", "" }},
2056 { "<?xml version=\"1.0\" ?><a/>",
2057 { "", "" }},
2058 { "<a><?pi ?></a>",
2059 { "", "", "" }},
2060 { "<a><!-- comment --></a>",
2061 { "", "", "" }},
2062 };
2063 IXmlReader *reader;
2064 XmlNodeType type;
2065 unsigned int i;
2066 HRESULT hr;
2067
2068 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
2069 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2070
2071 for (i = 0; i < ARRAY_SIZE(uri_tests); i++) {
2072 unsigned int j = 0;
2073
2074 set_input_string(reader, uri_tests[i].xml);
2075
2076 type = ~0u;
2077 while (IXmlReader_Read(reader, &type) == S_OK) {
2078 const WCHAR *local, *qname;
2079 UINT length, length2;
2080
2081 ok(type == XmlNodeType_Element ||
2082 type == XmlNodeType_Text ||
2083 type == XmlNodeType_CDATA ||
2084 type == XmlNodeType_ProcessingInstruction ||
2085 type == XmlNodeType_Comment ||
2086 type == XmlNodeType_Whitespace ||
2087 type == XmlNodeType_EndElement ||
2088 type == XmlNodeType_XmlDeclaration, "Unexpected node type %d.\n", type);
2089
2090 local = NULL;
2091 length = 0;
2092 hr = IXmlReader_GetLocalName(reader, &local, &length);
2093 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2094 ok(local != NULL, "Unexpected NULL local name pointer\n");
2095
2096 qname = NULL;
2097 length2 = 0;
2098 hr = IXmlReader_GetQualifiedName(reader, &qname, &length2);
2099 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2100 ok(qname != NULL, "Unexpected NULL qualified name pointer\n");
2101
2102 if (type == XmlNodeType_Element ||
2103 type == XmlNodeType_EndElement ||
2104 type == XmlNodeType_ProcessingInstruction ||
2105 type == XmlNodeType_XmlDeclaration)
2106 {
2107 ok(*local != 0, "Unexpected empty local name\n");
2108 ok(length > 0, "Unexpected local name length\n");
2109
2110 ok(*qname != 0, "Unexpected empty qualified name\n");
2111 ok(length2 > 0, "Unexpected qualified name length\n");
2112 }
2113
2114 reader_namespace(reader, uri_tests[i].uri[j]);
2115
2116 j++;
2117 }
2118 ok(type == XmlNodeType_None, "Unexpected node type %d\n", type);
2119 }
2120
2121 IXmlReader_Release(reader);
2122 }
2123
test_read_charref(void)2124 static void test_read_charref(void)
2125 {
2126 static const char testA[] = "<a b=\"c\">dză></a>";
2127 static const WCHAR chardataW[] = {0x01f3,0x0103,'>',0};
2128 const WCHAR *value;
2129 IXmlReader *reader;
2130 XmlNodeType type;
2131 HRESULT hr;
2132
2133 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2134 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2135
2136 set_input_string(reader, testA);
2137
2138 hr = IXmlReader_Read(reader, &type);
2139 ok(hr == S_OK, "got %08x\n", hr);
2140 ok(type == XmlNodeType_Element, "Unexpected node type %d\n", type);
2141
2142 hr = IXmlReader_Read(reader, &type);
2143 ok(hr == S_OK, "got %08x\n", hr);
2144 ok(type == XmlNodeType_Text, "Unexpected node type %d\n", type);
2145
2146 hr = IXmlReader_GetValue(reader, &value, NULL);
2147 ok(hr == S_OK, "got %08x\n", hr);
2148 ok(!lstrcmpW(value, chardataW), "Text value : %s\n", wine_dbgstr_w(value));
2149
2150 hr = IXmlReader_Read(reader, &type);
2151 ok(hr == S_OK, "got %08x\n", hr);
2152 ok(type == XmlNodeType_EndElement, "Unexpected node type %d\n", type);
2153
2154 hr = IXmlReader_Read(reader, &type);
2155 ok(hr == S_FALSE, "got %08x\n", hr);
2156 ok(type == XmlNodeType_None, "Unexpected node type %d\n", type);
2157
2158 IXmlReader_Release(reader);
2159 }
2160
test_encoding_detection(void)2161 static void test_encoding_detection(void)
2162 {
2163 static const struct encoding_testW
2164 {
2165 WCHAR text[16];
2166 }
2167 encoding_testsW[] =
2168 {
2169 { { '<','?','p','i',' ','?','>',0 } },
2170 { { '<','!','-','-',' ','c','-','-','>',0 } },
2171 { { 0xfeff,'<','a','/','>',0 } },
2172 { { '<','a','/','>',0 } },
2173 };
2174 static const char *encoding_testsA[] =
2175 {
2176 "<?pi ?>",
2177 "<!-- comment -->",
2178 "\xef\xbb\xbf<a/>", /* UTF-8 BOM */
2179 "<a/>",
2180 };
2181 IXmlReader *reader;
2182 XmlNodeType type;
2183 IStream *stream;
2184 unsigned int i;
2185 HRESULT hr;
2186
2187 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2188 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2189
2190 /* there's no way to query detected encoding back, so just verify that document is browsable */
2191
2192 for (i = 0; i < ARRAY_SIZE(encoding_testsA); i++)
2193 {
2194 set_input_string(reader, encoding_testsA[i]);
2195
2196 type = XmlNodeType_None;
2197 hr = IXmlReader_Read(reader, &type);
2198 ok(hr == S_OK, "got %08x\n", hr);
2199 ok(type != XmlNodeType_None, "Unexpected node type %d\n", type);
2200 }
2201
2202 for (i = 0; i < ARRAY_SIZE(encoding_testsW); i++)
2203 {
2204 stream = create_stream_on_data(encoding_testsW[i].text, lstrlenW(encoding_testsW[i].text) * sizeof(WCHAR));
2205
2206 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2207 ok(hr == S_OK, "got %08x\n", hr);
2208
2209 type = XmlNodeType_None;
2210 hr = IXmlReader_Read(reader, &type);
2211 ok(hr == S_OK, "%u: got %08x\n", i, hr);
2212 ok(type != XmlNodeType_None, "%u: unexpected node type %d\n", i, type);
2213
2214 IStream_Release(stream);
2215 }
2216
2217 IXmlReader_Release(reader);
2218 }
2219
test_eof_state(IXmlReader * reader,BOOL eof)2220 static void test_eof_state(IXmlReader *reader, BOOL eof)
2221 {
2222 LONG_PTR state;
2223 HRESULT hr;
2224
2225 ok(IXmlReader_IsEOF(reader) == eof, "Unexpected IsEOF() result\n");
2226 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
2227 ok(hr == S_OK, "GetProperty() failed, %#x\n", hr);
2228 ok((state == XmlReadState_EndOfFile) == eof, "Unexpected EndOfFile state %ld\n", state);
2229 }
2230
test_endoffile(void)2231 static void test_endoffile(void)
2232 {
2233 IXmlReader *reader;
2234 XmlNodeType type;
2235 HRESULT hr;
2236
2237 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2238 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2239
2240 test_eof_state(reader, FALSE);
2241
2242 set_input_string(reader, "<a/>");
2243
2244 test_eof_state(reader, FALSE);
2245
2246 type = XmlNodeType_None;
2247 hr = IXmlReader_Read(reader, &type);
2248 ok(hr == S_OK, "got %#x\n", hr);
2249 ok(type == XmlNodeType_Element, "Unexpected type %d\n", type);
2250
2251 test_eof_state(reader, FALSE);
2252
2253 type = XmlNodeType_Element;
2254 hr = IXmlReader_Read(reader, &type);
2255 ok(hr == S_FALSE, "got %#x\n", hr);
2256 ok(type == XmlNodeType_None, "Unexpected type %d\n", type);
2257
2258 test_eof_state(reader, TRUE);
2259
2260 hr = IXmlReader_SetInput(reader, NULL);
2261 ok(hr == S_OK, "got %08x\n", hr);
2262
2263 test_eof_state(reader, FALSE);
2264
2265 IXmlReader_Release(reader);
2266
2267 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2268 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2269
2270 set_input_string(reader, "<a/>text");
2271
2272 type = XmlNodeType_None;
2273 hr = IXmlReader_Read(reader, &type);
2274 ok(hr == S_OK, "got %#x\n", hr);
2275 ok(type == XmlNodeType_Element, "Unexpected type %d\n", type);
2276
2277 test_eof_state(reader, FALSE);
2278
2279 type = XmlNodeType_Element;
2280 hr = IXmlReader_Read(reader, &type);
2281 ok(hr == WC_E_SYNTAX, "got %#x\n", hr);
2282 ok(type == XmlNodeType_None, "Unexpected type %d\n", type);
2283
2284 test_eof_state(reader, FALSE);
2285
2286 hr = IXmlReader_SetInput(reader, NULL);
2287 ok(hr == S_OK, "got %08x\n", hr);
2288
2289 IXmlReader_Release(reader);
2290 }
2291
test_max_element_depth(void)2292 static void test_max_element_depth(void)
2293 {
2294 static const char *xml =
2295 "<a>"
2296 "<b attrb=\"_b\">"
2297 "<c>"
2298 "<d></d>"
2299 "</c>"
2300 "</b>"
2301 "</a>";
2302 XmlNodeType nodetype;
2303 unsigned int count;
2304 IXmlReader *reader;
2305 HRESULT hr;
2306
2307 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2308 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2309
2310 set_input_string(reader, xml);
2311
2312 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2);
2313 ok(hr == S_OK, "got %08x\n", hr);
2314
2315 TEST_DEPTH(reader, 0);
2316
2317 hr = IXmlReader_Read(reader, NULL);
2318 ok(hr == S_OK, "got %08x\n", hr);
2319
2320 TEST_DEPTH(reader, 0);
2321
2322 hr = IXmlReader_Read(reader, NULL);
2323 ok(hr == S_OK, "got %08x\n", hr);
2324
2325 TEST_DEPTH(reader, 1);
2326 TEST_READER_STATE(reader, XmlReadState_Interactive);
2327
2328 hr = IXmlReader_Read(reader, NULL);
2329 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2330
2331 TEST_DEPTH2(reader, 0, 2);
2332 TEST_READER_STATE(reader, XmlReadState_Error);
2333
2334 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 10);
2335 ok(hr == S_OK, "got %08x\n", hr);
2336
2337 hr = IXmlReader_Read(reader, NULL);
2338 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2339
2340 TEST_DEPTH2(reader, 0, 2);
2341 TEST_READER_STATE(reader, XmlReadState_Error);
2342
2343 /* test if stepping into attributes enforces depth limit too */
2344 set_input_string(reader, xml);
2345
2346 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2);
2347 ok(hr == S_OK, "got %08x\n", hr);
2348
2349 TEST_DEPTH(reader, 0);
2350
2351 hr = IXmlReader_Read(reader, NULL);
2352 ok(hr == S_OK, "got %08x\n", hr);
2353
2354 TEST_DEPTH(reader, 0);
2355
2356 hr = IXmlReader_Read(reader, NULL);
2357 ok(hr == S_OK, "got %08x\n", hr);
2358
2359 TEST_DEPTH(reader, 1);
2360
2361 hr = IXmlReader_MoveToFirstAttribute(reader);
2362 ok(hr == S_OK, "got %08x\n", hr);
2363
2364 TEST_DEPTH(reader, 2);
2365 TEST_READER_STATE(reader, XmlReadState_Interactive);
2366
2367 nodetype = 123;
2368 hr = IXmlReader_Read(reader, &nodetype);
2369 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2370 ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype);
2371
2372 nodetype = 123;
2373 hr = IXmlReader_Read(reader, &nodetype);
2374 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2375 ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype);
2376
2377 TEST_DEPTH2(reader, 0, 2);
2378 TEST_READER_STATE(reader, XmlReadState_Error);
2379
2380 /* set max depth to 0, this disables depth limit */
2381 set_input_string(reader, xml);
2382
2383 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
2384 ok(hr == S_OK, "got %08x\n", hr);
2385
2386 count = 0;
2387 while (IXmlReader_Read(reader, NULL) == S_OK)
2388 count++;
2389 ok(count == 8, "Unexpected node number %u\n", count);
2390 TEST_READER_STATE(reader, XmlReadState_EndOfFile);
2391
2392 IXmlReader_Release(reader);
2393 }
2394
test_reader_position(void)2395 static void test_reader_position(void)
2396 {
2397 static const char *xml = "<c:a xmlns:c=\"nsdef c\" b=\"attr b\">\n</c:a>";
2398 IXmlReader *reader;
2399 XmlNodeType type;
2400 UINT position;
2401 HRESULT hr;
2402
2403 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2404 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2405
2406 TEST_READER_STATE(reader, XmlReadState_Closed);
2407
2408 /* position methods with Null args */
2409 hr = IXmlReader_GetLineNumber(reader, NULL);
2410 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
2411
2412 hr = IXmlReader_GetLinePosition(reader, NULL);
2413 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
2414
2415 position = 123;
2416 hr = IXmlReader_GetLinePosition(reader, &position);
2417 ok(hr == S_FALSE, "got %#x\n", hr);
2418 ok(position == 0, "got %u\n", position);
2419
2420 position = 123;
2421 hr = IXmlReader_GetLineNumber(reader, &position);
2422 ok(hr == S_FALSE, "got %#x\n", hr);
2423 ok(position == 0, "got %u\n", position);
2424
2425 set_input_string(reader, xml);
2426
2427 TEST_READER_STATE(reader, XmlReadState_Initial);
2428 TEST_READER_POSITION(reader, 0, 0);
2429 hr = IXmlReader_Read(reader, &type);
2430 ok(hr == S_OK, "got %08x\n", hr);
2431 ok(type == XmlNodeType_Element, "got type %d\n", type);
2432 TEST_READER_POSITION2(reader, 1, 2, ~0u, 34);
2433
2434 next_attribute(reader);
2435 TEST_READER_POSITION2(reader, 1, 6, ~0u, 34);
2436
2437 next_attribute(reader);
2438 TEST_READER_POSITION2(reader, 1, 24, ~0u, 34);
2439
2440 move_to_element(reader);
2441 TEST_READER_POSITION2(reader, 1, 2, ~0u, 34);
2442
2443 hr = IXmlReader_Read(reader, &type);
2444 ok(hr == S_OK, "got %08x\n", hr);
2445 ok(type == XmlNodeType_Whitespace, "got type %d\n", type);
2446 TEST_READER_POSITION2(reader, 1, 35, 2, 6);
2447
2448 hr = IXmlReader_Read(reader, &type);
2449 ok(hr == S_OK, "got %08x\n", hr);
2450 ok(type == XmlNodeType_EndElement, "got type %d\n", type);
2451 TEST_READER_POSITION2(reader, 2, 3, 2, 6);
2452
2453 hr = IXmlReader_SetInput(reader, NULL);
2454 ok(hr == S_OK, "got %08x\n", hr);
2455 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
2456 TEST_READER_POSITION(reader, 0, 0);
2457
2458 IXmlReader_Release(reader);
2459 }
2460
test_string_pointers(void)2461 static void test_string_pointers(void)
2462 {
2463 const WCHAR *ns, *nsq, *empty, *xmlns_ns, *xmlns_name, *name, *p, *q, *xml, *ptr, *value;
2464 IXmlReader *reader;
2465 HRESULT hr;
2466
2467 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2468 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2469
2470 set_input_string(reader, "<elem xmlns=\"myns\">myns<elem2 /></elem>");
2471
2472 read_node(reader, XmlNodeType_Element);
2473 empty = reader_value(reader, "");
2474 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2475 name = reader_name(reader, "elem");
2476 ok(name == reader_qname(reader, "elem"), "name != qname\n");
2477 ns = reader_namespace(reader, "myns");
2478
2479 next_attribute(reader);
2480 ptr = reader_value(reader, "myns");
2481 if (ns != ptr)
2482 {
2483 win_skip("attr value is different than namespace pointer, assuming old xmllite\n");
2484 IXmlReader_Release(reader);
2485 return;
2486 }
2487 ok(ns == ptr, "ns != value\n");
2488 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2489 xmlns_ns = reader_namespace(reader, "http://www.w3.org/2000/xmlns/");
2490 xmlns_name = reader_name(reader, "xmlns");
2491 ok(xmlns_name == reader_qname(reader, "xmlns"), "xmlns_name != qname\n");
2492
2493 read_node(reader, XmlNodeType_Text);
2494 ok(ns != reader_value(reader, "myns"), "ns == value\n");
2495 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2496 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2497 ok(empty == reader_name(reader, ""), "empty != name\n");
2498 ok(empty == reader_qname(reader, ""), "empty != qname\n");
2499
2500 read_node(reader, XmlNodeType_Element);
2501 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2502 ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n");
2503
2504 read_node(reader, XmlNodeType_EndElement);
2505 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2506 ok(name == reader_name(reader, "elem"), "empty != name\n");
2507 ok(name == reader_qname(reader, "elem"), "empty != qname\n");
2508 ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n");
2509
2510 set_input_string(reader, "<elem xmlns:p=\"myns\" xmlns:q=\"mynsq\"><p:elem2 q:attr=\"\"></p:elem2></elem>");
2511
2512 read_node(reader, XmlNodeType_Element);
2513 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2514 name = reader_name(reader, "elem");
2515 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2516
2517 next_attribute(reader);
2518 ns = reader_value(reader, "myns");
2519 ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n");
2520 p = reader_name(reader, "p");
2521 ok(xmlns_ns == reader_namespace(reader, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n");
2522
2523 next_attribute(reader);
2524 nsq = reader_value(reader, "mynsq");
2525 ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n");
2526 q = reader_name(reader, "q");
2527 ok(xmlns_ns == reader_namespace(reader, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n");
2528
2529 read_node(reader, XmlNodeType_Element);
2530 ok(p == reader_prefix(reader, "p"), "p != prefix\n");
2531 ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n");
2532 name = reader_qname(reader, "p:elem2");
2533
2534 next_attribute(reader);
2535 ok(empty != reader_value(reader, ""), "empty == value\n");
2536 ok(q == reader_prefix(reader, "q"), "q != prefix\n");
2537 ok(nsq == reader_namespace(reader, "mynsq"), "nsq != namespace\n");
2538
2539 read_node(reader, XmlNodeType_EndElement);
2540 ptr = reader_qname(reader, "p:elem2"); todo_wine ok(name != ptr, "q == qname\n");
2541
2542 set_input_string(reader, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
2543
2544 read_node(reader, XmlNodeType_XmlDeclaration);
2545 ok(empty == reader_value(reader, ""), "empty != value\n");
2546 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2547 xml = reader_name(reader, "xml");
2548 ptr = reader_qname(reader, "xml"); todo_wine ok(xml == ptr, "xml != qname\n");
2549 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2550
2551 next_attribute(reader);
2552 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2553 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2554
2555 set_input_string(reader, "<elem xmlns:p=\"myns\"><p:elem2 attr=\"\" /></elem>");
2556
2557 read_node(reader, XmlNodeType_Element);
2558 next_attribute(reader);
2559 read_value_char(reader, 'm');
2560 p = reader_value(reader, "yns");
2561
2562 read_node(reader, XmlNodeType_Element);
2563 ns = reader_namespace(reader, "myns");
2564 ok(ns+1 == p, "ns+1 != p\n");
2565
2566 set_input_string(reader, "<elem attr=\"value\"></elem>");
2567
2568 read_node(reader, XmlNodeType_Element);
2569 next_attribute(reader);
2570 name = reader_name(reader, "attr");
2571 value = reader_value(reader, "value");
2572
2573 move_to_element(reader);
2574 next_attribute(reader);
2575 ok(name == reader_name(reader, "attr"), "attr pointer changed\n");
2576 ok(value == reader_value(reader, "value"), "value pointer changed\n");
2577
2578 IXmlReader_Release(reader);
2579 }
2580
test_attribute_by_name(void)2581 static void test_attribute_by_name(void)
2582 {
2583 static const char *xml = "<a><elem xmlns=\"myns\" a=\"value a\" b=\"value b\" xmlns:ns=\"ns uri\" "
2584 "ns:c=\"value c\" c=\"value c2\"/></a>";
2585 static const WCHAR xmlns_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
2586 '2','0','0','0','/','x','m','l','n','s','/',0};
2587 static const WCHAR nsuriW[] = {'n','s',' ','u','r','i',0};
2588 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
2589 static const WCHAR mynsW[] = {'m','y','n','s',0};
2590 static const WCHAR nsW[] = {'n','s',0};
2591 static const WCHAR emptyW[] = {0};
2592 static const WCHAR aW[] = {'a',0};
2593 static const WCHAR bW[] = {'b',0};
2594 static const WCHAR cW[] = {'c',0};
2595 IXmlReader *reader;
2596 HRESULT hr;
2597
2598 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2599 ok(hr == S_OK, "Failed to create reader, hr %#x.\n", hr);
2600
2601 set_input_string(reader, xml);
2602
2603 hr = IXmlReader_MoveToAttributeByName(reader, NULL, NULL);
2604 ok(hr == E_INVALIDARG || broken(hr == S_FALSE) /* WinXP */, "Unexpected hr %#x.\n", hr);
2605
2606 hr = IXmlReader_MoveToAttributeByName(reader, emptyW, NULL);
2607 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2608
2609 read_node(reader, XmlNodeType_Element);
2610
2611 hr = IXmlReader_MoveToAttributeByName(reader, emptyW, NULL);
2612 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2613
2614 read_node(reader, XmlNodeType_Element);
2615
2616 hr = IXmlReader_MoveToAttributeByName(reader, NULL, NULL);
2617 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2618
2619 hr = IXmlReader_MoveToAttributeByName(reader, NULL, xmlns_uriW);
2620 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2621
2622 hr = IXmlReader_MoveToAttributeByName(reader, emptyW, xmlns_uriW);
2623 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2624
2625 hr = IXmlReader_MoveToAttributeByName(reader, xmlnsW, NULL);
2626 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2627
2628 hr = IXmlReader_MoveToAttributeByName(reader, xmlnsW, xmlns_uriW);
2629 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2630 reader_value(reader, "myns");
2631
2632 hr = IXmlReader_MoveToAttributeByName(reader, aW, NULL);
2633 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2634 reader_value(reader, "value a");
2635
2636 hr = IXmlReader_MoveToAttributeByName(reader, bW, NULL);
2637 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2638 reader_value(reader, "value b");
2639
2640 hr = IXmlReader_MoveToAttributeByName(reader, aW, mynsW);
2641 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2642
2643 hr = IXmlReader_MoveToAttributeByName(reader, nsW, NULL);
2644 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2645
2646 hr = IXmlReader_MoveToAttributeByName(reader, nsW, xmlns_uriW);
2647 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2648 reader_value(reader, "ns uri");
2649
2650 hr = IXmlReader_MoveToAttributeByName(reader, bW, emptyW);
2651 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2652 reader_value(reader, "value b");
2653
2654 hr = IXmlReader_MoveToAttributeByName(reader, cW, NULL);
2655 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2656 reader_value(reader, "value c2");
2657
2658 hr = IXmlReader_MoveToAttributeByName(reader, cW, nsuriW);
2659 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2660 reader_value(reader, "value c");
2661
2662 IXmlReader_Release(reader);
2663 }
2664
START_TEST(reader)2665 START_TEST(reader)
2666 {
2667 test_reader_create();
2668 test_readerinput();
2669 test_reader_state();
2670 test_read_attribute();
2671 test_read_cdata();
2672 test_read_comment();
2673 test_read_pi();
2674 test_read_system_dtd();
2675 test_read_public_dtd();
2676 test_read_element();
2677 test_isemptyelement();
2678 test_read_text();
2679 test_read_full();
2680 test_read_pending();
2681 test_readvaluechunk();
2682 test_read_xmldeclaration();
2683 test_reader_properties();
2684 test_prefix();
2685 test_namespaceuri();
2686 test_read_charref();
2687 test_encoding_detection();
2688 test_endoffile();
2689 test_max_element_depth();
2690 test_reader_position();
2691 test_string_pointers();
2692 test_attribute_by_name();
2693 }
2694