xmllite/writer: Implement WriteNodeShallow().
[wine.git] / dlls / xmllite / tests / writer.c
blob25dc9e3b8c1a4398e29838fe77e3d7e47dbb1692
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 HRESULT hr;
141 /* FIXME: add WriteAttributes */
143 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"a");
144 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
146 hr = IXmlWriter_WriteCData(writer, L"a");
147 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
149 hr = IXmlWriter_WriteCharEntity(writer, 'a');
150 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
152 hr = IXmlWriter_WriteChars(writer, L"a", 1);
153 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
155 hr = IXmlWriter_WriteComment(writer, L"a");
156 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
158 hr = IXmlWriter_WriteDocType(writer, L"a", NULL, NULL, NULL);
159 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
161 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, L"a");
162 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
164 hr = IXmlWriter_WriteEndDocument(writer);
165 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
167 hr = IXmlWriter_WriteEndElement(writer);
168 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
170 hr = IXmlWriter_WriteEntityRef(writer, L"a");
171 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
173 hr = IXmlWriter_WriteFullEndElement(writer);
174 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
176 hr = IXmlWriter_WriteName(writer, L"a");
177 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
179 hr = IXmlWriter_WriteNmToken(writer, L"a");
180 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
182 /* FIXME: add WriteNode */
183 /* FIXME: add WriteNodeShallow */
185 hr = IXmlWriter_WriteProcessingInstruction(writer, L"a", L"a");
186 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
188 hr = IXmlWriter_WriteQualifiedName(writer, L"a", NULL);
189 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
191 hr = IXmlWriter_WriteRaw(writer, L"a");
192 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
194 hr = IXmlWriter_WriteRawChars(writer, L"a", 1);
195 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
197 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
198 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
200 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
201 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
203 hr = IXmlWriter_WriteString(writer, L"a");
204 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
206 /* FIXME: add WriteSurrogateCharEntity */
208 hr = IXmlWriter_WriteWhitespace(writer, L" ");
209 ok(hr == exp_hr, "Unexpected hr %#lx, expected %#lx.\n", hr, exp_hr);
212 static IStream *writer_set_output(IXmlWriter *writer)
214 IStream *stream;
215 HRESULT hr;
217 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
218 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
220 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
221 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
223 return stream;
226 static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
228 if (IsEqualGUID(riid, &IID_IUnknown)) {
229 *obj = iface;
230 return S_OK;
232 else {
233 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
234 return E_NOINTERFACE;
238 static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
240 return 2;
243 static ULONG WINAPI testoutput_Release(IUnknown *iface)
245 return 1;
248 static const IUnknownVtbl testoutputvtbl = {
249 testoutput_QueryInterface,
250 testoutput_AddRef,
251 testoutput_Release
254 static IUnknown testoutput = { &testoutputvtbl };
256 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
258 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
260 *obj = iface;
261 return S_OK;
264 *obj = NULL;
265 return E_NOINTERFACE;
268 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
270 return 2;
273 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
275 return 1;
278 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
280 ok(0, "unexpected call\n");
281 return E_NOTIMPL;
284 static ULONG g_write_len;
285 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
287 g_write_len = cb;
288 *written = cb;
289 return S_OK;
292 static const ISequentialStreamVtbl teststreamvtbl =
294 teststream_QueryInterface,
295 teststream_AddRef,
296 teststream_Release,
297 teststream_Read,
298 teststream_Write
301 static ISequentialStream teststream = { &teststreamvtbl };
303 static void test_writer_create(void)
305 HRESULT hr;
306 IXmlWriter *writer;
307 LONG_PTR value;
308 IUnknown *unk;
310 /* crashes native */
311 if (0)
313 CreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
314 CreateXmlWriter(NULL, (void**)&writer, NULL);
317 hr = CreateXmlWriter(&IID_IStream, (void **)&unk, NULL);
318 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
320 hr = CreateXmlWriter(&IID_IUnknown, (void **)&unk, NULL);
321 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
322 hr = IUnknown_QueryInterface(unk, &IID_IXmlWriter, (void **)&writer);
323 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
324 ok(unk == (IUnknown *)writer, "unexpected interface pointer\n");
325 IUnknown_Release(unk);
326 IXmlWriter_Release(writer);
328 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
329 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
331 /* check default properties values */
332 value = 0;
333 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
334 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
335 ok(value == TRUE, "got %Id.\n", value);
337 value = TRUE;
338 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
339 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
340 ok(value == FALSE, "got %Id.\n", value);
342 value = TRUE;
343 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
345 ok(value == FALSE, "got %Id.\n", value);
347 value = XmlConformanceLevel_Auto;
348 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
350 ok(value == XmlConformanceLevel_Document, "got %Id.\n", value);
352 IXmlWriter_Release(writer);
355 static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown *output)
357 HRESULT hr;
359 hr = IXmlWriter_SetOutput(writer, output);
360 ok(hr == S_OK, "Failed to set output, hr %#lx.\n", hr);
362 /* TODO: WriteAttributes */
364 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"a");
365 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
367 hr = IXmlWriter_WriteCData(writer, L"a");
368 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
370 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
371 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
373 hr = IXmlWriter_WriteChars(writer, L"a", 1);
374 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
376 hr = IXmlWriter_WriteComment(writer, L"a");
377 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
379 hr = IXmlWriter_WriteDocType(writer, L"a", NULL, NULL, NULL);
380 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
382 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, NULL);
383 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
385 hr = IXmlWriter_WriteEndDocument(writer);
386 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
388 hr = IXmlWriter_WriteEndElement(writer);
389 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
391 hr = IXmlWriter_WriteEntityRef(writer, L"a");
392 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
394 hr = IXmlWriter_WriteFullEndElement(writer);
395 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
397 hr = IXmlWriter_WriteName(writer, L"a");
398 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
400 hr = IXmlWriter_WriteNmToken(writer, L"a");
401 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
403 /* TODO: WriteNode */
404 /* TODO: WriteNodeShallow */
406 hr = IXmlWriter_WriteProcessingInstruction(writer, L"a", L"a");
407 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
409 hr = IXmlWriter_WriteQualifiedName(writer, L"a", NULL);
410 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
412 hr = IXmlWriter_WriteRaw(writer, L"a");
413 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
415 hr = IXmlWriter_WriteRawChars(writer, L"a", 1);
416 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
418 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
419 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
421 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
422 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
424 hr = IXmlWriter_WriteString(writer, L"a");
425 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
427 /* TODO: WriteSurrogateCharEntity */
429 hr = IXmlWriter_WriteWhitespace(writer, L" ");
430 ok(hr == MX_E_ENCODING, "Unexpected hr %#lx.\n", hr);
432 hr = IXmlWriter_Flush(writer);
433 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
436 static void test_writeroutput(void)
438 static const WCHAR utf16_outputW[] = {0xfeff,'<','a'};
439 IXmlWriterOutput *output;
440 IXmlWriter *writer;
441 IStream *stream;
442 IUnknown *unk;
443 HRESULT hr;
445 output = NULL;
446 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
447 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
448 EXPECT_REF(output, 1);
449 IUnknown_Release(output);
451 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, L"utf-16", &output);
452 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
453 unk = NULL;
454 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
455 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
456 todo_wine
457 ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output);
458 EXPECT_REF(output, 2);
459 /* releasing 'unk' crashes on native */
460 IUnknown_Release(output);
461 EXPECT_REF(output, 1);
462 IUnknown_Release(output);
464 output = NULL;
465 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output);
466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
467 IUnknown_Release(output);
469 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, CP_UTF8, &output);
470 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
471 unk = NULL;
472 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
474 ok(unk != NULL, "got %p\n", unk);
475 /* releasing 'unk' crashes on native */
476 IUnknown_Release(output);
477 IUnknown_Release(output);
479 /* create with us-ascii */
480 output = NULL;
481 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, L"us-ascii", &output);
482 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
483 IUnknown_Release(output);
485 /* Output with codepage 1200. */
486 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
487 ok(hr == S_OK, "Failed to create writer, hr %#lx.\n", hr);
489 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
490 ok(hr == S_OK, "Failed to create stream, hr %#lx.\n", hr);
492 hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, 1200, &output);
493 ok(hr == S_OK, "Failed to create writer output, hr %#lx.\n", hr);
495 hr = IXmlWriter_SetOutput(writer, output);
496 ok(hr == S_OK, "Failed to set writer output, hr %#lx.\n", hr);
498 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
499 ok(hr == S_OK, "Write failed, hr %#lx.\n", hr);
501 hr = IXmlWriter_Flush(writer);
502 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
504 CHECK_OUTPUT_RAW(stream, utf16_outputW, sizeof(utf16_outputW));
506 IStream_Release(stream);
507 IUnknown_Release(output);
509 /* Create output with meaningless code page value. */
510 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
511 ok(hr == S_OK, "Failed to create stream, hr %#lx.\n", hr);
513 output = NULL;
514 hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, ~0u, &output);
515 ok(hr == S_OK, "Failed to create writer output, hr %#lx.\n", hr);
517 test_invalid_output_encoding(writer, output);
518 CHECK_OUTPUT(stream, "");
520 IStream_Release(stream);
521 IUnknown_Release(output);
523 /* Same, with invalid encoding name. */
524 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
527 output = NULL;
528 hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, L"dummy", &output);
529 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
531 test_invalid_output_encoding(writer, output);
532 CHECK_OUTPUT(stream, "");
534 IStream_Release(stream);
535 IUnknown_Release(output);
537 IXmlWriter_Release(writer);
540 static void test_writestartdocument(void)
542 static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
543 static const char *prologversion2 = "<?xml version=\"1.0\" encoding=\"uS-asCii\"?>";
544 static const char prologversion[] = "<?xml version=\"1.0\"?>";
545 IXmlWriterOutput *output;
546 IXmlWriter *writer;
547 IStream *stream;
548 HRESULT hr;
550 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
551 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
553 /* output not set */
554 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
555 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
557 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
558 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
560 hr = IXmlWriter_Flush(writer);
561 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
563 stream = writer_set_output(writer);
565 /* nothing written yet */
566 hr = IXmlWriter_Flush(writer);
567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
569 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
570 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
572 hr = IXmlWriter_Flush(writer);
573 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
575 CHECK_OUTPUT(stream, fullprolog);
577 /* one more time */
578 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
579 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
580 IStream_Release(stream);
582 /* now add PI manually, and try to start a document */
583 stream = writer_set_output(writer);
585 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
586 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
588 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
589 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
591 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
592 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
594 /* another attempt to add 'xml' PI */
595 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
596 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
598 hr = IXmlWriter_Flush(writer);
599 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
601 CHECK_OUTPUT(stream, prologversion);
603 IStream_Release(stream);
604 IXmlWriter_Release(writer);
606 /* create with us-ascii */
607 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
608 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
610 output = NULL;
611 hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, L"uS-asCii", &output);
612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
614 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
615 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
617 hr = IXmlWriter_SetOutput(writer, output);
618 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
620 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
621 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
623 hr = IXmlWriter_Flush(writer);
624 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
626 CHECK_OUTPUT(stream, prologversion2);
628 IStream_Release(stream);
629 IXmlWriter_Release(writer);
630 IUnknown_Release(output);
633 static void test_flush(void)
635 IXmlWriter *writer;
636 HRESULT hr;
638 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
639 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
641 hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
644 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
645 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
647 g_write_len = 0;
648 hr = IXmlWriter_Flush(writer);
649 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
650 ok(g_write_len > 0, "Unexpected length %lu.\n", g_write_len);
652 g_write_len = 1;
653 hr = IXmlWriter_Flush(writer);
654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
655 ok(g_write_len == 0, "Unexpected length %lu.\n", g_write_len);
657 /* Release() flushes too */
658 g_write_len = 1;
659 IXmlWriter_Release(writer);
660 ok(g_write_len == 0, "Unexpected length %lu.\n", g_write_len);
663 static void test_omitxmldeclaration(void)
665 static const char prologversion[] = "<?xml version=\"1.0\"?>";
666 IXmlWriter *writer;
667 HGLOBAL hglobal;
668 IStream *stream;
669 HRESULT hr;
670 char *ptr;
672 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
673 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
675 stream = writer_set_output(writer);
677 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
679 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
682 hr = IXmlWriter_Flush(writer);
683 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
685 hr = GetHGlobalFromStream(stream, &hglobal);
686 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
688 ptr = GlobalLock(hglobal);
689 ok(!ptr, "got %p\n", ptr);
690 GlobalUnlock(hglobal);
692 /* one more time */
693 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
694 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
696 IStream_Release(stream);
698 /* now add PI manually, and try to start a document */
699 stream = writer_set_output(writer);
701 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
702 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
704 hr = IXmlWriter_Flush(writer);
705 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
707 CHECK_OUTPUT(stream, prologversion);
709 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
710 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
712 hr = IXmlWriter_Flush(writer);
713 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
715 CHECK_OUTPUT(stream, prologversion);
717 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
718 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
720 hr = IXmlWriter_Flush(writer);
721 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
723 CHECK_OUTPUT(stream, prologversion);
725 /* another attempt to add 'xml' PI */
726 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
727 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
729 hr = IXmlWriter_Flush(writer);
730 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
732 IStream_Release(stream);
733 IXmlWriter_Release(writer);
736 static void test_bom(void)
738 static const WCHAR piW[] = {0xfeff,'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>'};
739 static const WCHAR aopenW[] = {0xfeff,'<','a'};
740 static const WCHAR afullW[] = {0xfeff,'<','a',' ','/','>'};
741 static const WCHAR bomW[] = {0xfeff};
742 IXmlWriterOutput *output;
743 IXmlWriter *writer;
744 IStream *stream;
745 HGLOBAL hglobal;
746 HRESULT hr;
748 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
751 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
752 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
754 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
755 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
757 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
759 hr = IXmlWriter_SetOutput(writer, output);
760 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
762 /* BOM is on by default */
763 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
764 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
766 hr = IXmlWriter_Flush(writer);
767 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
769 CHECK_OUTPUT_RAW(stream, bomW, sizeof(bomW));
771 IStream_Release(stream);
772 IUnknown_Release(output);
774 /* start with PI */
775 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
776 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
778 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
779 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
781 hr = IXmlWriter_SetOutput(writer, output);
782 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
784 hr = IXmlWriter_WriteProcessingInstruction(writer, L"xml", L"version=\"1.0\"");
785 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
787 hr = IXmlWriter_Flush(writer);
788 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
790 CHECK_OUTPUT_RAW(stream, piW, sizeof(piW));
792 IUnknown_Release(output);
793 IStream_Release(stream);
795 /* start with element */
796 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
797 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
799 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
802 hr = IXmlWriter_SetOutput(writer, output);
803 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
805 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
806 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
808 hr = IXmlWriter_Flush(writer);
809 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
811 CHECK_OUTPUT_RAW(stream, aopenW, sizeof(aopenW));
813 IUnknown_Release(output);
814 IStream_Release(stream);
816 /* WriteElementString */
817 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
818 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
820 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, L"utf-16", &output);
821 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
823 hr = IXmlWriter_SetOutput(writer, output);
824 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
826 writer_set_property(writer, XmlWriterProperty_Indent);
828 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, NULL);
829 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
831 hr = IXmlWriter_Flush(writer);
832 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
834 hr = GetHGlobalFromStream(stream, &hglobal);
835 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
837 CHECK_OUTPUT_RAW(stream, afullW, sizeof(afullW));
839 IUnknown_Release(output);
840 IStream_Release(stream);
842 IXmlWriter_Release(writer);
845 static void test_WriteStartElement(void)
847 static const struct
849 const WCHAR *prefix;
850 const WCHAR *local;
851 const WCHAR *uri;
852 const char *output;
853 const char *output_partial;
854 HRESULT hr;
855 int todo;
856 int todo_partial;
858 start_element_tests[] =
860 { L"prefix", L"local", L"uri", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local" },
861 { NULL, L"local", L"uri", "<local xmlns=\"uri\" />", "<local" },
862 { L"", L"local", L"uri", "<local xmlns=\"uri\" />", "<local" },
863 { L"", L"local", L"uri", "<local xmlns=\"uri\" />", "<local" },
864 { NULL, L"local", NULL, "<local />", "<local" },
865 { NULL, L"local", L"", "<local />", "<local" },
867 { L"prefix", NULL, NULL, NULL, NULL, E_INVALIDARG },
868 { NULL, NULL, L"uri", NULL, NULL, E_INVALIDARG },
869 { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
870 { NULL, L"prefix:local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
871 { L"pre:fix", L"local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
872 { NULL, L":local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
873 { L":", L"local", L"uri", NULL, NULL, WC_E_NAMECHARACTER },
874 { NULL, L"local", L"http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
875 { L"prefix", L"local", L"http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION },
877 IXmlWriter *writer;
878 IStream *stream;
879 unsigned int i;
880 HRESULT hr;
882 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
883 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
885 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
886 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
888 stream = writer_set_output(writer);
890 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
891 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
893 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
894 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
896 hr = IXmlWriter_Flush(writer);
897 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
899 CHECK_OUTPUT(stream, "<a");
901 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
902 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
904 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
905 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
907 hr = IXmlWriter_WriteProcessingInstruction(writer, L"a", L"a");
908 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
910 IStream_Release(stream);
911 IXmlWriter_Release(writer);
913 /* WriteElementString */
914 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
917 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
918 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
920 stream = writer_set_output(writer);
922 hr = IXmlWriter_WriteStartElement(writer, L"prefix", L"a", L"uri");
923 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
925 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
926 ok(hr == S_OK, "Failed to write element string, hr %#lx.\n", hr);
928 hr = IXmlWriter_WriteElementString(writer, NULL, L"c", NULL, NULL);
929 ok(hr == S_OK, "Failed to write element string, hr %#lx.\n", hr);
931 hr = IXmlWriter_WriteStartElement(writer, NULL, L"d", L"uri");
932 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
934 hr = IXmlWriter_WriteStartElement(writer, L"", L"e", L"uri");
935 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
937 hr = IXmlWriter_WriteStartElement(writer, L"prefix2", L"f", L"uri");
938 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
940 hr = IXmlWriter_Flush(writer);
941 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
943 CHECK_OUTPUT(stream,
944 "<prefix:a xmlns:prefix=\"uri\">"
945 "<b>value</b>"
946 "<c />"
947 "<prefix:d>"
948 "<e xmlns=\"uri\">"
949 "<prefix2:f");
951 IStream_Release(stream);
953 /* WriteStartElement */
954 for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i)
956 stream = writer_set_output(writer);
958 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
960 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
961 ok(hr == S_OK, "Failed to start document, hr %#lx.\n", hr);
963 hr = IXmlWriter_WriteStartElement(writer, start_element_tests[i].prefix, start_element_tests[i].local,
964 start_element_tests[i].uri);
965 ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
967 if (SUCCEEDED(start_element_tests[i].hr))
969 hr = IXmlWriter_Flush(writer);
970 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
972 check_output(stream, start_element_tests[i].output_partial, start_element_tests[i].todo_partial, __LINE__);
974 hr = IXmlWriter_WriteEndDocument(writer);
975 ok(hr == S_OK, "Failed to end document, hr %#lx.\n", hr);
977 hr = IXmlWriter_Flush(writer);
978 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
980 check_output(stream, start_element_tests[i].output, start_element_tests[i].todo, __LINE__);
983 IStream_Release(stream);
986 IXmlWriter_Release(writer);
989 static void test_WriteElementString(void)
991 static const struct
993 const WCHAR *prefix;
994 const WCHAR *local;
995 const WCHAR *uri;
996 const WCHAR *value;
997 const char *output;
998 HRESULT hr;
999 int todo;
1001 element_string_tests[] =
1003 { L"prefix", L"local", L"uri", L"value", "<prefix:local xmlns:prefix=\"uri\">value</prefix:local>" },
1004 { NULL, L"local", L"uri", L"value", "<local xmlns=\"uri\">value</local>" },
1005 { L"", L"local", L"uri", L"value", "<local xmlns=\"uri\">value</local>" },
1006 { L"prefix", L"local", L"uri", NULL, "<prefix:local xmlns:prefix=\"uri\" />" },
1007 { NULL, L"local", L"uri", NULL, "<local xmlns=\"uri\" />" },
1008 { L"", L"local", L"uri", NULL, "<local xmlns=\"uri\" />" },
1009 { NULL, L"local", NULL, NULL, "<local />" },
1010 { L"prefix", L"local", L"uri", L"", "<prefix:local xmlns:prefix=\"uri\"></prefix:local>" },
1011 { NULL, L"local", L"uri", L"", "<local xmlns=\"uri\"></local>" },
1012 { L"", L"local", L"uri", L"", "<local xmlns=\"uri\"></local>" },
1013 { NULL, L"local", NULL, L"", "<local></local>" },
1014 { L"", L"local", L"http://www.w3.org/2000/xmlns/", NULL, "<local xmlns=\"http://www.w3.org/2000/xmlns/\" />" },
1016 { L"prefix", NULL, NULL, L"value", NULL, E_INVALIDARG },
1017 { NULL, NULL, L"uri", L"value", NULL, E_INVALIDARG },
1018 { NULL, NULL, NULL, L"value", NULL, E_INVALIDARG },
1019 { NULL, L"prefix:local", L"uri", L"value", NULL, WC_E_NAMECHARACTER },
1020 { NULL, L":local", L"uri", L"value", NULL, WC_E_NAMECHARACTER },
1021 { L":", L"local", L"uri", L"value", NULL, WC_E_NAMECHARACTER },
1022 { L"prefix", L"local", NULL, L"value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1023 { L"prefix", L"local", L"", L"value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1024 { NULL, L"local", L"http://www.w3.org/2000/xmlns/", L"value", NULL, WR_E_XMLNSPREFIXDECLARATION },
1025 { L"prefix", L"local", L"http://www.w3.org/2000/xmlns/", L"value", NULL, WR_E_XMLNSURIDECLARATION },
1027 IXmlWriter *writer;
1028 IStream *stream;
1029 unsigned int i;
1030 HRESULT hr;
1032 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1033 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1035 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
1036 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1038 stream = writer_set_output(writer);
1040 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1041 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1043 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, L"value");
1044 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1046 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, NULL);
1047 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1049 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"b", L"uri", NULL);
1050 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1052 hr = IXmlWriter_WriteStartElement(writer, L"prefix", L"c", L"uri");
1053 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1055 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"d", NULL, NULL);
1056 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1058 hr = IXmlWriter_WriteElementString(writer, L"prefix2", L"d", L"uri", NULL);
1059 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1061 hr = IXmlWriter_WriteElementString(writer, NULL, L"e", L"uri", NULL);
1062 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1064 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"f", L"uri2", NULL);
1065 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1067 hr = IXmlWriter_WriteElementString(writer, NULL, L"g", L"uri3", NULL);
1068 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1070 hr = IXmlWriter_WriteElementString(writer, L"prefix", L"h", NULL, NULL);
1071 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1073 hr = IXmlWriter_WriteElementString(writer, L"prefix_i", L"i", NULL, NULL);
1074 ok(hr == WR_E_NSPREFIXWITHEMPTYNSURI, "Failed to write element, hr %#lx.\n", hr);
1076 hr = IXmlWriter_WriteElementString(writer, L"", L"j", L"uri", NULL);
1077 ok(hr == S_OK, "Failed to write element, hr %#lx.\n", hr);
1079 hr = IXmlWriter_Flush(writer);
1080 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1082 CHECK_OUTPUT(stream,
1083 "<a><b>value</b><b />"
1084 "<prefix:b xmlns:prefix=\"uri\" />"
1085 "<prefix:c xmlns:prefix=\"uri\">"
1086 "<prefix:d />"
1087 "<prefix2:d xmlns:prefix2=\"uri\" />"
1088 "<prefix:e />"
1089 "<prefix:f xmlns:prefix=\"uri2\" />"
1090 "<g xmlns=\"uri3\" />"
1091 "<prefix:h />"
1092 "<j xmlns=\"uri\" />");
1094 IStream_Release(stream);
1096 for (i = 0; i < ARRAY_SIZE(element_string_tests); ++i)
1098 stream = writer_set_output(writer);
1100 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1102 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1103 ok(hr == S_OK, "Failed to start document, hr %#lx.\n", hr);
1105 hr = IXmlWriter_WriteElementString(writer, element_string_tests[i].prefix, element_string_tests[i].local,
1106 element_string_tests[i].uri, element_string_tests[i].value);
1107 ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
1109 if (SUCCEEDED(element_string_tests[i].hr))
1111 hr = IXmlWriter_Flush(writer);
1112 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1114 check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1116 hr = IXmlWriter_WriteEndDocument(writer);
1117 ok(hr == S_OK, "Failed to end document, hr %#lx.\n", hr);
1119 hr = IXmlWriter_Flush(writer);
1120 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1122 check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1125 IStream_Release(stream);
1128 IXmlWriter_Release(writer);
1131 static void test_WriteEndElement(void)
1133 IXmlWriter *writer;
1134 IStream *stream;
1135 HRESULT hr;
1137 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1138 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1140 stream = writer_set_output(writer);
1142 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1143 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1145 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1146 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1148 hr = IXmlWriter_WriteEndElement(writer);
1149 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1151 hr = IXmlWriter_WriteEndElement(writer);
1152 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1154 hr = IXmlWriter_Flush(writer);
1155 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1157 CHECK_OUTPUT(stream, "<a><b /></a>");
1159 IXmlWriter_Release(writer);
1160 IStream_Release(stream);
1163 static void test_writeenddocument(void)
1165 IXmlWriter *writer;
1166 IStream *stream;
1167 HGLOBAL hglobal;
1168 HRESULT hr;
1169 char *ptr;
1171 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1172 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1174 hr = IXmlWriter_WriteEndDocument(writer);
1175 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1177 stream = writer_set_output(writer);
1179 /* WriteEndDocument resets it to initial state */
1180 hr = IXmlWriter_WriteEndDocument(writer);
1181 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1183 hr = IXmlWriter_WriteEndDocument(writer);
1184 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1186 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1187 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1189 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1190 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1192 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
1193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1195 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1196 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1198 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1201 hr = IXmlWriter_WriteEndDocument(writer);
1202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1204 hr = GetHGlobalFromStream(stream, &hglobal);
1205 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1207 ptr = GlobalLock(hglobal);
1208 ok(ptr == NULL, "got %p\n", ptr);
1210 /* we still need to flush manually, WriteEndDocument doesn't do that */
1211 hr = IXmlWriter_Flush(writer);
1212 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1214 CHECK_OUTPUT(stream, "<a><b /></a>");
1216 IXmlWriter_Release(writer);
1217 IStream_Release(stream);
1220 static void test_WriteComment(void)
1222 IXmlWriter *writer;
1223 IStream *stream;
1224 HRESULT hr;
1226 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1229 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1231 hr = IXmlWriter_WriteComment(writer, L"a");
1232 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1234 stream = writer_set_output(writer);
1236 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1239 hr = IXmlWriter_WriteComment(writer, L"a");
1240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1242 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1243 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1245 hr = IXmlWriter_WriteComment(writer, L"a");
1246 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1248 hr = IXmlWriter_WriteComment(writer, NULL);
1249 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1251 hr = IXmlWriter_WriteComment(writer, L"-->");
1252 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1254 hr = IXmlWriter_Flush(writer);
1255 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1257 CHECK_OUTPUT(stream, "<!--a--><b><!--a--><!----><!--- ->-->");
1259 IXmlWriter_Release(writer);
1260 IStream_Release(stream);
1263 static void test_WriteCData(void)
1265 IXmlWriter *writer;
1266 IStream *stream;
1267 HRESULT hr;
1269 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1270 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1272 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1274 hr = IXmlWriter_WriteCData(writer, L"a");
1275 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1277 stream = writer_set_output(writer);
1279 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1280 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1282 hr = IXmlWriter_WriteCData(writer, L"a");
1283 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1285 hr = IXmlWriter_WriteCData(writer, NULL);
1286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1288 hr = IXmlWriter_WriteCData(writer, L"]]>");
1289 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1291 hr = IXmlWriter_WriteCData(writer, L"a]]>b");
1292 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1294 hr = IXmlWriter_Flush(writer);
1295 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1297 CHECK_OUTPUT(stream,
1298 "<b>"
1299 "<![CDATA[a]]>"
1300 "<![CDATA[]]>"
1301 "<![CDATA[]]]]>"
1302 "<![CDATA[>]]>"
1303 "<![CDATA[a]]]]>"
1304 "<![CDATA[>b]]>");
1306 IXmlWriter_Release(writer);
1307 IStream_Release(stream);
1310 static void test_WriteRaw(void)
1312 static const WCHAR rawW[] = L"a<:";
1313 IXmlWriter *writer;
1314 IStream *stream;
1315 HRESULT hr;
1317 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1320 hr = IXmlWriter_WriteRaw(writer, NULL);
1321 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1323 hr = IXmlWriter_WriteRaw(writer, rawW);
1324 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1326 stream = writer_set_output(writer);
1328 hr = IXmlWriter_WriteRaw(writer, NULL);
1329 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1331 hr = IXmlWriter_WriteRaw(writer, rawW);
1332 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1334 hr = IXmlWriter_WriteRaw(writer, rawW);
1335 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1337 hr = IXmlWriter_WriteComment(writer, rawW);
1338 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1340 hr = IXmlWriter_WriteRaw(writer, rawW);
1341 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1343 hr = IXmlWriter_WriteElementString(writer, NULL, L"a", NULL, L"a");
1344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1346 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
1347 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1349 hr = IXmlWriter_WriteComment(writer, rawW);
1350 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1352 hr = IXmlWriter_WriteEndDocument(writer);
1353 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1355 hr = IXmlWriter_WriteRaw(writer, rawW);
1356 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1358 hr = IXmlWriter_Flush(writer);
1359 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1360 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>a<:a<:<!--a<:-->a<:<a>a</a>");
1361 IStream_Release(stream);
1363 /* With open element. */
1364 stream = writer_set_output(writer);
1366 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
1367 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1368 hr = IXmlWriter_WriteRaw(writer, L"text");
1369 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1371 hr = IXmlWriter_Flush(writer);
1372 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1373 CHECK_OUTPUT(stream, "<w>text");
1374 IStream_Release(stream);
1376 IXmlWriter_Release(writer);
1379 static void test_writer_state(void)
1381 IXmlWriter *writer;
1382 IStream *stream;
1383 HRESULT hr;
1385 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1386 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1388 /* initial state */
1389 check_writer_state(writer, E_UNEXPECTED);
1391 /* set output and call 'wrong' method, WriteEndElement */
1392 stream = writer_set_output(writer);
1394 hr = IXmlWriter_WriteEndElement(writer);
1395 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1397 check_writer_state(writer, WR_E_INVALIDACTION);
1398 IStream_Release(stream);
1400 /* WriteAttributeString */
1401 stream = writer_set_output(writer);
1403 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"a");
1404 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1406 check_writer_state(writer, WR_E_INVALIDACTION);
1407 IStream_Release(stream);
1409 /* WriteEndDocument */
1410 stream = writer_set_output(writer);
1412 hr = IXmlWriter_WriteEndDocument(writer);
1413 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1415 check_writer_state(writer, WR_E_INVALIDACTION);
1416 IStream_Release(stream);
1418 /* WriteFullEndElement */
1419 stream = writer_set_output(writer);
1421 hr = IXmlWriter_WriteFullEndElement(writer);
1422 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1424 check_writer_state(writer, WR_E_INVALIDACTION);
1425 IStream_Release(stream);
1427 /* WriteCData */
1428 stream = writer_set_output(writer);
1430 hr = IXmlWriter_WriteCData(writer, L"a");
1431 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1433 check_writer_state(writer, WR_E_INVALIDACTION);
1434 IStream_Release(stream);
1436 /* WriteName */
1437 stream = writer_set_output(writer);
1439 hr = IXmlWriter_WriteName(writer, L"a");
1440 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1442 check_writer_state(writer, WR_E_INVALIDACTION);
1443 IStream_Release(stream);
1445 /* WriteNmToken */
1446 stream = writer_set_output(writer);
1448 hr = IXmlWriter_WriteNmToken(writer, L"a");
1449 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1451 check_writer_state(writer, WR_E_INVALIDACTION);
1452 IStream_Release(stream);
1454 /* WriteString */
1455 stream = writer_set_output(writer);
1457 hr = IXmlWriter_WriteString(writer, L"a");
1458 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
1460 check_writer_state(writer, WR_E_INVALIDACTION);
1461 IStream_Release(stream);
1463 IXmlWriter_Release(writer);
1466 static void test_indentation(void)
1468 IXmlWriter *writer;
1469 IStream *stream;
1470 HRESULT hr;
1472 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1475 stream = writer_set_output(writer);
1477 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1478 writer_set_property(writer, XmlWriterProperty_Indent);
1480 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1481 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1483 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1486 hr = IXmlWriter_WriteComment(writer, L"comment");
1487 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1489 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1490 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1492 hr = IXmlWriter_WriteEndDocument(writer);
1493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1495 hr = IXmlWriter_Flush(writer);
1496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1498 CHECK_OUTPUT(stream,
1499 "<a>\r\n"
1500 " <!--comment-->\r\n"
1501 " <b />\r\n"
1502 "</a>");
1504 IStream_Release(stream);
1506 /* WriteElementString */
1507 stream = writer_set_output(writer);
1509 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1510 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1512 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, NULL);
1513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1515 hr = IXmlWriter_WriteElementString(writer, NULL, L"b", NULL, NULL);
1516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1518 hr = IXmlWriter_WriteEndElement(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 " <b />\r\n"
1527 " <b />\r\n"
1528 "</a>");
1530 IStream_Release(stream);
1532 IXmlWriter_Release(writer);
1535 static void test_WriteAttributeString(void)
1537 static const struct
1539 const WCHAR *prefix;
1540 const WCHAR *local;
1541 const WCHAR *uri;
1542 const WCHAR *value;
1543 const char *output;
1544 const char *output_partial;
1545 HRESULT hr;
1546 int todo;
1547 int todo_partial;
1548 int todo_hr;
1550 attribute_tests[] =
1552 { NULL, L"a", NULL, L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1553 { L"", L"a", NULL, L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1554 { NULL, L"a", L"", L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1555 { L"", L"a", L"", L"b", "<e a=\"b\" />", "<e a=\"b\"" },
1556 { L"prefix", L"local", L"uri", L"b", "<e prefix:local=\"b\" xmlns:prefix=\"uri\" />", "<e prefix:local=\"b\"" },
1557 { NULL, L"a", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e xmlns:a=\"defuri\" />", "<e xmlns:a=\"defuri\"" },
1558 { L"xmlns", L"a", NULL, L"uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1559 { L"xmlns", L"a", L"", L"uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1560 { L"prefix", L"xmlns", L"uri", L"value", "<e prefix:xmlns=\"value\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"value\"" },
1561 { L"prefix", L"xmlns", L"uri", NULL, "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1562 { L"prefix", L"xmlns", L"uri", L"", "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1563 { L"prefix", L"xmlns", NULL, L"uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1564 { L"prefix", L"xmlns", L"", L"uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1565 { L"xml", L"space", NULL, L"preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1566 { L"xml", L"space", L"", L"preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1567 { L"xml", L"space", NULL, L"default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1568 { L"xml", L"space", L"", L"default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1569 { L"xml", L"a", NULL, L"value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1570 { L"xml", L"a", L"", L"value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1572 /* Autogenerated prefix names. */
1573 { NULL, L"a", L"defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1574 { NULL, L"a", L"defuri", L"b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1575 { L"", L"a", L"defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1576 { NULL, L"a", L"defuri", L"", "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1577 { L"", L"a", L"defuri", L"b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1579 /* Failing cases. */
1580 { NULL, NULL, L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1581 { L"", L"a", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 1, 1, 1 },
1582 { L"", NULL, L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1583 { L"", L"", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1584 { NULL, L"", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1585 { L"prefix", L"a", L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION, 1, 1, 1 },
1586 { L"prefix", NULL, L"http://www.w3.org/2000/xmlns/", L"defuri", "<e />", "<e", E_INVALIDARG },
1587 { L"prefix", NULL, NULL, L"b", "<e />", "<e", E_INVALIDARG },
1588 { L"prefix", NULL, L"uri", NULL, "<e />", "<e", E_INVALIDARG },
1589 { L"xml", NULL, NULL, L"value", "<e />", "<e", E_INVALIDARG },
1590 { L"xmlns", L"a", L"defuri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1591 { L"xmlns", L"a", L"b", L"uri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1592 { NULL, L"xmlns", L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1593 { L"xmlns", NULL, L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1594 { L"pre:fix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER },
1595 { L"pre:fix", NULL, L"uri", L"b", "<e />", "<e", E_INVALIDARG },
1596 { L"prefix", L"lo:cal", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER },
1597 { L"xmlns", NULL, NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1598 { L"xmlns", NULL, L"", L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1599 { L"xmlns", L"", NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1600 { L"xmlns", L"", L"", L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1601 { L"xml", L"space", L"", L"value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1602 { L"xml", L"space", NULL, L"value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1603 { L"xml", L"a", L"uri", L"value", "<e />", "<e", WR_E_XMLPREFIXDECLARATION },
1604 { L"xml", L"space", NULL, L"preServe", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1605 { L"xml", L"space", NULL, L"defAult", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1606 { L"xml", L"space", NULL, NULL, "<e />", "<e", WR_E_INVALIDXMLSPACE },
1607 { L"xml", L"space", NULL, L"", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1610 IXmlWriter *writer;
1611 IStream *stream;
1612 unsigned int i;
1613 HRESULT hr;
1615 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1616 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1618 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1620 for (i = 0; i < ARRAY_SIZE(attribute_tests); ++i)
1622 winetest_push_context("Test %u", i);
1624 stream = writer_set_output(writer);
1626 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1627 ok(hr == S_OK, "Failed to start document, hr %#lx.\n", hr);
1629 hr = IXmlWriter_WriteStartElement(writer, NULL, L"e", NULL);
1630 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1632 hr = IXmlWriter_WriteAttributeString(writer, attribute_tests[i].prefix, attribute_tests[i].local,
1633 attribute_tests[i].uri, attribute_tests[i].value);
1634 todo_wine_if(attribute_tests[i].todo_hr)
1635 ok(hr == attribute_tests[i].hr, "Unexpected hr %#lx, expected %#lx.\n", hr, attribute_tests[i].hr);
1637 hr = IXmlWriter_Flush(writer);
1638 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1640 check_output(stream, attribute_tests[i].output_partial, attribute_tests[i].todo_partial, __LINE__);
1642 hr = IXmlWriter_WriteEndDocument(writer);
1643 ok(hr == S_OK, "Failed to end document, hr %#lx.\n", hr);
1645 hr = IXmlWriter_Flush(writer);
1646 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1648 check_output(stream, attribute_tests[i].output, attribute_tests[i].todo, __LINE__);
1649 IStream_Release(stream);
1651 winetest_pop_context();
1654 /* With namespaces */
1655 stream = writer_set_output(writer);
1657 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1658 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1660 hr = IXmlWriter_WriteStartElement(writer, L"p", L"a", L"outeruri");
1661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1663 hr = IXmlWriter_WriteAttributeString(writer, L"prefix", L"local", L"uri", L"b");
1664 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1666 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"a", NULL, L"b");
1667 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1669 hr = IXmlWriter_WriteAttributeString(writer, L"xmlns", L"prefix", NULL, L"uri");
1670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1672 hr = IXmlWriter_WriteAttributeString(writer, L"p", L"attr", NULL, L"value");
1673 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
1675 hr = IXmlWriter_WriteAttributeString(writer, L"prefix", L"local", NULL, L"b");
1676 todo_wine
1677 ok(hr == WR_E_DUPLICATEATTRIBUTE, "Unexpected hr %#lx.\n", hr);
1679 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1682 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"attr2", L"outeruri", L"value");
1683 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
1685 hr = IXmlWriter_WriteAttributeString(writer, L"pr", L"attr3", L"outeruri", L"value");
1686 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
1688 hr = IXmlWriter_WriteEndDocument(writer);
1689 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1691 hr = IXmlWriter_Flush(writer);
1692 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1694 CHECK_OUTPUT_TODO(stream,
1695 "<p:a prefix:local=\"b\" a=\"b\" xmlns:prefix=\"uri\" p:attr=\"value\" xmlns:p=\"outeruri\">"
1696 "<b p:attr2=\"value\" pr:attr3=\"value\" xmlns:pr=\"outeruri\" />"
1697 "</p:a>");
1699 IStream_Release(stream);
1701 /* Define prefix, write attribute with it. */
1702 stream = writer_set_output(writer);
1704 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1705 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1707 hr = IXmlWriter_WriteStartElement(writer, NULL, L"e", NULL);
1708 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1710 hr = IXmlWriter_WriteAttributeString(writer, L"xmlns", L"prefix", NULL, L"uri");
1711 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1713 hr = IXmlWriter_WriteAttributeString(writer, L"prefix", L"attr", NULL, L"value");
1714 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1716 hr = IXmlWriter_WriteEndDocument(writer);
1717 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1719 hr = IXmlWriter_Flush(writer);
1720 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1722 CHECK_OUTPUT(stream,
1723 "<e xmlns:prefix=\"uri\" prefix:attr=\"value\" />");
1725 IStream_Release(stream);
1727 IXmlWriter_Release(writer);
1730 static void test_WriteFullEndElement(void)
1732 IXmlWriter *writer;
1733 IStream *stream;
1734 HRESULT hr;
1736 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1737 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1739 /* standalone element */
1740 stream = writer_set_output(writer);
1742 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1743 writer_set_property(writer, XmlWriterProperty_Indent);
1745 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1746 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1748 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1751 hr = IXmlWriter_WriteFullEndElement(writer);
1752 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1754 hr = IXmlWriter_WriteEndDocument(writer);
1755 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1757 hr = IXmlWriter_Flush(writer);
1758 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1760 CHECK_OUTPUT(stream,
1761 "<a></a>");
1762 IStream_Release(stream);
1764 /* nested elements */
1765 stream = writer_set_output(writer);
1767 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1768 writer_set_property(writer, XmlWriterProperty_Indent);
1770 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1771 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1773 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1774 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1776 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1777 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1779 hr = IXmlWriter_WriteFullEndElement(writer);
1780 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1782 hr = IXmlWriter_WriteEndDocument(writer);
1783 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1785 hr = IXmlWriter_Flush(writer);
1786 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1788 CHECK_OUTPUT(stream,
1789 "<a>\r\n"
1790 " <a></a>\r\n"
1791 "</a>");
1792 IStream_Release(stream);
1794 /* Empty strings for prefix and uri. */
1795 stream = writer_set_output(writer);
1797 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_Indent, FALSE);
1798 ok(hr == S_OK, "Failed to set property, hr %#lx.\n", hr);
1800 hr = IXmlWriter_WriteStartElement(writer, L"", L"a", NULL);
1801 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1802 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", L"");
1803 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1804 hr = IXmlWriter_WriteStartElement(writer, L"", L"c", L"");
1805 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1806 hr = IXmlWriter_WriteFullEndElement(writer);
1807 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1808 hr = IXmlWriter_WriteFullEndElement(writer);
1809 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1810 hr = IXmlWriter_WriteFullEndElement(writer);
1811 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1813 hr = IXmlWriter_Flush(writer);
1814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1815 CHECK_OUTPUT(stream, "<a><b><c></c></b></a>");
1816 IStream_Release(stream);
1818 IXmlWriter_Release(writer);
1821 static void test_WriteCharEntity(void)
1823 IXmlWriter *writer;
1824 IStream *stream;
1825 HRESULT hr;
1827 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1828 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1830 /* without indentation */
1831 stream = writer_set_output(writer);
1833 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1835 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1836 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1838 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1841 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
1842 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1844 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1845 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1847 hr = IXmlWriter_WriteEndDocument(writer);
1848 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1850 hr = IXmlWriter_Flush(writer);
1851 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1853 CHECK_OUTPUT(stream,
1854 "<a>&#x100;<a /></a>");
1856 IXmlWriter_Release(writer);
1857 IStream_Release(stream);
1860 static void test_WriteString(void)
1862 IXmlWriter *writer;
1863 IStream *stream;
1864 HRESULT hr;
1866 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1867 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1869 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1871 hr = IXmlWriter_WriteString(writer, L"a");
1872 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1874 hr = IXmlWriter_WriteString(writer, NULL);
1875 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1877 hr = IXmlWriter_WriteString(writer, L"");
1878 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
1880 stream = writer_set_output(writer);
1882 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1883 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1885 hr = IXmlWriter_WriteString(writer, NULL);
1886 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1888 hr = IXmlWriter_WriteString(writer, L"");
1889 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1891 hr = IXmlWriter_WriteString(writer, L"a");
1892 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1894 /* WriteString automatically escapes markup characters */
1895 hr = IXmlWriter_WriteString(writer, L"<&\">=");
1896 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1898 hr = IXmlWriter_Flush(writer);
1899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1901 CHECK_OUTPUT(stream,
1902 "<b>a&lt;&amp;\"&gt;=");
1903 IStream_Release(stream);
1905 stream = writer_set_output(writer);
1907 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1908 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1910 hr = IXmlWriter_WriteString(writer, NULL);
1911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1913 hr = IXmlWriter_Flush(writer);
1914 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1916 CHECK_OUTPUT(stream,
1917 "<b");
1919 hr = IXmlWriter_WriteString(writer, L"");
1920 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1922 hr = IXmlWriter_Flush(writer);
1923 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1925 CHECK_OUTPUT(stream,
1926 "<b>");
1928 IStream_Release(stream);
1929 IXmlWriter_Release(writer);
1931 /* With indentation */
1932 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
1933 ok(hr == S_OK, "Failed to create a writer, hr %#lx.\n", hr);
1935 stream = writer_set_output(writer);
1937 writer_set_property(writer, XmlWriterProperty_Indent);
1939 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1940 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1942 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1943 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1945 hr = IXmlWriter_WriteString(writer, L"text");
1946 ok(hr == S_OK, "Failed to write a string, hr %#lx.\n", hr);
1948 hr = IXmlWriter_Flush(writer);
1949 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1951 CHECK_OUTPUT(stream,
1952 "<a>\r\n"
1953 " <b>text");
1955 hr = IXmlWriter_WriteFullEndElement(writer);
1956 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
1958 hr = IXmlWriter_Flush(writer);
1959 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1961 CHECK_OUTPUT(stream,
1962 "<a>\r\n"
1963 " <b>text</b>");
1965 hr = IXmlWriter_WriteFullEndElement(writer);
1966 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
1968 hr = IXmlWriter_Flush(writer);
1969 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1971 CHECK_OUTPUT(stream,
1972 "<a>\r\n"
1973 " <b>text</b>\r\n"
1974 "</a>");
1976 IStream_Release(stream);
1978 stream = writer_set_output(writer);
1980 hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL);
1981 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1983 hr = IXmlWriter_WriteStartElement(writer, NULL, L"b", NULL);
1984 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1986 hr = IXmlWriter_WriteEndElement(writer);
1987 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
1989 hr = IXmlWriter_Flush(writer);
1990 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1992 CHECK_OUTPUT(stream,
1993 "<a>\r\n"
1994 " <b />");
1996 hr = IXmlWriter_WriteStartElement(writer, NULL, L"c", NULL);
1997 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
1999 hr = IXmlWriter_WriteAttributeString(writer, NULL, L"attr", NULL, L"value");
2000 ok(hr == S_OK, "Failed to write attribute string, hr %#lx.\n", hr);
2002 hr = IXmlWriter_Flush(writer);
2003 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2005 CHECK_OUTPUT(stream,
2006 "<a>\r\n"
2007 " <b />\r\n"
2008 " <c attr=\"value\"");
2010 hr = IXmlWriter_WriteString(writer, L"text");
2011 ok(hr == S_OK, "Failed to write a string, hr %#lx.\n", hr);
2013 hr = IXmlWriter_Flush(writer);
2014 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2016 CHECK_OUTPUT(stream,
2017 "<a>\r\n"
2018 " <b />\r\n"
2019 " <c attr=\"value\">text");
2021 hr = IXmlWriter_WriteEndElement(writer);
2022 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2024 hr = IXmlWriter_Flush(writer);
2025 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2027 CHECK_OUTPUT(stream,
2028 "<a>\r\n"
2029 " <b />\r\n"
2030 " <c attr=\"value\">text</c>");
2032 hr = IXmlWriter_WriteStartElement(writer, NULL, L"d", NULL);
2033 ok(hr == S_OK, "Failed to start element, hr %#lx.\n", hr);
2035 hr = IXmlWriter_WriteString(writer, L"");
2036 ok(hr == S_OK, "Failed to write a string, hr %#lx.\n", hr);
2038 hr = IXmlWriter_WriteEndElement(writer);
2039 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2041 hr = IXmlWriter_Flush(writer);
2042 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2044 CHECK_OUTPUT(stream,
2045 "<a>\r\n"
2046 " <b />\r\n"
2047 " <c attr=\"value\">text</c>\r\n"
2048 " <d></d>");
2050 hr = IXmlWriter_WriteEndElement(writer);
2051 ok(hr == S_OK, "Failed to end element, hr %#lx.\n", hr);
2053 hr = IXmlWriter_Flush(writer);
2054 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2056 CHECK_OUTPUT(stream,
2057 "<a>\r\n"
2058 " <b />\r\n"
2059 " <c attr=\"value\">text</c>\r\n"
2060 " <d></d>\r\n"
2061 "</a>");
2063 IXmlWriter_Release(writer);
2064 IStream_Release(stream);
2067 static void test_WriteDocType(void)
2069 static const struct
2071 const WCHAR *name;
2072 const WCHAR *pubid;
2073 const WCHAR *sysid;
2074 const WCHAR *subset;
2075 const char *output;
2077 doctype_tests[] =
2079 { L"a", L"", NULL, NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2080 { L"a", NULL, NULL, NULL, "<!DOCTYPE a>" },
2081 { L"a", NULL, L"", NULL, "<!DOCTYPE a SYSTEM \"\">" },
2082 { L"a", L"", L"", NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2083 { L"a", L"pubid", L"", NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2084 { L"a", L"pubid", NULL, NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2085 { L"a", L"", L"sysid", NULL, "<!DOCTYPE a PUBLIC \"\" \"sysid\">" },
2086 { L"a", NULL, NULL, L"", "<!DOCTYPE a []>" },
2087 { L"a", NULL, NULL, L"subset", "<!DOCTYPE a [subset]>" },
2088 { L"a", L"", NULL, L"subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2089 { L"a", NULL, L"", L"subset", "<!DOCTYPE a SYSTEM \"\" [subset]>" },
2090 { L"a", L"", L"", L"subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2091 { L"a", L"pubid", NULL, L"subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2092 { L"a", L"pubid", L"", L"subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2093 { L"a", NULL, L"sysid", L"subset", "<!DOCTYPE a SYSTEM \"sysid\" [subset]>" },
2094 { L"a", L"", L"sysid", L"subset", "<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
2095 { L"a", L"pubid", L"sysid", L"subset", "<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
2097 static const WCHAR pubidW[] = {'p',0x100,'i','d',0};
2098 IXmlWriter *writer;
2099 IStream *stream;
2100 unsigned int i;
2101 HRESULT hr;
2103 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2104 ok(hr == S_OK, "Failed to create writer instance, hr %#lx.\n", hr);
2106 stream = writer_set_output(writer);
2108 hr = IXmlWriter_WriteDocType(writer, NULL, NULL, NULL, NULL);
2109 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2111 hr = IXmlWriter_WriteDocType(writer, L"", NULL, NULL, NULL);
2112 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2114 /* Name validation. */
2115 hr = IXmlWriter_WriteDocType(writer, L"-a", NULL, NULL, NULL);
2116 ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr);
2118 /* Pubid validation. */
2119 hr = IXmlWriter_WriteDocType(writer, L"a", pubidW, NULL, NULL);
2120 ok(hr == WC_E_PUBLICID, "Unexpected hr %#lx.\n", hr);
2122 IStream_Release(stream);
2124 for (i = 0; i < ARRAY_SIZE(doctype_tests); i++)
2126 stream = writer_set_output(writer);
2128 hr = IXmlWriter_WriteDocType(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2129 doctype_tests[i].subset);
2130 ok(hr == S_OK, "%u: failed to write doctype, hr %#lx.\n", i, hr);
2132 hr = IXmlWriter_Flush(writer);
2133 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2135 CHECK_OUTPUT(stream, doctype_tests[i].output);
2137 hr = IXmlWriter_WriteDocType(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2138 doctype_tests[i].subset);
2139 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr);
2141 IStream_Release(stream);
2144 IXmlWriter_Release(writer);
2147 static void test_WriteWhitespace(void)
2149 IXmlWriter *writer;
2150 IStream *stream;
2151 HRESULT hr;
2153 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2154 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2156 stream = writer_set_output(writer);
2158 hr = IXmlWriter_WriteWhitespace(writer, L" ");
2159 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2160 hr = IXmlWriter_WriteWhitespace(writer, L"ab");
2161 ok(hr == WR_E_NONWHITESPACE, "Unexpected hr %#lx.\n", hr);
2162 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2164 hr = IXmlWriter_WriteWhitespace(writer, L"\t");
2165 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2167 hr = IXmlWriter_Flush(writer);
2168 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2169 CHECK_OUTPUT(stream, " <w>\t");
2170 IStream_Release(stream);
2172 IXmlWriter_Release(writer);
2175 static void test_WriteProcessingInstruction(void)
2177 IXmlWriter *writer;
2178 IStream *stream;
2179 HRESULT hr;
2181 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2182 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2184 stream = writer_set_output(writer);
2186 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2187 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2188 hr = IXmlWriter_WriteProcessingInstruction(writer, L"pi", L"content");
2189 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2191 hr = IXmlWriter_Flush(writer);
2192 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2193 CHECK_OUTPUT(stream, "<w><?pi content?>");
2194 IStream_Release(stream);
2196 IXmlWriter_Release(writer);
2199 static void test_WriteAttributes(void)
2201 XmlNodeType node_type;
2202 IXmlWriter *writer;
2203 IXmlReader *reader;
2204 const WCHAR *name;
2205 IStream *stream;
2206 HRESULT hr;
2208 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2209 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2211 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2212 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2214 /* No attributes. */
2215 reader_set_input(reader, "<a/>");
2216 stream = writer_set_output(writer);
2217 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2218 ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
2219 hr = IXmlReader_Read(reader, NULL);
2220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2221 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2222 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2223 hr = IXmlWriter_Flush(writer);
2224 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2225 CHECK_OUTPUT(stream, "");
2226 IStream_Release(stream);
2228 /* Position on element with attributes. */
2229 reader_set_input(reader, "<a attr1=\'b\' attr2=\'c\' attr3=\'d\' />");
2230 stream = writer_set_output(writer);
2231 hr = IXmlReader_Read(reader, NULL);
2232 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2233 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2234 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2235 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2237 hr = IXmlReader_GetNodeType(reader, &node_type);
2238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2239 ok(node_type == XmlNodeType_Element, "Unexpected node type %d.\n", node_type);
2240 hr = IXmlWriter_Flush(writer);
2241 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2242 CHECK_OUTPUT(stream, "<w attr1=\"b\" attr2=\"c\" attr3=\"d\"");
2243 IStream_Release(stream);
2245 /* Position on second attribute. */
2246 hr = IXmlReader_MoveToAttributeByName(reader, L"attr2", NULL);
2247 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2248 stream = writer_set_output(writer);
2249 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2250 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2251 hr = IXmlWriter_WriteAttributes(writer, reader, FALSE);
2252 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2253 hr = IXmlReader_GetNodeType(reader, &node_type);
2254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2255 ok(node_type == XmlNodeType_Attribute, "Unexpected node type %d.\n", node_type);
2256 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2257 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2258 ok(!wcscmp(name, L"attr3"), "Unexpected node %s.\n", debugstr_w(name));
2259 hr = IXmlWriter_Flush(writer);
2260 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2261 CHECK_OUTPUT(stream, "<w attr2=\"c\" attr3=\"d\"");
2262 IStream_Release(stream);
2264 IXmlWriter_Release(writer);
2265 IXmlReader_Release(reader);
2268 static void test_WriteNode(void)
2270 static const struct
2272 const char *input;
2273 const char *output;
2274 XmlNodeType node_type;
2276 write_node_tests[] =
2278 { "<r><!-- comment --></r>", "<w><!-- comment -->", XmlNodeType_Comment },
2279 { "<r>text</r>", "<w>text", XmlNodeType_Text },
2280 { "<r> </r>", "<w> ", XmlNodeType_Whitespace },
2281 { "<r><![CDATA[ cdata ]]></r>", "<w><![CDATA[ cdata ]]>", XmlNodeType_CDATA },
2282 { "<r><?pi pidata ?></r>", "<w><?pi pidata ?>", XmlNodeType_ProcessingInstruction },
2283 { "<r><e1><e2 attr1=\'a\'/></e1></r>", "<w><e1><e2 attr1=\"a\" /></e1>", XmlNodeType_Element },
2284 { "<r><e1/></r>", "<w><e1 />", XmlNodeType_Element },
2285 { "<r></r>", "<w></w>", XmlNodeType_EndElement },
2287 XmlNodeType node_type;
2288 IXmlWriter *writer;
2289 IXmlReader *reader;
2290 const WCHAR *name;
2291 IStream *stream;
2292 unsigned int i;
2293 HRESULT hr;
2295 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2296 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2298 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2301 for (i = 0; i < ARRAY_SIZE(write_node_tests); ++i)
2303 winetest_push_context("Test %s", debugstr_a(write_node_tests[i].input));
2305 stream = writer_set_output(writer);
2306 reader_set_input(reader, write_node_tests[i].input);
2308 /* Skip top level element. */
2309 hr = IXmlReader_Read(reader, &node_type);
2310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2312 hr = IXmlReader_Read(reader, &node_type);
2313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2314 ok(node_type == write_node_tests[i].node_type, "Unexpected node type %d.\n", node_type);
2316 /* Always write a root node to give a valid context for following nodes. */
2317 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2319 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2320 ok(SUCCEEDED(hr), "Failed to write a node, hr %#lx.\n", hr);
2322 if (hr == S_OK)
2324 hr = IXmlReader_GetNodeType(reader, &node_type);
2325 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2326 ok(node_type == XmlNodeType_EndElement, "Unexpected node type on return %d.\n", node_type);
2327 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2328 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2329 ok(!wcscmp(name, L"r"), "Unexpected node name %s.\n", debugstr_w(name));
2332 hr = IXmlWriter_Flush(writer);
2333 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2335 CHECK_OUTPUT(stream, write_node_tests[i].output);
2337 IStream_Release(stream);
2339 winetest_pop_context();
2342 /* Current node is an attribute. */
2343 reader_set_input(reader, "<a attr=\'b\' ></a>");
2344 hr = IXmlReader_Read(reader, &node_type);
2345 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2346 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2347 hr = IXmlReader_MoveToFirstAttribute(reader);
2348 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2350 stream = writer_set_output(writer);
2351 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2352 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2353 hr = IXmlReader_GetNodeType(reader, &node_type);
2354 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2355 ok(node_type == XmlNodeType_EndElement, "Unexpected node type on return %d.\n", node_type);
2356 hr = IXmlWriter_Flush(writer);
2357 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2358 CHECK_OUTPUT(stream, "");
2359 IStream_Release(stream);
2361 /* Xml declaration node. */
2362 reader_set_input(reader, "<?xml version=\"1.0\" ?><a/>");
2363 hr = IXmlReader_Read(reader, &node_type);
2364 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2365 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2367 stream = writer_set_output(writer);
2368 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2369 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2370 hr = IXmlReader_GetNodeType(reader, &node_type);
2371 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2372 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2373 hr = IXmlWriter_Flush(writer);
2374 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2375 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
2376 IStream_Release(stream);
2378 /* With standalone attribute. */
2379 reader_set_input(reader, "<?xml version=\"1.0\" standalone=\'yes\'?><a/>");
2380 hr = IXmlReader_Read(reader, &node_type);
2381 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2382 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2384 stream = writer_set_output(writer);
2385 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2386 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2387 hr = IXmlReader_GetNodeType(reader, &node_type);
2388 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2389 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2390 hr = IXmlWriter_Flush(writer);
2391 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2392 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
2393 IStream_Release(stream);
2395 /* Initial state. */
2396 reader_set_input(reader, "<?xml version=\"1.0\" ?><a><b/></a>");
2397 hr = IXmlReader_GetNodeType(reader, &node_type);
2398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2399 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2400 stream = writer_set_output(writer);
2401 hr = IXmlWriter_WriteNode(writer, reader, FALSE);
2402 ok(hr == S_FALSE, "Failed to write a node, hr %#lx.\n", hr);
2403 node_type = XmlNodeType_Element;
2404 hr = IXmlReader_GetNodeType(reader, &node_type);
2405 todo_wine
2406 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
2407 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2408 hr = IXmlWriter_Flush(writer);
2409 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2410 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><a><b /></a>");
2411 IStream_Release(stream);
2413 IXmlReader_Release(reader);
2414 IXmlWriter_Release(writer);
2417 static void test_WriteNodeShallow(void)
2419 static const struct
2421 const char *input;
2422 const char *output;
2423 XmlNodeType node_type;
2425 write_node_tests[] =
2427 { "<r><!-- comment --></r>", "<w><!-- comment -->", XmlNodeType_Comment },
2428 { "<r>text</r>", "<w>text", XmlNodeType_Text },
2429 { "<r> </r>", "<w> ", XmlNodeType_Whitespace },
2430 { "<r><![CDATA[ cdata ]]></r>", "<w><![CDATA[ cdata ]]>", XmlNodeType_CDATA },
2431 { "<r><?pi pidata ?></r>", "<w><?pi pidata ?>", XmlNodeType_ProcessingInstruction },
2432 { "<r><e1><e2 attr1=\'a\'/></e1></r>", "<w><e1", XmlNodeType_Element },
2433 { "<r><e1/></r>", "<w><e1 />", XmlNodeType_Element },
2434 { "<r><e1 attr1=\'a\'/></r>", "<w><e1 attr1=\"a\" />", XmlNodeType_Element },
2435 { "<r><e1 attr1=\'a\'></e1></r>", "<w><e1 attr1=\"a\"", XmlNodeType_Element },
2436 { "<r></r>", "<w></w>", XmlNodeType_EndElement },
2438 XmlNodeType node_type;
2439 IXmlWriter *writer;
2440 IXmlReader *reader;
2441 IStream *stream;
2442 unsigned int i;
2443 HRESULT hr;
2445 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2446 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2448 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2451 for (i = 0; i < ARRAY_SIZE(write_node_tests); ++i)
2453 winetest_push_context("Test %s", debugstr_a(write_node_tests[i].input));
2455 stream = writer_set_output(writer);
2456 reader_set_input(reader, write_node_tests[i].input);
2458 /* Skip top level element. */
2459 hr = IXmlReader_Read(reader, &node_type);
2460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2462 hr = IXmlReader_Read(reader, &node_type);
2463 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2464 ok(node_type == write_node_tests[i].node_type, "Unexpected node type %d.\n", node_type);
2466 /* Always write a root node to give a valid context for following nodes. */
2467 hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL);
2468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2469 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2470 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2472 hr = IXmlReader_GetNodeType(reader, &node_type);
2473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2474 ok(node_type == write_node_tests[i].node_type, "Unexpected node type on return %d.\n", node_type);
2476 hr = IXmlWriter_Flush(writer);
2477 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2479 CHECK_OUTPUT(stream, write_node_tests[i].output);
2481 IStream_Release(stream);
2483 winetest_pop_context();
2486 /* Current node is an attribute. */
2487 reader_set_input(reader, "<a attr=\'b\' ></a>");
2488 hr = IXmlReader_Read(reader, &node_type);
2489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2490 ok(node_type == XmlNodeType_Element, "Unexpected node type on return %d.\n", node_type);
2491 hr = IXmlReader_MoveToFirstAttribute(reader);
2492 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2494 stream = writer_set_output(writer);
2495 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2496 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2497 hr = IXmlReader_GetNodeType(reader, &node_type);
2498 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2499 ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type);
2500 hr = IXmlWriter_Flush(writer);
2501 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2502 CHECK_OUTPUT(stream, "");
2503 IStream_Release(stream);
2505 /* Xml declaration node. */
2506 reader_set_input(reader, "<?xml version=\"1.0\" ?><a/>");
2507 hr = IXmlReader_Read(reader, &node_type);
2508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2509 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2511 stream = writer_set_output(writer);
2512 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2513 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2514 hr = IXmlReader_GetNodeType(reader, &node_type);
2515 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2516 ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type);
2517 hr = IXmlWriter_Flush(writer);
2518 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2519 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
2520 IStream_Release(stream);
2522 /* With standalone attribute. */
2523 reader_set_input(reader, "<?xml version=\"1.0\" standalone=\'yes\'?><a/>");
2524 hr = IXmlReader_Read(reader, &node_type);
2525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2526 ok(node_type == XmlNodeType_XmlDeclaration, "Unexpected node type on return %d.\n", node_type);
2528 stream = writer_set_output(writer);
2529 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2530 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2531 hr = IXmlReader_GetNodeType(reader, &node_type);
2532 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2533 ok(node_type == XmlNodeType_Attribute, "Unexpected node type on return %d.\n", node_type);
2534 hr = IXmlWriter_Flush(writer);
2535 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2536 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
2537 IStream_Release(stream);
2539 /* Initial state. */
2540 reader_set_input(reader, "<?xml version=\"1.0\" ?><a><b/></a>");
2541 hr = IXmlReader_GetNodeType(reader, &node_type);
2542 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2543 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2544 stream = writer_set_output(writer);
2545 hr = IXmlWriter_WriteNodeShallow(writer, reader, FALSE);
2546 ok(hr == S_OK, "Failed to write a node, hr %#lx.\n", hr);
2547 node_type = XmlNodeType_Element;
2548 hr = IXmlReader_GetNodeType(reader, &node_type);
2549 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2550 ok(node_type == XmlNodeType_None, "Unexpected node type on return %d.\n", node_type);
2551 hr = IXmlWriter_Flush(writer);
2552 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
2553 CHECK_OUTPUT(stream, "");
2554 IStream_Release(stream);
2556 IXmlReader_Release(reader);
2557 IXmlWriter_Release(writer);
2560 START_TEST(writer)
2562 test_writer_create();
2563 test_writer_state();
2564 test_writeroutput();
2565 test_writestartdocument();
2566 test_WriteStartElement();
2567 test_WriteElementString();
2568 test_WriteEndElement();
2569 test_flush();
2570 test_omitxmldeclaration();
2571 test_bom();
2572 test_writeenddocument();
2573 test_WriteComment();
2574 test_WriteCData();
2575 test_WriteRaw();
2576 test_indentation();
2577 test_WriteAttributeString();
2578 test_WriteFullEndElement();
2579 test_WriteCharEntity();
2580 test_WriteString();
2581 test_WriteDocType();
2582 test_WriteWhitespace();
2583 test_WriteProcessingInstruction();
2584 test_WriteAttributes();
2585 test_WriteNode();
2586 test_WriteNodeShallow();