From 4c2c978917fe0996fb73d9210838aedff1f84075 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 4 Jun 2017 01:49:50 +0000 Subject: [PATCH] [XMLLITE_WINETEST] Sync with Wine Staging 2.9. CORE-13362 svn path=/trunk/; revision=74873 --- rostests/winetests/xmllite/reader.c | 1487 ++++++++++++++++++--------- rostests/winetests/xmllite/writer.c | 151 ++- 2 files changed, 1157 insertions(+), 481 deletions(-) diff --git a/rostests/winetests/xmllite/reader.c b/rostests/winetests/xmllite/reader.c index 1af1e0d9463..059c8c625e6 100644 --- a/rostests/winetests/xmllite/reader.c +++ b/rostests/winetests/xmllite/reader.c @@ -1,7 +1,7 @@ /* * IXmlReader tests * - * Copyright 2010, 2012-2013 Nikolay Sivov + * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,10 +51,18 @@ static void free_str(WCHAR *str) HeapFree(GetProcessHeap(), 0, str); } +static int strcmp_wa(const WCHAR *str1, const char *stra) +{ + WCHAR *str2 = a2w(stra); + int r = lstrcmpW(str1, str2); + free_str(str2); + return r; +} + static const char xmldecl_full[] = "\xef\xbb\xbf\n"; static const char xmldecl_short[] = ""; -static IStream *create_stream_on_data(const char *data, int size) +static IStream *create_stream_on_data(const void *data, unsigned int size) { IStream *stream = NULL; HGLOBAL hglobal; @@ -75,29 +83,28 @@ static IStream *create_stream_on_data(const char *data, int size) return stream; } -static void ok_pos_(IXmlReader *reader, int line, int pos, int line_broken, - int pos_broken, BOOL todo, int _line_) +static void test_reader_pos(IXmlReader *reader, UINT line, UINT pos, UINT line_broken, + UINT pos_broken, int _line_) { - UINT l, p; - HRESULT hr; + UINT l = ~0u, p = ~0u; BOOL broken_state; - hr = IXmlReader_GetLineNumber(reader, &l); - ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr); - hr = IXmlReader_GetLinePosition(reader, &p); - ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr); + IXmlReader_GetLineNumber(reader, &l); + IXmlReader_GetLinePosition(reader, &p); - if (line_broken == -1 && pos_broken == -1) + if (line_broken == ~0u && pos_broken == ~0u) broken_state = FALSE; else - broken_state = broken((line_broken == -1 ? line : line_broken) == l && - (pos_broken == -1 ? pos : pos_broken) == p); + broken_state = broken((line_broken == ~0u ? line : line_broken) == l && + (pos_broken == ~0u ? pos : pos_broken) == p); - todo_wine_if (todo) - ok_(__FILE__, _line_)((l == line && pos == p) || broken_state, - "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p); + ok_(__FILE__, _line_)((l == line && pos == p) || broken_state, + "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p); } -#define ok_pos(reader, l, p, l_brk, p_brk, todo) ok_pos_(reader, l, p, l_brk, p_brk, todo, __LINE__) +#define TEST_READER_POSITION(reader, line, pos) \ + test_reader_pos(reader, line, pos, ~0u, ~0u, __LINE__) +#define TEST_READER_POSITION2(reader, line, pos, line_broken, pos_broken) \ + test_reader_pos(reader, line, pos, line_broken, pos_broken, __LINE__) typedef struct input_iids_t { IID iids[10]; @@ -218,28 +225,153 @@ static const char *type_to_str(XmlNodeType type) } } -static void test_read_state_(IXmlReader *reader, XmlReadState expected, - XmlReadState exp_broken, BOOL todo, int line) +#define set_input_string(a,b) _set_input_string(__LINE__,a,b); +static void _set_input_string(unsigned line, IXmlReader *reader, const char *xml) +{ + IStream *stream; + HRESULT hr; + + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr); + + IStream_Release(stream); +} + +#define read_node(a,b) _read_node(__LINE__,a,b) +static void _read_node(unsigned line, IXmlReader *reader, XmlNodeType expected_type) +{ + XmlNodeType type; + HRESULT hr; + + hr = IXmlReader_Read(reader, &type); + if (expected_type == XmlNodeType_None) + ok_(__FILE__,line)(hr == S_FALSE, "Read returned %08x, expected S_FALSE\n", hr); + else + ok_(__FILE__,line)(hr == S_OK, "Read returned %08x\n", hr); + ok_(__FILE__,line)(type == expected_type, "read type %d, expected %d\n", type, expected_type); +} + +#define next_attribute(a) _next_attribute(__LINE__,a) +static void _next_attribute(unsigned line, IXmlReader *reader) { - LONG_PTR state; HRESULT hr; + hr = IXmlReader_MoveToNextAttribute(reader); + ok_(__FILE__,line)(hr == S_OK, "MoveToNextAttribute returned %08x\n", hr); +} + +#define move_to_element(a) _move_to_element(__LINE__,a) +static void _move_to_element(unsigned line, IXmlReader *reader) +{ + HRESULT hr; + hr = IXmlReader_MoveToElement(reader); + ok_(__FILE__,line)(hr == S_OK, "MoveToElement failed: %08x\n", hr); +} + +static void test_read_state(IXmlReader *reader, XmlReadState expected, + XmlReadState exp_broken, int line) +{ BOOL broken_state; + LONG_PTR state; - state = -1; /* invalid value */ - hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); - ok_(__FILE__, line)(hr == S_OK, "Expected S_OK, got %08x\n", hr); + state = -1; /* invalid state value */ + IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); if (exp_broken == -1) broken_state = FALSE; else broken_state = broken(exp_broken == state); - todo_wine_if (todo) - ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n", - state_to_str(expected), state_to_str(state)); + ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n", + state_to_str(expected), state_to_str(state)); +} + +#define TEST_READER_STATE(reader, state) test_read_state(reader, state, -1, __LINE__) +#define TEST_READER_STATE2(reader, state, brk) test_read_state(reader, state, brk, __LINE__) + +#define reader_value(a,b) _reader_value(__LINE__,a,b) +static const WCHAR *_reader_value(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetValue(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetValue returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "value = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_name(a,b) _reader_name(__LINE__,a,b) +static const WCHAR *_reader_name(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetLocalName returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "name = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_prefix(a,b) _reader_prefix(__LINE__,a,b) +static const WCHAR *_reader_prefix(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetPrefix(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetPrefix returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "prefix = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_namespace(a,b) _reader_namespace(__LINE__,a,b) +static const WCHAR *_reader_namespace(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetNamespaceUri(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetNamespaceUri returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "namespace = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_qname(a,b) _reader_qname(a,b,__LINE__) +static const WCHAR *_reader_qname(IXmlReader *reader, const char *expect, unsigned line) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetQualifiedName returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "name = %s\n", wine_dbgstr_w(str)); + return str; } -#define test_read_state(reader, exp, brk, todo) test_read_state_(reader, exp, brk, todo, __LINE__) +#define read_value_char(a,b) _read_value_char(a,b,__LINE__) +static void _read_value_char(IXmlReader *reader, WCHAR expected_char, unsigned line) +{ + WCHAR c = 0xffff; + UINT count = 0; + HRESULT hr; + + hr = IXmlReader_ReadValueChunk(reader, &c, 1, &count); + ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr); + ok_(__FILE__,line)(count == 1, "got %u\n", c); + ok_(__FILE__,line)(c == expected_char, "got %x\n", c); +} typedef struct _testinput { @@ -409,11 +541,11 @@ static IXmlResolver testresolver = { &resolvervtbl }; static void test_reader_create(void) { IXmlResolver *resolver; - HRESULT hr; + IUnknown *input, *unk; IXmlReader *reader; - IUnknown *input; DtdProcessing dtd; XmlNodeType nodetype; + HRESULT hr; /* crashes native */ if (0) @@ -422,10 +554,25 @@ static void test_reader_create(void) CreateXmlReader(NULL, (void**)&reader, NULL); } + hr = CreateXmlReader(&IID_IStream, (void **)&unk, NULL); + ok(hr == E_NOINTERFACE, "got %08x\n", hr); + + hr = CreateXmlReader(&IID_IUnknown, (void **)&unk, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + hr = IUnknown_QueryInterface(unk, &IID_IXmlReader, (void **)&reader); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(unk == (IUnknown *)reader, "unexpected interface\n"); + IXmlReader_Release(reader); + IUnknown_Release(unk); + + hr = CreateXmlReader(&IID_IUnknown, (void **)&reader, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + IXmlReader_Release(reader); + hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); nodetype = XmlNodeType_Element; hr = IXmlReader_GetNodeType(reader, &nodetype); @@ -475,7 +622,7 @@ static void test_reader_create(void) hr = IXmlReader_SetInput(reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); /* test input interface selection sequence */ hr = testinput_createinstance((void**)&input); @@ -538,7 +685,7 @@ static void test_readerinput(void) hr = IXmlReader_SetInput(reader, reader_input); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Initial); nodetype = XmlNodeType_Element; hr = IXmlReader_GetNodeType(reader, &nodetype); @@ -558,7 +705,7 @@ static void test_readerinput(void) hr = IXmlReader_SetInput(reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); IXmlReader_Release(reader); @@ -616,7 +763,7 @@ static void test_readerinput(void) ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr); ok_iids(&input_iids, setinput_readerinput, NULL, FALSE); - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); ref = IUnknown_AddRef(input); ok(ref == 3, "Expected 3, got %d\n", ref); @@ -652,8 +799,9 @@ static void test_readerinput(void) static void test_reader_state(void) { - IXmlReader *reader; XmlNodeType nodetype; + IXmlReader *reader; + IStream *stream; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); @@ -664,20 +812,59 @@ static void test_reader_state(void) ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); /* attempt to read on closed reader */ - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); + if (0) { - /* newer versions crash here, probably cause no input was set */ + /* newer versions crash here, probably because no input was set */ hr = IXmlReader_Read(reader, &nodetype); ok(hr == S_FALSE, "got %08x\n", hr); } + + stream = create_stream_on_data("xml", sizeof("xml")); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Initial); + + nodetype = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &nodetype); +todo_wine + ok(FAILED(hr), "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype); + +todo_wine + TEST_READER_STATE(reader, XmlReadState_Error); + + nodetype = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &nodetype); +todo_wine + ok(FAILED(hr), "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype); + + IStream_Release(stream); IXmlReader_Release(reader); } +static void test_reader_depth(IXmlReader *reader, UINT depth, UINT brk, int line) +{ + BOOL condition; + UINT d = ~0u; + + IXmlReader_GetDepth(reader, &d); + + condition = d == depth; + if (brk != ~0u) + condition |= broken(d == brk); + ok_(__FILE__, line)(condition, "Unexpected nesting depth %u, expected %u\n", d, depth); +} + +#define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__) +#define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__) + static void test_read_xmldeclaration(void) { - static const WCHAR xmlW[] = {'x','m','l',0}; - static const WCHAR RegistrationInfoW[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0}; static const struct { WCHAR name[12]; @@ -699,13 +886,6 @@ static void test_read_xmldeclaration(void) hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - /* position methods with Null args */ - hr = IXmlReader_GetLineNumber(reader, NULL); - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - - hr = IXmlReader_GetLinePosition(reader, NULL); - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full)); hr = IXmlReader_SetInput(reader, (IUnknown*)stream); @@ -725,37 +905,33 @@ static void test_read_xmldeclaration(void) hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_FALSE, "got %08x\n", hr); - ok_pos(reader, 0, 0, -1, -1, FALSE); + TEST_READER_POSITION(reader, 0, 0); + + read_node(reader, XmlNodeType_XmlDeclaration); - type = -1; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(type == XmlNodeType_XmlDeclaration, - "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type)); /* new version 1.2.x and 1.3.x properly update position for */ - ok_pos(reader, 1, 3, -1, 55, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, FALSE); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 55); - hr = IXmlReader_GetValue(reader, &val, NULL); - ok(hr == S_OK, "got %08x\n", hr); - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); + TEST_DEPTH(reader, 0); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + reader_value(reader, ""); /* check attributes */ - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); + next_attribute(reader); + + TEST_DEPTH(reader, 1); type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - ok_pos(reader, 1, 7, -1, 55, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 55); /* try to move from last attribute */ - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); + next_attribute(reader); + next_attribute(reader); hr = IXmlReader_MoveToNextAttribute(reader); ok(hr == S_FALSE, "got %08x\n", hr); @@ -766,7 +942,7 @@ static void test_read_xmldeclaration(void) hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "got %08x\n", hr); - ok_pos(reader, 1, 7, -1, 55, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 55); hr = IXmlReader_GetAttributeCount(reader, NULL); ok(hr == E_INVALIDARG, "got %08x\n", hr); @@ -793,12 +969,10 @@ static void test_read_xmldeclaration(void) ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr); } - hr = IXmlReader_GetDepth(reader, &count); - ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(count == 1, "Expected 1, got %d\n", count); + TEST_DEPTH(reader, 1); - hr = IXmlReader_MoveToElement(reader); - ok(hr == S_OK, "got %08x\n", hr); + move_to_element(reader); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 55); type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); @@ -821,12 +995,9 @@ todo_wine { hr = IXmlReader_SetInput(reader, (IUnknown *)stream); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - type = -1; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 3, 1, 21, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, TRUE); + read_node(reader, XmlNodeType_XmlDeclaration); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 21); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetAttributeCount(reader, &count); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); @@ -835,35 +1006,27 @@ todo_wine { ret = IXmlReader_IsEmptyElement(reader); ok(!ret, "element should not be empty\n"); - hr = IXmlReader_GetValue(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); + reader_value(reader, ""); + reader_name(reader, "xml"); - hr = IXmlReader_GetLocalName(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); -todo_wine - ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val)); + reader_qname(reader, "xml"); /* check attributes */ - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); + next_attribute(reader); type = -1; hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - ok_pos(reader, 1, 7, 1, 21, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 21); /* try to move from last attribute */ hr = IXmlReader_MoveToNextAttribute(reader); ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr); - type = -1; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 23, 1, 40, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, TRUE); + read_node(reader, XmlNodeType_Element); + TEST_READER_POSITION2(reader, 1, 23, ~0u, 40); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetAttributeCount(reader, &count); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); @@ -872,23 +1035,17 @@ todo_wine ret = IXmlReader_IsEmptyElement(reader); ok(ret, "element should be empty\n"); - hr = IXmlReader_GetValue(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); -todo_wine - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); - - hr = IXmlReader_GetLocalName(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(!lstrcmpW(val, RegistrationInfoW), "got %s\n", wine_dbgstr_w(val)); + reader_value(reader, ""); + reader_name(reader, "RegistrationInfo"); type = -1; hr = IXmlReader_Read(reader, &type); todo_wine ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr); + ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type)); + TEST_READER_POSITION(reader, 1, 41); todo_wine - ok(type == XmlNodeType_None, "expected None, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 41, -1, -1, TRUE); - test_read_state(reader, XmlReadState_Error, -1, TRUE); + TEST_READER_STATE(reader, XmlReadState_Error); IStream_Release(stream); IXmlReader_Release(reader); @@ -913,21 +1070,43 @@ static struct test_entry comment_tests[] = { static void test_read_comment(void) { + static const char *teststr = "text"; struct test_entry *test = comment_tests; + static const XmlNodeType types[] = + { + XmlNodeType_Element, + XmlNodeType_Text, + XmlNodeType_Comment, + XmlNodeType_EndElement, + }; + unsigned int i = 0; IXmlReader *reader; + XmlNodeType type; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - while (test->xml) + set_input_string(reader, teststr); + + while (IXmlReader_Read(reader, &type) == S_OK) { - XmlNodeType type; - IStream *stream; + const WCHAR *value; - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + ok(type == types[i], "%d: unexpected node type %d\n", i, type); + + if (type == XmlNodeType_Text || type == XmlNodeType_Comment) + { + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(*value != 0, "Expected node value\n"); + } + i++; + } + + while (test->xml) + { + set_input_string(reader, test->xml); type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); @@ -938,41 +1117,27 @@ static void test_read_comment(void) if (hr == S_OK) { const WCHAR *str; - WCHAR *str_exp; - UINT len; ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml); - len = 1; + reader_name(reader, ""); + str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + reader_qname(reader, ""); - len = 1; str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->value), "got %u\n", len); - str_exp = a2w(test->value); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_value(reader, test->value); } - IStream_Release(stream); test++; } @@ -1005,11 +1170,8 @@ static void test_read_pi(void) while (test->xml) { XmlNodeType type; - IStream *stream; - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, test->xml); type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); @@ -1025,14 +1187,7 @@ static void test_read_pi(void) ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml); - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_name(reader, test->name); len = 0; str = NULL; @@ -1044,17 +1199,9 @@ static void test_read_pi(void) free_str(str_exp); /* value */ - len = !strlen(test->value); - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->value), "got %u\n", len); - str_exp = a2w(test->value); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_value(reader, test->value); } - IStream_Release(stream); test++; } @@ -1063,7 +1210,10 @@ static void test_read_pi(void) struct nodes_test { const char *xml; - XmlNodeType types[20]; + struct { + XmlNodeType type; + const char *value; + } nodes[20]; }; static const char misc_test_xml[] = @@ -1087,22 +1237,22 @@ static const char misc_test_xml[] = static struct nodes_test misc_test = { misc_test_xml, { - XmlNodeType_Comment, - XmlNodeType_Comment, - XmlNodeType_ProcessingInstruction, - XmlNodeType_Comment, - XmlNodeType_Whitespace, - XmlNodeType_Comment, - XmlNodeType_Element, - XmlNodeType_Whitespace, - XmlNodeType_Element, - XmlNodeType_Text, - XmlNodeType_Comment, - XmlNodeType_Text, - XmlNodeType_ProcessingInstruction, - XmlNodeType_Whitespace, - XmlNodeType_EndElement, - XmlNodeType_None + {XmlNodeType_Comment, " comment1 "}, + {XmlNodeType_Comment, " comment2 "}, + {XmlNodeType_ProcessingInstruction, "pi1body "}, + {XmlNodeType_Comment, " comment3 "}, + {XmlNodeType_Whitespace, " \t \n \n"}, + {XmlNodeType_Comment, " comment4 "}, + {XmlNodeType_Element, ""}, + {XmlNodeType_Whitespace, "\n\t"}, + {XmlNodeType_Element, ""}, + {XmlNodeType_Text, "text"}, + {XmlNodeType_Comment, " comment "}, + {XmlNodeType_Text, "text2"}, + {XmlNodeType_ProcessingInstruction, "pibody "}, + {XmlNodeType_Whitespace, "\n"}, + {XmlNodeType_EndElement, ""}, + {XmlNodeType_None, ""} } }; @@ -1110,41 +1260,21 @@ static void test_read_full(void) { struct nodes_test *test = &misc_test; IXmlReader *reader; - XmlNodeType type; - IStream *stream; HRESULT hr; int i; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, test->xml); i = 0; - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - while (hr == S_OK) + do { - ok(test->types[i] != XmlNodeType_None, "%d: unexpected end of test data\n", i); - if (test->types[i] == XmlNodeType_None) break; - ok(type == test->types[i], "%d: got wrong type %d, expected %d\n", i, type, test->types[i]); - if (type == XmlNodeType_Whitespace) - { - const WCHAR *ptr; - UINT len = 0; + read_node(reader, test->nodes[i].type); + reader_value(reader, test->nodes[i].value); + } while(test->nodes[i++].type != XmlNodeType_None); - hr = IXmlReader_GetValue(reader, &ptr, &len); - ok(hr == S_OK, "%d: GetValue failed 0x%08x\n", i, hr); - ok(len > 0, "%d: wrong value length %d\n", i, len); - } - hr = IXmlReader_Read(reader, &type); - i++; - } - ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]); - - IStream_Release(stream); IXmlReader_Release(reader); } @@ -1153,11 +1283,7 @@ static const char test_public_dtd[] = static void test_read_public_dtd(void) { - static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0}; - static const WCHAR pubvalW[] = {'p','u','b','i','d',0}; static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0}; - static const WCHAR sysW[] = {'S','Y','S','T','E','M',0}; - static const WCHAR pubW[] = {'P','U','B','L','I','C',0}; IXmlReader *reader; const WCHAR *str; XmlNodeType type; @@ -1175,10 +1301,7 @@ static void test_read_public_dtd(void) hr = IXmlReader_SetInput(reader, (IUnknown*)stream); ok(hr == S_OK, "got %08x\n", hr); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got 0x%8x\n", hr); - ok(type == XmlNodeType_DocumentType, "got type %d\n", type); + read_node(reader, XmlNodeType_DocumentType); count = 0; hr = IXmlReader_GetAttributeCount(reader, &count); @@ -1193,60 +1316,30 @@ static void test_read_public_dtd(void) ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(pubW), "got %u\n", len); - ok(!lstrcmpW(str, pubW), "got %s\n", wine_dbgstr_w(str)); - - len = 0; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(pubvalW), "got %u\n", len); - ok(!lstrcmpW(str, pubvalW), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, "PUBLIC"); + reader_value(reader, "pubid"); - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); + next_attribute(reader); type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysW), "got %u\n", len); - ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str)); - - len = 0; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysvalW), "got %u\n", len); - ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, "SYSTEM"); + reader_value(reader, "externalid uri"); - hr = IXmlReader_MoveToElement(reader); - ok(hr == S_OK, "got 0x%08x\n", hr); + move_to_element(reader); + reader_name(reader, "testdtd"); len = 0; str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine { ok(len == lstrlenW(dtdnameW), "got %u\n", len); ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); } - len = 0; - str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(dtdnameW), "got %u\n", len); - ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); - IStream_Release(stream); IXmlReader_Release(reader); } @@ -1257,9 +1350,7 @@ static const char test_system_dtd[] = static void test_read_system_dtd(void) { - static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0}; static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0}; - static const WCHAR sysW[] = {'S','Y','S','T','E','M',0}; IXmlReader *reader; const WCHAR *str; XmlNodeType type; @@ -1277,10 +1368,7 @@ static void test_read_system_dtd(void) hr = IXmlReader_SetInput(reader, (IUnknown*)stream); ok(hr == S_OK, "got %08x\n", hr); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got 0x%8x\n", hr); - ok(type == XmlNodeType_DocumentType, "got type %d\n", type); + read_node(reader, XmlNodeType_DocumentType); count = 0; hr = IXmlReader_GetAttributeCount(reader, &count); @@ -1295,42 +1383,22 @@ static void test_read_system_dtd(void) ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysW), "got %u\n", len); - ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str)); - - len = 0; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysvalW), "got %u\n", len); - ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, "SYSTEM"); + reader_value(reader, "externalid uri"); - hr = IXmlReader_MoveToElement(reader); - ok(hr == S_OK, "got 0x%08x\n", hr); + move_to_element(reader); + reader_name(reader, "testdtd"); len = 0; str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine { ok(len == lstrlenW(dtdnameW), "got %u\n", len); ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); } - len = 0; - str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(dtdnameW), "got %u\n", len); - ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got 0x%8x\n", hr); - ok(type == XmlNodeType_Comment, "got type %d\n", type); + read_node(reader, XmlNodeType_Comment); IStream_Release(stream); IXmlReader_Release(reader); @@ -1346,17 +1414,26 @@ static struct test_entry element_tests[] = { { "", "a", "", S_OK }, { "", "a", "", S_OK }, { "", NULL, NULL, NC_E_QNAMECHARACTER }, + { "", NULL, NULL, NC_E_QNAMECOLON }, + { "<:b:c />", NULL, NULL, NC_E_QNAMECHARACTER }, { NULL } }; static void test_read_element(void) { struct test_entry *test = element_tests; - static const char stag[] = ""; - static const char mismatch[] = ""; + static const char stag[] = + "" + "" + "text" + "" + "" + "" + ""; + static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 }; IXmlReader *reader; XmlNodeType type; - IStream *stream; + unsigned int i; UINT depth; HRESULT hr; @@ -1365,9 +1442,7 @@ static void test_read_element(void) while (test->xml) { - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, test->xml); type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); @@ -1394,90 +1469,110 @@ static void test_read_element(void) free_str(str_exp); /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == 0, "got %u\n", len); - ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + reader_value(reader, ""); } - IStream_Release(stream); test++; } /* test reader depth increment */ - stream = create_stream_on_data(stag, sizeof(stag)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, stag); - depth = 1; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 0, "got %d\n", depth); + i = 0; + while (IXmlReader_Read(reader, &type) == S_OK) + { + UINT count; - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); + ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement || + type == XmlNodeType_Text, "Unexpected node type %d\n", type); - depth = 1; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 0, "got %d\n", depth); + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); + if (type == XmlNodeType_Element || type == XmlNodeType_EndElement) + { + const WCHAR *prefix; - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 1, "got %d\n", depth); + prefix = NULL; + hr = IXmlReader_GetPrefix(reader, &prefix, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(prefix != NULL, "got %p\n", prefix); - /* read end tag for inner element */ - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_EndElement, "got %d\n", type); + if (!*prefix) + { + const WCHAR *local, *qname; - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); -todo_wine - ok(depth == 2, "got %d\n", depth); + local = NULL; + hr = IXmlReader_GetLocalName(reader, &local, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(local != NULL, "got %p\n", local); - /* read end tag for container element */ - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_EndElement, "got %d\n", type); + qname = NULL; + hr = IXmlReader_GetQualifiedName(reader, &qname, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(qname != NULL, "got %p\n", qname); - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 1, "got %d\n", depth); + ok(local == qname, "expected same pointer\n"); + } + } - IStream_Release(stream); + if (type == XmlNodeType_EndElement) + { + count = 1; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + ok(count == 0, "got %u\n", count); + } + + if (type == XmlNodeType_Element) + { + count = 0; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + + /* moving to attributes increases depth */ + if (count) + { + const WCHAR *value; + + reader_value(reader, ""); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(*value != 0, "Unexpected value %s\n", wine_dbgstr_w(value)); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1); + + move_to_element(reader); + reader_value(reader, ""); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]); + } + } + + i++; + } /* start/end tag mismatch */ - stream = create_stream_on_data(mismatch, sizeof(mismatch)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, ""); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); + read_node(reader, XmlNodeType_Element); type = XmlNodeType_Element; hr = IXmlReader_Read(reader, &type); ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr); -todo_wine ok(type == XmlNodeType_None, "got %d\n", type); - - IStream_Release(stream); + TEST_READER_STATE(reader, XmlReadState_Error); IXmlReader_Release(reader); } @@ -1505,6 +1600,7 @@ static void test_read_pending(void) ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr); /* newer versions are happy when it's enough data to detect node type, older versions keep reading until it fails to read more */ +todo_wine ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall); ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type); @@ -1521,11 +1617,9 @@ static void test_read_pending(void) static void test_readvaluechunk(void) { - static const char testA[] = ""; IXmlReader *reader; XmlNodeType type; - IStream *stream; - const WCHAR *value; + WCHAR buf[64]; WCHAR b; HRESULT hr; UINT c; @@ -1533,25 +1627,17 @@ static void test_readvaluechunk(void) hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - stream = create_stream_on_data(testA, sizeof(testA)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, ""); hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Comment, "type = %u\n", type); - c = 0; - b = 0; - hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c); - ok(hr == S_OK, "got %08x\n", hr); - ok(c == 1, "got %u\n", c); - ok(b == ' ', "got %x\n", b); + read_value_char(reader, ' '); + read_value_char(reader, 'c'); /* portion read as chunk is skipped from resulting node value */ - value = NULL; - hr = IXmlReader_GetValue(reader, &value, NULL); - ok(hr == S_OK, "got %08x\n", hr); - ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value)); + reader_value(reader, "omment1 "); /* once value is returned/allocated it's not possible to read by chunk */ c = 0; @@ -1561,20 +1647,57 @@ static void test_readvaluechunk(void) ok(c == 0, "got %u\n", c); ok(b == 0, "got %x\n", b); - value = NULL; - hr = IXmlReader_GetValue(reader, &value, NULL); + c = 0xdeadbeef; + hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c); + ok(hr == S_OK, "got %08x\n", hr); + ok(!c, "c = %u\n", c); + + reader_value(reader, "omment1 "); + + /* read comment2 */ + read_node(reader, XmlNodeType_Comment); + + c = 0xdeadbeef; + hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c); + ok(hr == S_OK, "got %08x\n", hr); + ok(!c, "c = %u\n", c); + + c = 0xdeadbeef; + memset(buf, 0xcc, sizeof(buf)); + hr = IXmlReader_ReadValueChunk(reader, buf, sizeof(buf)/sizeof(WCHAR), &c); ok(hr == S_OK, "got %08x\n", hr); - ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value)); + ok(c == 10, "got %u\n", c); + ok(buf[c] == 0xcccc, "buffer overflow\n"); + buf[c] = 0; + ok(!strcmp_wa(buf, " comment2 "), "buf = %s\n", wine_dbgstr_w(buf)); + + c = 0xdeadbeef; + memset(buf, 0xcc, sizeof(buf)); + hr = IXmlReader_ReadValueChunk(reader, buf, sizeof(buf)/sizeof(WCHAR), &c); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(!c, "got %u\n", c); + + /* portion read as chunk is skipped from resulting node value */ + reader_value(reader, ""); + + /* once value is returned/allocated it's not possible to read by chunk */ + c = 0xdeadbeef; + b = 0xffff; + hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(c == 0, "got %u\n", c); + ok(b == 0xffff, "got %x\n", b); + + reader_value(reader, ""); IXmlReader_Release(reader); - IStream_Release(stream); } static struct test_entry cdata_tests[] = { { "", "", " ]]data ", S_OK }, { "", "", "", "", "\n \n \n\n ", S_OK, S_OK, TRUE }, - { "", "", "\n \n\n \n\n ", S_OK, S_OK, TRUE }, + { "", "", "\n \n \n\n ", S_OK, S_OK }, + { "", "", "\n \n\n \n\n ", S_OK, S_OK }, { "", "", "\n\n \n\n \n \n\n ", S_OK }, { NULL } }; @@ -1614,49 +1737,31 @@ static void test_read_cdata(void) if (hr == S_OK) { const WCHAR *str; - WCHAR *str_exp; UINT len; ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml); - str_exp = a2w(test->name); - - len = 1; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, ""); str = NULL; hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); - /* value */ - len = 1; str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); - str_exp = a2w(test->value); - todo_wine_if (test->todo) - { - ok(len == strlen(test->value), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - } - free_str(str_exp); + /* value */ + reader_value(reader, test->value); } IStream_Release(stream); @@ -1669,6 +1774,8 @@ static void test_read_cdata(void) static struct test_entry text_tests[] = { { "simple text", "", "simple text", S_OK }, { "text ]]> text", "", "", WC_E_CDSECTEND }, + { "\n \r\n \n\n text", "", "\n \n \n\n text", S_OK, S_OK }, + { "\r \r\r\n \n\n text", "", "\n \n\n \n\n text", S_OK, S_OK }, { NULL } }; @@ -1693,63 +1800,41 @@ static void test_read_text(void) type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); - /* read one more to get to CDATA */ + /* read one more to get to text node */ if (type == XmlNodeType_Element) { type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); } - - if (test->hr_broken) - ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); - else - ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); if (hr == S_OK) { const WCHAR *str; - WCHAR *str_exp; UINT len; ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml); - str_exp = a2w(test->name); - - len = 1; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, ""); str = NULL; hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); - /* value */ - len = 1; str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); - str_exp = a2w(test->value); - todo_wine_if (test->todo) - { - ok(len == strlen(test->value), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - } - free_str(str_exp); + /* value */ + reader_value(reader, test->value); } IStream_Release(stream); @@ -1867,34 +1952,19 @@ static void test_read_attribute(void) hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "got 0x%08x\n", hr); - len = 1; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_name(reader, test->name); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine { ok(len == strlen(test->name), "got %u\n", len); str_exp = a2w(test->name); ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); free_str(str_exp); - } + /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->value), "got %u\n", len); - str_exp = a2w(test->value); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_value(reader, test->value); } IStream_Release(stream); @@ -1907,17 +1977,28 @@ static void test_read_attribute(void) static void test_reader_properties(void) { IXmlReader *reader; + LONG_PTR value; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); + value = 0; + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value); + ok(hr == S_OK, "GetProperty failed: %08x\n", hr); + ok(value == 256, "Unexpected default max depth value %ld\n", value); + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0); ok(hr == S_OK, "SetProperty failed: %08x\n", hr); hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0); ok(hr == S_OK, "SetProperty failed: %08x\n", hr); + value = 256; + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value); + ok(hr == S_OK, "GetProperty failed: %08x\n", hr); + ok(value == 0, "Unexpected max depth value %ld\n", value); + IXmlReader_Release(reader); } @@ -1932,6 +2013,7 @@ static void test_prefix(void) } prefix_tests[] = { { "", "", "", "xml" }, + { "", "c", "xmlns", "xml" }, }; IXmlReader *reader; unsigned int i; @@ -1941,9 +2023,7 @@ static void test_prefix(void) ok(hr == S_OK, "S_OK, got %08x\n", hr); for (i = 0; i < sizeof(prefix_tests)/sizeof(prefix_tests[0]); i++) { - const WCHAR *prefix; XmlNodeType type; - WCHAR *expected; IStream *stream; stream = create_stream_on_data(prefix_tests[i].xml, strlen(prefix_tests[i].xml) + 1); @@ -1954,12 +2034,7 @@ static void test_prefix(void) ok(hr == S_OK, "Read() failed, %#x\n", hr); ok(type == XmlNodeType_Element, "Unexpected node type %d.\n", type); - expected = a2w(prefix_tests[i].prefix1); - hr = IXmlReader_GetPrefix(reader, &prefix, NULL); - ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); - ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), - wine_dbgstr_w(expected)); - free_str(expected); + reader_prefix(reader, prefix_tests[i].prefix1); hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "MoveToFirstAttribute() failed, %#x.\n", hr); @@ -1968,26 +2043,19 @@ static void test_prefix(void) ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr); ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type); - expected = a2w(prefix_tests[i].prefix2); - hr = IXmlReader_GetPrefix(reader, &prefix, NULL); - ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); - ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), - wine_dbgstr_w(expected)); - free_str(expected); + reader_prefix(reader, prefix_tests[i].prefix2); - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "MoveToNextAttribute() failed, %#x.\n", hr); + next_attribute(reader); hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr); ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type); - expected = a2w(prefix_tests[i].prefix3); - hr = IXmlReader_GetPrefix(reader, &prefix, NULL); - ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); - ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), - wine_dbgstr_w(expected)); - free_str(expected); + reader_prefix(reader, prefix_tests[i].prefix3); + + /* back to the element, check prefix */ + move_to_element(reader); + reader_prefix(reader, prefix_tests[i].prefix1); IStream_Release(stream); } @@ -2013,6 +2081,18 @@ static void test_namespaceuri(void) { "defns a", "ns r", "defns a" }}, { "", { "", "", "", "", "" }}, + { "text", + { "", "", "" }}, + { "\r\n", + { "", "", "" }}, + { "", + { "", "", "" }}, + { "", + { "", "" }}, + { "", + { "", "", "" }}, + { "", + { "", "", "" }}, }; IXmlReader *reader; XmlNodeType type; @@ -2029,24 +2109,49 @@ static void test_namespaceuri(void) hr = IXmlReader_SetInput(reader, (IUnknown *)stream); ok(hr == S_OK, "got %08x\n", hr); + type = ~0u; while (IXmlReader_Read(reader, &type) == S_OK) { - const WCHAR *uri, *local; - WCHAR *uriW; - - ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement, "Unexpected node type %d.\n", type); - - hr = IXmlReader_GetLocalName(reader, &local, NULL); + const WCHAR *local, *qname; + UINT length, length2; + + ok(type == XmlNodeType_Element || + type == XmlNodeType_Text || + type == XmlNodeType_CDATA || + type == XmlNodeType_ProcessingInstruction || + type == XmlNodeType_Comment || + type == XmlNodeType_Whitespace || + type == XmlNodeType_EndElement || + type == XmlNodeType_XmlDeclaration, "Unexpected node type %d.\n", type); + + local = NULL; + length = 0; + hr = IXmlReader_GetLocalName(reader, &local, &length); ok(hr == S_OK, "S_OK, got %08x\n", hr); + ok(local != NULL, "Unexpected NULL local name pointer\n"); - hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL); + qname = NULL; + length2 = 0; + hr = IXmlReader_GetQualifiedName(reader, &qname, &length2); ok(hr == S_OK, "S_OK, got %08x\n", hr); + ok(qname != NULL, "Unexpected NULL qualified name pointer\n"); + + if (type == XmlNodeType_Element || + type == XmlNodeType_EndElement || + type == XmlNodeType_ProcessingInstruction || + type == XmlNodeType_XmlDeclaration) + { + ok(*local != 0, "Unexpected empty local name\n"); + ok(length > 0, "Unexpected local name length\n"); + + ok(*qname != 0, "Unexpected empty qualified name\n"); + ok(length2 > 0, "Unexpected qualified name length\n"); + } - uriW = a2w(uri_tests[i].uri[j]); - ok(!lstrcmpW(uriW, uri), "%s: uri %s\n", wine_dbgstr_w(local), wine_dbgstr_w(uri)); - free_str(uriW); + reader_namespace(reader, uri_tests[i].uri[j]); j++; } + ok(type == XmlNodeType_None, "Unexpected node type %d\n", type); IStream_Release(stream); } @@ -2056,20 +2161,17 @@ static void test_namespaceuri(void) static void test_read_charref(void) { - static const char testA[] = "dză"; - static const WCHAR chardataW[] = {0x01f3,0x0103,0}; + static const char testA[] = "dză>"; + static const WCHAR chardataW[] = {0x01f3,0x0103,'>',0}; const WCHAR *value; IXmlReader *reader; XmlNodeType type; - IStream *stream; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - stream = create_stream_on_data(testA, sizeof(testA)); - hr = IXmlReader_SetInput(reader, (IUnknown *)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, testA); hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr); @@ -2087,8 +2189,436 @@ static void test_read_charref(void) ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_EndElement, "Unexpected node type %d\n", type); + hr = IXmlReader_Read(reader, &type); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(type == XmlNodeType_None, "Unexpected node type %d\n", type); + + IXmlReader_Release(reader); +} + +static void test_encoding_detection(void) +{ + static const struct encoding_testW + { + WCHAR text[16]; + } + encoding_testsW[] = + { + { { '<','?','p','i',' ','?','>',0 } }, + { { '<','!','-','-',' ','c','-','-','>',0 } }, + { { 0xfeff,'<','a','/','>',0 } }, + { { '<','a','/','>',0 } }, + }; + static const char *encoding_testsA[] = + { + "", + "", + "\xef\xbb\xbf", /* UTF-8 BOM */ + "", + }; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + unsigned int i; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + /* there's no way to query detected encoding back, so just verify that document is browsable */ + + for (i = 0; i < sizeof(encoding_testsA)/sizeof(encoding_testsA[0]); i++) + { + stream = create_stream_on_data(encoding_testsA[i], strlen(encoding_testsA[i])); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type != XmlNodeType_None, "Unexpected node type %d\n", type); + + IStream_Release(stream); + } + + for (i = 0; i < sizeof(encoding_testsW)/sizeof(encoding_testsW[0]); i++) + { + stream = create_stream_on_data(encoding_testsW[i].text, lstrlenW(encoding_testsW[i].text) * sizeof(WCHAR)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "%u: got %08x\n", i, hr); + ok(type != XmlNodeType_None, "%u: unexpected node type %d\n", i, type); + + IStream_Release(stream); + } + + IXmlReader_Release(reader); +} + +static void test_eof_state(IXmlReader *reader, BOOL eof) +{ + LONG_PTR state; + HRESULT hr; + + ok(IXmlReader_IsEOF(reader) == eof, "Unexpected IsEOF() result\n"); + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); + ok(hr == S_OK, "GetProperty() failed, %#x\n", hr); + ok((state == XmlReadState_EndOfFile) == eof, "Unexpected EndOfFile state %ld\n", state); +} + +static void test_endoffile(void) +{ + IXmlReader *reader; + XmlNodeType type; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + test_eof_state(reader, FALSE); + + set_input_string(reader, ""); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %#x\n", hr); + ok(type == XmlNodeType_Element, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(type == XmlNodeType_None, "Unexpected type %d\n", type); + + test_eof_state(reader, TRUE); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + test_eof_state(reader, FALSE); + + IXmlReader_Release(reader); + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + set_input_string(reader, "text"); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %#x\n", hr); + ok(type == XmlNodeType_Element, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == WC_E_SYNTAX, "got %#x\n", hr); + ok(type == XmlNodeType_None, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + IXmlReader_Release(reader); +} + +static void test_max_element_depth(void) +{ + static const char *xml = + "" + "" + "" + "" + "" + "" + ""; + XmlNodeType nodetype; + unsigned int count; + IXmlReader *reader; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + set_input_string(reader, xml); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 1); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 10); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + /* test if stepping into attributes enforces depth limit too */ + set_input_string(reader, xml); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 1); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 2); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + nodetype = 123; + hr = IXmlReader_Read(reader, &nodetype); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype); + + nodetype = 123; + hr = IXmlReader_Read(reader, &nodetype); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + /* set max depth to 0, this disables depth limit */ + set_input_string(reader, xml); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0); + ok(hr == S_OK, "got %08x\n", hr); + + count = 0; + while (IXmlReader_Read(reader, NULL) == S_OK) + count++; + ok(count == 8, "Unexpected node number %u\n", count); + TEST_READER_STATE(reader, XmlReadState_EndOfFile); + + IXmlReader_Release(reader); +} + +static void test_reader_position(void) +{ + static const char *xml = "\n"; + IXmlReader *reader; + XmlNodeType type; + UINT position; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Closed); + + /* position methods with Null args */ + hr = IXmlReader_GetLineNumber(reader, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); + + hr = IXmlReader_GetLinePosition(reader, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); + + position = 123; + hr = IXmlReader_GetLinePosition(reader, &position); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(position == 0, "got %u\n", position); + + position = 123; + hr = IXmlReader_GetLineNumber(reader, &position); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(position == 0, "got %u\n", position); + + set_input_string(reader, xml); + + TEST_READER_STATE(reader, XmlReadState_Initial); + TEST_READER_POSITION(reader, 0, 0); + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Element, "got type %d\n", type); + TEST_READER_POSITION2(reader, 1, 2, ~0u, 34); + + next_attribute(reader); + TEST_READER_POSITION2(reader, 1, 6, ~0u, 34); + + next_attribute(reader); + TEST_READER_POSITION2(reader, 1, 24, ~0u, 34); + + move_to_element(reader); + TEST_READER_POSITION2(reader, 1, 2, ~0u, 34); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Whitespace, "got type %d\n", type); + TEST_READER_POSITION2(reader, 1, 35, 2, 6); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_EndElement, "got type %d\n", type); + TEST_READER_POSITION2(reader, 2, 3, 2, 6); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); + TEST_READER_POSITION(reader, 0, 0); + + IXmlReader_Release(reader); +} + +static void test_string_pointers(void) +{ + const WCHAR *ns, *nsq, *empty, *xmlns_ns, *xmlns_name, *name, *p, *q, *xml, *ptr, *value; + IXmlReader *reader; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + set_input_string(reader, "myns"); + + read_node(reader, XmlNodeType_Element); + empty = reader_value(reader, ""); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + name = reader_name(reader, "elem"); + ok(name == reader_qname(reader, "elem"), "name != qname\n"); + ns = reader_namespace(reader, "myns"); + + next_attribute(reader); + ptr = reader_value(reader, "myns"); + if (ns != ptr) + { + win_skip("attr value is different than namespace pointer, assuming old xmllite\n"); + IXmlReader_Release(reader); + return; + } + ok(ns == ptr, "ns != value\n"); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + xmlns_ns = reader_namespace(reader, "http://www.w3.org/2000/xmlns/"); + xmlns_name = reader_name(reader, "xmlns"); + ok(xmlns_name == reader_qname(reader, "xmlns"), "xmlns_name != qname\n"); + + read_node(reader, XmlNodeType_Text); + ok(ns != reader_value(reader, "myns"), "ns == value\n"); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + ok(empty == reader_name(reader, ""), "empty != name\n"); + ok(empty == reader_qname(reader, ""), "empty != qname\n"); + + read_node(reader, XmlNodeType_Element); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n"); + + read_node(reader, XmlNodeType_EndElement); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(name == reader_name(reader, "elem"), "empty != name\n"); + ok(name == reader_qname(reader, "elem"), "empty != qname\n"); + ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n"); + + set_input_string(reader, ""); + + read_node(reader, XmlNodeType_Element); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + name = reader_name(reader, "elem"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + + next_attribute(reader); + ns = reader_value(reader, "myns"); + ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n"); + p = reader_name(reader, "p"); + ok(xmlns_ns == reader_namespace(reader, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n"); + + next_attribute(reader); + nsq = reader_value(reader, "mynsq"); + ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n"); + q = reader_name(reader, "q"); + ok(xmlns_ns == reader_namespace(reader, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n"); + + read_node(reader, XmlNodeType_Element); + ok(p == reader_prefix(reader, "p"), "p != prefix\n"); + ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n"); + name = reader_qname(reader, "p:elem2"); + + next_attribute(reader); + ok(empty != reader_value(reader, ""), "empty == value\n"); + ok(q == reader_prefix(reader, "q"), "q != prefix\n"); + ok(nsq == reader_namespace(reader, "mynsq"), "nsq != namespace\n"); + + read_node(reader, XmlNodeType_EndElement); + ptr = reader_qname(reader, "p:elem2"); todo_wine ok(name != ptr, "q == qname\n"); + + set_input_string(reader, "\n"); + + read_node(reader, XmlNodeType_XmlDeclaration); + ok(empty == reader_value(reader, ""), "empty != value\n"); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + xml = reader_name(reader, "xml"); + ptr = reader_qname(reader, "xml"); todo_wine ok(xml == ptr, "xml != qname\n"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + + next_attribute(reader); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + + set_input_string(reader, ""); + + read_node(reader, XmlNodeType_Element); + next_attribute(reader); + read_value_char(reader, 'm'); + p = reader_value(reader, "yns"); + + read_node(reader, XmlNodeType_Element); + ns = reader_namespace(reader, "myns"); + ok(ns+1 == p, "ns+1 != p\n"); + + set_input_string(reader, ""); + + read_node(reader, XmlNodeType_Element); + next_attribute(reader); + name = reader_name(reader, "attr"); + value = reader_value(reader, "value"); + + move_to_element(reader); + next_attribute(reader); + ok(name == reader_name(reader, "attr"), "attr pointer changed\n"); + ok(value == reader_value(reader, "value"), "value pointer changed\n"); + IXmlReader_Release(reader); - IStream_Release(stream); } START_TEST(reader) @@ -2113,4 +2643,9 @@ START_TEST(reader) test_prefix(); test_namespaceuri(); test_read_charref(); + test_encoding_detection(); + test_endoffile(); + test_max_element_depth(); + test_reader_position(); + test_string_pointers(); } diff --git a/rostests/winetests/xmllite/writer.c b/rostests/winetests/xmllite/writer.c index effb2e3e975..953371ba526 100644 --- a/rostests/winetests/xmllite/writer.c +++ b/rostests/winetests/xmllite/writer.c @@ -39,12 +39,21 @@ #include DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a); +#define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__) +static void _expect_ref(IUnknown *obj, ULONG ref, int line) +{ + ULONG refcount; + IUnknown_AddRef(obj); + refcount = IUnknown_Release(obj); + ok_(__FILE__, line)(refcount == ref, "expected refcount %d, got %d\n", ref, refcount); +} + static void check_output(IStream *stream, const char *expected, BOOL todo, int line) { - HGLOBAL hglobal; int len = strlen(expected), size; - char *ptr; + HGLOBAL hglobal; HRESULT hr; + char *ptr; hr = GetHGlobalFromStream(stream, &hglobal); ok_(__FILE__, line)(hr == S_OK, "got 0x%08x\n", hr); @@ -56,10 +65,10 @@ static void check_output(IStream *stream, const char *expected, BOOL todo, int l if (size != len) { ok_(__FILE__, line)(0, "data size mismatch, expected %u, got %u\n", len, size); - ok_(__FILE__, line)(0, "got %s, expected %s\n", ptr, expected); + ok_(__FILE__, line)(0, "got |%s|, expected |%s|\n", ptr, expected); } else - ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got %s, expected %s\n", ptr, expected); + ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got |%s|, expected |%s|\n", ptr, expected); } GlobalUnlock(hglobal); } @@ -236,6 +245,7 @@ static void test_writer_create(void) HRESULT hr; IXmlWriter *writer; LONG_PTR value; + IUnknown *unk; /* crashes native */ if (0) @@ -244,6 +254,17 @@ static void test_writer_create(void) CreateXmlWriter(NULL, (void**)&writer, NULL); } + hr = CreateXmlWriter(&IID_IStream, (void **)&unk, NULL); + ok(hr == E_NOINTERFACE, "got %08x\n", hr); + + hr = CreateXmlWriter(&IID_IUnknown, (void **)&unk, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + hr = IUnknown_QueryInterface(unk, &IID_IXmlWriter, (void **)&writer); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(unk == (IUnknown *)writer, "unexpected interface pointer\n"); + IUnknown_Release(unk); + IXmlWriter_Release(writer); + hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); @@ -274,6 +295,7 @@ static void test_writer_create(void) static void test_writeroutput(void) { static const WCHAR utf16W[] = {'u','t','f','-','1','6',0}; + static const WCHAR usasciiW[] = {'u','s','-','a','s','c','i','i',0}; IXmlWriterOutput *output; IUnknown *unk; HRESULT hr; @@ -281,6 +303,7 @@ static void test_writeroutput(void) output = NULL; hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output); ok(hr == S_OK, "got %08x\n", hr); + EXPECT_REF(output, 1); IUnknown_Release(output); hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output); @@ -288,9 +311,13 @@ static void test_writeroutput(void) unk = NULL; hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk); ok(hr == S_OK, "got %08x\n", hr); - ok(unk != NULL, "got %p\n", unk); +todo_wine + ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output); + EXPECT_REF(output, 2); /* releasing 'unk' crashes on native */ IUnknown_Release(output); + EXPECT_REF(output, 1); + IUnknown_Release(output); output = NULL; hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output); @@ -305,14 +332,24 @@ static void test_writeroutput(void) ok(unk != NULL, "got %p\n", unk); /* releasing 'unk' crashes on native */ IUnknown_Release(output); + IUnknown_Release(output); + + /* create with us-ascii */ + output = NULL; + hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, usasciiW, &output); + ok(hr == S_OK, "got %08x\n", hr); + IUnknown_Release(output); } static void test_writestartdocument(void) { static const char fullprolog[] = ""; + static const char *prologversion2 = ""; static const char prologversion[] = ""; static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0}; + static const WCHAR usasciiW[] = {'u','S','-','a','s','C','i','i',0}; static const WCHAR xmlW[] = {'x','m','l',0}; + IXmlWriterOutput *output; IXmlWriter *writer; IStream *stream; HRESULT hr; @@ -372,6 +409,32 @@ static void test_writestartdocument(void) IStream_Release(stream); IXmlWriter_Release(writer); + + /* create with us-ascii */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + output = NULL; + hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, usasciiW, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, prologversion2); + + IStream_Release(stream); + IXmlWriter_Release(writer); + IUnknown_Release(output); } static void test_flush(void) @@ -1266,6 +1329,83 @@ static void test_WriteCharEntity(void) IStream_Release(stream); } +static void test_WriteString(void) +{ + static const WCHAR markupW[] = {'<','&','"','>','=',0}; + static const WCHAR aW[] = {'a',0}; + static const WCHAR bW[] = {'b',0}; + static const WCHAR emptyW[] = {0}; + IXmlWriter *writer; + IStream *stream; + HRESULT hr; + + hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, aW); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, emptyW); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + stream = writer_set_output(writer); + + hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, emptyW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, aW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* WriteString automatically escapes markup characters */ + hr = IXmlWriter_WriteString(writer, markupW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, + "a<&\">="); + IStream_Release(stream); + + stream = writer_set_output(writer); + + hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, + ""); + + IXmlWriter_Release(writer); + IStream_Release(stream); +} + START_TEST(writer) { test_writer_create(); @@ -1285,4 +1425,5 @@ START_TEST(writer) test_WriteAttributeString(); test_WriteFullEndElement(); test_WriteCharEntity(); + test_WriteString(); } -- 2.17.1