xmllite/writer: Properly validate DocType name.
[wine.git] / dlls / xmllite / tests / writer.c
blobc4ab079373c06e706501f291a30efa93d15a2109
1 /*
2 * XMLLite IXmlWriter tests
4 * Copyright 2011 (C) Alistair Leslie-Hughes
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include <stdarg.h>
23 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "ole2.h"
28 #include "xmllite.h"
30 #include "wine/test.h"
32 #include "initguid.h"
33 DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
35 static IStream *create_stream_on_data(const void *data, unsigned int size)
37 IStream *stream = NULL;
38 HGLOBAL hglobal;
39 void *ptr;
40 HRESULT hr;
42 hglobal = GlobalAlloc(GHND, size);
43 ptr = GlobalLock(hglobal);
45 memcpy(ptr, data, size);
47 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
48 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
49 ok(stream != NULL, "Expected non-NULL stream\n");
51 GlobalUnlock(hglobal);
53 return stream;
56 #define reader_set_input(a, b) _reader_set_input(__LINE__, a, b)
57 static void _reader_set_input(unsigned line, IXmlReader *reader, const char *xml)
59 IStream *stream;
60 HRESULT hr;
62 stream = create_stream_on_data(xml, strlen(xml));
64 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
65 ok_(__FILE__,line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
67 IStream_Release(stream);
70 #define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
71 static void _expect_ref(IUnknown *obj, ULONG ref, int line)
73 ULONG refcount;
74 IUnknown_AddRef(obj);
75 refcount = IUnknown_Release(obj);
76 ok_(__FILE__, line)(refcount == ref, "expected refcount %lu, got %lu.\n", ref, refcount);
79 static void check_output_raw(IStream *stream, const void *expected, SIZE_T size, int line)
81 SIZE_T content_size;
82 HGLOBAL hglobal;
83 HRESULT hr;
84 WCHAR *ptr;
86 hr = GetHGlobalFromStream(stream, &hglobal);
87 ok_(__FILE__, line)(hr == S_OK, "Failed to get the stream handle, hr %#lx.\n", hr);
89 content_size = GlobalSize(hglobal);
90 ok_(__FILE__, line)(size == content_size, "Unexpected test output size %Id.\n", content_size);
91 ptr = GlobalLock(hglobal);
92 if (size <= content_size)
93 ok_(__FILE__, line)(!memcmp(expected, ptr, size), "Unexpected output content.\n");
94 if (size != content_size && *ptr == 0xfeff)
95 ok_(__FILE__, line)(0, "Content: %s.\n", wine_dbgstr_wn(ptr, content_size / sizeof(WCHAR)));
97 GlobalUnlock(hglobal);
100 static void check_output(IStream *stream, const char *expected, BOOL todo, int line)
102 int len = strlen(expected), size;
103 HGLOBAL hglobal;
104 HRESULT hr;
105 char *ptr;
107 hr = GetHGlobalFromStream(stream, &hglobal);
108 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
110 size = GlobalSize(hglobal);
111 ptr = GlobalLock(hglobal);
112 todo_wine_if(todo)
114 if (size != len)
116 ok_(__FILE__, line)(0, "data size mismatch, expected %u, got %u\n", len, size);
117 ok_(__FILE__, line)(0, "got |%s|, expected |%s|\n", ptr, expected);
119 else
120 ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got |%s|, expected |%s|\n", ptr, expected);
122 GlobalUnlock(hglobal);
124 #define CHECK_OUTPUT(stream, expected) check_output(stream, expected, FALSE, __LINE__)
125 #define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE, __LINE__)
126 #define CHECK_OUTPUT_RAW(stream, expected, size) check_output_raw(stream, expected, size, __LINE__)
128 static void writer_set_property(IXmlWriter *writer, XmlWriterProperty property)
130 HRESULT hr;
132 hr = IXmlWriter_SetProperty(writer, property, TRUE);
133 ok(hr == S_OK, "Failed to set writer property, hr %#lx.\n", hr);
136 /* used to test all Write* methods for consistent error state */
137 static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
139 IXmlReader *reader;
140 HRESULT hr;
142 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
143 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
145 /* FIXME: add WriteAttributes */
147 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"a");
148 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
150 hr = IXmlWriter_WriteCData(writer, L"a");
151 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
153 hr = IXmlWriter_WriteCharEntity(writer, 'a');
154 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
156 hr = IXmlWriter_WriteChars(writer, L"a", 1);
157 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
159 hr = IXmlWriter_WriteComment(writer, L"a");
160 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
162 hr = IXmlWriter_WriteDocType(writer, L"a", NULL, NULL, NULL);
163 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
165 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, L"a");
166 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
168 hr = IXmlWriter_WriteEndDocument(writer);
169 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
171 hr = IXmlWriter_WriteEndElement(writer);
172 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
174 hr = IXmlWriter_WriteEntityRef(writer, L"a");
175 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
177 hr = IXmlWriter_WriteFullEndElement(writer);
178 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
180 hr = IXmlWriter_WriteName(writer, L"a");
181 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
183 hr = IXmlWriter_WriteNmToken(writer, L"a");
184 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
186 hr = IXmlWriter_WriteNode(writer, NULL, FALSE);
187 ok(hr == E_INVALIDARG, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
189 reader_set_input(reader, "<a/>");
190 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
191 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
193 reader_set_input(reader, "<a/>");
194 hr = IXmlReader_Read(reader, NULL);
195 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
196 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
197 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
199 hr = IXmlWriter_WriteProcessingInstruction(writer, L"a", L"a");
200 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
202 hr = IXmlWriter_WriteQualifiedName(writer, L"a", NULL);
203 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
205 hr = IXmlWriter_WriteRaw(writer, L"a");
206 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
208 hr = IXmlWriter_WriteRawChars(writer, L"a", 1);
209 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
211 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
212 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
214 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
215 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
217 hr = IXmlWriter_WriteString(writer, L"a");
218 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
220 /* FIXME: add WriteSurrogateCharEntity */
222 hr = IXmlWriter_WriteWhitespace(writer, L" ");
223 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
225 IXmlReader_Release(reader);
228 static IStream *writer_set_output(IXmlWriter *writer)
230 IStream *stream;
231 HRESULT hr;
233 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
234 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
236 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
239 return stream;
242 static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
244 if (IsEqualGUID(riid, &IID_IUnknown)) {
245 *obj = iface;
246 return S_OK;
248 else {
249 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
250 return E_NOINTERFACE;
254 static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
256 return 2;
259 static ULONG WINAPI testoutput_Release(IUnknown *iface)
261 return 1;
264 static const IUnknownVtbl testoutputvtbl = {
265 testoutput_QueryInterface,
266 testoutput_AddRef,
267 testoutput_Release
270 static IUnknown testoutput = { &testoutputvtbl };
272 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
274 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
276 *obj = iface;
277 return S_OK;
280 *obj = NULL;
281 return E_NOINTERFACE;
284 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
286 return 2;
289 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
291 return 1;
294 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
296 ok(0, "unexpected call\n");
297 return E_NOTIMPL;
300 static ULONG g_write_len;
301 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
303 g_write_len = cb;
304 *written = cb;
305 return S_OK;
308 static const ISequentialStreamVtbl teststreamvtbl =
310 teststream_QueryInterface,
311 teststream_AddRef,
312 teststream_Release,
313 teststream_Read,
314 teststream_Write
317 static ISequentialStream teststream = { &teststreamvtbl };
319 static void test_writer_create(void)
321 HRESULT hr;
322 IXmlWriter *writer;
323 LONG_PTR value;
324 IUnknown *unk;
326 /* crashes native */
327 if (0)
329 CreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
330 CreateXmlWriter(NULL, (void**)&writer, NULL);
333 hr = CreateXmlWriter(&IID_IStream, (void **)&unk, NULL);
334 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
336 hr = CreateXmlWriter(&IID_IUnknown, (void **)&unk, NULL);
337 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
338 hr = IUnknown_QueryInterface(unk, &IID_IXmlWriter, (void **)&writer);
339 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
340 ok(unk == (IUnknown *)writer, "unexpected interface pointer\n");
341 IUnknown_Release(unk);
342 IXmlWriter_Release(writer);
344 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
345 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
347 /* check default properties values */
348 value = 0;
349 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
350 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
351 ok(value == TRUE, "got %Id.\n", value);
353 value = TRUE;
354 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
356 ok(value == FALSE, "got %Id.\n", value);
358 value = TRUE;
359 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
360 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
361 ok(value == FALSE, "got %Id.\n", value);
363 value = XmlConformanceLevel_Auto;
364 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
365 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
366 ok(value == XmlConformanceLevel_Document, "got %Id.\n", value);
368 IXmlWriter_Release(writer);
371 static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown *output)
373 IXmlReader *reader;
374 HRESULT hr;
376 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
377 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
379 hr = IXmlWriter_SetOutput(writer, output);
380 ok(hr == S_OK, "Failed to set output, hr %#lx.\n", hr);
382 /* TODO: WriteAttributes */
384 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"a");
385 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
387 hr = IXmlWriter_WriteCData(writer, L"a");
388 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
390 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
391 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
393 hr = IXmlWriter_WriteChars(writer, L"a", 1);
394 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
396 hr = IXmlWriter_WriteComment(writer, L"a");
397 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
399 hr = IXmlWriter_WriteDocType(writer, L"a", NULL, NULL, NULL);
400 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
402 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, NULL);
403 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
405 hr = IXmlWriter_WriteEndDocument(writer);
406 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
408 hr = IXmlWriter_WriteEndElement(writer);
409 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
411 hr = IXmlWriter_WriteEntityRef(writer, L"a");
412 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
414 hr = IXmlWriter_WriteFullEndElement(writer);
415 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
417 hr = IXmlWriter_WriteName(writer, L"a");
418 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
420 hr = IXmlWriter_WriteNmToken(writer, L"a");
421 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
423 reader_set_input(reader, "<a/>");
424 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
425 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
427 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
428 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
430 hr = IXmlWriter_WriteProcessingInstruction(writer, L"a", L"a");
431 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
433 hr = IXmlWriter_WriteQualifiedName(writer, L"a", NULL);
434 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
436 hr = IXmlWriter_WriteRaw(writer, L"a");
437 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
439 hr = IXmlWriter_WriteRawChars(writer, L"a", 1);
440 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
442 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
443 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
445 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
446 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
448 hr = IXmlWriter_WriteString(writer, L"a");
449 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
451 /* TODO: WriteSurrogateCharEntity */
453 hr = IXmlWriter_WriteWhitespace(writer, L" ");
454 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
456 hr = IXmlWriter_Flush(writer);
457 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
459 IXmlReader_Release(reader);
462 static void test_writeroutput(void)
464 static const WCHAR utf16_outputW[] = {0xfeff,'<','a'};
465 IXmlWriterOutput *output;
466 IXmlWriter *writer;
467 IStream *stream;
468 IUnknown *unk;
469 HRESULT hr;
471 output = NULL;
472 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
474 EXPECT_REF(output, 1);
475 IUnknown_Release(output);
477 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, L"utf-16", &output);
478 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
479 unk = NULL;
480 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
481 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
482 todo_wine
483 ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output);
484 EXPECT_REF(output, 2);
485 /* releasing 'unk' crashes on native */
486 IUnknown_Release(output);
487 EXPECT_REF(output, 1);
488 IUnknown_Release(output);
490 output = NULL;
491 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output);
492 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
493 IUnknown_Release(output);
495 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, CP_UTF8, &output);
496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
497 unk = NULL;
498 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
499 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
500 ok(unk != NULL, "got %p\n", unk);
501 /* releasing 'unk' crashes on native */
502 IUnknown_Release(output);
503 IUnknown_Release(output);
505 /* create with us-ascii */
506 output = NULL;
507 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, L"us-ascii", &output);
508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
509 IUnknown_Release(output);
511 /* Output with codepage 1200. */
512 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
513 ok(hr == S_OK, "Failed to create writer, hr %#lx.\n", hr);
515 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
516 ok(hr == S_OK, "Failed to create stream, hr %#lx.\n", hr);
518 hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, 1200, &output);
519 ok(hr == S_OK, "Failed to create writer output, hr %#lx.\n", hr);
521 hr = IXmlWriter_SetOutput(writer, output);
522 ok(hr == S_OK, "Failed to set writer output, hr %#lx.\n", hr);
524 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
525 ok(hr == S_OK, "Write failed, hr %#lx.\n", hr);
527 hr = IXmlWriter_Flush(writer);
528 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
530 CHECK_OUTPUT_RAW(stream, utf16_outputW, sizeof(utf16_outputW));
532 IStream_Release(stream);
533 IUnknown_Release(output);
535 /* Create output with meaningless code page value. */
536 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
537 ok(hr == S_OK, "Failed to create stream, hr %#lx.\n", hr);
539 output = NULL;
540 hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, ~0u, &output);
541 ok(hr == S_OK, "Failed to create writer output, hr %#lx.\n", hr);
543 test_invalid_output_encoding(writer, output);
544 CHECK_OUTPUT(stream, "");
546 IStream_Release(stream);
547 IUnknown_Release(output);
549 /* Same, with invalid encoding name. */
550 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
551 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
553 output = NULL;
554 hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, L"dummy", &output);
555 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
557 test_invalid_output_encoding(writer, output);
558 CHECK_OUTPUT(stream, "");
560 IStream_Release(stream);
561 IUnknown_Release(output);
563 IXmlWriter_Release(writer);
566 static void test_writestartdocument(void)
568 static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
569 static const char *prologversion2 = "<?xml version=\"1.0\" encoding=\"uS-asCii\"?>";
570 static const char prologversion[] = "<?xml version=\"1.0\"?>";
571 IXmlWriterOutput *output;
572 IXmlWriter *writer;
573 IStream *stream;
574 HRESULT hr;
576 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
579 /* output not set */
580 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
581 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
583 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
584 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
586 hr = IXmlWriter_Flush(writer);
587 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
589 stream = writer_set_output(writer);
591 /* nothing written yet */
592 hr = IXmlWriter_Flush(writer);
593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
595 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
596 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
598 hr = IXmlWriter_Flush(writer);
599 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
601 CHECK_OUTPUT(stream, fullprolog);
603 /* one more time */
604 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
605 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
606 IStream_Release(stream);
608 /* now add PI manually, and try to start a document */
609 stream = writer_set_output(writer);
611 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
614 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
615 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
617 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
618 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
620 /* another attempt to add 'xml' PI */
621 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
622 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
624 hr = IXmlWriter_Flush(writer);
625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
627 CHECK_OUTPUT(stream, prologversion);
629 IStream_Release(stream);
630 IXmlWriter_Release(writer);
632 /* create with us-ascii */
633 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
634 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
636 output = NULL;
637 hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, L"uS-asCii", &output);
638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
640 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
641 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
643 hr = IXmlWriter_SetOutput(writer, output);
644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
646 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
649 hr = IXmlWriter_Flush(writer);
650 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
652 CHECK_OUTPUT(stream, prologversion2);
654 IStream_Release(stream);
655 IXmlWriter_Release(writer);
656 IUnknown_Release(output);
659 static void test_flush(void)
661 IXmlWriter *writer;
662 HRESULT hr;
664 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
665 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
667 hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
668 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
670 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
671 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
673 g_write_len = 0;
674 hr = IXmlWriter_Flush(writer);
675 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
676 ok(g_write_len > 0, "Unexpected length %lu.\n", g_write_len);
678 g_write_len = 1;
679 hr = IXmlWriter_Flush(writer);
680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
681 ok(g_write_len == 0, "Unexpected length %lu.\n", g_write_len);
683 /* Release() flushes too */
684 g_write_len = 1;
685 IXmlWriter_Release(writer);
686 ok(g_write_len == 0, "Unexpected length %lu.\n", g_write_len);
689 static void test_omitxmldeclaration(void)
691 static const char prologversion[] = "<?xml version=\"1.0\"?>";
692 IXmlWriter *writer;
693 HGLOBAL hglobal;
694 IStream *stream;
695 HRESULT hr;
696 char *ptr;
698 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
699 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
701 stream = writer_set_output(writer);
703 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
705 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
706 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
708 hr = IXmlWriter_Flush(writer);
709 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
711 hr = GetHGlobalFromStream(stream, &hglobal);
712 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
714 ptr = GlobalLock(hglobal);
715 ok(!ptr, "got %p\n", ptr);
716 GlobalUnlock(hglobal);
718 /* one more time */
719 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
720 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
722 IStream_Release(stream);
724 /* now add PI manually, and try to start a document */
725 stream = writer_set_output(writer);
727 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
728 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
730 hr = IXmlWriter_Flush(writer);
731 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
733 CHECK_OUTPUT(stream, prologversion);
735 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
736 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
738 hr = IXmlWriter_Flush(writer);
739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
741 CHECK_OUTPUT(stream, prologversion);
743 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
744 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
746 hr = IXmlWriter_Flush(writer);
747 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
749 CHECK_OUTPUT(stream, prologversion);
751 /* another attempt to add 'xml' PI */
752 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
753 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
755 hr = IXmlWriter_Flush(writer);
756 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
758 IStream_Release(stream);
759 IXmlWriter_Release(writer);
762 static void test_bom(void)
764 static const WCHAR piW[] = {0xfeff,'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>'};
765 static const WCHAR aopenW[] = {0xfeff,'<','a'};
766 static const WCHAR afullW[] = {0xfeff,'<','a',' ','/','>'};
767 static const WCHAR bomW[] = {0xfeff};
768 IXmlWriterOutput *output;
769 IXmlWriter *writer;
770 IStream *stream;
771 HGLOBAL hglobal;
772 HRESULT hr;
774 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
775 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
777 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
780 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
781 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
783 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
785 hr = IXmlWriter_SetOutput(writer, output);
786 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
788 /* BOM is on by default */
789 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
790 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
792 hr = IXmlWriter_Flush(writer);
793 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
795 CHECK_OUTPUT_RAW(stream, bomW, sizeof(bomW));
797 IStream_Release(stream);
798 IUnknown_Release(output);
800 /* start with PI */
801 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
802 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
804 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
805 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
807 hr = IXmlWriter_SetOutput(writer, output);
808 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
810 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
811 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
813 hr = IXmlWriter_Flush(writer);
814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
816 CHECK_OUTPUT_RAW(stream, piW, sizeof(piW));
818 IUnknown_Release(output);
819 IStream_Release(stream);
821 /* start with element */
822 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
823 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
825 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
826 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
828 hr = IXmlWriter_SetOutput(writer, output);
829 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
831 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
832 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
834 hr = IXmlWriter_Flush(writer);
835 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
837 CHECK_OUTPUT_RAW(stream, aopenW, sizeof(aopenW));
839 IUnknown_Release(output);
840 IStream_Release(stream);
842 /* WriteElementString */
843 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
844 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
846 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
847 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
849 hr = IXmlWriter_SetOutput(writer, output);
850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
852 writer_set_property(writer, XmlWriterProperty_Indent);
854 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, NULL);
855 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
857 hr = IXmlWriter_Flush(writer);
858 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
860 hr = GetHGlobalFromStream(stream, &hglobal);
861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
863 CHECK_OUTPUT_RAW(stream, afullW, sizeof(afullW));
865 IUnknown_Release(output);
866 IStream_Release(stream);
868 IXmlWriter_Release(writer);
871 static void test_WriteStartElement(void)
873 static const struct
875 const WCHAR *prefix;
876 const WCHAR *local;
877 const WCHAR *uri;
878 const char *output;
879 const char *output_partial;
880 HRESULT hr;
881 int todo;
882 int todo_partial;
884 start_element_tests[] =
886 { L"prefix", L"local", L"uri", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local" },
887 { NULL, L"local", L"uri", "<local xmlns=\"uri\" />", "<local" },
888 { L"", L"local", L"uri", "<local xmlns=\"uri\" />", "<local" },
889 { L"", L"local", L"uri", "<local xmlns=\"uri\" />", "<local" },
890 { NULL, L"local", NULL, "<local />", "<local" },
891 { NULL, L"local", L"", "<local />", "<local" },
893 { L"prefix", NULL, NULL, NULL, NULL, E_INVALIDARG },
894 { NULL, NULL, L"uri", NULL, NULL, E_INVALIDARG },
895 { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
896 { NULL, L"prefix:local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
897 { L"pre:fix", L"local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
898 { NULL, L":local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
899 { L":", L"local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
900 { NULL, L"local", L"http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
901 { L"prefix", L"local", L"http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION },
903 IXmlWriter *writer;
904 IStream *stream;
905 unsigned int i;
906 HRESULT hr;
908 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
911 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
912 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
914 stream = writer_set_output(writer);
916 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
917 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
919 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
920 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
922 hr = IXmlWriter_Flush(writer);
923 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
925 CHECK_OUTPUT(stream, "<a");
927 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
928 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
930 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
931 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
933 hr = IXmlWriter_WriteProcessingInstruction(writer, L"a", L"a");
934 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
936 IStream_Release(stream);
937 IXmlWriter_Release(writer);
939 /* WriteElementString */
940 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
941 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
943 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
944 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
946 stream = writer_set_output(writer);
948 hr = IXmlWriter_WriteStartElement(writer, L"prefix", L"a", L"uri");
949 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
951 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
952 ok(hr == S_OK, "Failed to write element string, hr %#lx.\n", hr);
954 hr = IXmlWriter_WriteElementString(writer, NULL, L"c", NULL, NULL);
955 ok(hr == S_OK, "Failed to write element string, hr %#lx.\n", hr);
957 hr = IXmlWriter_WriteStartElement(writer, NULL, L"d", L"uri");
958 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
960 hr = IXmlWriter_WriteStartElement(writer, L"", L"e", L"uri");
961 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
963 hr = IXmlWriter_WriteStartElement(writer, L"prefix2", L"f", L"uri");
964 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
966 hr = IXmlWriter_Flush(writer);
967 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
969 CHECK_OUTPUT(stream,
970 "<prefix:a xmlns:prefix=\"uri\">"
971 "<b>value</b>"
972 "<c />"
973 "<prefix:d>"
974 "<e xmlns=\"uri\">"
975 "<prefix2:f");
977 IStream_Release(stream);
979 /* WriteStartElement */
980 for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i)
982 stream = writer_set_output(writer);
984 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
986 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
987 ok(hr == S_OK, "Failed to start document, hr %#lx.\n", hr);
989 hr = IXmlWriter_WriteStartElement(writer, start_element_tests[i].prefix, start_element_tests[i].local,
990 start_element_tests[i].uri);
991 ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
993 if (SUCCEEDED(start_element_tests[i].hr))
995 hr = IXmlWriter_Flush(writer);
996 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
998 check_output(stream, start_element_tests[i].output_partial, start_element_tests[i].todo_partial, __LINE__);
1000 hr = IXmlWriter_WriteEndDocument(writer);
1001 ok(hr == S_OK, "Failed to end document, hr %#lx.\n", hr);
1003 hr = IXmlWriter_Flush(writer);
1004 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1006 check_output(stream, start_element_tests[i].output, start_element_tests[i].todo, __LINE__);
1009 IStream_Release(stream);
1012 IXmlWriter_Release(writer);
1015 static void test_WriteElementString(void)
1017 static const struct
1019 const WCHAR *prefix;
1020 const WCHAR *local;
1021 const WCHAR *uri;
1022 const WCHAR *value;
1023 const char *output;
1024 HRESULT hr;
1025 int todo;
1027 element_string_tests[] =
1029 { L"prefix", L"local", L"uri", L"value", "<prefix:local xmlns:prefix=\"uri\">value</prefix:local>" },
1030 { NULL, L"local", L"uri", L"value", "<local xmlns=\"uri\">value</local>" },
1031 { L"", L"local", L"uri", L"value", "<local xmlns=\"uri\">value</local>" },
1032 { L"prefix", L"local", L"uri", NULL, "<prefix:local xmlns:prefix=\"uri\" />" },
1033 { NULL, L"local", L"uri", NULL, "<local xmlns=\"uri\" />" },
1034 { L"", L"local", L"uri", NULL, "<local xmlns=\"uri\" />" },
1035 { NULL, L"local", NULL, NULL, "<local />" },
1036 { L"prefix", L"local", L"uri", L"", "<prefix:local xmlns:prefix=\"uri\"></prefix:local>" },
1037 { NULL, L"local", L"uri", L"", "<local xmlns=\"uri\"></local>" },
1038 { L"", L"local", L"uri", L"", "<local xmlns=\"uri\"></local>" },
1039 { NULL, L"local", NULL, L"", "<local></local>" },
1040 { L"", L"local", L"http://www.w3.org/2000/xmlns/", NULL, "<local xmlns=\"http://www.w3.org/2000/xmlns/\" />" },
1042 { L"prefix", NULL, NULL, L"value", NULL, E_INVALIDARG },
1043 { NULL, NULL, L"uri", L"value", NULL, E_INVALIDARG },
1044 { NULL, NULL, NULL, L"value", NULL, E_INVALIDARG },
1045 { NULL, L"prefix:local", L"uri", L"value", NULL, WC_E_NAMECHARACTER },
1046 { NULL, L":local", L"uri", L"value", NULL, WC_E_NAMECHARACTER },
1047 { L":", L"local", L"uri", L"value", NULL, WC_E_NAMECHARACTER },
1048 { L"prefix", L"local", NULL, L"value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1049 { L"prefix", L"local", L"", L"value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1050 { NULL, L"local", L"http://www.w3.org/2000/xmlns/", L"value", NULL, WR_E_XMLNSPREFIXDECLARATION },
1051 { L"prefix", L"local", L"http://www.w3.org/2000/xmlns/", L"value", NULL, WR_E_XMLNSURIDECLARATION },
1053 IXmlWriter *writer;
1054 IStream *stream;
1055 unsigned int i;
1056 HRESULT hr;
1058 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1059 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1061 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
1062 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1064 stream = writer_set_output(writer);
1066 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1067 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1069 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
1070 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1072 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, NULL);
1073 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1075 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"b", L"uri", NULL);
1076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1078 hr = IXmlWriter_WriteStartElement(writer, L"prefix", L"c", L"uri");
1079 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1081 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"d", NULL, NULL);
1082 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1084 hr = IXmlWriter_WriteElementString(writer, L"prefix2", L"d", L"uri", NULL);
1085 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1087 hr = IXmlWriter_WriteElementString(writer, NULL, L"e", L"uri", NULL);
1088 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1090 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"f", L"uri2", NULL);
1091 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1093 hr = IXmlWriter_WriteElementString(writer, NULL, L"g", L"uri3", NULL);
1094 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1096 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"h", NULL, NULL);
1097 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1099 hr = IXmlWriter_WriteElementString(writer, L"prefix_i", L"i", NULL, NULL);
1100 ok(hr == WR_E_NSPREFIXWITHEMPTYNSURI, "Failed to write element, hr %#lx.\n", hr);
1102 hr = IXmlWriter_WriteElementString(writer, L"", L"j", L"uri", NULL);
1103 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1105 hr = IXmlWriter_Flush(writer);
1106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1108 CHECK_OUTPUT(stream,
1109 "<a><b>value</b><b />"
1110 "<prefix:b xmlns:prefix=\"uri\" />"
1111 "<prefix:c xmlns:prefix=\"uri\">"
1112 "<prefix:d />"
1113 "<prefix2:d xmlns:prefix2=\"uri\" />"
1114 "<prefix:e />"
1115 "<prefix:f xmlns:prefix=\"uri2\" />"
1116 "<g xmlns=\"uri3\" />"
1117 "<prefix:h />"
1118 "<j xmlns=\"uri\" />");
1120 IStream_Release(stream);
1122 for (i = 0; i < ARRAY_SIZE(element_string_tests); ++i)
1124 stream = writer_set_output(writer);
1126 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1128 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1129 ok(hr == S_OK, "Failed to start document, hr %#lx.\n", hr);
1131 hr = IXmlWriter_WriteElementString(writer, element_string_tests[i].prefix, element_string_tests[i].local,
1132 element_string_tests[i].uri, element_string_tests[i].value);
1133 ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
1135 if (SUCCEEDED(element_string_tests[i].hr))
1137 hr = IXmlWriter_Flush(writer);
1138 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1140 check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1142 hr = IXmlWriter_WriteEndDocument(writer);
1143 ok(hr == S_OK, "Failed to end document, hr %#lx.\n", hr);
1145 hr = IXmlWriter_Flush(writer);
1146 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1148 check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1151 IStream_Release(stream);
1154 IXmlWriter_Release(writer);
1157 static void test_WriteEndElement(void)
1159 IXmlWriter *writer;
1160 IStream *stream;
1161 HRESULT hr;
1163 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1164 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1166 stream = writer_set_output(writer);
1168 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1169 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1171 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1172 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1174 hr = IXmlWriter_WriteEndElement(writer);
1175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1177 hr = IXmlWriter_WriteEndElement(writer);
1178 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1180 hr = IXmlWriter_Flush(writer);
1181 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1183 CHECK_OUTPUT(stream, "<a><b /></a>");
1185 IXmlWriter_Release(writer);
1186 IStream_Release(stream);
1189 static void test_writeenddocument(void)
1191 IXmlWriter *writer;
1192 IStream *stream;
1193 HGLOBAL hglobal;
1194 HRESULT hr;
1195 char *ptr;
1197 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1198 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1200 hr = IXmlWriter_WriteEndDocument(writer);
1201 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1203 stream = writer_set_output(writer);
1205 /* WriteEndDocument resets it to initial state */
1206 hr = IXmlWriter_WriteEndDocument(writer);
1207 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1209 hr = IXmlWriter_WriteEndDocument(writer);
1210 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1212 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1213 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1215 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1216 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1218 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
1219 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1221 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1222 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1224 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1227 hr = IXmlWriter_WriteEndDocument(writer);
1228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1230 hr = GetHGlobalFromStream(stream, &hglobal);
1231 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1233 ptr = GlobalLock(hglobal);
1234 ok(ptr == NULL, "got %p\n", ptr);
1236 /* we still need to flush manually, WriteEndDocument doesn't do that */
1237 hr = IXmlWriter_Flush(writer);
1238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1240 CHECK_OUTPUT(stream, "<a><b /></a>");
1242 IXmlWriter_Release(writer);
1243 IStream_Release(stream);
1246 static void test_WriteComment(void)
1248 IXmlWriter *writer;
1249 IStream *stream;
1250 HRESULT hr;
1252 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1253 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1255 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1257 hr = IXmlWriter_WriteComment(writer, L"a");
1258 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1260 stream = writer_set_output(writer);
1262 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1263 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1265 hr = IXmlWriter_WriteComment(writer, L"a");
1266 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1268 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1269 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1271 hr = IXmlWriter_WriteComment(writer, L"a");
1272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1274 hr = IXmlWriter_WriteComment(writer, NULL);
1275 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1277 hr = IXmlWriter_WriteComment(writer, L"-->");
1278 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1280 hr = IXmlWriter_Flush(writer);
1281 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1283 CHECK_OUTPUT(stream, "<!--a--><b><!--a--><!----><!--- ->-->");
1285 IXmlWriter_Release(writer);
1286 IStream_Release(stream);
1289 static void test_WriteCData(void)
1291 IXmlWriter *writer;
1292 IStream *stream;
1293 HRESULT hr;
1295 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1296 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1298 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1300 hr = IXmlWriter_WriteCData(writer, L"a");
1301 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1303 stream = writer_set_output(writer);
1305 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1306 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1308 hr = IXmlWriter_WriteCData(writer, L"a");
1309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1311 hr = IXmlWriter_WriteCData(writer, NULL);
1312 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1314 hr = IXmlWriter_WriteCData(writer, L"]]>");
1315 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1317 hr = IXmlWriter_WriteCData(writer, L"a]]>b");
1318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1320 hr = IXmlWriter_Flush(writer);
1321 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1323 CHECK_OUTPUT(stream,
1324 "<b>"
1325 "<![CDATA[a]]>"
1326 "<![CDATA[]]>"
1327 "<![CDATA[]]]]>"
1328 "<![CDATA[>]]>"
1329 "<![CDATA[a]]]]>"
1330 "<![CDATA[>b]]>");
1332 IXmlWriter_Release(writer);
1333 IStream_Release(stream);
1336 static void test_WriteRaw(void)
1338 static const WCHAR rawW[] = L"a<:";
1339 IXmlWriter *writer;
1340 IStream *stream;
1341 HRESULT hr;
1343 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1346 hr = IXmlWriter_WriteRaw(writer, NULL);
1347 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1349 hr = IXmlWriter_WriteRaw(writer, rawW);
1350 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1352 stream = writer_set_output(writer);
1354 hr = IXmlWriter_WriteRaw(writer, NULL);
1355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1357 hr = IXmlWriter_WriteRaw(writer, rawW);
1358 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1360 hr = IXmlWriter_WriteRaw(writer, rawW);
1361 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1363 hr = IXmlWriter_WriteComment(writer, rawW);
1364 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1366 hr = IXmlWriter_WriteRaw(writer, rawW);
1367 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1369 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, L"a");
1370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1372 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
1373 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1375 hr = IXmlWriter_WriteComment(writer, rawW);
1376 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1378 hr = IXmlWriter_WriteEndDocument(writer);
1379 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1381 hr = IXmlWriter_WriteRaw(writer, rawW);
1382 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1384 hr = IXmlWriter_Flush(writer);
1385 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1386 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>a<:a<:<!--a<:-->a<:<a>a</a>");
1387 IStream_Release(stream);
1389 /* With open element. */
1390 stream = writer_set_output(writer);
1392 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
1393 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1394 hr = IXmlWriter_WriteRaw(writer, L"text");
1395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1397 hr = IXmlWriter_Flush(writer);
1398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1399 CHECK_OUTPUT(stream, "<w>text");
1400 IStream_Release(stream);
1402 IXmlWriter_Release(writer);
1405 static void test_writer_state(void)
1407 IXmlWriter *writer;
1408 IStream *stream;
1409 HRESULT hr;
1411 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1412 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1414 /* initial state */
1415 check_writer_state(writer, E_UNEXPECTED);
1417 /* set output and call 'wrong' method, WriteEndElement */
1418 stream = writer_set_output(writer);
1420 hr = IXmlWriter_WriteEndElement(writer);
1421 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1423 check_writer_state(writer, WR_E_INVALIDACTION);
1424 IStream_Release(stream);
1426 /* WriteAttributeString */
1427 stream = writer_set_output(writer);
1429 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"a");
1430 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1432 check_writer_state(writer, WR_E_INVALIDACTION);
1433 IStream_Release(stream);
1435 /* WriteEndDocument */
1436 stream = writer_set_output(writer);
1438 hr = IXmlWriter_WriteEndDocument(writer);
1439 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1441 check_writer_state(writer, WR_E_INVALIDACTION);
1442 IStream_Release(stream);
1444 /* WriteFullEndElement */
1445 stream = writer_set_output(writer);
1447 hr = IXmlWriter_WriteFullEndElement(writer);
1448 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1450 check_writer_state(writer, WR_E_INVALIDACTION);
1451 IStream_Release(stream);
1453 /* WriteCData */
1454 stream = writer_set_output(writer);
1456 hr = IXmlWriter_WriteCData(writer, L"a");
1457 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1459 check_writer_state(writer, WR_E_INVALIDACTION);
1460 IStream_Release(stream);
1462 /* WriteName */
1463 stream = writer_set_output(writer);
1465 hr = IXmlWriter_WriteName(writer, L"a");
1466 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1468 check_writer_state(writer, WR_E_INVALIDACTION);
1469 IStream_Release(stream);
1471 /* WriteNmToken */
1472 stream = writer_set_output(writer);
1474 hr = IXmlWriter_WriteNmToken(writer, L"a");
1475 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1477 check_writer_state(writer, WR_E_INVALIDACTION);
1478 IStream_Release(stream);
1480 /* WriteString */
1481 stream = writer_set_output(writer);
1483 hr = IXmlWriter_WriteString(writer, L"a");
1484 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1486 check_writer_state(writer, WR_E_INVALIDACTION);
1487 IStream_Release(stream);
1489 IXmlWriter_Release(writer);
1492 static void test_indentation(void)
1494 IXmlWriter *writer;
1495 IStream *stream;
1496 HRESULT hr;
1498 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1499 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1501 stream = writer_set_output(writer);
1503 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1504 writer_set_property(writer, XmlWriterProperty_Indent);
1506 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1509 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1510 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1512 hr = IXmlWriter_WriteComment(writer, L"comment");
1513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1515 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1518 hr = IXmlWriter_WriteEndDocument(writer);
1519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1521 hr = IXmlWriter_Flush(writer);
1522 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1524 CHECK_OUTPUT(stream,
1525 "<a>\r\n"
1526 " <!--comment-->\r\n"
1527 " <b />\r\n"
1528 "</a>");
1530 IStream_Release(stream);
1532 /* WriteElementString */
1533 stream = writer_set_output(writer);
1535 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1536 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1538 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, NULL);
1539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1541 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, NULL);
1542 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1544 hr = IXmlWriter_WriteEndElement(writer);
1545 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1547 hr = IXmlWriter_Flush(writer);
1548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1550 CHECK_OUTPUT(stream,
1551 "<a>\r\n"
1552 " <b />\r\n"
1553 " <b />\r\n"
1554 "</a>");
1556 IStream_Release(stream);
1558 IXmlWriter_Release(writer);
1561 static void test_WriteAttributeString(void)
1563 static const struct
1565 const WCHAR *prefix;
1566 const WCHAR *local;
1567 const WCHAR *uri;
1568 const WCHAR *value;
1569 const char *output;
1570 const char *output_partial;
1571 HRESULT hr;
1572 int todo;
1573 int todo_partial;
1574 int todo_hr;
1576 attribute_tests[] =
1578 { NULL, L"a", NULL, L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1579 { L"", L"a", NULL, L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1580 { NULL, L"a", L"", L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1581 { L"", L"a", L"", L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1582 { L"prefix", L"local", L"uri", L"b", "<e prefix:local=\"b\" xmlns:prefix=\"uri\" />", "<e prefix:local=\"b\"" },
1583 { NULL, L"a", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e xmlns:a=\"defuri\" />", "<e xmlns:a=\"defuri\"" },
1584 { L"xmlns", L"a", NULL, L"uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1585 { L"xmlns", L"a", L"", L"uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1586 { L"prefix", L"xmlns", L"uri", L"value", "<e prefix:xmlns=\"value\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"value\"" },
1587 { L"prefix", L"xmlns", L"uri", NULL, "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1588 { L"prefix", L"xmlns", L"uri", L"", "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1589 { L"prefix", L"xmlns", NULL, L"uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1590 { L"prefix", L"xmlns", L"", L"uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1591 { L"xml", L"space", NULL, L"preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1592 { L"xml", L"space", L"", L"preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1593 { L"xml", L"space", NULL, L"default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1594 { L"xml", L"space", L"", L"default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1595 { L"xml", L"a", NULL, L"value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1596 { L"xml", L"a", L"", L"value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1598 /* Autogenerated prefix names. */
1599 { NULL, L"a", L"defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1600 { NULL, L"a", L"defuri", L"b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1601 { L"", L"a", L"defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1602 { NULL, L"a", L"defuri", L"", "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1603 { L"", L"a", L"defuri", L"b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1605 /* Failing cases. */
1606 { NULL, NULL, L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1607 { L"", L"a", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 1, 1, 1 },
1608 { L"", NULL, L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1609 { L"", L"", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1610 { NULL, L"", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1611 { L"prefix", L"a", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION, 1, 1, 1 },
1612 { L"prefix", NULL, L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1613 { L"prefix", NULL, NULL, L"b", "<e />", "<e", E_INVALIDARG },
1614 { L"prefix", NULL, L"uri", NULL, "<e />", "<e", E_INVALIDARG },
1615 { L"xml", NULL, NULL, L"value", "<e />", "<e", E_INVALIDARG },
1616 { L"xmlns", L"a", L"defuri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1617 { L"xmlns", L"a", L"b", L"uri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1618 { NULL, L"xmlns", L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1619 { L"xmlns", NULL, L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1620 { L"pre:fix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER },
1621 { L"pre:fix", NULL, L"uri", L"b", "<e />", "<e", E_INVALIDARG },
1622 { L"prefix", L"lo:cal", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER },
1623 { L"xmlns", NULL, NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1624 { L"xmlns", NULL, L"", L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1625 { L"xmlns", L"", NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1626 { L"xmlns", L"", L"", L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1627 { L"xml", L"space", L"", L"value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1628 { L"xml", L"space", NULL, L"value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1629 { L"xml", L"a", L"uri", L"value", "<e />", "<e", WR_E_XMLPREFIXDECLARATION },
1630 { L"xml", L"space", NULL, L"preServe", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1631 { L"xml", L"space", NULL, L"defAult", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1632 { L"xml", L"space", NULL, NULL, "<e />", "<e", WR_E_INVALIDXMLSPACE },
1633 { L"xml", L"space", NULL, L"", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1636 IXmlWriter *writer;
1637 IStream *stream;
1638 unsigned int i;
1639 HRESULT hr;
1641 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1644 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1646 for (i = 0; i < ARRAY_SIZE(attribute_tests); ++i)
1648 winetest_push_context("Test %u", i);
1650 stream = writer_set_output(writer);
1652 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1653 ok(hr == S_OK, "Failed to start document, hr %#lx.\n", hr);
1655 hr = IXmlWriter_WriteStartElement(writer, NULL, L"e", NULL);
1656 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1658 hr = IXmlWriter_WriteAttributeString(writer, attribute_tests[i].prefix, attribute_tests[i].local,
1659 attribute_tests[i].uri, attribute_tests[i].value);
1660 todo_wine_if(attribute_tests[i].todo_hr)
1661 ok(hr == attribute_tests[i].hr, "Unexpected hr %#lx, expected %#lx.\n", hr, attribute_tests[i].hr);
1663 hr = IXmlWriter_Flush(writer);
1664 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1666 check_output(stream, attribute_tests[i].output_partial, attribute_tests[i].todo_partial, __LINE__);
1668 hr = IXmlWriter_WriteEndDocument(writer);
1669 ok(hr == S_OK, "Failed to end document, hr %#lx.\n", hr);
1671 hr = IXmlWriter_Flush(writer);
1672 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1674 check_output(stream, attribute_tests[i].output, attribute_tests[i].todo, __LINE__);
1675 IStream_Release(stream);
1677 winetest_pop_context();
1680 /* With namespaces */
1681 stream = writer_set_output(writer);
1683 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1684 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1686 hr = IXmlWriter_WriteStartElement(writer, L"p", L"a", L"outeruri");
1687 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1689 hr = IXmlWriter_WriteAttributeString(writer, L"prefix", L"local", L"uri", L"b");
1690 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1692 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"b");
1693 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1695 hr = IXmlWriter_WriteAttributeString(writer, L"xmlns", L"prefix", NULL, L"uri");
1696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1698 hr = IXmlWriter_WriteAttributeString(writer, L"p", L"attr", NULL, L"value");
1699 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
1701 hr = IXmlWriter_WriteAttributeString(writer, L"prefix", L"local", NULL, L"b");
1702 todo_wine
1703 ok(hr == WR_E_DUPLICATEATTRIBUTE, "Unexpected hr %#lx.\n", hr);
1705 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1706 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1708 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"attr2", L"outeruri", L"value");
1709 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
1711 hr = IXmlWriter_WriteAttributeString(writer, L"pr", L"attr3", L"outeruri", L"value");
1712 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
1714 hr = IXmlWriter_WriteEndDocument(writer);
1715 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1717 hr = IXmlWriter_Flush(writer);
1718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1720 CHECK_OUTPUT_TODO(stream,
1721 "<p:a prefix:local=\"b\" a=\"b\" xmlns:prefix=\"uri\" p:attr=\"value\" xmlns:p=\"outeruri\">"
1722 "<b p:attr2=\"value\" pr:attr3=\"value\" xmlns:pr=\"outeruri\" />"
1723 "</p:a>");
1725 IStream_Release(stream);
1727 /* Define prefix, write attribute with it. */
1728 stream = writer_set_output(writer);
1730 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1731 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1733 hr = IXmlWriter_WriteStartElement(writer, NULL, L"e", NULL);
1734 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1736 hr = IXmlWriter_WriteAttributeString(writer, L"xmlns", L"prefix", NULL, L"uri");
1737 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1739 hr = IXmlWriter_WriteAttributeString(writer, L"prefix", L"attr", NULL, L"value");
1740 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1742 hr = IXmlWriter_WriteEndDocument(writer);
1743 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1745 hr = IXmlWriter_Flush(writer);
1746 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1748 CHECK_OUTPUT(stream,
1749 "<e xmlns:prefix=\"uri\" prefix:attr=\"value\" />");
1751 IStream_Release(stream);
1753 IXmlWriter_Release(writer);
1756 static void test_WriteFullEndElement(void)
1758 IXmlWriter *writer;
1759 IStream *stream;
1760 HRESULT hr;
1762 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1763 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1765 /* standalone element */
1766 stream = writer_set_output(writer);
1768 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1769 writer_set_property(writer, XmlWriterProperty_Indent);
1771 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1774 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1775 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1777 hr = IXmlWriter_WriteFullEndElement(writer);
1778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1780 hr = IXmlWriter_WriteEndDocument(writer);
1781 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1783 hr = IXmlWriter_Flush(writer);
1784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1786 CHECK_OUTPUT(stream,
1787 "<a></a>");
1788 IStream_Release(stream);
1790 /* nested elements */
1791 stream = writer_set_output(writer);
1793 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1794 writer_set_property(writer, XmlWriterProperty_Indent);
1796 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1797 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1799 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1802 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1803 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1805 hr = IXmlWriter_WriteFullEndElement(writer);
1806 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1808 hr = IXmlWriter_WriteEndDocument(writer);
1809 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1811 hr = IXmlWriter_Flush(writer);
1812 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1814 CHECK_OUTPUT(stream,
1815 "<a>\r\n"
1816 " <a></a>\r\n"
1817 "</a>");
1818 IStream_Release(stream);
1820 /* Empty strings for prefix and uri. */
1821 stream = writer_set_output(writer);
1823 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_Indent, FALSE);
1824 ok(hr == S_OK, "Failed to set property, hr %#lx.\n", hr);
1826 hr = IXmlWriter_WriteStartElement(writer, L"", L"a", NULL);
1827 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1828 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", L"");
1829 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1830 hr = IXmlWriter_WriteStartElement(writer, L"", L"c", L"");
1831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1832 hr = IXmlWriter_WriteFullEndElement(writer);
1833 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1834 hr = IXmlWriter_WriteFullEndElement(writer);
1835 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1836 hr = IXmlWriter_WriteFullEndElement(writer);
1837 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1839 hr = IXmlWriter_Flush(writer);
1840 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1841 CHECK_OUTPUT(stream, "<a><b><c></c></b></a>");
1842 IStream_Release(stream);
1844 IXmlWriter_Release(writer);
1847 static void test_WriteCharEntity(void)
1849 IXmlWriter *writer;
1850 IStream *stream;
1851 HRESULT hr;
1853 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1854 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1856 /* without indentation */
1857 stream = writer_set_output(writer);
1859 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1861 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1862 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1864 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1865 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1867 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
1868 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1870 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1873 hr = IXmlWriter_WriteEndDocument(writer);
1874 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1876 hr = IXmlWriter_Flush(writer);
1877 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1879 CHECK_OUTPUT(stream,
1880 "<a>&#x100;<a /></a>");
1882 IXmlWriter_Release(writer);
1883 IStream_Release(stream);
1886 static void test_WriteString(void)
1888 IXmlWriter *writer;
1889 IStream *stream;
1890 HRESULT hr;
1892 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1893 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1895 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1897 hr = IXmlWriter_WriteString(writer, L"a");
1898 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1900 hr = IXmlWriter_WriteString(writer, NULL);
1901 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1903 hr = IXmlWriter_WriteString(writer, L"");
1904 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1906 stream = writer_set_output(writer);
1908 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1911 hr = IXmlWriter_WriteString(writer, NULL);
1912 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1914 hr = IXmlWriter_WriteString(writer, L"");
1915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1917 hr = IXmlWriter_WriteString(writer, L"a");
1918 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1920 /* WriteString automatically escapes markup characters */
1921 hr = IXmlWriter_WriteString(writer, L"<&\">=");
1922 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1924 hr = IXmlWriter_Flush(writer);
1925 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1927 CHECK_OUTPUT(stream,
1928 "<b>a&lt;&amp;\"&gt;=");
1929 IStream_Release(stream);
1931 stream = writer_set_output(writer);
1933 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1934 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1936 hr = IXmlWriter_WriteString(writer, NULL);
1937 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1939 hr = IXmlWriter_Flush(writer);
1940 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1942 CHECK_OUTPUT(stream,
1943 "<b");
1945 hr = IXmlWriter_WriteString(writer, L"");
1946 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1948 hr = IXmlWriter_Flush(writer);
1949 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1951 CHECK_OUTPUT(stream,
1952 "<b>");
1954 IStream_Release(stream);
1955 IXmlWriter_Release(writer);
1957 /* With indentation */
1958 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
1959 ok(hr == S_OK, "Failed to create a writer, hr %#lx.\n", hr);
1961 stream = writer_set_output(writer);
1963 writer_set_property(writer, XmlWriterProperty_Indent);
1965 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1966 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1968 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1969 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1971 hr = IXmlWriter_WriteString(writer, L"text");
1972 ok(hr == S_OK, "Failed to write a string, hr %#lx.\n", hr);
1974 hr = IXmlWriter_Flush(writer);
1975 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1977 CHECK_OUTPUT(stream,
1978 "<a>\r\n"
1979 " <b>text");
1981 hr = IXmlWriter_WriteFullEndElement(writer);
1982 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
1984 hr = IXmlWriter_Flush(writer);
1985 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1987 CHECK_OUTPUT(stream,
1988 "<a>\r\n"
1989 " <b>text</b>");
1991 hr = IXmlWriter_WriteFullEndElement(writer);
1992 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
1994 hr = IXmlWriter_Flush(writer);
1995 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1997 CHECK_OUTPUT(stream,
1998 "<a>\r\n"
1999 " <b>text</b>\r\n"
2000 "</a>");
2002 IStream_Release(stream);
2004 stream = writer_set_output(writer);
2006 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
2007 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
2009 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
2010 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
2012 hr = IXmlWriter_WriteEndElement(writer);
2013 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2015 hr = IXmlWriter_Flush(writer);
2016 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2018 CHECK_OUTPUT(stream,
2019 "<a>\r\n"
2020 " <b />");
2022 hr = IXmlWriter_WriteStartElement(writer, NULL, L"c", NULL);
2023 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
2025 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"attr", NULL, L"value");
2026 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
2028 hr = IXmlWriter_Flush(writer);
2029 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2031 CHECK_OUTPUT(stream,
2032 "<a>\r\n"
2033 " <b />\r\n"
2034 " <c attr=\"value\"");
2036 hr = IXmlWriter_WriteString(writer, L"text");
2037 ok(hr == S_OK, "Failed to write a string, hr %#lx.\n", hr);
2039 hr = IXmlWriter_Flush(writer);
2040 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2042 CHECK_OUTPUT(stream,
2043 "<a>\r\n"
2044 " <b />\r\n"
2045 " <c attr=\"value\">text");
2047 hr = IXmlWriter_WriteEndElement(writer);
2048 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2050 hr = IXmlWriter_Flush(writer);
2051 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2053 CHECK_OUTPUT(stream,
2054 "<a>\r\n"
2055 " <b />\r\n"
2056 " <c attr=\"value\">text</c>");
2058 hr = IXmlWriter_WriteStartElement(writer, NULL, L"d", NULL);
2059 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
2061 hr = IXmlWriter_WriteString(writer, L"");
2062 ok(hr == S_OK, "Failed to write a string, hr %#lx.\n", hr);
2064 hr = IXmlWriter_WriteEndElement(writer);
2065 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2067 hr = IXmlWriter_Flush(writer);
2068 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2070 CHECK_OUTPUT(stream,
2071 "<a>\r\n"
2072 " <b />\r\n"
2073 " <c attr=\"value\">text</c>\r\n"
2074 " <d></d>");
2076 hr = IXmlWriter_WriteEndElement(writer);
2077 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2079 hr = IXmlWriter_Flush(writer);
2080 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2082 CHECK_OUTPUT(stream,
2083 "<a>\r\n"
2084 " <b />\r\n"
2085 " <c attr=\"value\">text</c>\r\n"
2086 " <d></d>\r\n"
2087 "</a>");
2089 IXmlWriter_Release(writer);
2090 IStream_Release(stream);
2093 static void test_WriteDocType(void)
2095 static const struct
2097 const WCHAR *name;
2098 const WCHAR *pubid;
2099 const WCHAR *sysid;
2100 const WCHAR *subset;
2101 const char *output;
2103 doctype_tests[] =
2105 { L"a", L"", NULL, NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2106 { L"a", NULL, NULL, NULL, "<!DOCTYPE a>" },
2107 { L"a", NULL, L"", NULL, "<!DOCTYPE a SYSTEM \"\">" },
2108 { L"a", L"", L"", NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2109 { L"a", L"pubid", L"", NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2110 { L"a", L"pubid", NULL, NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2111 { L"a", L"", L"sysid", NULL, "<!DOCTYPE a PUBLIC \"\" \"sysid\">" },
2112 { L"a", NULL, NULL, L"", "<!DOCTYPE a []>" },
2113 { L"a", NULL, NULL, L"subset", "<!DOCTYPE a [subset]>" },
2114 { L"a", L"", NULL, L"subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2115 { L"a", NULL, L"", L"subset", "<!DOCTYPE a SYSTEM \"\" [subset]>" },
2116 { L"a", L"", L"", L"subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2117 { L"a", L"pubid", NULL, L"subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2118 { L"a", L"pubid", L"", L"subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2119 { L"a", NULL, L"sysid", L"subset", "<!DOCTYPE a SYSTEM \"sysid\" [subset]>" },
2120 { L"a", L"", L"sysid", L"subset", "<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
2121 { L"a", L"pubid", L"sysid", L"subset", "<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
2123 static const WCHAR pubidW[] = {'p',0x100,'i','d',0};
2124 IXmlWriter *writer;
2125 IStream *stream;
2126 unsigned int i;
2127 HRESULT hr;
2129 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2130 ok(hr == S_OK, "Failed to create writer instance, hr %#lx.\n", hr);
2132 stream = writer_set_output(writer);
2134 hr = IXmlWriter_WriteDocType(writer, NULL, NULL, NULL, NULL);
2135 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2137 hr = IXmlWriter_WriteDocType(writer, L"", NULL, NULL, NULL);
2138 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2140 /* Name validation. */
2141 hr = IXmlWriter_WriteDocType(writer, L"-a", NULL, NULL, NULL);
2142 ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr);
2144 /* Pubid validation. */
2145 hr = IXmlWriter_WriteDocType(writer, L"a", pubidW, NULL, NULL);
2146 ok(hr == WC_E_PUBLICID, "Unexpected hr %#lx.\n", hr);
2148 /* Invalid multi-character string */
2149 hr = IXmlWriter_WriteDocType(writer, L":ax>m", NULL, NULL, NULL);
2150 ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr);
2152 /* Valid multi-character string */
2153 hr = IXmlWriter_WriteDocType(writer, L"root", NULL, NULL, NULL);
2154 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2156 IStream_Release(stream);
2158 for (i = 0; i < ARRAY_SIZE(doctype_tests); i++)
2160 stream = writer_set_output(writer);
2162 hr = IXmlWriter_WriteDocType(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2163 doctype_tests[i].subset);
2164 ok(hr == S_OK, "%u: failed to write doctype, hr %#lx.\n", i, hr);
2166 hr = IXmlWriter_Flush(writer);
2167 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2169 CHECK_OUTPUT(stream, doctype_tests[i].output);
2171 hr = IXmlWriter_WriteDocType(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2172 doctype_tests[i].subset);
2173 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
2175 IStream_Release(stream);
2178 IXmlWriter_Release(writer);
2181 static void test_WriteWhitespace(void)
2183 IXmlWriter *writer;
2184 IStream *stream;
2185 HRESULT hr;
2187 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2188 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2190 stream = writer_set_output(writer);
2192 hr = IXmlWriter_WriteWhitespace(writer, L" ");
2193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2194 hr = IXmlWriter_WriteWhitespace(writer, L"ab");
2195 ok(hr == WR_E_NONWHITESPACE, "Unexpected hr %#lx.\n", hr);
2196 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2197 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2198 hr = IXmlWriter_WriteWhitespace(writer, L"\t");
2199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2201 hr = IXmlWriter_Flush(writer);
2202 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2203 CHECK_OUTPUT(stream, " <w>\t");
2204 IStream_Release(stream);
2206 IXmlWriter_Release(writer);
2209 static void test_WriteProcessingInstruction(void)
2211 IXmlWriter *writer;
2212 IStream *stream;
2213 HRESULT hr;
2215 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2218 stream = writer_set_output(writer);
2220 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2221 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2222 hr = IXmlWriter_WriteProcessingInstruction(writer, L"pi", L"content");
2223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2225 hr = IXmlWriter_Flush(writer);
2226 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2227 CHECK_OUTPUT(stream, "<w><?pi content?>");
2228 IStream_Release(stream);
2230 IXmlWriter_Release(writer);
2233 static void test_WriteAttributes(void)
2235 XmlNodeType node_type;
2236 IXmlWriter *writer;
2237 IXmlReader *reader;
2238 const WCHAR *name;
2239 IStream *stream;
2240 HRESULT hr;
2242 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2243 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2245 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2246 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2248 /* No attributes. */
2249 reader_set_input(reader, "<a/>");
2250 stream = writer_set_output(writer);
2251 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2252 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
2253 hr = IXmlReader_Read(reader, NULL);
2254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2255 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2256 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2257 hr = IXmlWriter_Flush(writer);
2258 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2259 CHECK_OUTPUT(stream, "");
2260 IStream_Release(stream);
2262 /* Position on element with attributes. */
2263 reader_set_input(reader, "<a attr1=\'b\' attr2=\'c\' attr3=\'d\' />");
2264 stream = writer_set_output(writer);
2265 hr = IXmlReader_Read(reader, NULL);
2266 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2267 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2269 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2270 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2271 hr = IXmlReader_GetNodeType(reader, &node_type);
2272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2273 ok(node_type == XmlNodeType_Element, "Unexpected node type %d.\n", node_type);
2274 hr = IXmlWriter_Flush(writer);
2275 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2276 CHECK_OUTPUT(stream, "<w attr1=\"b\" attr2=\"c\" attr3=\"d\"");
2277 IStream_Release(stream);
2279 /* Position on second attribute. */
2280 hr = IXmlReader_MoveToAttributeByName(reader, L"attr2", NULL);
2281 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2282 stream = writer_set_output(writer);
2283 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2284 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2285 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2287 hr = IXmlReader_GetNodeType(reader, &node_type);
2288 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2289 ok(node_type == XmlNodeType_Attribute, "Unexpected node type %d.\n", node_type);
2290 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2291 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2292 ok(!wcscmp(name, L"attr3"), "Unexpected node %s.\n", debugstr_w(name));
2293 hr = IXmlWriter_Flush(writer);
2294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2295 CHECK_OUTPUT(stream, "<w attr2=\"c\" attr3=\"d\"");
2296 IStream_Release(stream);
2298 IXmlWriter_Release(writer);
2299 IXmlReader_Release(reader);
2302 static void test_WriteNode(void)
2304 static const struct
2306 const char *input;
2307 const char *output;
2308 XmlNodeType node_type;
2310 write_node_tests[] =
2312 { "<r><!-- comment --></r>", "<w><!-- comment -->", XmlNodeType_Comment },
2313 { "<r>text</r>", "<w>text", XmlNodeType_Text },
2314 { "<r> </r>", "<w> ", XmlNodeType_Whitespace },
2315 { "<r><![CDATA[ cdata ]]></r>", "<w><![CDATA[ cdata ]]>", XmlNodeType_CDATA },
2316 { "<r><?pi pidata ?></r>", "<w><?pi pidata ?>", XmlNodeType_ProcessingInstruction },
2317 { "<r><e1><e2 attr1=\'a\'/></e1></r>", "<w><e1><e2 attr1=\"a\" /></e1>", XmlNodeType_Element },
2318 { "<r><e1/></r>", "<w><e1 />", XmlNodeType_Element },
2319 { "<r></r>", "<w></w>", XmlNodeType_EndElement },
2321 XmlNodeType node_type;
2322 IXmlWriter *writer;
2323 IXmlReader *reader;
2324 const WCHAR *name;
2325 IStream *stream;
2326 unsigned int i;
2327 HRESULT hr;
2329 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2330 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2332 hr = IXmlWriter_WriteNode(writer, NULL, FALSE);
2333 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2335 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2336 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2338 for (i = 0; i < ARRAY_SIZE(write_node_tests); ++i)
2340 winetest_push_context("Test %s", debugstr_a(write_node_tests[i].input));
2342 stream = writer_set_output(writer);
2343 reader_set_input(reader, write_node_tests[i].input);
2345 /* Skip top level element. */
2346 hr = IXmlReader_Read(reader, &node_type);
2347 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2349 hr = IXmlReader_Read(reader, &node_type);
2350 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2351 ok(node_type == write_node_tests[i].node_type, "Unexpected node type %d.\n", node_type);
2353 /* Always write a root node to give a valid context for following nodes. */
2354 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2356 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2357 ok(SUCCEEDED(hr), "Failed to write a node, hr %#lx.\n", hr);
2359 if (hr == S_OK)
2361 hr = IXmlReader_GetNodeType(reader, &node_type);
2362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2363 ok(node_type == XmlNodeType_EndElement, "Unexpected node type on return %d.\n", node_type);
2364 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2365 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2366 ok(!wcscmp(name, L"r"), "Unexpected node name %s.\n", debugstr_w(name));
2369 hr = IXmlWriter_Flush(writer);
2370 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2372 CHECK_OUTPUT(stream, write_node_tests[i].output);
2374 IStream_Release(stream);
2376 winetest_pop_context();
2379 /* Current node is an attribute. */
2380 reader_set_input(reader, "<a attr=\'b\' ></a>");
2381 hr = IXmlReader_Read(reader, &node_type);
2382 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2383 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2384 hr = IXmlReader_MoveToFirstAttribute(reader);
2385 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2387 stream = writer_set_output(writer);
2388 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2389 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2390 hr = IXmlReader_GetNodeType(reader, &node_type);
2391 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2392 ok(node_type == XmlNodeType_EndElement, "Unexpected node type on return %d.\n", node_type);
2393 hr = IXmlWriter_Flush(writer);
2394 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2395 CHECK_OUTPUT(stream, "");
2396 IStream_Release(stream);
2398 /* Xml declaration node. */
2399 reader_set_input(reader, "<?xml version=\"1.0\" ?><a/>");
2400 hr = IXmlReader_Read(reader, &node_type);
2401 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2402 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2404 stream = writer_set_output(writer);
2405 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2406 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2407 hr = IXmlReader_GetNodeType(reader, &node_type);
2408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2409 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2410 hr = IXmlWriter_Flush(writer);
2411 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2412 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
2413 IStream_Release(stream);
2415 /* With standalone attribute. */
2416 reader_set_input(reader, "<?xml version=\"1.0\" standalone=\'yes\'?><a/>");
2417 hr = IXmlReader_Read(reader, &node_type);
2418 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2419 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2421 stream = writer_set_output(writer);
2422 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2423 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2424 hr = IXmlReader_GetNodeType(reader, &node_type);
2425 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2426 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2427 hr = IXmlWriter_Flush(writer);
2428 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2429 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
2430 IStream_Release(stream);
2432 /* Initial state. */
2433 reader_set_input(reader, "<?xml version=\"1.0\" ?><a><b/></a>");
2434 hr = IXmlReader_GetNodeType(reader, &node_type);
2435 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2436 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2437 stream = writer_set_output(writer);
2438 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2439 ok(hr == S_FALSE, "Failed to write a node, hr %#lx.\n", hr);
2440 node_type = XmlNodeType_Element;
2441 hr = IXmlReader_GetNodeType(reader, &node_type);
2442 todo_wine
2443 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
2444 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2445 hr = IXmlWriter_Flush(writer);
2446 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2447 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><a><b /></a>");
2448 IStream_Release(stream);
2450 IXmlReader_Release(reader);
2451 IXmlWriter_Release(writer);
2454 static void test_WriteNodeShallow(void)
2456 static const struct
2458 const char *input;
2459 const char *output;
2460 XmlNodeType node_type;
2462 write_node_tests[] =
2464 { "<r><!-- comment --></r>", "<w><!-- comment -->", XmlNodeType_Comment },
2465 { "<r>text</r>", "<w>text", XmlNodeType_Text },
2466 { "<r> </r>", "<w> ", XmlNodeType_Whitespace },
2467 { "<r><![CDATA[ cdata ]]></r>", "<w><![CDATA[ cdata ]]>", XmlNodeType_CDATA },
2468 { "<r><?pi pidata ?></r>", "<w><?pi pidata ?>", XmlNodeType_ProcessingInstruction },
2469 { "<r><e1><e2 attr1=\'a\'/></e1></r>", "<w><e1", XmlNodeType_Element },
2470 { "<r><e1/></r>", "<w><e1 />", XmlNodeType_Element },
2471 { "<r><e1 attr1=\'a\'/></r>", "<w><e1 attr1=\"a\" />", XmlNodeType_Element },
2472 { "<r><e1 attr1=\'a\'></e1></r>", "<w><e1 attr1=\"a\"", XmlNodeType_Element },
2473 { "<r></r>", "<w></w>", XmlNodeType_EndElement },
2475 XmlNodeType node_type;
2476 IXmlWriter *writer;
2477 IXmlReader *reader;
2478 IStream *stream;
2479 unsigned int i;
2480 HRESULT hr;
2482 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2483 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2485 hr = IXmlWriter_WriteNodeShallow(writer, NULL, FALSE);
2486 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2488 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2491 for (i = 0; i < ARRAY_SIZE(write_node_tests); ++i)
2493 winetest_push_context("Test %s", debugstr_a(write_node_tests[i].input));
2495 stream = writer_set_output(writer);
2496 reader_set_input(reader, write_node_tests[i].input);
2498 /* Skip top level element. */
2499 hr = IXmlReader_Read(reader, &node_type);
2500 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2502 hr = IXmlReader_Read(reader, &node_type);
2503 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2504 ok(node_type == write_node_tests[i].node_type, "Unexpected node type %d.\n", node_type);
2506 /* Always write a root node to give a valid context for following nodes. */
2507 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2509 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2510 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2512 hr = IXmlReader_GetNodeType(reader, &node_type);
2513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2514 ok(node_type == write_node_tests[i].node_type, "Unexpected node type on return %d.\n", node_type);
2516 hr = IXmlWriter_Flush(writer);
2517 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2519 CHECK_OUTPUT(stream, write_node_tests[i].output);
2521 IStream_Release(stream);
2523 winetest_pop_context();
2526 /* Current node is an attribute. */
2527 reader_set_input(reader, "<a attr=\'b\' ></a>");
2528 hr = IXmlReader_Read(reader, &node_type);
2529 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2530 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2531 hr = IXmlReader_MoveToFirstAttribute(reader);
2532 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2534 stream = writer_set_output(writer);
2535 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2536 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2537 hr = IXmlReader_GetNodeType(reader, &node_type);
2538 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2539 ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type);
2540 hr = IXmlWriter_Flush(writer);
2541 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2542 CHECK_OUTPUT(stream, "");
2543 IStream_Release(stream);
2545 /* Xml declaration node. */
2546 reader_set_input(reader, "<?xml version=\"1.0\" ?><a/>");
2547 hr = IXmlReader_Read(reader, &node_type);
2548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2549 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2551 stream = writer_set_output(writer);
2552 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2553 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2554 hr = IXmlReader_GetNodeType(reader, &node_type);
2555 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2556 ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type);
2557 hr = IXmlWriter_Flush(writer);
2558 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2559 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
2560 IStream_Release(stream);
2562 /* With standalone attribute. */
2563 reader_set_input(reader, "<?xml version=\"1.0\" standalone=\'yes\'?><a/>");
2564 hr = IXmlReader_Read(reader, &node_type);
2565 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2566 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2568 stream = writer_set_output(writer);
2569 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2570 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2571 hr = IXmlReader_GetNodeType(reader, &node_type);
2572 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2573 ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type);
2574 hr = IXmlWriter_Flush(writer);
2575 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2576 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
2577 IStream_Release(stream);
2579 /* Initial state. */
2580 reader_set_input(reader, "<?xml version=\"1.0\" ?><a><b/></a>");
2581 hr = IXmlReader_GetNodeType(reader, &node_type);
2582 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2583 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2584 stream = writer_set_output(writer);
2585 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2586 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2587 node_type = XmlNodeType_Element;
2588 hr = IXmlReader_GetNodeType(reader, &node_type);
2589 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2590 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2591 hr = IXmlWriter_Flush(writer);
2592 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2593 CHECK_OUTPUT(stream, "");
2594 IStream_Release(stream);
2596 IXmlReader_Release(reader);
2597 IXmlWriter_Release(writer);
2600 START_TEST(writer)
2602 test_writer_create();
2603 test_writer_state();
2604 test_writeroutput();
2605 test_writestartdocument();
2606 test_WriteStartElement();
2607 test_WriteElementString();
2608 test_WriteEndElement();
2609 test_flush();
2610 test_omitxmldeclaration();
2611 test_bom();
2612 test_writeenddocument();
2613 test_WriteComment();
2614 test_WriteCData();
2615 test_WriteRaw();
2616 test_indentation();
2617 test_WriteAttributeString();
2618 test_WriteFullEndElement();
2619 test_WriteCharEntity();
2620 test_WriteString();
2621 test_WriteDocType();
2622 test_WriteWhitespace();
2623 test_WriteProcessingInstruction();
2624 test_WriteAttributes();
2625 test_WriteNode();
2626 test_WriteNodeShallow();