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 #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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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