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