https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4d74a058bd0862bd4b731…
commit 4d74a058bd0862bd4b731f536ae069a7bd12c9a7
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Mon Dec 23 00:56:47 2019 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Mon Dec 23 00:56:47 2019 +0100
[XMLLITE_WINETEST] Sync with Wine Staging 4.18. CORE-16441
---
modules/rostests/winetests/xmllite/writer.c | 839 ++++++++++++++++++++++++----
1 file changed, 734 insertions(+), 105 deletions(-)
diff --git a/modules/rostests/winetests/xmllite/writer.c
b/modules/rostests/winetests/xmllite/writer.c
index 8a15f384cb2..4e91419829d 100644
--- a/modules/rostests/winetests/xmllite/writer.c
+++ b/modules/rostests/winetests/xmllite/writer.c
@@ -31,6 +31,8 @@
#include "winbase.h"
#include "ole2.h"
#include "xmllite.h"
+
+#include "wine/heap.h"
#include "wine/test.h"
#include "initguid.h"
@@ -52,16 +54,18 @@ static void check_output_raw(IStream *stream, const void *expected,
SIZE_T size,
SIZE_T content_size;
HGLOBAL hglobal;
HRESULT hr;
- char *ptr;
+ WCHAR *ptr;
hr = GetHGlobalFromStream(stream, &hglobal);
ok_(__FILE__, line)(hr == S_OK, "Failed to get the stream handle, hr
%#x.\n", hr);
content_size = GlobalSize(hglobal);
- ok_(__FILE__, line)(size <= content_size, "Unexpected test output
size.\n");
+ ok_(__FILE__, line)(size == content_size, "Unexpected test output size
%ld.\n", content_size);
ptr = GlobalLock(hglobal);
if (size <= content_size)
ok_(__FILE__, line)(!memcmp(expected, ptr, size), "Unexpected output
content.\n");
+ if (size != content_size && *ptr == 0xfeff)
+ ok_(__FILE__, line)(0, "Content: %s.\n", wine_dbgstr_wn(ptr,
content_size / sizeof(WCHAR)));
GlobalUnlock(hglobal);
}
@@ -94,6 +98,19 @@ static void check_output(IStream *stream, const char *expected, BOOL
todo, int l
#define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE,
__LINE__)
#define CHECK_OUTPUT_RAW(stream, expected, size) check_output_raw(stream, expected, size,
__LINE__)
+static WCHAR *strdupAtoW(const char *str)
+{
+ WCHAR *ret = NULL;
+ DWORD len;
+
+ if (!str) return ret;
+ len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ ret = heap_alloc(len * sizeof(WCHAR));
+ if (ret)
+ MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+ return ret;
+}
+
static void writer_set_property(IXmlWriter *writer, XmlWriterProperty property)
{
HRESULT hr;
@@ -125,7 +142,8 @@ static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
hr = IXmlWriter_WriteComment(writer, aW);
ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
- /* FIXME: add WriteDocType */
+ hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
+ ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
@@ -343,7 +361,8 @@ static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown
*output)
hr = IXmlWriter_WriteComment(writer, aW);
ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
- /* TODO: WriteDocType */
+ hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
+ ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
@@ -471,6 +490,7 @@ todo_wine
CHECK_OUTPUT_RAW(stream, utf16_outputW, sizeof(utf16_outputW));
IStream_Release(stream);
+ IUnknown_Release(output);
/* Create output with meaningless code page value. */
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
@@ -706,11 +726,14 @@ static void test_omitxmldeclaration(void)
static void test_bom(void)
{
+ static const WCHAR piW[] =
{0xfeff,'<','?','x','m','l','
','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>'};
+ static const WCHAR aopenW[] = {0xfeff,'<','a'};
+ static const WCHAR afullW[] = {0xfeff,'<','a','
','/','>'};
static const WCHAR versionW[] =
{'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
static const WCHAR utf16W[] =
{'u','t','f','-','1','6',0};
static const WCHAR xmlW[] = {'x','m','l',0};
+ static const WCHAR bomW[] = {0xfeff};
IXmlWriterOutput *output;
- unsigned char *ptr;
IXmlWriter *writer;
IStream *stream;
HGLOBAL hglobal;
@@ -737,12 +760,7 @@ static void test_bom(void)
hr = IXmlWriter_Flush(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = GetHGlobalFromStream(stream, &hglobal);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- ptr = GlobalLock(hglobal);
- ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0],
ptr[1]);
- GlobalUnlock(hglobal);
+ CHECK_OUTPUT_RAW(stream, bomW, sizeof(bomW));
IStream_Release(stream);
IUnknown_Release(output);
@@ -763,12 +781,7 @@ static void test_bom(void)
hr = IXmlWriter_Flush(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = GetHGlobalFromStream(stream, &hglobal);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- ptr = GlobalLock(hglobal);
- ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0],
ptr[1]);
- GlobalUnlock(hglobal);
+ CHECK_OUTPUT_RAW(stream, piW, sizeof(piW));
IUnknown_Release(output);
IStream_Release(stream);
@@ -789,12 +802,7 @@ static void test_bom(void)
hr = IXmlWriter_Flush(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = GetHGlobalFromStream(stream, &hglobal);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- ptr = GlobalLock(hglobal);
- ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0],
ptr[1]);
- GlobalUnlock(hglobal);
+ CHECK_OUTPUT_RAW(stream, aopenW, sizeof(aopenW));
IUnknown_Release(output);
IStream_Release(stream);
@@ -820,10 +828,7 @@ static void test_bom(void)
hr = GetHGlobalFromStream(stream, &hglobal);
ok(hr == S_OK, "got 0x%08x\n", hr);
- ptr = GlobalLock(hglobal);
- ok(ptr[0] == 0xff && ptr[1] == 0xfe && ptr[2] == '<',
"Unexpected output: %#x,%#x,%#x\n",
- ptr[0], ptr[1], ptr[2]);
- GlobalUnlock(hglobal);
+ CHECK_OUTPUT_RAW(stream, afullW, sizeof(afullW));
IUnknown_Release(output);
IStream_Release(stream);
@@ -831,33 +836,105 @@ static void test_bom(void)
IXmlWriter_Release(writer);
}
-static void test_writestartelement(void)
+static HRESULT write_start_element(IXmlWriter *writer, const char *prefix, const char
*local,
+ const char *uri)
+{
+ WCHAR *prefixW, *localW, *uriW;
+ HRESULT hr;
+
+ prefixW = strdupAtoW(prefix);
+ localW = strdupAtoW(local);
+ uriW = strdupAtoW(uri);
+
+ hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW);
+
+ heap_free(prefixW);
+ heap_free(localW);
+ heap_free(uriW);
+
+ return hr;
+}
+
+static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, const char
*local,
+ const char *uri, const char *value)
{
- static const WCHAR valueW[] =
{'v','a','l','u','e',0};
+ WCHAR *prefixW, *localW, *uriW, *valueW;
+ HRESULT hr;
+
+ prefixW = strdupAtoW(prefix);
+ localW = strdupAtoW(local);
+ uriW = strdupAtoW(uri);
+ valueW = strdupAtoW(value);
+
+ hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW);
+
+ heap_free(prefixW);
+ heap_free(localW);
+ heap_free(uriW);
+ heap_free(valueW);
+
+ return hr;
+}
+
+static HRESULT write_string(IXmlWriter *writer, const char *str)
+{
+ WCHAR *strW;
+ HRESULT hr;
+
+ strW = strdupAtoW(str);
+
+ hr = IXmlWriter_WriteString(writer, strW);
+
+ heap_free(strW);
+
+ return hr;
+}
+
+static void test_WriteStartElement(void)
+{
+ static const struct
+ {
+ const char *prefix;
+ const char *local;
+ const char *uri;
+ const char *output;
+ const char *output_partial;
+ HRESULT hr;
+ int todo;
+ int todo_partial;
+ }
+ start_element_tests[] =
+ {
+ { "prefix", "local", "uri", "<prefix:local
xmlns:prefix=\"uri\" />", "<prefix:local" },
+ { NULL, "local", "uri", "<local
xmlns=\"uri\" />", "<local" },
+ { "", "local", "uri", "<local
xmlns=\"uri\" />", "<local" },
+ { "", "local", "uri", "<local
xmlns=\"uri\" />", "<local" },
+
+ { "prefix", NULL, NULL, NULL, NULL, E_INVALIDARG },
+ { NULL, NULL, "uri", NULL, NULL, E_INVALIDARG },
+ { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
+ { NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER
},
+ { "pre:fix", "local", "uri", NULL, NULL,
WC_E_NAMECHARACTER },
+ { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
+ { ":", "local", "uri", NULL, NULL,
WC_E_NAMECHARACTER },
+ { NULL, "local", "http://www.w3.org/2000/xmlns/", NULL, NULL,
WR_E_XMLNSPREFIXDECLARATION },
+ { "prefix", "local",
"http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION },
+ };
static const WCHAR aW[] = {'a',0};
- static const WCHAR bW[] = {'b',0};
IXmlWriter *writer;
IStream *stream;
+ unsigned int i;
HRESULT hr;
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, NULL, "a", NULL);
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, aW, NULL, NULL);
- ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
-
- hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
- ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
-
- hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, aW);
- ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
-
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, NULL, "a", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
@@ -884,34 +961,222 @@ static void test_writestartelement(void)
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
+ hr = write_element_string(writer, NULL, "b", NULL, "value");
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, "prefix", "a",
"uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, NULL, "b", NULL, "value");
+ ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, NULL, "c", NULL, NULL);
+ ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "d", "uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, "", "e", "uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, "prefix2", "f",
"uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<prefix:a xmlns:prefix=\"uri\">"
+ "<b>value</b>"
+ "<c />"
+ "<prefix:d>"
+ "<e xmlns=\"uri\">"
+ "<prefix2:f");
+
+ IStream_Release(stream);
+
+ /* WriteStartElement */
+ for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i)
+ {
+ stream = writer_set_output(writer);
+
+ writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
+
+ hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
+ ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, start_element_tests[i].prefix,
start_element_tests[i].local,
+ start_element_tests[i].uri);
+ ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#x.\n", i,
hr);
+
+ if (SUCCEEDED(start_element_tests[i].hr))
+ {
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ check_output(stream, start_element_tests[i].output_partial,
start_element_tests[i].todo_partial, __LINE__);
+
+ hr = IXmlWriter_WriteEndDocument(writer);
+ ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ check_output(stream, start_element_tests[i].output,
start_element_tests[i].todo, __LINE__);
+ }
+
+ IStream_Release(stream);
+ }
+
+ IXmlWriter_Release(writer);
+}
+
+static void test_WriteElementString(void)
+{
+ static const struct
+ {
+ const char *prefix;
+ const char *local;
+ const char *uri;
+ const char *value;
+ const char *output;
+ HRESULT hr;
+ int todo;
+ }
+ element_string_tests[] =
+ {
+ { "prefix", "local", "uri", "value",
"<prefix:local xmlns:prefix=\"uri\">value</prefix:local>"
},
+ { NULL, "local", "uri", "value", "<local
xmlns=\"uri\">value</local>" },
+ { "", "local", "uri", "value",
"<local xmlns=\"uri\">value</local>" },
+ { "prefix", "local", "uri", NULL,
"<prefix:local xmlns:prefix=\"uri\" />" },
+ { NULL, "local", "uri", NULL, "<local
xmlns=\"uri\" />" },
+ { "", "local", "uri", NULL, "<local
xmlns=\"uri\" />" },
+ { NULL, "local", NULL, NULL, "<local />" },
+ { "prefix", "local", "uri", "",
"<prefix:local xmlns:prefix=\"uri\"></prefix:local>" },
+ { NULL, "local", "uri", "", "<local
xmlns=\"uri\"></local>" },
+ { "", "local", "uri", "", "<local
xmlns=\"uri\"></local>" },
+ { NULL, "local", NULL, "",
"<local></local>" },
+ { "", "local", "http://www.w3.org/2000/xmlns/",
NULL, "<local
xmlns=\"http://www.w3.org/2000/xmlns/\" />" },
+
+ { "prefix", NULL, NULL, "value", NULL, E_INVALIDARG },
+ { NULL, NULL, "uri", "value", NULL, E_INVALIDARG },
+ { NULL, NULL, NULL, "value", NULL, E_INVALIDARG },
+ { NULL, "prefix:local", "uri", "value", NULL,
WC_E_NAMECHARACTER },
+ { NULL, ":local", "uri", "value", NULL,
WC_E_NAMECHARACTER },
+ { ":", "local", "uri", "value", NULL,
WC_E_NAMECHARACTER },
+ { "prefix", "local", NULL, "value", NULL,
WR_E_NSPREFIXWITHEMPTYNSURI },
+ { "prefix", "local", "", "value", NULL,
WR_E_NSPREFIXWITHEMPTYNSURI },
+ { NULL, "local", "http://www.w3.org/2000/xmlns/",
"value", NULL, WR_E_XMLNSPREFIXDECLARATION },
+ { "prefix", "local",
"http://www.w3.org/2000/xmlns/", "value", NULL,
WR_E_XMLNSURIDECLARATION },
+ };
+ IXmlWriter *writer;
+ IStream *stream;
+ unsigned int i;
+ HRESULT hr;
+
+ hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
+ ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+ hr = write_element_string(writer, NULL, "b", NULL, "value");
+ ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
+
+ stream = writer_set_output(writer);
+
+ hr = write_start_element(writer, NULL, "a", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
+ hr = write_element_string(writer, NULL, "b", NULL, "value");
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL);
+ hr = write_element_string(writer, NULL, "b", NULL, NULL);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = write_element_string(writer, "prefix", "b", "uri",
NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = write_start_element(writer, "prefix", "c",
"uri");
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, "prefix", "d", NULL, NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, "prefix2", "d",
"uri", NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, NULL, "e", "uri", NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, "prefix", "f",
"uri2", NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, NULL, "g", "uri3", NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, "prefix", "h", NULL, NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, "prefix_i", "i", NULL, NULL);
+ ok(hr == WR_E_NSPREFIXWITHEMPTYNSURI, "Failed to write element, hr %#x.\n",
hr);
+
+ hr = write_element_string(writer, "", "j", "uri",
NULL);
+ ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
+
hr = IXmlWriter_Flush(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
CHECK_OUTPUT(stream,
- "<a><b>value</b><b />");
+ "<a><b>value</b><b />"
+ "<prefix:b xmlns:prefix=\"uri\" />"
+ "<prefix:c xmlns:prefix=\"uri\">"
+ "<prefix:d />"
+ "<prefix2:d xmlns:prefix2=\"uri\" />"
+ "<prefix:e />"
+ "<prefix:f xmlns:prefix=\"uri2\" />"
+ "<g xmlns=\"uri3\" />"
+ "<prefix:h />"
+ "<j xmlns=\"uri\" />");
IStream_Release(stream);
+
+ for (i = 0; i < ARRAY_SIZE(element_string_tests); ++i)
+ {
+ stream = writer_set_output(writer);
+
+ writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
+
+ hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
+ ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
+
+ hr = write_element_string(writer, element_string_tests[i].prefix,
element_string_tests[i].local,
+ element_string_tests[i].uri, element_string_tests[i].value);
+ ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#x.\n", i,
hr);
+
+ if (SUCCEEDED(element_string_tests[i].hr))
+ {
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ check_output(stream, element_string_tests[i].output,
element_string_tests[i].todo, __LINE__);
+
+ hr = IXmlWriter_WriteEndDocument(writer);
+ ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ check_output(stream, element_string_tests[i].output,
element_string_tests[i].todo, __LINE__);
+ }
+
+ IStream_Release(stream);
+ }
+
IXmlWriter_Release(writer);
}
-static void test_writeendelement(void)
+static void test_WriteEndElement(void)
{
- static const WCHAR aW[] = {'a',0};
- static const WCHAR bW[] = {'b',0};
IXmlWriter *writer;
IStream *stream;
HRESULT hr;
@@ -921,10 +1186,10 @@ static void test_writeendelement(void)
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, NULL, "a", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
+ hr = write_start_element(writer, NULL, "b", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_WriteEndElement(writer);
@@ -1316,88 +1581,216 @@ static void test_indentation(void)
IXmlWriter_Release(writer);
}
+static HRESULT write_attribute_string(IXmlWriter *writer, const char *prefix, const char
*local,
+ const char *uri, const char *value)
+{
+ WCHAR *prefixW, *localW, *uriW, *valueW;
+ HRESULT hr;
+
+ prefixW = strdupAtoW(prefix);
+ localW = strdupAtoW(local);
+ uriW = strdupAtoW(uri);
+ valueW = strdupAtoW(value);
+
+ hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, uriW, valueW);
+
+ heap_free(prefixW);
+ heap_free(localW);
+ heap_free(uriW);
+ heap_free(valueW);
+
+ return hr;
+}
+
static void test_WriteAttributeString(void)
{
- static const WCHAR prefixW[] =
{'p','r','e','f','i','x',0};
- static const WCHAR localW[] =
{'l','o','c','a','l',0};
- static const WCHAR uriW[] = {'u','r','i',0};
- static const WCHAR uri2W[] = {'u','r','i','2',0};
- static const WCHAR xmlnsW[] =
{'x','m','l','n','s',0};
- static const WCHAR aW[] = {'a',0};
- static const WCHAR bW[] = {'b',0};
+ static const struct
+ {
+ const char *prefix;
+ const char *local;
+ const char *uri;
+ const char *value;
+ const char *output;
+ const char *output_partial;
+ HRESULT hr;
+ int todo;
+ int todo_partial;
+ int todo_hr;
+ }
+ attribute_tests[] =
+ {
+ { NULL, "a", NULL, "b", "<e a=\"b\"
/>", "<e a=\"b\"" },
+ { "", "a", NULL, "b", "<e a=\"b\"
/>", "<e a=\"b\"" },
+ { NULL, "a", "", "b", "<e a=\"b\"
/>", "<e a=\"b\"" },
+ { "", "a", "", "b", "<e
a=\"b\" />", "<e a=\"b\"" },
+ { "prefix", "local", "uri", "b",
"<e prefix:local=\"b\" xmlns:prefix=\"uri\" />",
"<e prefix:local=\"b\"" },
+ { NULL, "a", "http://www.w3.org/2000/xmlns/",
"defuri", "<e xmlns:a=\"defuri\" />", "<e
xmlns:a=\"defuri\"" },
+ { "xmlns", "a", NULL, "uri", "<e
xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
+ { "xmlns", "a", "", "uri", "<e
xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
+ { "prefix", "xmlns", "uri", "value",
"<e prefix:xmlns=\"value\" xmlns:prefix=\"uri\" />",
"<e prefix:xmlns=\"value\"" },
+ { "prefix", "xmlns", "uri", NULL, "<e
prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e
prefix:xmlns=\"\"" },
+ { "prefix", "xmlns", "uri", "",
"<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />",
"<e prefix:xmlns=\"\"" },
+ { "prefix", "xmlns", NULL, "uri", "<e
xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
+ { "prefix", "xmlns", "", "uri",
"<e xmlns=\"uri\" />", "<e xmlns=\"uri\""
},
+ { "xml", "space", NULL, "preserve", "<e
xml:space=\"preserve\" />", "<e
xml:space=\"preserve\"" },
+ { "xml", "space", "", "preserve",
"<e xml:space=\"preserve\" />", "<e
xml:space=\"preserve\"" },
+ { "xml", "space", NULL, "default", "<e
xml:space=\"default\" />", "<e
xml:space=\"default\"" },
+ { "xml", "space", "", "default",
"<e xml:space=\"default\" />", "<e
xml:space=\"default\"" },
+ { "xml", "a", NULL, "value", "<e
xml:a=\"value\" />", "<e xml:a=\"value\"" },
+ { "xml", "a", "", "value", "<e
xml:a=\"value\" />", "<e xml:a=\"value\"" },
+
+ /* Autogenerated prefix names. */
+ { NULL, "a", "defuri", NULL, "<e p1:a=\"\"
xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1,
1, 1 },
+ { NULL, "a", "defuri", "b", "<e
p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e
p1:a=\"b\"", S_OK, 1, 1, 1 },
+ { "", "a", "defuri", NULL, "<e
p1:a=\"\" xmlns:p1=\"defuri\" />", "<e
p1:a=\"\"", S_OK, 1, 1, 1 },
+ { NULL, "a", "defuri", "", "<e
p1:a=\"\" xmlns:p1=\"defuri\" />", "<e
p1:a=\"\"", S_OK, 1, 1, 1 },
+ { "", "a", "defuri", "b", "<e
p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e
p1:a=\"b\"", S_OK, 1, 1, 1 },
+
+ /* Failing cases. */
+ { NULL, NULL, "http://www.w3.org/2000/xmlns/", "defuri",
"<e />", "<e", E_INVALIDARG },
+ { "", "a", "http://www.w3.org/2000/xmlns/",
"defuri", "<e />", "<e",
WR_E_XMLNSPREFIXDECLARATION, 1, 1, 1 },
+ { "", NULL, "http://www.w3.org/2000/xmlns/",
"defuri", "<e />", "<e", E_INVALIDARG },
+ { "", "", "http://www.w3.org/2000/xmlns/",
"defuri", "<e />", "<e", E_INVALIDARG, 1, 1, 1 },
+ { NULL, "", "http://www.w3.org/2000/xmlns/",
"defuri", "<e />", "<e", E_INVALIDARG, 1, 1, 1 },
+ { "prefix", "a", "http://www.w3.org/2000/xmlns/",
"defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION,
1, 1, 1 },
+ { "prefix", NULL, "http://www.w3.org/2000/xmlns/",
"defuri", "<e />", "<e", E_INVALIDARG },
+ { "prefix", NULL, NULL, "b", "<e />",
"<e", E_INVALIDARG },
+ { "prefix", NULL, "uri", NULL, "<e />",
"<e", E_INVALIDARG },
+ { "xml", NULL, NULL, "value", "<e />",
"<e", E_INVALIDARG },
+ { "xmlns", "a", "defuri", NULL, "<e
/>", "<e", WR_E_XMLNSPREFIXDECLARATION },
+ { "xmlns", "a", "b", "uri", "<e
/>", "<e", WR_E_XMLNSPREFIXDECLARATION },
+ { NULL, "xmlns", "uri", NULL, "<e />",
"<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
+ { "xmlns", NULL, "uri", NULL, "<e />",
"<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
+ { "pre:fix", "local", "uri", "b",
"<e />", "<e", WC_E_NAMECHARACTER },
+ { "pre:fix", NULL, "uri", "b", "<e
/>", "<e", E_INVALIDARG },
+ { "prefix", "lo:cal", "uri", "b",
"<e />", "<e", WC_E_NAMECHARACTER },
+ { "xmlns", NULL, NULL, "uri", "<e />",
"<e", WR_E_NSPREFIXDECLARED },
+ { "xmlns", NULL, "", "uri", "<e
/>", "<e", WR_E_NSPREFIXDECLARED },
+ { "xmlns", "", NULL, "uri", "<e
/>", "<e", WR_E_NSPREFIXDECLARED },
+ { "xmlns", "", "", "uri", "<e
/>", "<e", WR_E_NSPREFIXDECLARED },
+ { "xml", "space", "", "value",
"<e />", "<e", WR_E_INVALIDXMLSPACE },
+ { "xml", "space", NULL, "value", "<e
/>", "<e", WR_E_INVALIDXMLSPACE },
+ { "xml", "a", "uri", "value", "<e
/>", "<e", WR_E_XMLPREFIXDECLARATION },
+ { "xml", "space", NULL, "preServe", "<e
/>", "<e", WR_E_INVALIDXMLSPACE },
+ { "xml", "space", NULL, "defAult", "<e
/>", "<e", WR_E_INVALIDXMLSPACE },
+ { "xml", "space", NULL, NULL, "<e />",
"<e", WR_E_INVALIDXMLSPACE },
+ { "xml", "space", NULL, "", "<e
/>", "<e", WR_E_INVALIDXMLSPACE },
+ };
+
IXmlWriter *writer;
IStream *stream;
+ unsigned int i;
HRESULT hr;
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = writer_set_output(writer);
-
writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
+ for (i = 0; i < ARRAY_SIZE(attribute_tests); ++i)
+ {
+ stream = writer_set_output(writer);
+
+ hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
+ ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "e", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_attribute_string(writer, attribute_tests[i].prefix,
attribute_tests[i].local,
+ attribute_tests[i].uri, attribute_tests[i].value);
+ todo_wine_if(attribute_tests[i].todo_hr)
+ ok(hr == attribute_tests[i].hr, "%u: unexpected hr %#x, expected
%#x.\n", i, hr, attribute_tests[i].hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ check_output(stream, attribute_tests[i].output_partial,
attribute_tests[i].todo_partial, __LINE__);
+
+ hr = IXmlWriter_WriteEndDocument(writer);
+ ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ check_output(stream, attribute_tests[i].output, attribute_tests[i].todo,
__LINE__);
+ IStream_Release(stream);
+ }
+
+ /* With namespaces */
+ stream = writer_set_output(writer);
+
hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, "p", "a",
"outeruri");
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = write_attribute_string(writer, "prefix", "local",
"uri", "b");
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = write_attribute_string(writer, NULL, "a", NULL, "b");
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, bW);
+ hr = write_attribute_string(writer, "xmlns", "prefix", NULL,
"uri");
ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = write_attribute_string(writer, "p", "attr", NULL,
"value");
+ ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
+
+ hr = write_attribute_string(writer, "prefix", "local", NULL,
"b");
+todo_wine
+ ok(hr == WR_E_DUPLICATEATTRIBUTE, "got 0x%08x\n", hr);
+
+ hr = write_start_element(writer, NULL, "b", NULL);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = write_attribute_string(writer, NULL, "attr2", "outeruri",
"value");
+ ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
+
+ hr = write_attribute_string(writer, "pr", "attr3",
"outeruri", "value");
+ ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
+
hr = IXmlWriter_WriteEndDocument(writer);
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 a=\"b\" />");
+ CHECK_OUTPUT_TODO(stream,
+ "<p:a prefix:local=\"b\" a=\"b\"
xmlns:prefix=\"uri\" p:attr=\"value\"
xmlns:p=\"outeruri\">"
+ "<b p:attr2=\"value\" pr:attr3=\"value\"
xmlns:pr=\"outeruri\" />"
+ "</p:a>");
+
IStream_Release(stream);
- /* with namespaces */
+ /* Define prefix, write attribute with it. */
stream = writer_set_output(writer);
hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+ hr = write_start_element(writer, NULL, "e", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteAttributeString(writer, aW, NULL, NULL, bW);
-todo_wine
- ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
-
- hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, uriW, bW);
-todo_wine
+ hr = write_attribute_string(writer, "xmlns", "prefix", NULL,
"uri");
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, bW);
+ hr = write_attribute_string(writer, "prefix", "attr", NULL,
"value");
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteAttributeString(writer, NULL, xmlnsW, uri2W, NULL);
-todo_wine
- ok(hr == WR_E_XMLNSPREFIXDECLARATION, "got 0x%08x\n", hr);
-
- hr = IXmlWriter_WriteAttributeString(writer, NULL, xmlnsW, NULL, uri2W);
-todo_wine
- ok(hr == WR_E_NSPREFIXDECLARED, "got 0x%08x\n", hr);
-
- hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, NULL, bW);
-todo_wine
- ok(hr == WR_E_DUPLICATEATTRIBUTE, "got 0x%08x\n", hr);
-
hr = IXmlWriter_WriteEndDocument(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
ok(hr == S_OK, "got 0x%08x\n", hr);
- CHECK_OUTPUT_TODO(stream,
- "<a prefix:local=\"b\" a=\"b\"
xmlns:prefix=\"uri\" />");
+ CHECK_OUTPUT(stream,
+ "<e xmlns:prefix=\"uri\" prefix:attr=\"value\"
/>");
- IXmlWriter_Release(writer);
IStream_Release(stream);
+
+ IXmlWriter_Release(writer);
}
static void test_WriteFullEndElement(void)
@@ -1510,10 +1903,6 @@ static void test_WriteCharEntity(void)
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;
@@ -1523,31 +1912,31 @@ static void test_WriteString(void)
writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
- hr = IXmlWriter_WriteString(writer, aW);
+ hr = write_string(writer, "a");
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL);
+ hr = write_string(writer, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, emptyW);
+ hr = write_string(writer, "");
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
+ hr = write_start_element(writer, NULL, "b", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL);
+ hr = write_string(writer, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, emptyW);
+ hr = write_string(writer, "");
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, aW);
+ hr = write_string(writer, "a");
ok(hr == S_OK, "got 0x%08x\n", hr);
/* WriteString automatically escapes markup characters */
- hr = IXmlWriter_WriteString(writer, markupW);
+ hr = write_string(writer, "<&\">=");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
@@ -1559,10 +1948,10 @@ static void test_WriteString(void)
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
+ hr = write_start_element(writer, NULL, "b", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL);
+ hr = write_string(writer, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
@@ -1571,7 +1960,7 @@ static void test_WriteString(void)
CHECK_OUTPUT(stream,
"<b");
- hr = IXmlWriter_WriteString(writer, emptyW);
+ hr = write_string(writer, "");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
@@ -1580,18 +1969,257 @@ static void test_WriteString(void)
CHECK_OUTPUT(stream,
"<b>");
+ IStream_Release(stream);
+ IXmlWriter_Release(writer);
+
+ /* With indentation */
+ hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
+ ok(hr == S_OK, "Failed to create a writer, hr %#x.\n", hr);
+
+ stream = writer_set_output(writer);
+
+ writer_set_property(writer, XmlWriterProperty_Indent);
+
+ hr = write_start_element(writer, NULL, "a", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "b", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_string(writer, "text");
+ ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b>text");
+
+ hr = IXmlWriter_WriteFullEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b>text</b>");
+
+ hr = IXmlWriter_WriteFullEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b>text</b>\r\n"
+ "</a>");
+
+ IStream_Release(stream);
+
+ stream = writer_set_output(writer);
+
+ hr = write_start_element(writer, NULL, "a", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "b", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />");
+
+ hr = write_start_element(writer, NULL, "c", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_attribute_string(writer, NULL, "attr", NULL,
"value");
+ ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\"");
+
+ hr = write_string(writer, "text");
+ ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text");
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text</c>");
+
+ hr = write_start_element(writer, NULL, "d", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_string(writer, "");
+ ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text</c>\r\n"
+ " <d></d>");
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text</c>\r\n"
+ " <d></d>\r\n"
+ "</a>");
+
IXmlWriter_Release(writer);
IStream_Release(stream);
}
+static HRESULT write_doctype(IXmlWriter *writer, const char *name, const char *pubid,
const char *sysid,
+ const char *subset)
+{
+ WCHAR *nameW, *pubidW, *sysidW, *subsetW;
+ HRESULT hr;
+
+ nameW = strdupAtoW(name);
+ pubidW = strdupAtoW(pubid);
+ sysidW = strdupAtoW(sysid);
+ subsetW = strdupAtoW(subset);
+
+ hr = IXmlWriter_WriteDocType(writer, nameW, pubidW, sysidW, subsetW);
+
+ heap_free(nameW);
+ heap_free(pubidW);
+ heap_free(sysidW);
+ heap_free(subsetW);
+
+ return hr;
+}
+
+static void test_WriteDocType(void)
+{
+ static const struct
+ {
+ const char *name;
+ const char *pubid;
+ const char *sysid;
+ const char *subset;
+ const char *output;
+ }
+ doctype_tests[] =
+ {
+ { "a", "", NULL, NULL, "<!DOCTYPE a PUBLIC
\"\" \"\">" },
+ { "a", NULL, NULL, NULL, "<!DOCTYPE a>" },
+ { "a", NULL, "", NULL, "<!DOCTYPE a SYSTEM
\"\">" },
+ { "a", "", "", NULL, "<!DOCTYPE a PUBLIC
\"\" \"\">" },
+ { "a", "pubid", "", NULL, "<!DOCTYPE a
PUBLIC \"pubid\" \"\">" },
+ { "a", "pubid", NULL, NULL, "<!DOCTYPE a PUBLIC
\"pubid\" \"\">" },
+ { "a", "", "sysid", NULL, "<!DOCTYPE a
PUBLIC \"\" \"sysid\">" },
+ { "a", NULL, NULL, "", "<!DOCTYPE a []>" },
+ { "a", NULL, NULL, "subset", "<!DOCTYPE a
[subset]>" },
+ { "a", "", NULL, "subset", "<!DOCTYPE a
PUBLIC \"\" \"\" [subset]>" },
+ { "a", NULL, "", "subset", "<!DOCTYPE a
SYSTEM \"\" [subset]>" },
+ { "a", "", "", "subset",
"<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
+ { "a", "pubid", NULL, "subset", "<!DOCTYPE
a PUBLIC \"pubid\" \"\" [subset]>" },
+ { "a", "pubid", "", "subset",
"<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
+ { "a", NULL, "sysid", "subset", "<!DOCTYPE
a SYSTEM \"sysid\" [subset]>" },
+ { "a", "", "sysid", "subset",
"<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
+ { "a", "pubid", "sysid", "subset",
"<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
+ };
+ static const WCHAR pubidW[] = {'p',0x100,'i','d',0};
+ static const WCHAR nameW[] = {'-','a',0};
+ static const WCHAR emptyW[] = { 0 };
+ IXmlWriter *writer;
+ IStream *stream;
+ unsigned int i;
+ HRESULT hr;
+
+ hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
+ ok(hr == S_OK, "Failed to create writer instance, hr %#x.\n", hr);
+
+ stream = writer_set_output(writer);
+
+ hr = IXmlWriter_WriteDocType(writer, NULL, NULL, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlWriter_WriteDocType(writer, emptyW, NULL, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ /* Name validation. */
+ hr = IXmlWriter_WriteDocType(writer, nameW, NULL, NULL, NULL);
+ ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#x.\n", hr);
+
+ /* Pubid validation. */
+ hr = IXmlWriter_WriteDocType(writer, aW, pubidW, NULL, NULL);
+ ok(hr == WC_E_PUBLICID, "Unexpected hr %#x.\n", hr);
+
+ IStream_Release(stream);
+
+ for (i = 0; i < ARRAY_SIZE(doctype_tests); i++)
+ {
+ stream = writer_set_output(writer);
+
+ hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid,
doctype_tests[i].sysid,
+ doctype_tests[i].subset);
+ ok(hr == S_OK, "%u: failed to write doctype, hr %#x.\n", i, hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream, doctype_tests[i].output);
+
+ hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid,
doctype_tests[i].sysid,
+ doctype_tests[i].subset);
+ ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#x.\n", hr);
+
+ IStream_Release(stream);
+ }
+
+ IXmlWriter_Release(writer);
+}
+
START_TEST(writer)
{
test_writer_create();
test_writer_state();
test_writeroutput();
test_writestartdocument();
- test_writestartelement();
- test_writeendelement();
+ test_WriteStartElement();
+ test_WriteElementString();
+ test_WriteEndElement();
test_flush();
test_omitxmldeclaration();
test_bom();
@@ -1604,4 +2232,5 @@ START_TEST(writer)
test_WriteFullEndElement();
test_WriteCharEntity();
test_WriteString();
+ test_WriteDocType();
}