wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / xmllite / tests / writer.c
blob13d67becbe4112e7ef8022ded75f1d8145ebe209
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/heap.h"
31 #include "wine/test.h"
33 #include "initguid.h"
34 DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
36 static const WCHAR aW[] = {'a',0};
38 #define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
39 static void _expect_ref(IUnknown *obj, ULONG ref, int line)
41 ULONG refcount;
42 IUnknown_AddRef(obj);
43 refcount = IUnknown_Release(obj);
44 ok_(__FILE__, line)(refcount == ref, "expected refcount %d, got %d\n", ref, refcount);
47 static void check_output_raw(IStream *stream, const void *expected, SIZE_T size, int line)
49 SIZE_T content_size;
50 HGLOBAL hglobal;
51 HRESULT hr;
52 WCHAR *ptr;
54 hr = GetHGlobalFromStream(stream, &hglobal);
55 ok_(__FILE__, line)(hr == S_OK, "Failed to get the stream handle, hr %#x.\n", hr);
57 content_size = GlobalSize(hglobal);
58 ok_(__FILE__, line)(size == content_size, "Unexpected test output size %ld.\n", content_size);
59 ptr = GlobalLock(hglobal);
60 if (size <= content_size)
61 ok_(__FILE__, line)(!memcmp(expected, ptr, size), "Unexpected output content.\n");
62 if (size != content_size && *ptr == 0xfeff)
63 ok_(__FILE__, line)(0, "Content: %s.\n", wine_dbgstr_wn(ptr, content_size / sizeof(WCHAR)));
65 GlobalUnlock(hglobal);
68 static void check_output(IStream *stream, const char *expected, BOOL todo, int line)
70 int len = strlen(expected), size;
71 HGLOBAL hglobal;
72 HRESULT hr;
73 char *ptr;
75 hr = GetHGlobalFromStream(stream, &hglobal);
76 ok_(__FILE__, line)(hr == S_OK, "got 0x%08x\n", hr);
78 size = GlobalSize(hglobal);
79 ptr = GlobalLock(hglobal);
80 todo_wine_if(todo)
82 if (size != len)
84 ok_(__FILE__, line)(0, "data size mismatch, expected %u, got %u\n", len, size);
85 ok_(__FILE__, line)(0, "got |%s|, expected |%s|\n", ptr, expected);
87 else
88 ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got |%s|, expected |%s|\n", ptr, expected);
90 GlobalUnlock(hglobal);
92 #define CHECK_OUTPUT(stream, expected) check_output(stream, expected, FALSE, __LINE__)
93 #define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE, __LINE__)
94 #define CHECK_OUTPUT_RAW(stream, expected, size) check_output_raw(stream, expected, size, __LINE__)
96 static WCHAR *strdupAtoW(const char *str)
98 WCHAR *ret = NULL;
99 DWORD len;
101 if (!str) return ret;
102 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
103 ret = heap_alloc(len * sizeof(WCHAR));
104 if (ret)
105 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
106 return ret;
109 static void writer_set_property(IXmlWriter *writer, XmlWriterProperty property)
111 HRESULT hr;
113 hr = IXmlWriter_SetProperty(writer, property, TRUE);
114 ok(hr == S_OK, "Failed to set writer property, hr %#x.\n", hr);
117 /* used to test all Write* methods for consistent error state */
118 static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
120 static const WCHAR aW[] = {'a',0};
121 HRESULT hr;
123 /* FIXME: add WriteAttributes */
125 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
126 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
128 hr = IXmlWriter_WriteCData(writer, aW);
129 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
131 hr = IXmlWriter_WriteCharEntity(writer, aW[0]);
132 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
134 hr = IXmlWriter_WriteChars(writer, aW, 1);
135 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
137 hr = IXmlWriter_WriteComment(writer, aW);
138 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
140 hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
141 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
143 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
144 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
146 hr = IXmlWriter_WriteEndDocument(writer);
147 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
149 hr = IXmlWriter_WriteEndElement(writer);
150 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
152 hr = IXmlWriter_WriteEntityRef(writer, aW);
153 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
155 hr = IXmlWriter_WriteFullEndElement(writer);
156 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
158 hr = IXmlWriter_WriteName(writer, aW);
159 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
161 hr = IXmlWriter_WriteNmToken(writer, aW);
162 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
164 /* FIXME: add WriteNode */
165 /* FIXME: add WriteNodeShallow */
167 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
168 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
170 hr = IXmlWriter_WriteQualifiedName(writer, aW, NULL);
171 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
173 hr = IXmlWriter_WriteRaw(writer, aW);
174 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
176 hr = IXmlWriter_WriteRawChars(writer, aW, 1);
177 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
179 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
180 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
182 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
183 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
185 hr = IXmlWriter_WriteString(writer, aW);
186 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
188 /* FIXME: add WriteSurrogateCharEntity */
189 /* FIXME: add WriteWhitespace */
192 static IStream *writer_set_output(IXmlWriter *writer)
194 IStream *stream;
195 HRESULT hr;
197 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
198 ok(hr == S_OK, "got 0x%08x\n", hr);
200 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
201 ok(hr == S_OK, "got 0x%08x\n", hr);
203 return stream;
206 static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
208 if (IsEqualGUID(riid, &IID_IUnknown)) {
209 *obj = iface;
210 return S_OK;
212 else {
213 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
214 return E_NOINTERFACE;
218 static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
220 return 2;
223 static ULONG WINAPI testoutput_Release(IUnknown *iface)
225 return 1;
228 static const IUnknownVtbl testoutputvtbl = {
229 testoutput_QueryInterface,
230 testoutput_AddRef,
231 testoutput_Release
234 static IUnknown testoutput = { &testoutputvtbl };
236 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
238 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
240 *obj = iface;
241 return S_OK;
244 *obj = NULL;
245 return E_NOINTERFACE;
248 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
250 return 2;
253 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
255 return 1;
258 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
260 ok(0, "unexpected call\n");
261 return E_NOTIMPL;
264 static ULONG g_write_len;
265 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
267 g_write_len = cb;
268 *written = cb;
269 return S_OK;
272 static const ISequentialStreamVtbl teststreamvtbl =
274 teststream_QueryInterface,
275 teststream_AddRef,
276 teststream_Release,
277 teststream_Read,
278 teststream_Write
281 static ISequentialStream teststream = { &teststreamvtbl };
283 static void test_writer_create(void)
285 HRESULT hr;
286 IXmlWriter *writer;
287 LONG_PTR value;
288 IUnknown *unk;
290 /* crashes native */
291 if (0)
293 CreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
294 CreateXmlWriter(NULL, (void**)&writer, NULL);
297 hr = CreateXmlWriter(&IID_IStream, (void **)&unk, NULL);
298 ok(hr == E_NOINTERFACE, "got %08x\n", hr);
300 hr = CreateXmlWriter(&IID_IUnknown, (void **)&unk, NULL);
301 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
302 hr = IUnknown_QueryInterface(unk, &IID_IXmlWriter, (void **)&writer);
303 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
304 ok(unk == (IUnknown *)writer, "unexpected interface pointer\n");
305 IUnknown_Release(unk);
306 IXmlWriter_Release(writer);
308 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
309 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
311 /* check default properties values */
312 value = 0;
313 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
314 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
315 ok(value == TRUE, "got %ld\n", value);
317 value = TRUE;
318 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
319 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
320 ok(value == FALSE, "got %ld\n", value);
322 value = TRUE;
323 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
324 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
325 ok(value == FALSE, "got %ld\n", value);
327 value = XmlConformanceLevel_Auto;
328 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
329 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
330 ok(value == XmlConformanceLevel_Document, "got %ld\n", value);
332 IXmlWriter_Release(writer);
335 static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown *output)
337 HRESULT hr;
339 hr = IXmlWriter_SetOutput(writer, output);
340 ok(hr == S_OK, "Failed to set output, hr %#x.\n", hr);
342 /* TODO: WriteAttributes */
344 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
345 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
347 hr = IXmlWriter_WriteCData(writer, aW);
348 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
350 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
351 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
353 hr = IXmlWriter_WriteChars(writer, aW, 1);
354 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
356 hr = IXmlWriter_WriteComment(writer, aW);
357 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
359 hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
360 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
362 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
363 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
365 hr = IXmlWriter_WriteEndDocument(writer);
366 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
368 hr = IXmlWriter_WriteEndElement(writer);
369 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
371 hr = IXmlWriter_WriteEntityRef(writer, aW);
372 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
374 hr = IXmlWriter_WriteFullEndElement(writer);
375 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
377 hr = IXmlWriter_WriteName(writer, aW);
378 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
380 hr = IXmlWriter_WriteNmToken(writer, aW);
381 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
383 /* TODO: WriteNode */
384 /* TODO: WriteNodeShallow */
386 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
387 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
389 hr = IXmlWriter_WriteQualifiedName(writer, aW, NULL);
390 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
392 hr = IXmlWriter_WriteRaw(writer, aW);
393 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
395 hr = IXmlWriter_WriteRawChars(writer, aW, 1);
396 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
398 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
399 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
401 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
402 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
404 hr = IXmlWriter_WriteString(writer, aW);
405 ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
407 /* TODO: WriteSurrogateCharEntity */
408 /* ًُُTODO: WriteWhitespace */
410 hr = IXmlWriter_Flush(writer);
411 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
414 static void test_writeroutput(void)
416 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
417 static const WCHAR usasciiW[] = {'u','s','-','a','s','c','i','i',0};
418 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
419 static const WCHAR utf16_outputW[] = {0xfeff,'<','a'};
420 IXmlWriterOutput *output;
421 IXmlWriter *writer;
422 IStream *stream;
423 IUnknown *unk;
424 HRESULT hr;
426 output = NULL;
427 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
428 ok(hr == S_OK, "got %08x\n", hr);
429 EXPECT_REF(output, 1);
430 IUnknown_Release(output);
432 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output);
433 ok(hr == S_OK, "got %08x\n", hr);
434 unk = NULL;
435 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
436 ok(hr == S_OK, "got %08x\n", hr);
437 todo_wine
438 ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output);
439 EXPECT_REF(output, 2);
440 /* releasing 'unk' crashes on native */
441 IUnknown_Release(output);
442 EXPECT_REF(output, 1);
443 IUnknown_Release(output);
445 output = NULL;
446 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output);
447 ok(hr == S_OK, "got %08x\n", hr);
448 IUnknown_Release(output);
450 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, CP_UTF8, &output);
451 ok(hr == S_OK, "got %08x\n", hr);
452 unk = NULL;
453 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
454 ok(hr == S_OK, "got %08x\n", hr);
455 ok(unk != NULL, "got %p\n", unk);
456 /* releasing 'unk' crashes on native */
457 IUnknown_Release(output);
458 IUnknown_Release(output);
460 /* create with us-ascii */
461 output = NULL;
462 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, usasciiW, &output);
463 ok(hr == S_OK, "got %08x\n", hr);
464 IUnknown_Release(output);
466 /* Output with codepage 1200. */
467 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
468 ok(hr == S_OK, "Failed to create writer, hr %#x.\n", hr);
470 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
471 ok(hr == S_OK, "Failed to create stream, hr %#x.\n", hr);
473 hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, 1200, &output);
474 ok(hr == S_OK, "Failed to create writer output, hr %#x.\n", hr);
476 hr = IXmlWriter_SetOutput(writer, output);
477 ok(hr == S_OK, "Failed to set writer output, hr %#x.\n", hr);
479 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
480 ok(hr == S_OK, "Write failed, hr %#x.\n", hr);
482 hr = IXmlWriter_Flush(writer);
483 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
485 CHECK_OUTPUT_RAW(stream, utf16_outputW, sizeof(utf16_outputW));
487 IStream_Release(stream);
488 IUnknown_Release(output);
490 /* Create output with meaningless code page value. */
491 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
492 ok(hr == S_OK, "Failed to create stream, hr %#x.\n", hr);
494 output = NULL;
495 hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, ~0u, &output);
496 ok(hr == S_OK, "Failed to create writer output, hr %#x.\n", hr);
498 test_invalid_output_encoding(writer, output);
499 CHECK_OUTPUT(stream, "");
501 IStream_Release(stream);
502 IUnknown_Release(output);
504 /* Same, with invalid encoding name. */
505 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
506 ok(hr == S_OK, "got 0x%08x\n", hr);
508 output = NULL;
509 hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, dummyW, &output);
510 ok(hr == S_OK, "got %08x\n", hr);
512 test_invalid_output_encoding(writer, output);
513 CHECK_OUTPUT(stream, "");
515 IStream_Release(stream);
516 IUnknown_Release(output);
518 IXmlWriter_Release(writer);
521 static void test_writestartdocument(void)
523 static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
524 static const char *prologversion2 = "<?xml version=\"1.0\" encoding=\"uS-asCii\"?>";
525 static const char prologversion[] = "<?xml version=\"1.0\"?>";
526 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
527 static const WCHAR usasciiW[] = {'u','S','-','a','s','C','i','i',0};
528 static const WCHAR xmlW[] = {'x','m','l',0};
529 IXmlWriterOutput *output;
530 IXmlWriter *writer;
531 IStream *stream;
532 HRESULT hr;
534 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
535 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
537 /* output not set */
538 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
539 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
541 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
542 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
544 hr = IXmlWriter_Flush(writer);
545 ok(hr == S_OK, "got 0x%08x\n", hr);
547 stream = writer_set_output(writer);
549 /* nothing written yet */
550 hr = IXmlWriter_Flush(writer);
551 ok(hr == S_OK, "got 0x%08x\n", hr);
553 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
554 ok(hr == S_OK, "got 0x%08x\n", hr);
556 hr = IXmlWriter_Flush(writer);
557 ok(hr == S_OK, "got 0x%08x\n", hr);
559 CHECK_OUTPUT(stream, fullprolog);
561 /* one more time */
562 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
563 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
564 IStream_Release(stream);
566 /* now add PI manually, and try to start a document */
567 stream = writer_set_output(writer);
569 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
570 ok(hr == S_OK, "got 0x%08x\n", hr);
572 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
573 ok(hr == S_OK, "got 0x%08x\n", hr);
575 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
576 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
578 /* another attempt to add 'xml' PI */
579 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
580 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
582 hr = IXmlWriter_Flush(writer);
583 ok(hr == S_OK, "got 0x%08x\n", hr);
585 CHECK_OUTPUT(stream, prologversion);
587 IStream_Release(stream);
588 IXmlWriter_Release(writer);
590 /* create with us-ascii */
591 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
592 ok(hr == S_OK, "got 0x%08x\n", hr);
594 output = NULL;
595 hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, usasciiW, &output);
596 ok(hr == S_OK, "got %08x\n", hr);
598 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
599 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
601 hr = IXmlWriter_SetOutput(writer, output);
602 ok(hr == S_OK, "got %08x\n", hr);
604 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
605 ok(hr == S_OK, "got 0x%08x\n", hr);
607 hr = IXmlWriter_Flush(writer);
608 ok(hr == S_OK, "got 0x%08x\n", hr);
610 CHECK_OUTPUT(stream, prologversion2);
612 IStream_Release(stream);
613 IXmlWriter_Release(writer);
614 IUnknown_Release(output);
617 static void test_flush(void)
619 IXmlWriter *writer;
620 HRESULT hr;
622 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
623 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
625 hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
626 ok(hr == S_OK, "got 0x%08x\n", hr);
628 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
629 ok(hr == S_OK, "got 0x%08x\n", hr);
631 g_write_len = 0;
632 hr = IXmlWriter_Flush(writer);
633 ok(hr == S_OK, "got 0x%08x\n", hr);
634 ok(g_write_len > 0, "got %d\n", g_write_len);
636 g_write_len = 1;
637 hr = IXmlWriter_Flush(writer);
638 ok(hr == S_OK, "got 0x%08x\n", hr);
639 ok(g_write_len == 0, "got %d\n", g_write_len);
641 /* Release() flushes too */
642 g_write_len = 1;
643 IXmlWriter_Release(writer);
644 ok(g_write_len == 0, "got %d\n", g_write_len);
647 static void test_omitxmldeclaration(void)
649 static const char prologversion[] = "<?xml version=\"1.0\"?>";
650 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
651 static const WCHAR xmlW[] = {'x','m','l',0};
652 IXmlWriter *writer;
653 HGLOBAL hglobal;
654 IStream *stream;
655 HRESULT hr;
656 char *ptr;
658 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
659 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
661 stream = writer_set_output(writer);
663 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
665 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
666 ok(hr == S_OK, "got 0x%08x\n", hr);
668 hr = IXmlWriter_Flush(writer);
669 ok(hr == S_OK, "got 0x%08x\n", hr);
671 hr = GetHGlobalFromStream(stream, &hglobal);
672 ok(hr == S_OK, "got 0x%08x\n", hr);
674 ptr = GlobalLock(hglobal);
675 ok(!ptr, "got %p\n", ptr);
676 GlobalUnlock(hglobal);
678 /* one more time */
679 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
680 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
682 IStream_Release(stream);
684 /* now add PI manually, and try to start a document */
685 stream = writer_set_output(writer);
687 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
688 ok(hr == S_OK, "got 0x%08x\n", hr);
690 hr = IXmlWriter_Flush(writer);
691 ok(hr == S_OK, "got 0x%08x\n", hr);
693 CHECK_OUTPUT(stream, prologversion);
695 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
696 ok(hr == S_OK, "got 0x%08x\n", hr);
698 hr = IXmlWriter_Flush(writer);
699 ok(hr == S_OK, "got 0x%08x\n", hr);
701 CHECK_OUTPUT(stream, prologversion);
703 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
704 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
706 hr = IXmlWriter_Flush(writer);
707 ok(hr == S_OK, "got 0x%08x\n", hr);
709 CHECK_OUTPUT(stream, prologversion);
711 /* another attempt to add 'xml' PI */
712 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
713 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
715 hr = IXmlWriter_Flush(writer);
716 ok(hr == S_OK, "got 0x%08x\n", hr);
718 IStream_Release(stream);
719 IXmlWriter_Release(writer);
722 static void test_bom(void)
724 static const WCHAR piW[] = {0xfeff,'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>'};
725 static const WCHAR aopenW[] = {0xfeff,'<','a'};
726 static const WCHAR afullW[] = {0xfeff,'<','a',' ','/','>'};
727 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
728 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
729 static const WCHAR xmlW[] = {'x','m','l',0};
730 static const WCHAR bomW[] = {0xfeff};
731 IXmlWriterOutput *output;
732 IXmlWriter *writer;
733 IStream *stream;
734 HGLOBAL hglobal;
735 HRESULT hr;
737 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
738 ok(hr == S_OK, "got 0x%08x\n", hr);
740 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
741 ok(hr == S_OK, "got %08x\n", hr);
743 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
744 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
746 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
748 hr = IXmlWriter_SetOutput(writer, output);
749 ok(hr == S_OK, "got 0x%08x\n", hr);
751 /* BOM is on by default */
752 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
753 ok(hr == S_OK, "got 0x%08x\n", hr);
755 hr = IXmlWriter_Flush(writer);
756 ok(hr == S_OK, "got 0x%08x\n", hr);
758 CHECK_OUTPUT_RAW(stream, bomW, sizeof(bomW));
760 IStream_Release(stream);
761 IUnknown_Release(output);
763 /* start with PI */
764 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
765 ok(hr == S_OK, "got 0x%08x\n", hr);
767 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
768 ok(hr == S_OK, "got %08x\n", hr);
770 hr = IXmlWriter_SetOutput(writer, output);
771 ok(hr == S_OK, "got 0x%08x\n", hr);
773 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
774 ok(hr == S_OK, "got 0x%08x\n", hr);
776 hr = IXmlWriter_Flush(writer);
777 ok(hr == S_OK, "got 0x%08x\n", hr);
779 CHECK_OUTPUT_RAW(stream, piW, sizeof(piW));
781 IUnknown_Release(output);
782 IStream_Release(stream);
784 /* start with element */
785 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
786 ok(hr == S_OK, "got 0x%08x\n", hr);
788 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
789 ok(hr == S_OK, "got %08x\n", hr);
791 hr = IXmlWriter_SetOutput(writer, output);
792 ok(hr == S_OK, "got 0x%08x\n", hr);
794 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
795 ok(hr == S_OK, "got 0x%08x\n", hr);
797 hr = IXmlWriter_Flush(writer);
798 ok(hr == S_OK, "got 0x%08x\n", hr);
800 CHECK_OUTPUT_RAW(stream, aopenW, sizeof(aopenW));
802 IUnknown_Release(output);
803 IStream_Release(stream);
805 /* WriteElementString */
806 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
807 ok(hr == S_OK, "got 0x%08x\n", hr);
809 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
810 ok(hr == S_OK, "got %08x\n", hr);
812 hr = IXmlWriter_SetOutput(writer, output);
813 ok(hr == S_OK, "got 0x%08x\n", hr);
815 writer_set_property(writer, XmlWriterProperty_Indent);
817 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
818 ok(hr == S_OK, "got 0x%08x\n", hr);
820 hr = IXmlWriter_Flush(writer);
821 ok(hr == S_OK, "got 0x%08x\n", hr);
823 hr = GetHGlobalFromStream(stream, &hglobal);
824 ok(hr == S_OK, "got 0x%08x\n", hr);
826 CHECK_OUTPUT_RAW(stream, afullW, sizeof(afullW));
828 IUnknown_Release(output);
829 IStream_Release(stream);
831 IXmlWriter_Release(writer);
834 static HRESULT write_start_element(IXmlWriter *writer, const char *prefix, const char *local,
835 const char *uri)
837 WCHAR *prefixW, *localW, *uriW;
838 HRESULT hr;
840 prefixW = strdupAtoW(prefix);
841 localW = strdupAtoW(local);
842 uriW = strdupAtoW(uri);
844 hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW);
846 heap_free(prefixW);
847 heap_free(localW);
848 heap_free(uriW);
850 return hr;
853 static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, const char *local,
854 const char *uri, const char *value)
856 WCHAR *prefixW, *localW, *uriW, *valueW;
857 HRESULT hr;
859 prefixW = strdupAtoW(prefix);
860 localW = strdupAtoW(local);
861 uriW = strdupAtoW(uri);
862 valueW = strdupAtoW(value);
864 hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW);
866 heap_free(prefixW);
867 heap_free(localW);
868 heap_free(uriW);
869 heap_free(valueW);
871 return hr;
874 static HRESULT write_string(IXmlWriter *writer, const char *str)
876 WCHAR *strW;
877 HRESULT hr;
879 strW = strdupAtoW(str);
881 hr = IXmlWriter_WriteString(writer, strW);
883 heap_free(strW);
885 return hr;
888 static void test_WriteStartElement(void)
890 static const struct
892 const char *prefix;
893 const char *local;
894 const char *uri;
895 const char *output;
896 const char *output_partial;
897 HRESULT hr;
898 int todo;
899 int todo_partial;
901 start_element_tests[] =
903 { "prefix", "local", "uri", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local" },
904 { NULL, "local", "uri", "<local xmlns=\"uri\" />", "<local" },
905 { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
906 { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
908 { "prefix", NULL, NULL, NULL, NULL, E_INVALIDARG },
909 { NULL, NULL, "uri", NULL, NULL, E_INVALIDARG },
910 { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
911 { NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
912 { "pre:fix", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
913 { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
914 { ":", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
915 { NULL, "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
916 { "prefix", "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION },
918 static const WCHAR aW[] = {'a',0};
919 IXmlWriter *writer;
920 IStream *stream;
921 unsigned int i;
922 HRESULT hr;
924 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
925 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
927 hr = write_start_element(writer, NULL, "a", NULL);
928 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
930 stream = writer_set_output(writer);
932 hr = write_start_element(writer, NULL, "a", NULL);
933 ok(hr == S_OK, "got 0x%08x\n", hr);
935 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
936 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
938 hr = IXmlWriter_Flush(writer);
939 ok(hr == S_OK, "got 0x%08x\n", hr);
941 CHECK_OUTPUT(stream, "<a");
943 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
944 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
946 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
947 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
949 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
950 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
952 IStream_Release(stream);
953 IXmlWriter_Release(writer);
955 /* WriteElementString */
956 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
957 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
959 hr = write_element_string(writer, NULL, "b", NULL, "value");
960 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
962 stream = writer_set_output(writer);
964 hr = write_start_element(writer, "prefix", "a", "uri");
965 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
967 hr = write_element_string(writer, NULL, "b", NULL, "value");
968 ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
970 hr = write_element_string(writer, NULL, "c", NULL, NULL);
971 ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
973 hr = write_start_element(writer, NULL, "d", "uri");
974 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
976 hr = write_start_element(writer, "", "e", "uri");
977 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
979 hr = write_start_element(writer, "prefix2", "f", "uri");
980 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
982 hr = IXmlWriter_Flush(writer);
983 ok(hr == S_OK, "got 0x%08x\n", hr);
985 CHECK_OUTPUT(stream,
986 "<prefix:a xmlns:prefix=\"uri\">"
987 "<b>value</b>"
988 "<c />"
989 "<prefix:d>"
990 "<e xmlns=\"uri\">"
991 "<prefix2:f");
993 IStream_Release(stream);
995 /* WriteStartElement */
996 for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i)
998 stream = writer_set_output(writer);
1000 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1002 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1003 ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
1005 hr = write_start_element(writer, start_element_tests[i].prefix, start_element_tests[i].local,
1006 start_element_tests[i].uri);
1007 ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
1009 if (SUCCEEDED(start_element_tests[i].hr))
1011 hr = IXmlWriter_Flush(writer);
1012 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1014 check_output(stream, start_element_tests[i].output_partial, start_element_tests[i].todo_partial, __LINE__);
1016 hr = IXmlWriter_WriteEndDocument(writer);
1017 ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
1019 hr = IXmlWriter_Flush(writer);
1020 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1022 check_output(stream, start_element_tests[i].output, start_element_tests[i].todo, __LINE__);
1025 IStream_Release(stream);
1028 IXmlWriter_Release(writer);
1031 static void test_WriteElementString(void)
1033 static const struct
1035 const char *prefix;
1036 const char *local;
1037 const char *uri;
1038 const char *value;
1039 const char *output;
1040 HRESULT hr;
1041 int todo;
1043 element_string_tests[] =
1045 { "prefix", "local", "uri", "value", "<prefix:local xmlns:prefix=\"uri\">value</prefix:local>" },
1046 { NULL, "local", "uri", "value", "<local xmlns=\"uri\">value</local>" },
1047 { "", "local", "uri", "value", "<local xmlns=\"uri\">value</local>" },
1048 { "prefix", "local", "uri", NULL, "<prefix:local xmlns:prefix=\"uri\" />" },
1049 { NULL, "local", "uri", NULL, "<local xmlns=\"uri\" />" },
1050 { "", "local", "uri", NULL, "<local xmlns=\"uri\" />" },
1051 { NULL, "local", NULL, NULL, "<local />" },
1052 { "prefix", "local", "uri", "", "<prefix:local xmlns:prefix=\"uri\"></prefix:local>" },
1053 { NULL, "local", "uri", "", "<local xmlns=\"uri\"></local>" },
1054 { "", "local", "uri", "", "<local xmlns=\"uri\"></local>" },
1055 { NULL, "local", NULL, "", "<local></local>" },
1056 { "", "local", "http://www.w3.org/2000/xmlns/", NULL, "<local xmlns=\"http://www.w3.org/2000/xmlns/\" />" },
1058 { "prefix", NULL, NULL, "value", NULL, E_INVALIDARG },
1059 { NULL, NULL, "uri", "value", NULL, E_INVALIDARG },
1060 { NULL, NULL, NULL, "value", NULL, E_INVALIDARG },
1061 { NULL, "prefix:local", "uri", "value", NULL, WC_E_NAMECHARACTER },
1062 { NULL, ":local", "uri", "value", NULL, WC_E_NAMECHARACTER },
1063 { ":", "local", "uri", "value", NULL, WC_E_NAMECHARACTER },
1064 { "prefix", "local", NULL, "value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1065 { "prefix", "local", "", "value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1066 { NULL, "local", "http://www.w3.org/2000/xmlns/", "value", NULL, WR_E_XMLNSPREFIXDECLARATION },
1067 { "prefix", "local", "http://www.w3.org/2000/xmlns/", "value", NULL, WR_E_XMLNSURIDECLARATION },
1069 IXmlWriter *writer;
1070 IStream *stream;
1071 unsigned int i;
1072 HRESULT hr;
1074 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1075 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1077 hr = write_element_string(writer, NULL, "b", NULL, "value");
1078 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1080 stream = writer_set_output(writer);
1082 hr = write_start_element(writer, NULL, "a", NULL);
1083 ok(hr == S_OK, "got 0x%08x\n", hr);
1085 hr = write_element_string(writer, NULL, "b", NULL, "value");
1086 ok(hr == S_OK, "got 0x%08x\n", hr);
1088 hr = write_element_string(writer, NULL, "b", NULL, NULL);
1089 ok(hr == S_OK, "got 0x%08x\n", hr);
1091 hr = write_element_string(writer, "prefix", "b", "uri", NULL);
1092 ok(hr == S_OK, "got 0x%08x\n", hr);
1094 hr = write_start_element(writer, "prefix", "c", "uri");
1095 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1097 hr = write_element_string(writer, "prefix", "d", NULL, NULL);
1098 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1100 hr = write_element_string(writer, "prefix2", "d", "uri", NULL);
1101 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1103 hr = write_element_string(writer, NULL, "e", "uri", NULL);
1104 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1106 hr = write_element_string(writer, "prefix", "f", "uri2", NULL);
1107 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1109 hr = write_element_string(writer, NULL, "g", "uri3", NULL);
1110 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1112 hr = write_element_string(writer, "prefix", "h", NULL, NULL);
1113 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1115 hr = write_element_string(writer, "prefix_i", "i", NULL, NULL);
1116 ok(hr == WR_E_NSPREFIXWITHEMPTYNSURI, "Failed to write element, hr %#x.\n", hr);
1118 hr = write_element_string(writer, "", "j", "uri", NULL);
1119 ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1121 hr = IXmlWriter_Flush(writer);
1122 ok(hr == S_OK, "got 0x%08x\n", hr);
1124 CHECK_OUTPUT(stream,
1125 "<a><b>value</b><b />"
1126 "<prefix:b xmlns:prefix=\"uri\" />"
1127 "<prefix:c xmlns:prefix=\"uri\">"
1128 "<prefix:d />"
1129 "<prefix2:d xmlns:prefix2=\"uri\" />"
1130 "<prefix:e />"
1131 "<prefix:f xmlns:prefix=\"uri2\" />"
1132 "<g xmlns=\"uri3\" />"
1133 "<prefix:h />"
1134 "<j xmlns=\"uri\" />");
1136 IStream_Release(stream);
1138 for (i = 0; i < ARRAY_SIZE(element_string_tests); ++i)
1140 stream = writer_set_output(writer);
1142 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1144 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1145 ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
1147 hr = write_element_string(writer, element_string_tests[i].prefix, element_string_tests[i].local,
1148 element_string_tests[i].uri, element_string_tests[i].value);
1149 ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
1151 if (SUCCEEDED(element_string_tests[i].hr))
1153 hr = IXmlWriter_Flush(writer);
1154 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1156 check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1158 hr = IXmlWriter_WriteEndDocument(writer);
1159 ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
1161 hr = IXmlWriter_Flush(writer);
1162 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1164 check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1167 IStream_Release(stream);
1170 IXmlWriter_Release(writer);
1173 static void test_WriteEndElement(void)
1175 IXmlWriter *writer;
1176 IStream *stream;
1177 HRESULT hr;
1179 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1180 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1182 stream = writer_set_output(writer);
1184 hr = write_start_element(writer, NULL, "a", NULL);
1185 ok(hr == S_OK, "got 0x%08x\n", hr);
1187 hr = write_start_element(writer, NULL, "b", NULL);
1188 ok(hr == S_OK, "got 0x%08x\n", hr);
1190 hr = IXmlWriter_WriteEndElement(writer);
1191 ok(hr == S_OK, "got 0x%08x\n", hr);
1193 hr = IXmlWriter_WriteEndElement(writer);
1194 ok(hr == S_OK, "got 0x%08x\n", hr);
1196 hr = IXmlWriter_Flush(writer);
1197 ok(hr == S_OK, "got 0x%08x\n", hr);
1199 CHECK_OUTPUT(stream, "<a><b /></a>");
1201 IXmlWriter_Release(writer);
1202 IStream_Release(stream);
1205 static void test_writeenddocument(void)
1207 static const WCHAR aW[] = {'a',0};
1208 static const WCHAR bW[] = {'b',0};
1209 IXmlWriter *writer;
1210 IStream *stream;
1211 HGLOBAL hglobal;
1212 HRESULT hr;
1213 char *ptr;
1215 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1216 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1218 hr = IXmlWriter_WriteEndDocument(writer);
1219 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1221 stream = writer_set_output(writer);
1223 /* WriteEndDocument resets it to initial state */
1224 hr = IXmlWriter_WriteEndDocument(writer);
1225 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1227 hr = IXmlWriter_WriteEndDocument(writer);
1228 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1230 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1231 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1233 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1234 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1236 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
1237 ok(hr == S_OK, "got 0x%08x\n", hr);
1239 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1240 ok(hr == S_OK, "got 0x%08x\n", hr);
1242 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1243 ok(hr == S_OK, "got 0x%08x\n", hr);
1245 hr = IXmlWriter_WriteEndDocument(writer);
1246 ok(hr == S_OK, "got 0x%08x\n", hr);
1248 hr = GetHGlobalFromStream(stream, &hglobal);
1249 ok(hr == S_OK, "got 0x%08x\n", hr);
1251 ptr = GlobalLock(hglobal);
1252 ok(ptr == NULL, "got %p\n", ptr);
1254 /* we still need to flush manually, WriteEndDocument doesn't do that */
1255 hr = IXmlWriter_Flush(writer);
1256 ok(hr == S_OK, "got 0x%08x\n", hr);
1258 CHECK_OUTPUT(stream, "<a><b /></a>");
1260 IXmlWriter_Release(writer);
1261 IStream_Release(stream);
1264 static void test_WriteComment(void)
1266 static const WCHAR closeW[] = {'-','-','>',0};
1267 static const WCHAR aW[] = {'a',0};
1268 static const WCHAR bW[] = {'b',0};
1269 IXmlWriter *writer;
1270 IStream *stream;
1271 HRESULT hr;
1273 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1274 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1276 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1278 hr = IXmlWriter_WriteComment(writer, aW);
1279 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1281 stream = writer_set_output(writer);
1283 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1284 ok(hr == S_OK, "got 0x%08x\n", hr);
1286 hr = IXmlWriter_WriteComment(writer, aW);
1287 ok(hr == S_OK, "got 0x%08x\n", hr);
1289 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1290 ok(hr == S_OK, "got 0x%08x\n", hr);
1292 hr = IXmlWriter_WriteComment(writer, aW);
1293 ok(hr == S_OK, "got 0x%08x\n", hr);
1295 hr = IXmlWriter_WriteComment(writer, NULL);
1296 ok(hr == S_OK, "got 0x%08x\n", hr);
1298 hr = IXmlWriter_WriteComment(writer, closeW);
1299 ok(hr == S_OK, "got 0x%08x\n", hr);
1301 hr = IXmlWriter_Flush(writer);
1302 ok(hr == S_OK, "got 0x%08x\n", hr);
1304 CHECK_OUTPUT(stream, "<!--a--><b><!--a--><!----><!--- ->-->");
1306 IXmlWriter_Release(writer);
1307 IStream_Release(stream);
1310 static void test_WriteCData(void)
1312 static const WCHAR closeW[] = {']',']','>',0};
1313 static const WCHAR close2W[] = {'a',']',']','>','b',0};
1314 static const WCHAR aW[] = {'a',0};
1315 static const WCHAR bW[] = {'b',0};
1316 IXmlWriter *writer;
1317 IStream *stream;
1318 HRESULT hr;
1320 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1321 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1323 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1325 hr = IXmlWriter_WriteCData(writer, aW);
1326 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1328 stream = writer_set_output(writer);
1330 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1331 ok(hr == S_OK, "got 0x%08x\n", hr);
1333 hr = IXmlWriter_WriteCData(writer, aW);
1334 ok(hr == S_OK, "got 0x%08x\n", hr);
1336 hr = IXmlWriter_WriteCData(writer, NULL);
1337 ok(hr == S_OK, "got 0x%08x\n", hr);
1339 hr = IXmlWriter_WriteCData(writer, closeW);
1340 ok(hr == S_OK, "got 0x%08x\n", hr);
1342 hr = IXmlWriter_WriteCData(writer, close2W);
1343 ok(hr == S_OK, "got 0x%08x\n", hr);
1345 hr = IXmlWriter_Flush(writer);
1346 ok(hr == S_OK, "got 0x%08x\n", hr);
1348 CHECK_OUTPUT(stream,
1349 "<b>"
1350 "<![CDATA[a]]>"
1351 "<![CDATA[]]>"
1352 "<![CDATA[]]]]>"
1353 "<![CDATA[>]]>"
1354 "<![CDATA[a]]]]>"
1355 "<![CDATA[>b]]>");
1357 IXmlWriter_Release(writer);
1358 IStream_Release(stream);
1361 static void test_WriteRaw(void)
1363 static const WCHAR rawW[] = {'a','<',':',0};
1364 static const WCHAR aW[] = {'a',0};
1365 IXmlWriter *writer;
1366 IStream *stream;
1367 HRESULT hr;
1369 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1370 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1372 hr = IXmlWriter_WriteRaw(writer, NULL);
1373 ok(hr == S_OK, "got 0x%08x\n", hr);
1375 hr = IXmlWriter_WriteRaw(writer, rawW);
1376 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1378 stream = writer_set_output(writer);
1380 hr = IXmlWriter_WriteRaw(writer, NULL);
1381 ok(hr == S_OK, "got 0x%08x\n", hr);
1383 hr = IXmlWriter_WriteRaw(writer, rawW);
1384 ok(hr == S_OK, "got 0x%08x\n", hr);
1386 hr = IXmlWriter_WriteRaw(writer, rawW);
1387 ok(hr == S_OK, "got 0x%08x\n", hr);
1389 hr = IXmlWriter_WriteComment(writer, rawW);
1390 ok(hr == S_OK, "got 0x%08x\n", hr);
1392 hr = IXmlWriter_WriteRaw(writer, rawW);
1393 ok(hr == S_OK, "got 0x%08x\n", hr);
1395 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
1396 ok(hr == S_OK, "got 0x%08x\n", hr);
1398 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
1399 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1401 hr = IXmlWriter_WriteComment(writer, rawW);
1402 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1404 hr = IXmlWriter_WriteEndDocument(writer);
1405 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1407 hr = IXmlWriter_WriteRaw(writer, rawW);
1408 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1410 hr = IXmlWriter_Flush(writer);
1411 ok(hr == S_OK, "got 0x%08x\n", hr);
1413 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>a<:a<:<!--a<:-->a<:<a>a</a>");
1415 IXmlWriter_Release(writer);
1416 IStream_Release(stream);
1419 static void test_writer_state(void)
1421 static const WCHAR aW[] = {'a',0};
1422 IXmlWriter *writer;
1423 IStream *stream;
1424 HRESULT hr;
1426 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1427 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1429 /* initial state */
1430 check_writer_state(writer, E_UNEXPECTED);
1432 /* set output and call 'wrong' method, WriteEndElement */
1433 stream = writer_set_output(writer);
1435 hr = IXmlWriter_WriteEndElement(writer);
1436 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1438 check_writer_state(writer, WR_E_INVALIDACTION);
1439 IStream_Release(stream);
1441 /* WriteAttributeString */
1442 stream = writer_set_output(writer);
1444 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
1445 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1447 check_writer_state(writer, WR_E_INVALIDACTION);
1448 IStream_Release(stream);
1450 /* WriteEndDocument */
1451 stream = writer_set_output(writer);
1453 hr = IXmlWriter_WriteEndDocument(writer);
1454 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1456 check_writer_state(writer, WR_E_INVALIDACTION);
1457 IStream_Release(stream);
1459 /* WriteFullEndElement */
1460 stream = writer_set_output(writer);
1462 hr = IXmlWriter_WriteFullEndElement(writer);
1463 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1465 check_writer_state(writer, WR_E_INVALIDACTION);
1466 IStream_Release(stream);
1468 /* WriteCData */
1469 stream = writer_set_output(writer);
1471 hr = IXmlWriter_WriteCData(writer, aW);
1472 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1474 check_writer_state(writer, WR_E_INVALIDACTION);
1475 IStream_Release(stream);
1477 /* WriteName */
1478 stream = writer_set_output(writer);
1480 hr = IXmlWriter_WriteName(writer, aW);
1481 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1483 check_writer_state(writer, WR_E_INVALIDACTION);
1484 IStream_Release(stream);
1486 /* WriteNmToken */
1487 stream = writer_set_output(writer);
1489 hr = IXmlWriter_WriteNmToken(writer, aW);
1490 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1492 check_writer_state(writer, WR_E_INVALIDACTION);
1493 IStream_Release(stream);
1495 /* WriteString */
1496 stream = writer_set_output(writer);
1498 hr = IXmlWriter_WriteString(writer, aW);
1499 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1501 check_writer_state(writer, WR_E_INVALIDACTION);
1502 IStream_Release(stream);
1504 IXmlWriter_Release(writer);
1507 static void test_indentation(void)
1509 static const WCHAR commentW[] = {'c','o','m','m','e','n','t',0};
1510 static const WCHAR aW[] = {'a',0};
1511 static const WCHAR bW[] = {'b',0};
1512 IXmlWriter *writer;
1513 IStream *stream;
1514 HRESULT hr;
1516 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1517 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1519 stream = writer_set_output(writer);
1521 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1522 writer_set_property(writer, XmlWriterProperty_Indent);
1524 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1525 ok(hr == S_OK, "got 0x%08x\n", hr);
1527 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1528 ok(hr == S_OK, "got 0x%08x\n", hr);
1530 hr = IXmlWriter_WriteComment(writer, commentW);
1531 ok(hr == S_OK, "got 0x%08x\n", hr);
1533 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1534 ok(hr == S_OK, "got 0x%08x\n", hr);
1536 hr = IXmlWriter_WriteEndDocument(writer);
1537 ok(hr == S_OK, "got 0x%08x\n", hr);
1539 hr = IXmlWriter_Flush(writer);
1540 ok(hr == S_OK, "got 0x%08x\n", hr);
1542 CHECK_OUTPUT(stream,
1543 "<a>\r\n"
1544 " <!--comment-->\r\n"
1545 " <b />\r\n"
1546 "</a>");
1548 IStream_Release(stream);
1550 /* WriteElementString */
1551 stream = writer_set_output(writer);
1553 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1554 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1556 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL);
1557 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1559 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL);
1560 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1562 hr = IXmlWriter_WriteEndElement(writer);
1563 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1565 hr = IXmlWriter_Flush(writer);
1566 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1568 CHECK_OUTPUT(stream,
1569 "<a>\r\n"
1570 " <b />\r\n"
1571 " <b />\r\n"
1572 "</a>");
1574 IStream_Release(stream);
1576 IXmlWriter_Release(writer);
1579 static HRESULT write_attribute_string(IXmlWriter *writer, const char *prefix, const char *local,
1580 const char *uri, const char *value)
1582 WCHAR *prefixW, *localW, *uriW, *valueW;
1583 HRESULT hr;
1585 prefixW = strdupAtoW(prefix);
1586 localW = strdupAtoW(local);
1587 uriW = strdupAtoW(uri);
1588 valueW = strdupAtoW(value);
1590 hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, uriW, valueW);
1592 heap_free(prefixW);
1593 heap_free(localW);
1594 heap_free(uriW);
1595 heap_free(valueW);
1597 return hr;
1600 static void test_WriteAttributeString(void)
1602 static const struct
1604 const char *prefix;
1605 const char *local;
1606 const char *uri;
1607 const char *value;
1608 const char *output;
1609 const char *output_partial;
1610 HRESULT hr;
1611 int todo;
1612 int todo_partial;
1613 int todo_hr;
1615 attribute_tests[] =
1617 { NULL, "a", NULL, "b", "<e a=\"b\" />", "<e a=\"b\"" },
1618 { "", "a", NULL, "b", "<e a=\"b\" />", "<e a=\"b\"" },
1619 { NULL, "a", "", "b", "<e a=\"b\" />", "<e a=\"b\"" },
1620 { "", "a", "", "b", "<e a=\"b\" />", "<e a=\"b\"" },
1621 { "prefix", "local", "uri", "b", "<e prefix:local=\"b\" xmlns:prefix=\"uri\" />", "<e prefix:local=\"b\"" },
1622 { NULL, "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e xmlns:a=\"defuri\" />", "<e xmlns:a=\"defuri\"" },
1623 { "xmlns", "a", NULL, "uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1624 { "xmlns", "a", "", "uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1625 { "prefix", "xmlns", "uri", "value", "<e prefix:xmlns=\"value\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"value\"" },
1626 { "prefix", "xmlns", "uri", NULL, "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1627 { "prefix", "xmlns", "uri", "", "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1628 { "prefix", "xmlns", NULL, "uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1629 { "prefix", "xmlns", "", "uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1630 { "xml", "space", NULL, "preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1631 { "xml", "space", "", "preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1632 { "xml", "space", NULL, "default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1633 { "xml", "space", "", "default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1634 { "xml", "a", NULL, "value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1635 { "xml", "a", "", "value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1637 /* Autogenerated prefix names. */
1638 { NULL, "a", "defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1639 { NULL, "a", "defuri", "b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1640 { "", "a", "defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1641 { NULL, "a", "defuri", "", "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1642 { "", "a", "defuri", "b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1644 /* Failing cases. */
1645 { NULL, NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG },
1646 { "", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 1, 1, 1 },
1647 { "", NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG },
1648 { "", "", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG, 1, 1, 1 },
1649 { NULL, "", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG, 1, 1, 1 },
1650 { "prefix", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION, 1, 1, 1 },
1651 { "prefix", NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG },
1652 { "prefix", NULL, NULL, "b", "<e />", "<e", E_INVALIDARG },
1653 { "prefix", NULL, "uri", NULL, "<e />", "<e", E_INVALIDARG },
1654 { "xml", NULL, NULL, "value", "<e />", "<e", E_INVALIDARG },
1655 { "xmlns", "a", "defuri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1656 { "xmlns", "a", "b", "uri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1657 { NULL, "xmlns", "uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1658 { "xmlns", NULL, "uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1659 { "pre:fix", "local", "uri", "b", "<e />", "<e", WC_E_NAMECHARACTER },
1660 { "pre:fix", NULL, "uri", "b", "<e />", "<e", E_INVALIDARG },
1661 { "prefix", "lo:cal", "uri", "b", "<e />", "<e", WC_E_NAMECHARACTER },
1662 { "xmlns", NULL, NULL, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1663 { "xmlns", NULL, "", "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1664 { "xmlns", "", NULL, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1665 { "xmlns", "", "", "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1666 { "xml", "space", "", "value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1667 { "xml", "space", NULL, "value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1668 { "xml", "a", "uri", "value", "<e />", "<e", WR_E_XMLPREFIXDECLARATION },
1669 { "xml", "space", NULL, "preServe", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1670 { "xml", "space", NULL, "defAult", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1671 { "xml", "space", NULL, NULL, "<e />", "<e", WR_E_INVALIDXMLSPACE },
1672 { "xml", "space", NULL, "", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1675 IXmlWriter *writer;
1676 IStream *stream;
1677 unsigned int i;
1678 HRESULT hr;
1680 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1681 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1683 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1685 for (i = 0; i < ARRAY_SIZE(attribute_tests); ++i)
1687 stream = writer_set_output(writer);
1689 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1690 ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
1692 hr = write_start_element(writer, NULL, "e", NULL);
1693 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1695 hr = write_attribute_string(writer, attribute_tests[i].prefix, attribute_tests[i].local,
1696 attribute_tests[i].uri, attribute_tests[i].value);
1697 todo_wine_if(attribute_tests[i].todo_hr)
1698 ok(hr == attribute_tests[i].hr, "%u: unexpected hr %#x, expected %#x.\n", i, hr, attribute_tests[i].hr);
1700 hr = IXmlWriter_Flush(writer);
1701 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1703 check_output(stream, attribute_tests[i].output_partial, attribute_tests[i].todo_partial, __LINE__);
1705 hr = IXmlWriter_WriteEndDocument(writer);
1706 ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
1708 hr = IXmlWriter_Flush(writer);
1709 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1711 check_output(stream, attribute_tests[i].output, attribute_tests[i].todo, __LINE__);
1712 IStream_Release(stream);
1715 /* With namespaces */
1716 stream = writer_set_output(writer);
1718 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1719 ok(hr == S_OK, "got 0x%08x\n", hr);
1721 hr = write_start_element(writer, "p", "a", "outeruri");
1722 ok(hr == S_OK, "got 0x%08x\n", hr);
1724 hr = write_attribute_string(writer, "prefix", "local", "uri", "b");
1725 ok(hr == S_OK, "got 0x%08x\n", hr);
1727 hr = write_attribute_string(writer, NULL, "a", NULL, "b");
1728 ok(hr == S_OK, "got 0x%08x\n", hr);
1730 hr = write_attribute_string(writer, "xmlns", "prefix", NULL, "uri");
1731 ok(hr == S_OK, "got 0x%08x\n", hr);
1733 hr = write_attribute_string(writer, "p", "attr", NULL, "value");
1734 ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
1736 hr = write_attribute_string(writer, "prefix", "local", NULL, "b");
1737 todo_wine
1738 ok(hr == WR_E_DUPLICATEATTRIBUTE, "got 0x%08x\n", hr);
1740 hr = write_start_element(writer, NULL, "b", NULL);
1741 ok(hr == S_OK, "got 0x%08x\n", hr);
1743 hr = write_attribute_string(writer, NULL, "attr2", "outeruri", "value");
1744 ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
1746 hr = write_attribute_string(writer, "pr", "attr3", "outeruri", "value");
1747 ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
1749 hr = IXmlWriter_WriteEndDocument(writer);
1750 ok(hr == S_OK, "got 0x%08x\n", hr);
1752 hr = IXmlWriter_Flush(writer);
1753 ok(hr == S_OK, "got 0x%08x\n", hr);
1755 CHECK_OUTPUT_TODO(stream,
1756 "<p:a prefix:local=\"b\" a=\"b\" xmlns:prefix=\"uri\" p:attr=\"value\" xmlns:p=\"outeruri\">"
1757 "<b p:attr2=\"value\" pr:attr3=\"value\" xmlns:pr=\"outeruri\" />"
1758 "</p:a>");
1760 IStream_Release(stream);
1762 /* Define prefix, write attribute with it. */
1763 stream = writer_set_output(writer);
1765 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1766 ok(hr == S_OK, "got 0x%08x\n", hr);
1768 hr = write_start_element(writer, NULL, "e", NULL);
1769 ok(hr == S_OK, "got 0x%08x\n", hr);
1771 hr = write_attribute_string(writer, "xmlns", "prefix", NULL, "uri");
1772 ok(hr == S_OK, "got 0x%08x\n", hr);
1774 hr = write_attribute_string(writer, "prefix", "attr", NULL, "value");
1775 ok(hr == S_OK, "got 0x%08x\n", hr);
1777 hr = IXmlWriter_WriteEndDocument(writer);
1778 ok(hr == S_OK, "got 0x%08x\n", hr);
1780 hr = IXmlWriter_Flush(writer);
1781 ok(hr == S_OK, "got 0x%08x\n", hr);
1783 CHECK_OUTPUT(stream,
1784 "<e xmlns:prefix=\"uri\" prefix:attr=\"value\" />");
1786 IStream_Release(stream);
1788 IXmlWriter_Release(writer);
1791 static void test_WriteFullEndElement(void)
1793 static const WCHAR aW[] = {'a',0};
1794 IXmlWriter *writer;
1795 IStream *stream;
1796 HRESULT hr;
1798 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1799 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1801 /* standalone element */
1802 stream = writer_set_output(writer);
1804 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1805 writer_set_property(writer, XmlWriterProperty_Indent);
1807 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1808 ok(hr == S_OK, "got 0x%08x\n", hr);
1810 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1811 ok(hr == S_OK, "got 0x%08x\n", hr);
1813 hr = IXmlWriter_WriteFullEndElement(writer);
1814 ok(hr == S_OK, "got 0x%08x\n", hr);
1816 hr = IXmlWriter_WriteEndDocument(writer);
1817 ok(hr == S_OK, "got 0x%08x\n", hr);
1819 hr = IXmlWriter_Flush(writer);
1820 ok(hr == S_OK, "got 0x%08x\n", hr);
1822 CHECK_OUTPUT(stream,
1823 "<a></a>");
1824 IStream_Release(stream);
1826 /* nested elements */
1827 stream = writer_set_output(writer);
1829 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1830 writer_set_property(writer, XmlWriterProperty_Indent);
1832 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1833 ok(hr == S_OK, "got 0x%08x\n", hr);
1835 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1836 ok(hr == S_OK, "got 0x%08x\n", hr);
1838 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1839 ok(hr == S_OK, "got 0x%08x\n", hr);
1841 hr = IXmlWriter_WriteFullEndElement(writer);
1842 ok(hr == S_OK, "got 0x%08x\n", hr);
1844 hr = IXmlWriter_WriteEndDocument(writer);
1845 ok(hr == S_OK, "got 0x%08x\n", hr);
1847 hr = IXmlWriter_Flush(writer);
1848 ok(hr == S_OK, "got 0x%08x\n", hr);
1850 CHECK_OUTPUT(stream,
1851 "<a>\r\n"
1852 " <a></a>\r\n"
1853 "</a>");
1855 IXmlWriter_Release(writer);
1856 IStream_Release(stream);
1859 static void test_WriteCharEntity(void)
1861 static const WCHAR aW[] = {'a',0};
1862 IXmlWriter *writer;
1863 IStream *stream;
1864 HRESULT hr;
1866 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1867 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1869 /* without indentation */
1870 stream = writer_set_output(writer);
1872 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1874 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1875 ok(hr == S_OK, "got 0x%08x\n", hr);
1877 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1878 ok(hr == S_OK, "got 0x%08x\n", hr);
1880 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
1881 ok(hr == S_OK, "got 0x%08x\n", hr);
1883 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1884 ok(hr == S_OK, "got 0x%08x\n", hr);
1886 hr = IXmlWriter_WriteEndDocument(writer);
1887 ok(hr == S_OK, "got 0x%08x\n", hr);
1889 hr = IXmlWriter_Flush(writer);
1890 ok(hr == S_OK, "got 0x%08x\n", hr);
1892 CHECK_OUTPUT(stream,
1893 "<a>&#x100;<a /></a>");
1895 IXmlWriter_Release(writer);
1896 IStream_Release(stream);
1899 static void test_WriteString(void)
1901 IXmlWriter *writer;
1902 IStream *stream;
1903 HRESULT hr;
1905 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1906 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1908 writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
1910 hr = write_string(writer, "a");
1911 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1913 hr = write_string(writer, NULL);
1914 ok(hr == S_OK, "got 0x%08x\n", hr);
1916 hr = write_string(writer, "");
1917 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1919 stream = writer_set_output(writer);
1921 hr = write_start_element(writer, NULL, "b", NULL);
1922 ok(hr == S_OK, "got 0x%08x\n", hr);
1924 hr = write_string(writer, NULL);
1925 ok(hr == S_OK, "got 0x%08x\n", hr);
1927 hr = write_string(writer, "");
1928 ok(hr == S_OK, "got 0x%08x\n", hr);
1930 hr = write_string(writer, "a");
1931 ok(hr == S_OK, "got 0x%08x\n", hr);
1933 /* WriteString automatically escapes markup characters */
1934 hr = write_string(writer, "<&\">=");
1935 ok(hr == S_OK, "got 0x%08x\n", hr);
1937 hr = IXmlWriter_Flush(writer);
1938 ok(hr == S_OK, "got 0x%08x\n", hr);
1940 CHECK_OUTPUT(stream,
1941 "<b>a&lt;&amp;\"&gt;=");
1942 IStream_Release(stream);
1944 stream = writer_set_output(writer);
1946 hr = write_start_element(writer, NULL, "b", NULL);
1947 ok(hr == S_OK, "got 0x%08x\n", hr);
1949 hr = write_string(writer, NULL);
1950 ok(hr == S_OK, "got 0x%08x\n", hr);
1952 hr = IXmlWriter_Flush(writer);
1953 ok(hr == S_OK, "got 0x%08x\n", hr);
1955 CHECK_OUTPUT(stream,
1956 "<b");
1958 hr = write_string(writer, "");
1959 ok(hr == S_OK, "got 0x%08x\n", hr);
1961 hr = IXmlWriter_Flush(writer);
1962 ok(hr == S_OK, "got 0x%08x\n", hr);
1964 CHECK_OUTPUT(stream,
1965 "<b>");
1967 IStream_Release(stream);
1968 IXmlWriter_Release(writer);
1970 /* With indentation */
1971 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
1972 ok(hr == S_OK, "Failed to create a writer, hr %#x.\n", hr);
1974 stream = writer_set_output(writer);
1976 writer_set_property(writer, XmlWriterProperty_Indent);
1978 hr = write_start_element(writer, NULL, "a", NULL);
1979 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1981 hr = write_start_element(writer, NULL, "b", NULL);
1982 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1984 hr = write_string(writer, "text");
1985 ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
1987 hr = IXmlWriter_Flush(writer);
1988 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1990 CHECK_OUTPUT(stream,
1991 "<a>\r\n"
1992 " <b>text");
1994 hr = IXmlWriter_WriteFullEndElement(writer);
1995 ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
1997 hr = IXmlWriter_Flush(writer);
1998 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2000 CHECK_OUTPUT(stream,
2001 "<a>\r\n"
2002 " <b>text</b>");
2004 hr = IXmlWriter_WriteFullEndElement(writer);
2005 ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2007 hr = IXmlWriter_Flush(writer);
2008 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2010 CHECK_OUTPUT(stream,
2011 "<a>\r\n"
2012 " <b>text</b>\r\n"
2013 "</a>");
2015 IStream_Release(stream);
2017 stream = writer_set_output(writer);
2019 hr = write_start_element(writer, NULL, "a", NULL);
2020 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2022 hr = write_start_element(writer, NULL, "b", NULL);
2023 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2025 hr = IXmlWriter_WriteEndElement(writer);
2026 ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2028 hr = IXmlWriter_Flush(writer);
2029 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2031 CHECK_OUTPUT(stream,
2032 "<a>\r\n"
2033 " <b />");
2035 hr = write_start_element(writer, NULL, "c", NULL);
2036 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2038 hr = write_attribute_string(writer, NULL, "attr", NULL, "value");
2039 ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
2041 hr = IXmlWriter_Flush(writer);
2042 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2044 CHECK_OUTPUT(stream,
2045 "<a>\r\n"
2046 " <b />\r\n"
2047 " <c attr=\"value\"");
2049 hr = write_string(writer, "text");
2050 ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
2052 hr = IXmlWriter_Flush(writer);
2053 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2055 CHECK_OUTPUT(stream,
2056 "<a>\r\n"
2057 " <b />\r\n"
2058 " <c attr=\"value\">text");
2060 hr = IXmlWriter_WriteEndElement(writer);
2061 ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2063 hr = IXmlWriter_Flush(writer);
2064 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2066 CHECK_OUTPUT(stream,
2067 "<a>\r\n"
2068 " <b />\r\n"
2069 " <c attr=\"value\">text</c>");
2071 hr = write_start_element(writer, NULL, "d", NULL);
2072 ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2074 hr = write_string(writer, "");
2075 ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
2077 hr = IXmlWriter_WriteEndElement(writer);
2078 ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2080 hr = IXmlWriter_Flush(writer);
2081 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2083 CHECK_OUTPUT(stream,
2084 "<a>\r\n"
2085 " <b />\r\n"
2086 " <c attr=\"value\">text</c>\r\n"
2087 " <d></d>");
2089 hr = IXmlWriter_WriteEndElement(writer);
2090 ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2092 hr = IXmlWriter_Flush(writer);
2093 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2095 CHECK_OUTPUT(stream,
2096 "<a>\r\n"
2097 " <b />\r\n"
2098 " <c attr=\"value\">text</c>\r\n"
2099 " <d></d>\r\n"
2100 "</a>");
2102 IXmlWriter_Release(writer);
2103 IStream_Release(stream);
2106 static HRESULT write_doctype(IXmlWriter *writer, const char *name, const char *pubid, const char *sysid,
2107 const char *subset)
2109 WCHAR *nameW, *pubidW, *sysidW, *subsetW;
2110 HRESULT hr;
2112 nameW = strdupAtoW(name);
2113 pubidW = strdupAtoW(pubid);
2114 sysidW = strdupAtoW(sysid);
2115 subsetW = strdupAtoW(subset);
2117 hr = IXmlWriter_WriteDocType(writer, nameW, pubidW, sysidW, subsetW);
2119 heap_free(nameW);
2120 heap_free(pubidW);
2121 heap_free(sysidW);
2122 heap_free(subsetW);
2124 return hr;
2127 static void test_WriteDocType(void)
2129 static const struct
2131 const char *name;
2132 const char *pubid;
2133 const char *sysid;
2134 const char *subset;
2135 const char *output;
2137 doctype_tests[] =
2139 { "a", "", NULL, NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2140 { "a", NULL, NULL, NULL, "<!DOCTYPE a>" },
2141 { "a", NULL, "", NULL, "<!DOCTYPE a SYSTEM \"\">" },
2142 { "a", "", "", NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2143 { "a", "pubid", "", NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2144 { "a", "pubid", NULL, NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2145 { "a", "", "sysid", NULL, "<!DOCTYPE a PUBLIC \"\" \"sysid\">" },
2146 { "a", NULL, NULL, "", "<!DOCTYPE a []>" },
2147 { "a", NULL, NULL, "subset", "<!DOCTYPE a [subset]>" },
2148 { "a", "", NULL, "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2149 { "a", NULL, "", "subset", "<!DOCTYPE a SYSTEM \"\" [subset]>" },
2150 { "a", "", "", "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2151 { "a", "pubid", NULL, "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2152 { "a", "pubid", "", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2153 { "a", NULL, "sysid", "subset", "<!DOCTYPE a SYSTEM \"sysid\" [subset]>" },
2154 { "a", "", "sysid", "subset", "<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
2155 { "a", "pubid", "sysid", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
2157 static const WCHAR pubidW[] = {'p',0x100,'i','d',0};
2158 static const WCHAR nameW[] = {'-','a',0};
2159 static const WCHAR emptyW[] = { 0 };
2160 IXmlWriter *writer;
2161 IStream *stream;
2162 unsigned int i;
2163 HRESULT hr;
2165 hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2166 ok(hr == S_OK, "Failed to create writer instance, hr %#x.\n", hr);
2168 stream = writer_set_output(writer);
2170 hr = IXmlWriter_WriteDocType(writer, NULL, NULL, NULL, NULL);
2171 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2173 hr = IXmlWriter_WriteDocType(writer, emptyW, NULL, NULL, NULL);
2174 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2176 /* Name validation. */
2177 hr = IXmlWriter_WriteDocType(writer, nameW, NULL, NULL, NULL);
2178 ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#x.\n", hr);
2180 /* Pubid validation. */
2181 hr = IXmlWriter_WriteDocType(writer, aW, pubidW, NULL, NULL);
2182 ok(hr == WC_E_PUBLICID, "Unexpected hr %#x.\n", hr);
2184 IStream_Release(stream);
2186 for (i = 0; i < ARRAY_SIZE(doctype_tests); i++)
2188 stream = writer_set_output(writer);
2190 hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2191 doctype_tests[i].subset);
2192 ok(hr == S_OK, "%u: failed to write doctype, hr %#x.\n", i, hr);
2194 hr = IXmlWriter_Flush(writer);
2195 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2197 CHECK_OUTPUT(stream, doctype_tests[i].output);
2199 hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2200 doctype_tests[i].subset);
2201 ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#x.\n", hr);
2203 IStream_Release(stream);
2206 IXmlWriter_Release(writer);
2209 START_TEST(writer)
2211 test_writer_create();
2212 test_writer_state();
2213 test_writeroutput();
2214 test_writestartdocument();
2215 test_WriteStartElement();
2216 test_WriteElementString();
2217 test_WriteEndElement();
2218 test_flush();
2219 test_omitxmldeclaration();
2220 test_bom();
2221 test_writeenddocument();
2222 test_WriteComment();
2223 test_WriteCData();
2224 test_WriteRaw();
2225 test_indentation();
2226 test_WriteAttributeString();
2227 test_WriteFullEndElement();
2228 test_WriteCharEntity();
2229 test_WriteString();
2230 test_WriteDocType();