webservices: Write empty prefix if "prefix" is NULL and "ns" is empty.
[wine.git] / dlls / webservices / tests / writer.c
blobaa33b7633a7fe9b56ffcf8802fe7fccf7b9eb21b
1 /*
2 * Copyright 2015 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdio.h>
20 #include "windows.h"
21 #include "webservices.h"
22 #include "wine/test.h"
24 #include <math.h>
25 #ifndef INFINITY
26 static inline float __port_infinity(void)
28 static const unsigned __inf_bytes = 0x7f800000;
29 return *(const float *)&__inf_bytes;
31 #define INFINITY __port_infinity()
32 #endif
34 #ifndef NAN
35 static inline float __port_nan(void)
37 static const unsigned __nan_bytes = 0x7fc00000;
38 return *(const float *)&__nan_bytes;
40 #define NAN __port_nan()
41 #endif
43 static HRESULT set_output( WS_XML_WRITER *writer )
45 WS_XML_WRITER_TEXT_ENCODING text = { {WS_XML_WRITER_ENCODING_TYPE_TEXT}, WS_CHARSET_UTF8 };
46 WS_XML_WRITER_BUFFER_OUTPUT buf = { {WS_XML_WRITER_OUTPUT_TYPE_BUFFER} };
47 return WsSetOutput( writer, &text.encoding, &buf.output, NULL, 0, NULL );
50 static void test_WsCreateWriter(void)
52 HRESULT hr;
53 WS_XML_WRITER *writer;
54 WS_XML_WRITER_PROPERTY prop;
55 ULONG size, max_depth, max_attrs, indent, trim_size, max_size, max_ns;
56 BOOL allow_fragment, write_decl, in_attr;
57 WS_CHARSET charset;
58 WS_BUFFERS buffers;
59 WS_BYTES bytes;
61 hr = WsCreateWriter( NULL, 0, NULL, NULL );
62 ok( hr == E_INVALIDARG, "got %08x\n", hr );
64 writer = NULL;
65 hr = WsCreateWriter( NULL, 0, &writer, NULL );
66 ok( hr == S_OK, "got %08x\n", hr );
67 ok( writer != NULL, "writer not set\n" );
69 /* can't retrieve properties before output is set */
70 max_depth = 0xdeadbeef;
71 size = sizeof(max_depth);
72 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, size, NULL );
73 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
74 ok( max_depth == 0xdeadbeef, "max_depth set\n" );
76 hr = set_output( writer );
77 ok( hr == S_OK, "got %08x\n", hr );
79 /* check some defaults */
80 max_depth = 0xdeadbeef;
81 size = sizeof(max_depth);
82 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, size, NULL );
83 ok( hr == S_OK, "got %08x\n", hr );
84 ok( max_depth == 32, "got %u\n", max_depth );
86 allow_fragment = TRUE;
87 size = sizeof(allow_fragment);
88 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT, &allow_fragment, size, NULL );
89 ok( hr == S_OK, "got %08x\n", hr );
90 ok( !allow_fragment, "got %d\n", allow_fragment );
92 max_attrs = 0xdeadbeef;
93 size = sizeof(max_attrs);
94 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, size, NULL );
95 ok( hr == S_OK, "got %08x\n", hr );
96 ok( max_attrs == 128, "got %u\n", max_attrs );
98 write_decl = TRUE;
99 size = sizeof(write_decl);
100 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_WRITE_DECLARATION, &write_decl, size, NULL );
101 ok( hr == S_OK, "got %08x\n", hr );
102 ok( !write_decl, "got %d\n", write_decl );
104 indent = 0xdeadbeef;
105 size = sizeof(indent);
106 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_INDENT, &indent, size, NULL );
107 ok( hr == S_OK, "got %08x\n", hr );
108 ok( !indent, "got %u\n", indent );
110 trim_size = 0xdeadbeef;
111 size = sizeof(trim_size);
112 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE, &trim_size, size, NULL );
113 ok( hr == S_OK, "got %08x\n", hr );
114 ok( trim_size == 4096, "got %u\n", trim_size );
116 charset = 0xdeadbeef;
117 size = sizeof(charset);
118 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_CHARSET, &charset, size, NULL );
119 ok( hr == S_OK, "got %08x\n", hr );
120 ok( charset == WS_CHARSET_UTF8, "got %u\n", charset );
122 buffers.bufferCount = 0xdeadbeef;
123 buffers.buffers = (WS_BYTES *)0xdeadbeef;
124 size = sizeof(buffers);
125 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BUFFERS, &buffers, size, NULL );
126 ok( hr == S_OK, "got %08x\n", hr );
127 ok( !buffers.bufferCount, "got %u\n", buffers.bufferCount );
128 ok( !buffers.buffers, "got %p\n", buffers.buffers );
130 max_size = 0xdeadbeef;
131 size = sizeof(max_size);
132 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE, &max_size, size, NULL );
133 ok( hr == S_OK, "got %08x\n", hr );
134 ok( max_size == 65536, "got %u\n", max_size );
136 bytes.length = 0xdeadbeef;
137 bytes.bytes = (BYTE *)0xdeadbeef;
138 size = sizeof(buffers);
139 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
140 ok( hr == S_OK, "got %08x\n", hr );
141 ok( !bytes.length, "got %u\n", bytes.length );
142 ok( bytes.bytes != NULL, "got %p\n", bytes.bytes );
144 max_size = 0xdeadbeef;
145 size = sizeof(max_size);
146 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE, &max_size, size, NULL );
147 ok( hr == S_OK, "got %08x\n", hr );
148 ok( max_size == 65536, "got %u\n", max_size );
150 bytes.length = 0xdeadbeef;
151 bytes.bytes = (BYTE *)0xdeadbeef;
152 size = sizeof(bytes);
153 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_INITIAL_BUFFER, &bytes, size, NULL );
154 ok( hr == S_OK, "got %08x\n", hr );
155 ok( !bytes.length, "got %u\n", bytes.length );
156 ok( !bytes.bytes, "got %p\n", bytes.bytes );
158 max_ns = 0xdeadbeef;
159 size = sizeof(max_ns);
160 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES, &max_ns, size, NULL );
161 ok( hr == S_OK, "got %08x\n", hr );
162 ok( max_ns == 32, "got %u\n", max_ns );
163 WsFreeWriter( writer );
165 /* change a property */
166 max_depth = 16;
167 prop.id = WS_XML_WRITER_PROPERTY_MAX_DEPTH;
168 prop.value = &max_depth;
169 prop.valueSize = sizeof(max_depth);
170 hr = WsCreateWriter( &prop, 1, &writer, NULL );
171 ok( hr == S_OK, "got %08x\n", hr );
173 hr = set_output( writer );
174 ok( hr == S_OK, "got %08x\n", hr );
176 max_depth = 0xdeadbeef;
177 size = sizeof(max_depth);
178 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, size, NULL );
179 ok( hr == S_OK, "got %08x\n", hr );
180 ok( max_depth == 16, "got %u\n", max_depth );
181 WsFreeWriter( writer );
183 /* show that some properties are read-only */
184 in_attr = TRUE;
185 prop.id = WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE;
186 prop.value = &in_attr;
187 prop.valueSize = sizeof(in_attr);
188 hr = WsCreateWriter( &prop, 1, &writer, NULL );
189 ok( hr == E_INVALIDARG, "got %08x\n", hr );
191 size = 1;
192 prop.id = WS_XML_WRITER_PROPERTY_BYTES_WRITTEN;
193 prop.value = &size;
194 prop.valueSize = sizeof(size);
195 hr = WsCreateWriter( &prop, 1, &writer, NULL );
196 ok( hr == E_INVALIDARG, "got %08x\n", hr );
198 size = 1;
199 prop.id = WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE;
200 prop.value = &size;
201 prop.valueSize = sizeof(size);
202 hr = WsCreateWriter( &prop, 1, &writer, NULL );
203 ok( hr == E_INVALIDARG, "got %08x\n", hr );
206 static void test_WsCreateXmlBuffer(void)
208 HRESULT hr;
209 WS_HEAP *heap;
210 WS_XML_WRITER *writer;
211 WS_XML_BUFFER *buffer;
212 WS_BYTES bytes;
213 ULONG size;
215 hr = WsCreateXmlBuffer( NULL, NULL, 0, NULL, NULL );
216 ok( hr == E_INVALIDARG, "got %08x\n", hr );
218 hr = WsCreateXmlBuffer( NULL, NULL, 0, &buffer, NULL );
219 ok( hr == E_INVALIDARG, "got %08x\n", hr );
221 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
222 ok( hr == S_OK, "got %08x\n", hr );
224 hr = WsCreateXmlBuffer( heap, NULL, 0, NULL, NULL );
225 ok( hr == E_INVALIDARG, "got %08x\n", hr );
227 buffer = NULL;
228 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
229 ok( hr == S_OK, "got %08x\n", hr );
230 ok( buffer != NULL, "buffer not set\n" );
232 hr = WsCreateWriter( NULL, 0, &writer, NULL );
233 ok( hr == S_OK, "got %08x\n", hr );
235 size = sizeof(bytes);
236 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
237 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
239 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
240 ok( hr == S_OK, "got %08x\n", hr );
242 size = sizeof(bytes);
243 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
244 todo_wine ok( hr == E_INVALIDARG, "got %08x\n", hr );
246 WsFreeWriter( writer );
247 WsFreeHeap( heap );
250 static void test_WsSetOutput(void)
252 HRESULT hr;
253 WS_XML_WRITER *writer;
254 WS_XML_WRITER_PROPERTY prop;
255 WS_XML_WRITER_TEXT_ENCODING encoding;
256 WS_XML_WRITER_BUFFER_OUTPUT output;
257 ULONG size, max_depth;
259 hr = WsCreateWriter( NULL, 0, &writer, NULL );
260 ok( hr == S_OK, "got %08x\n", hr );
262 hr = WsSetOutput( NULL, NULL, NULL, NULL, 0, NULL );
263 ok( hr == E_INVALIDARG, "got %08x\n", hr );
265 encoding.encoding.encodingType = WS_XML_WRITER_ENCODING_TYPE_TEXT;
266 encoding.charSet = WS_CHARSET_UTF8;
268 output.output.outputType = WS_XML_WRITER_OUTPUT_TYPE_BUFFER;
270 hr = WsSetOutput( writer, &encoding.encoding, &output.output, NULL, 0, NULL );
271 ok( hr == S_OK, "got %08x\n", hr );
273 /* multiple calls are allowed */
274 hr = WsSetOutput( writer, &encoding.encoding, &output.output, NULL, 0, NULL );
275 ok( hr == S_OK, "got %08x\n", hr );
277 /* writer properties can be set with WsSetOutput */
278 max_depth = 16;
279 prop.id = WS_XML_WRITER_PROPERTY_MAX_DEPTH;
280 prop.value = &max_depth;
281 prop.valueSize = sizeof(max_depth);
282 hr = WsSetOutput( writer, &encoding.encoding, &output.output, &prop, 1, NULL );
283 ok( hr == S_OK, "got %08x\n", hr );
285 max_depth = 0xdeadbeef;
286 size = sizeof(max_depth);
287 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, size, NULL );
288 ok( hr == S_OK, "got %08x\n", hr );
289 ok( max_depth == 16, "got %u\n", max_depth );
290 WsFreeWriter( writer );
293 static void test_WsSetOutputToBuffer(void)
295 HRESULT hr;
296 WS_HEAP *heap;
297 WS_XML_BUFFER *buffer;
298 WS_XML_WRITER *writer;
299 WS_XML_WRITER_PROPERTY prop;
300 ULONG size, max_depth;
302 hr = WsSetOutputToBuffer( NULL, NULL, NULL, 0, NULL );
303 ok( hr == E_INVALIDARG, "got %08x\n", hr );
305 hr = WsCreateWriter( NULL, 0, &writer, NULL );
306 ok( hr == S_OK, "got %08x\n", hr );
308 hr = WsSetOutputToBuffer( writer, NULL, NULL, 0, NULL );
309 ok( hr == E_INVALIDARG, "got %08x\n", hr );
311 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
312 ok( hr == S_OK, "got %08x\n", hr );
314 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
315 ok( hr == S_OK, "got %08x\n", hr );
317 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
318 ok( hr == S_OK, "got %08x\n", hr );
320 /* multiple calls are allowed */
321 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
322 ok( hr == S_OK, "got %08x\n", hr );
324 /* writer properties can be set with WsSetOutputToBuffer */
325 max_depth = 16;
326 prop.id = WS_XML_WRITER_PROPERTY_MAX_DEPTH;
327 prop.value = &max_depth;
328 prop.valueSize = sizeof(max_depth);
329 hr = WsSetOutputToBuffer( writer, buffer, &prop, 1, NULL );
330 ok( hr == S_OK, "got %08x\n", hr );
332 max_depth = 0xdeadbeef;
333 size = sizeof(max_depth);
334 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, size, NULL );
335 ok( hr == S_OK, "got %08x\n", hr );
336 ok( max_depth == 16, "got %u\n", max_depth );
338 WsFreeWriter( writer );
339 WsFreeHeap( heap );
342 static char strbuf[512];
343 static const char *debugstr_bytes( const BYTE *bytes, ULONG len )
345 const BYTE *src = bytes;
346 char *dst = strbuf;
348 while (len)
350 BYTE c = *src++;
351 if (dst - strbuf > sizeof(strbuf) - 7) break;
352 switch (c)
354 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
355 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
356 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
357 default:
358 if (c >= ' ' && c < 127) *dst++ = c;
359 else
361 sprintf( dst, "\\%02x", c );
362 dst += 3;
365 len--;
367 if (len)
369 *dst++ = '.';
370 *dst++ = '.';
371 *dst++ = '.';
373 *dst = 0;
374 return strbuf;
377 static void check_output( WS_XML_WRITER *writer, const char *expected, unsigned int line )
379 WS_BYTES bytes;
380 ULONG size = sizeof(bytes);
381 int len = strlen( expected );
382 HRESULT hr;
384 memset( &bytes, 0, sizeof(bytes) );
385 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
386 ok( hr == S_OK, "%u: got %08x\n", line, hr );
387 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
388 if (bytes.length != len) return;
389 ok( !memcmp( bytes.bytes, expected, len ),
390 "%u: got %s expected %s\n", line, debugstr_bytes(bytes.bytes, bytes.length), expected );
393 static void test_WsWriteStartElement(void)
395 HRESULT hr;
396 WS_XML_WRITER *writer;
397 WS_XML_STRING prefix = {1, (BYTE *)"p"}, ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
398 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, empty = {0, NULL};
400 hr = WsCreateWriter( NULL, 0, &writer, NULL );
401 ok( hr == S_OK, "got %08x\n", hr );
403 hr = set_output( writer );
404 ok( hr == S_OK, "got %08x\n", hr );
406 hr = WsWriteStartElement( NULL, &prefix, &localname, &ns, NULL );
407 ok( hr == E_INVALIDARG, "got %08x\n", hr );
409 /* first call to WsWriteStartElement doesn't output anything */
410 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
411 ok( hr == S_OK, "got %08x\n", hr );
412 check_output( writer, "", __LINE__ );
414 /* two ways to close an element */
415 hr = WsWriteEndStartElement( writer, NULL );
416 ok( hr == S_OK, "got %08x\n", hr );
417 check_output( writer, "<p:a xmlns:p=\"ns\">", __LINE__ );
419 hr = WsWriteEndElement( writer, NULL );
420 ok( hr == S_OK, "got %08x\n", hr );
421 check_output( writer, "<p:a xmlns:p=\"ns\"></p:a>", __LINE__ );
423 hr = set_output( writer );
424 ok( hr == S_OK, "got %08x\n", hr );
426 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
427 ok( hr == S_OK, "got %08x\n", hr );
429 hr = WsWriteEndElement( writer, NULL );
430 ok( hr == S_OK, "got %08x\n", hr );
431 check_output( writer, "<p:a xmlns:p=\"ns\"/>", __LINE__ );
433 /* nested elements */
434 hr = set_output( writer );
435 ok( hr == S_OK, "got %08x\n", hr );
437 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
438 ok( hr == S_OK, "got %08x\n", hr );
439 check_output( writer, "", __LINE__ );
441 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
442 ok( hr == S_OK, "got %08x\n", hr );
443 check_output( writer, "<p:a xmlns:p=\"ns\">", __LINE__ );
445 hr = WsWriteEndElement( writer, NULL );
446 ok( hr == S_OK, "got %08x\n", hr );
447 check_output( writer, "<p:a xmlns:p=\"ns\"><p:b/>", __LINE__ );
449 hr = WsWriteEndElement( writer, NULL );
450 ok( hr == S_OK, "got %08x\n", hr );
451 check_output( writer, "<p:a xmlns:p=\"ns\"><p:b/></p:a>", __LINE__ );
453 hr = set_output( writer );
454 ok( hr == S_OK, "got %08x\n", hr );
456 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
457 ok( hr == S_OK, "got %08x\n", hr );
458 check_output( writer, "", __LINE__ );
460 hr = WsWriteStartElement( writer, NULL, &localname2, &ns2, NULL );
461 ok( hr == S_OK, "got %08x\n", hr );
462 check_output( writer, "<p:a xmlns:p=\"ns\">", __LINE__ );
464 hr = WsWriteEndElement( writer, NULL );
465 ok( hr == S_OK, "got %08x\n", hr );
466 check_output( writer, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/>", __LINE__ );
468 hr = WsWriteEndElement( writer, NULL );
469 ok( hr == S_OK, "got %08x\n", hr );
470 check_output( writer, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/></p:a>", __LINE__ );
472 hr = set_output( writer );
473 ok( hr == S_OK, "got %08x\n", hr );
475 hr = WsWriteStartElement( writer, &empty, &localname, &empty, NULL );
476 ok( hr == S_OK, "got %08x\n", hr );
477 hr = WsWriteEndStartElement( writer, NULL );
478 ok( hr == S_OK, "got %08x\n", hr );
479 hr = WsWriteEndElement( writer, NULL );
480 ok( hr == S_OK, "got %08x\n", hr );
481 check_output( writer, "<a></a>", __LINE__ );
483 WsFreeWriter( writer );
486 static void test_WsWriteStartAttribute(void)
488 HRESULT hr;
489 WS_XML_WRITER *writer;
490 WS_XML_STRING prefix = {1, (BYTE *)"p"}, localname = {3, (BYTE *)"str"};
491 WS_XML_STRING localname2 = {3, (BYTE *)"len"}, ns = {2, (BYTE *)"ns"}, empty = {0, NULL};
492 WS_XML_UTF8_TEXT text = {{WS_XML_TEXT_TYPE_UTF8}};
494 hr = WsCreateWriter( NULL, 0, &writer, NULL );
495 ok( hr == S_OK, "got %08x\n", hr );
497 hr = set_output( writer );
498 ok( hr == S_OK, "got %08x\n", hr );
500 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
501 ok( hr == S_OK, "got %08x\n", hr );
503 hr = WsWriteStartAttribute( NULL, &prefix, &localname, &ns, FALSE, NULL );
504 ok( hr == E_INVALIDARG, "got %08x\n", hr );
506 /* WsWriteStartAttribute doesn't output anything */
507 hr = WsWriteStartAttribute( writer, &prefix, &localname2, &ns, FALSE, NULL );
508 ok( hr == S_OK, "got %08x\n", hr );
509 check_output( writer, "", __LINE__ );
511 text.value.length = 1;
512 text.value.bytes = (BYTE *)"0";
513 hr = WsWriteText( writer, &text.text, NULL );
514 ok( hr == S_OK, "got %08x\n", hr );
515 check_output( writer, "", __LINE__ );
517 /* WsWriteEndAttribute doesn't output anything */
518 hr = WsWriteEndAttribute( writer, NULL );
519 ok( hr == S_OK, "got %08x\n", hr );
520 check_output( writer, "", __LINE__ );
522 hr = WsWriteEndElement( writer, NULL );
523 ok( hr == S_OK, "got %08x\n", hr );
524 check_output( writer, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__ );
526 hr = set_output( writer );
527 ok( hr == S_OK, "got %08x\n", hr );
529 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
530 ok( hr == S_OK, "got %08x\n", hr );
532 hr = WsWriteStartAttribute( writer, &empty, &localname2, &empty, FALSE, NULL );
533 ok( hr == S_OK, "got %08x\n", hr );
534 hr = WsWriteEndAttribute( writer, NULL );
535 ok( hr == S_OK, "got %08x\n", hr );
537 hr = WsWriteEndElement( writer, NULL );
538 ok( hr == S_OK, "got %08x\n", hr );
539 check_output( writer, "<p:str len=\"\" xmlns:p=\"ns\"/>", __LINE__ );
541 hr = set_output( writer );
542 ok( hr == S_OK, "got %08x\n", hr );
544 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
545 ok( hr == S_OK, "got %08x\n", hr );
547 hr = WsWriteStartAttribute( writer, NULL, &localname2, &empty, FALSE, NULL );
548 ok( hr == S_OK, "got %08x\n", hr );
550 hr = WsWriteEndAttribute( writer, NULL );
551 ok( hr == S_OK, "got %08x\n", hr );
553 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
554 ok( hr == S_OK, "got %08x\n", hr );
556 hr = WsWriteEndAttribute( writer, NULL );
557 ok( hr == S_OK, "got %08x\n", hr );
559 hr = WsWriteEndElement( writer, NULL );
560 ok( hr == S_OK, "got %08x\n", hr );
561 check_output( writer, "<p:str len=\"\" p:str=\"\" xmlns:p=\"ns\"/>", __LINE__ );
563 WsFreeWriter( writer );
566 static void test_WsWriteType(void)
568 static const WCHAR testW[] = {'t','e','s','t',0};
569 HRESULT hr;
570 WS_XML_WRITER *writer;
571 WS_XML_STRING prefix = {1, (BYTE*)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
572 const WCHAR *val_str;
574 hr = WsCreateWriter( NULL, 0, &writer, NULL );
575 ok( hr == S_OK, "got %08x\n", hr );
577 hr = set_output( writer );
578 ok( hr == S_OK, "got %08x\n", hr );
580 val_str = testW;
581 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
582 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
583 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
585 hr = set_output( writer );
586 ok( hr == S_OK, "got %08x\n", hr );
588 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
589 ok( hr == S_OK, "got %08x\n", hr );
591 /* required value */
592 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
593 WS_WRITE_REQUIRED_VALUE, NULL, sizeof(testW), NULL );
594 ok( hr == E_INVALIDARG, "got %08x\n", hr );
596 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
597 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
598 ok( hr == E_INVALIDARG, "got %08x\n", hr );
600 /* required pointer */
601 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
602 WS_WRITE_REQUIRED_POINTER, NULL, sizeof(val_str), NULL );
603 ok( hr == E_INVALIDARG, "got %08x\n", hr );
605 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
606 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
607 ok( hr == E_INVALIDARG, "got %08x\n", hr );
609 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
610 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(WCHAR **), NULL );
611 ok( hr == S_OK, "got %08x\n", hr );
612 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
614 hr = WsWriteEndElement( writer, NULL );
615 ok( hr == S_OK, "got %08x\n", hr );
616 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
618 hr = set_output( writer );
619 ok( hr == S_OK, "got %08x\n", hr );
621 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
622 ok( hr == S_OK, "got %08x\n", hr );
624 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
625 ok( hr == S_OK, "got %08x\n", hr );
627 val_str = testW;
628 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
629 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
630 ok( hr == S_OK, "got %08x\n", hr );
631 check_output( writer, "", __LINE__ );
633 hr = WsWriteEndAttribute( writer, NULL );
634 ok( hr == S_OK, "got %08x\n", hr );
635 check_output( writer, "", __LINE__ );
637 hr = WsWriteEndElement( writer, NULL );
638 ok( hr == S_OK, "got %08x\n", hr );
639 check_output( writer, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__ );
641 hr = set_output( writer );
642 ok( hr == S_OK, "got %08x\n", hr );
644 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
645 ok( hr == S_OK, "got %08x\n", hr );
647 val_str = testW;
648 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
649 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
650 ok( hr == S_OK, "got %08x\n", hr );
651 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
653 hr = WsWriteEndElement( writer, NULL );
654 ok( hr == S_OK, "got %08x\n", hr );
655 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
657 WsFreeWriter( writer );
660 static void prepare_basic_type_test( WS_XML_WRITER *writer )
662 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
663 HRESULT hr;
665 hr = set_output( writer );
666 ok( hr == S_OK, "got %08x\n", hr );
667 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
668 ok( hr == S_OK, "got %08x\n", hr );
671 static void test_basic_type(void)
673 static WCHAR testW[] = {'t','e','s','t',0};
674 HRESULT hr;
675 WS_XML_WRITER *writer;
676 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, xmlstr;
677 GUID guid;
678 WCHAR *str;
679 WS_STRING string;
680 WS_BYTES bytes;
681 ULONG i;
682 static const struct
684 WS_TYPE type;
685 INT64 val;
686 ULONG size;
687 const char *result;
688 const char *result2;
690 tests[] =
692 { WS_BOOL_TYPE, TRUE, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
693 { WS_BOOL_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
694 { WS_INT8_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
695 { WS_INT16_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
696 { WS_INT32_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
697 "<t t=\"-2147483648\"/>" },
698 { WS_INT64_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
699 "<t t=\"-9223372036854775808\"/>" },
700 { WS_UINT8_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
701 { WS_UINT16_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
702 { WS_UINT32_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
703 { WS_UINT64_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
704 "<t t=\"18446744073709551615\"/>" },
707 hr = WsCreateWriter( NULL, 0, &writer, NULL );
708 ok( hr == S_OK, "got %08x\n", hr );
710 /* element content type mapping */
711 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
713 prepare_basic_type_test( writer );
714 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
715 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
716 ok( hr == S_OK, "%u: got %08x\n", i, hr );
718 hr = WsWriteEndElement( writer, NULL );
719 ok( hr == S_OK, "got %08x\n", hr );
720 check_output( writer, tests[i].result, __LINE__ );
723 /* element type mapping is the same as element content type mapping for basic types */
724 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
726 const INT64 *ptr = &tests[i].val;
728 prepare_basic_type_test( writer );
729 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
730 WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
731 ok( hr == S_OK, "%u: got %08x\n", i, hr );
733 hr = WsWriteEndElement( writer, NULL );
734 ok( hr == S_OK, "got %08x\n", hr );
735 check_output( writer, tests[i].result, __LINE__ );
738 /* attribute type mapping */
739 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
741 prepare_basic_type_test( writer );
742 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
743 ok( hr == S_OK, "got %08x\n", hr );
745 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, tests[i].type, NULL,
746 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
747 ok( hr == S_OK, "%u: got %08x\n", i, hr );
749 hr = WsWriteEndAttribute( writer, NULL );
750 ok( hr == S_OK, "got %08x\n", hr );
752 hr = WsWriteEndElement( writer, NULL );
753 ok( hr == S_OK, "got %08x\n", hr );
754 check_output( writer, tests[i].result2, __LINE__ );
757 prepare_basic_type_test( writer );
758 memset( &guid, 0, sizeof(guid) );
759 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
760 &guid, sizeof(guid), NULL );
761 ok( hr == S_OK, "got %08x\n", hr );
762 hr = WsWriteEndElement( writer, NULL );
763 ok( hr == S_OK, "got %08x\n", hr );
764 check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
766 prepare_basic_type_test( writer );
767 string.chars = testW;
768 string.length = 4;
769 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
770 &string, sizeof(string), NULL );
771 ok( hr == S_OK, "got %08x\n", hr );
772 hr = WsWriteEndElement( writer, NULL );
773 ok( hr == S_OK, "got %08x\n", hr );
774 check_output( writer, "<t>test</t>", __LINE__ );
776 prepare_basic_type_test( writer );
777 str = testW;
778 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
779 &str, sizeof(str), NULL );
780 ok( hr == S_OK, "got %08x\n", hr );
781 hr = WsWriteEndElement( writer, NULL );
782 ok( hr == S_OK, "got %08x\n", hr );
783 check_output( writer, "<t>test</t>", __LINE__ );
785 prepare_basic_type_test( writer );
786 xmlstr.bytes = (BYTE *)"test";
787 xmlstr.length = 4;
788 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
789 &xmlstr, sizeof(xmlstr), NULL );
790 ok( hr == S_OK, "got %08x\n", hr );
791 hr = WsWriteEndElement( writer, NULL );
792 ok( hr == S_OK, "got %08x\n", hr );
793 check_output( writer, "<t>test</t>", __LINE__ );
795 prepare_basic_type_test( writer );
796 bytes.bytes = (BYTE *)"test";
797 bytes.length = 4;
798 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
799 &bytes, sizeof(bytes), NULL );
800 ok( hr == S_OK, "got %08x\n", hr );
801 hr = WsWriteEndElement( writer, NULL );
802 ok( hr == S_OK, "got %08x\n", hr );
803 check_output( writer, "<t>dGVzdA==</t>", __LINE__ );
805 prepare_basic_type_test( writer );
806 bytes.length = 0;
807 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
808 &bytes, sizeof(bytes), NULL );
809 ok( hr == S_OK, "got %08x\n", hr );
810 hr = WsWriteEndElement( writer, NULL );
811 ok( hr == S_OK, "got %08x\n", hr );
812 check_output( writer, "<t/>", __LINE__ );
814 prepare_basic_type_test( writer );
815 bytes.bytes = NULL;
816 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
817 &bytes, sizeof(bytes), NULL );
818 ok( hr == S_OK, "got %08x\n", hr );
819 hr = WsWriteEndElement( writer, NULL );
820 ok( hr == S_OK, "got %08x\n", hr );
821 check_output( writer, "<t/>", __LINE__ );
823 prepare_basic_type_test( writer );
824 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_NILLABLE_VALUE,
825 &bytes, sizeof(bytes), NULL );
826 ok( hr == S_OK, "got %08x\n", hr );
827 hr = WsWriteEndElement( writer, NULL );
828 ok( hr == S_OK, "got %08x\n", hr );
829 check_output( writer, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
830 __LINE__ );
832 WsFreeWriter( writer );
835 static void test_simple_struct_type(void)
837 static const WCHAR valueW[] = {'v','a','l','u','e',0};
838 HRESULT hr;
839 WS_XML_WRITER *writer;
840 WS_STRUCT_DESCRIPTION s;
841 WS_FIELD_DESCRIPTION f, *fields[1];
842 WS_XML_STRING localname = {6, (BYTE *)"struct"}, ns = {0, NULL};
843 struct test
845 const WCHAR *field;
846 } *test;
848 hr = WsCreateWriter( NULL, 0, &writer, NULL );
849 ok( hr == S_OK, "got %08x\n", hr );
851 hr = set_output( writer );
852 ok( hr == S_OK, "got %08x\n", hr );
854 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
855 ok( hr == S_OK, "got %08x\n", hr );
857 memset( &f, 0, sizeof(f) );
858 f.mapping = WS_TEXT_FIELD_MAPPING;
859 f.type = WS_WSZ_TYPE;
860 fields[0] = &f;
862 memset( &s, 0, sizeof(s) );
863 s.size = sizeof(struct test);
864 s.alignment = TYPE_ALIGNMENT(struct test);
865 s.fields = fields;
866 s.fieldCount = 1;
868 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
869 test->field = valueW;
870 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
871 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
872 ok( hr == E_INVALIDARG, "got %08x\n", hr );
874 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
875 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
876 ok( hr == E_INVALIDARG, "got %08x\n", hr );
878 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
879 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
880 ok( hr == S_OK, "got %08x\n", hr );
882 hr = WsWriteEndElement( writer, NULL );
883 ok( hr == S_OK, "got %08x\n", hr );
884 check_output( writer, "<struct>value</struct>", __LINE__ );
886 /* required value */
887 hr = set_output( writer );
888 ok( hr == S_OK, "got %08x\n", hr );
890 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
891 ok( hr == S_OK, "got %08x\n", hr );
893 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
894 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
895 ok( hr == S_OK, "got %08x\n", hr );
897 hr = WsWriteEndElement( writer, NULL );
898 ok( hr == S_OK, "got %08x\n", hr );
899 check_output( writer, "<struct>value</struct>", __LINE__ );
901 hr = set_output( writer );
902 ok( hr == S_OK, "got %08x\n", hr );
904 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
905 ok( hr == S_OK, "got %08x\n", hr );
907 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
908 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
909 ok( hr == S_OK, "got %08x\n", hr );
911 hr = WsWriteEndElement( writer, NULL );
912 ok( hr == S_OK, "got %08x\n", hr );
913 check_output( writer, "<struct>value</struct>", __LINE__ );
915 hr = set_output( writer );
916 ok( hr == S_OK, "got %08x\n", hr );
918 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
919 ok( hr == S_OK, "got %08x\n", hr );
921 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
922 ok( hr == S_OK, "got %08x\n", hr );
924 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
925 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
926 ok( hr == S_OK, "got %08x\n", hr );
928 hr = WsWriteEndAttribute( writer, NULL );
929 ok( hr == S_OK, "got %08x\n", hr );
931 hr = WsWriteEndElement( writer, NULL );
932 ok( hr == S_OK, "got %08x\n", hr );
933 check_output( writer, "<struct struct=\"value\"/>", __LINE__ );
935 HeapFree( GetProcessHeap(), 0, test );
936 WsFreeWriter( writer );
939 static void test_WsWriteElement(void)
941 static const WCHAR testW[] = {'t','e','s','t',0};
942 HRESULT hr;
943 WS_XML_WRITER *writer;
944 WS_STRUCT_DESCRIPTION s;
945 WS_FIELD_DESCRIPTION f, *fields[1];
946 WS_ELEMENT_DESCRIPTION desc;
947 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
948 struct test { const WCHAR *str; } *test;
950 hr = WsCreateWriter( NULL, 0, &writer, NULL );
951 ok( hr == S_OK, "got %08x\n", hr );
953 hr = set_output( writer );
954 ok( hr == S_OK, "got %08x\n", hr );
956 /* text field mapping */
957 memset( &f, 0, sizeof(f) );
958 f.mapping = WS_TEXT_FIELD_MAPPING;
959 f.type = WS_WSZ_TYPE;
960 fields[0] = &f;
962 memset( &s, 0, sizeof(s) );
963 s.size = sizeof(struct test);
964 s.alignment = TYPE_ALIGNMENT(struct test);
965 s.fields = fields;
966 s.fieldCount = 1;
968 desc.elementLocalName = &localname;
969 desc.elementNs = &ns;
970 desc.type = WS_STRUCT_TYPE;
971 desc.typeDescription = &s;
973 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
974 test->str = testW;
975 hr = WsWriteElement( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
976 ok( hr == E_INVALIDARG, "got %08x\n", hr );
978 hr = WsWriteElement( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
979 ok( hr == E_INVALIDARG, "got %08x\n", hr );
981 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
982 ok( hr == E_INVALIDARG, "got %08x\n", hr );
984 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
985 ok( hr == S_OK, "got %08x\n", hr );
986 check_output( writer, "<str>test</str>", __LINE__ );
988 hr = set_output( writer );
989 ok( hr == S_OK, "got %08x\n", hr );
991 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
992 ok( hr == S_OK, "got %08x\n", hr );
994 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
995 ok( hr == S_OK, "got %08x\n", hr );
996 check_output( writer, "<str><str>test</str>", __LINE__ );
998 hr = set_output( writer );
999 ok( hr == S_OK, "got %08x\n", hr );
1001 /* attribute field mapping */
1002 f.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
1004 /* requires localName and ns to be set */
1005 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1006 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1008 hr = set_output( writer );
1009 ok( hr == S_OK, "got %08x\n", hr );
1011 f.localName = &localname;
1012 f.ns = &ns;
1013 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1014 ok( hr == S_OK, "got %08x\n", hr );
1015 check_output( writer, "<str str=\"test\"/>", __LINE__ );
1017 HeapFree( GetProcessHeap(), 0, test );
1018 WsFreeWriter( writer );
1021 static void test_WsWriteValue(void)
1023 HRESULT hr;
1024 WS_XML_WRITER *writer;
1025 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1026 ULONG i;
1027 static const struct
1029 WS_VALUE_TYPE type;
1030 INT64 val;
1031 ULONG size;
1032 const char *result;
1033 const char *result2;
1035 tests[] =
1037 { WS_BOOL_VALUE_TYPE, ~0, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
1038 { WS_BOOL_VALUE_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
1039 { WS_INT8_VALUE_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
1040 { WS_INT16_VALUE_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
1041 { WS_INT32_VALUE_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
1042 "<t t=\"-2147483648\"/>" },
1043 { WS_INT64_VALUE_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
1044 "<t t=\"-9223372036854775808\"/>" },
1045 { WS_UINT8_VALUE_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
1046 { WS_UINT16_VALUE_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
1047 { WS_UINT32_VALUE_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
1048 { WS_UINT64_VALUE_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
1049 "<t t=\"18446744073709551615\"/>" },
1052 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1053 ok( hr == S_OK, "got %08x\n", hr );
1055 hr = set_output( writer );
1056 ok( hr == S_OK, "got %08x\n", hr );
1058 hr = WsWriteValue( NULL, tests[0].type, &tests[0].val, tests[0].size, NULL );
1059 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1061 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, tests[0].size, NULL );
1062 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1064 hr = set_output( writer );
1065 ok( hr == S_OK, "got %08x\n", hr );
1067 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1068 ok( hr == S_OK, "got %08x\n", hr );
1070 /* zero size */
1071 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, 0, NULL );
1072 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1074 hr = set_output( writer );
1075 ok( hr == S_OK, "got %08x\n", hr );
1077 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1078 ok( hr == S_OK, "got %08x\n", hr );
1080 /* NULL value */
1081 hr = WsWriteValue( writer, tests[0].type, NULL, 0, NULL );
1082 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1084 /* element type mapping */
1085 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1087 hr = set_output( writer );
1088 ok( hr == S_OK, "got %08x\n", hr );
1090 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1091 ok( hr == S_OK, "got %08x\n", hr );
1093 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1094 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1096 hr = WsWriteEndElement( writer, NULL );
1097 ok( hr == S_OK, "got %08x\n", hr );
1098 check_output( writer, tests[i].result, __LINE__ );
1101 /* attribute type mapping */
1102 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1104 hr = set_output( writer );
1105 ok( hr == S_OK, "got %08x\n", hr );
1107 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1108 ok( hr == S_OK, "got %08x\n", hr );
1110 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
1111 ok( hr == S_OK, "got %08x\n", hr );
1113 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1114 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1116 hr = WsWriteEndAttribute( writer, NULL );
1117 ok( hr == S_OK, "got %08x\n", hr );
1119 hr = WsWriteEndElement( writer, NULL );
1120 ok( hr == S_OK, "got %08x\n", hr );
1121 check_output( writer, tests[i].result2, __LINE__ );
1124 WsFreeWriter( writer );
1127 static void test_WsWriteAttribute(void)
1129 static const WCHAR testW[] = {'t','e','s','t',0};
1130 HRESULT hr;
1131 WS_XML_WRITER *writer;
1132 WS_STRUCT_DESCRIPTION s;
1133 WS_FIELD_DESCRIPTION f, *fields[1];
1134 WS_ATTRIBUTE_DESCRIPTION desc;
1135 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
1136 struct test { const WCHAR *str; } *test;
1138 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1139 ok( hr == S_OK, "got %08x\n", hr );
1141 hr = set_output( writer );
1142 ok( hr == S_OK, "got %08x\n", hr );
1144 /* text field mapping */
1145 memset( &f, 0, sizeof(f) );
1146 f.mapping = WS_TEXT_FIELD_MAPPING;
1147 f.type = WS_WSZ_TYPE;
1148 fields[0] = &f;
1150 memset( &s, 0, sizeof(s) );
1151 s.size = sizeof(struct test);
1152 s.alignment = TYPE_ALIGNMENT(struct test);
1153 s.fields = fields;
1154 s.fieldCount = 1;
1156 desc.attributeLocalName = &localname;
1157 desc.attributeNs = &ns;
1158 desc.type = WS_STRUCT_TYPE;
1159 desc.typeDescription = &s;
1161 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
1162 test->str = testW;
1163 hr = WsWriteAttribute( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1164 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1166 hr = WsWriteAttribute( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1167 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1169 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
1170 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1172 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1173 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1175 hr = set_output( writer );
1176 ok( hr == S_OK, "got %08x\n", hr );
1178 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1179 ok( hr == S_OK, "got %08x\n", hr );
1181 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1182 ok( hr == S_OK, "got %08x\n", hr );
1184 hr = WsWriteEndElement( writer, NULL );
1185 ok( hr == S_OK, "got %08x\n", hr );
1186 check_output( writer, "<str str=\"test\"/>", __LINE__ );
1188 HeapFree( GetProcessHeap(), 0, test );
1189 WsFreeWriter( writer );
1192 static void test_WsWriteStartCData(void)
1194 HRESULT hr;
1195 WS_XML_WRITER *writer;
1196 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1197 WS_XML_UTF8_TEXT text = {{WS_XML_TEXT_TYPE_UTF8}};
1199 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1200 ok( hr == S_OK, "got %08x\n", hr );
1202 hr = set_output( writer );
1203 ok( hr == S_OK, "got %08x\n", hr );
1205 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1206 ok( hr == S_OK, "got %08x\n", hr );
1208 hr = WsWriteEndCData( writer, NULL );
1209 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1211 hr = set_output( writer );
1212 ok( hr == S_OK, "got %08x\n", hr );
1214 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1215 ok( hr == S_OK, "got %08x\n", hr );
1216 check_output( writer, "", __LINE__ );
1218 hr = WsWriteStartCData( writer, NULL );
1219 ok( hr == S_OK, "got %08x\n", hr );
1220 check_output( writer, "<t><![CDATA[", __LINE__ );
1222 text.value.bytes = (BYTE *)"<data>";
1223 text.value.length = 6;
1224 hr = WsWriteText( writer, &text.text, NULL );
1225 ok( hr == S_OK, "got %08x\n", hr );
1226 check_output( writer, "<t><![CDATA[<data>", __LINE__ );
1228 hr = WsWriteEndCData( writer, NULL );
1229 ok( hr == S_OK, "got %08x\n", hr );
1230 check_output( writer, "<t><![CDATA[<data>]]>", __LINE__ );
1232 hr = WsWriteEndElement( writer, NULL );
1233 ok( hr == S_OK, "got %08x\n", hr );
1234 check_output( writer, "<t><![CDATA[<data>]]></t>", __LINE__ );
1236 WsFreeWriter( writer );
1239 static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
1241 WS_XML_WRITER *writer;
1242 WS_BYTES bytes;
1243 ULONG size = sizeof(bytes);
1244 int len = strlen(expected);
1245 HRESULT hr;
1247 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1248 ok( hr == S_OK, "got %08x\n", hr );
1250 hr = set_output( writer );
1251 ok( hr == S_OK, "got %08x\n", hr );
1253 hr = WsWriteXmlBuffer( writer, buffer, NULL );
1254 ok( hr == S_OK, "got %08x\n", hr );
1256 memset( &bytes, 0, sizeof(bytes) );
1257 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
1258 ok( hr == S_OK, "%u: got %08x\n", line, hr );
1259 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
1260 if (bytes.length != len) return;
1261 ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
1263 WsFreeWriter( writer );
1266 static void prepare_xmlns_test( WS_XML_WRITER *writer, WS_HEAP **heap, WS_XML_BUFFER **buffer )
1268 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1269 HRESULT hr;
1271 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, heap, NULL );
1272 ok( hr == S_OK, "got %08x\n", hr );
1274 hr = WsCreateXmlBuffer( *heap, NULL, 0, buffer, NULL );
1275 ok( hr == S_OK, "got %08x\n", hr );
1277 hr = WsSetOutputToBuffer( writer, *buffer, NULL, 0, NULL );
1278 ok( hr == S_OK, "got %08x\n", hr );
1280 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
1281 ok( hr == S_OK, "got %08x\n", hr );
1284 static void test_WsWriteXmlnsAttribute(void)
1286 WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1287 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, prefix2 = {7, (BYTE *)"prefix2"};
1288 WS_XML_STRING xmlns = {6, (BYTE *)"xmlns"}, attr = {4, (BYTE *)"attr"};
1289 WS_XML_STRING localname = {1, (BYTE *)"u"};
1290 WS_HEAP *heap;
1291 WS_XML_BUFFER *buffer;
1292 WS_XML_WRITER *writer;
1293 HRESULT hr;
1295 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1296 ok( hr == S_OK, "got %08x\n", hr );
1298 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1299 ok( hr == S_OK, "got %08x\n", hr );
1301 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1302 ok( hr == S_OK, "got %08x\n", hr );
1304 hr = WsWriteXmlnsAttribute( NULL, NULL, NULL, FALSE, NULL );
1305 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1306 WsFreeHeap( heap );
1308 prepare_xmlns_test( writer, &heap, &buffer );
1309 hr = WsWriteXmlnsAttribute( writer, NULL, NULL, FALSE, NULL );
1310 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1311 WsFreeHeap( heap );
1313 prepare_xmlns_test( writer, &heap, &buffer );
1314 hr = WsWriteXmlnsAttribute( writer, &prefix2, NULL, FALSE, NULL );
1315 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1317 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1318 ok( hr == S_OK, "got %08x\n", hr );
1319 hr = WsWriteXmlnsAttribute( writer, NULL, &ns, FALSE, NULL );
1320 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1321 WsFreeHeap( heap );
1323 /* no prefix */
1324 prepare_xmlns_test( writer, &heap, &buffer );
1325 hr = WsWriteXmlnsAttribute( writer, NULL, &ns2, FALSE, NULL );
1326 ok( hr == S_OK, "got %08x\n", hr );
1327 hr = WsWriteEndElement( writer, NULL );
1328 ok( hr == S_OK, "got %08x\n", hr );
1329 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__ );
1330 WsFreeHeap( heap );
1332 /* prefix */
1333 prepare_xmlns_test( writer, &heap, &buffer );
1334 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1335 ok( hr == S_OK, "got %08x\n", hr );
1336 hr = WsWriteEndElement( writer, NULL );
1337 ok( hr == S_OK, "got %08x\n", hr );
1338 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__ );
1339 WsFreeHeap( heap );
1341 /* implicitly set element prefix namespace */
1342 prepare_xmlns_test( writer, &heap, &buffer );
1343 hr = WsWriteEndElement( writer, NULL );
1344 ok( hr == S_OK, "got %08x\n", hr );
1345 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__ );
1346 WsFreeHeap( heap );
1348 /* explicitly set element prefix namespace */
1349 prepare_xmlns_test( writer, &heap, &buffer );
1350 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1351 ok( hr == S_OK, "got %08x\n", hr );
1352 hr = WsWriteEndElement( writer, NULL );
1353 ok( hr == S_OK, "got %08x\n", hr );
1354 check_output_buffer( buffer, "<prefix:t xmlns:prefix='ns'/>", __LINE__ );
1355 WsFreeHeap( heap );
1357 /* repeated calls, same namespace */
1358 prepare_xmlns_test( writer, &heap, &buffer );
1359 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1360 ok( hr == S_OK, "got %08x\n", hr );
1361 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1362 ok( hr == S_OK, "got %08x\n", hr );
1363 hr = WsWriteEndElement( writer, NULL );
1364 ok( hr == S_OK, "got %08x\n", hr );
1365 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__ );
1366 WsFreeHeap( heap );
1368 /* repeated calls, different namespace */
1369 prepare_xmlns_test( writer, &heap, &buffer );
1370 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1371 ok( hr == S_OK, "got %08x\n", hr );
1372 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1373 ok( hr == S_OK, "got %08x\n", hr );
1374 hr = WsWriteEndElement( writer, NULL );
1375 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1376 WsFreeHeap( heap );
1378 /* single quotes */
1379 prepare_xmlns_test( writer, &heap, &buffer );
1380 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, TRUE, NULL );
1381 ok( hr == S_OK, "got %08x\n", hr );
1382 hr = WsWriteEndElement( writer, NULL );
1383 ok( hr == S_OK, "got %08x\n", hr );
1384 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns' xmlns:prefix=\"ns\"/>", __LINE__ );
1385 WsFreeHeap( heap );
1387 /* different namespace, different prefix */
1388 prepare_xmlns_test( writer, &heap, &buffer );
1389 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1390 ok( hr == S_OK, "got %08x\n", hr );
1391 hr = WsWriteEndElement( writer, NULL );
1392 ok( hr == S_OK, "got %08x\n", hr );
1393 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__ );
1394 WsFreeHeap( heap );
1396 /* different namespace, same prefix */
1397 prepare_xmlns_test( writer, &heap, &buffer );
1398 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns2, TRUE, NULL );
1399 ok( hr == S_OK, "got %08x\n", hr );
1400 hr = WsWriteEndElement( writer, NULL );
1401 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1402 WsFreeHeap( heap );
1404 /* regular attribute */
1405 prepare_xmlns_test( writer, &heap, &buffer );
1406 hr = WsWriteStartAttribute( writer, &xmlns, &prefix2, &ns2, TRUE, NULL );
1407 ok( hr == S_OK, "got %08x\n", hr );
1408 hr = WsWriteEndAttribute( writer, NULL );
1409 ok( hr == S_OK, "got %08x\n", hr );
1410 hr = WsWriteEndElement( writer, NULL );
1411 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1412 WsFreeHeap( heap );
1414 /* attribute order */
1415 prepare_xmlns_test( writer, &heap, &buffer );
1416 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1417 ok( hr == S_OK, "got %08x\n", hr );
1418 hr = WsWriteStartAttribute( writer, &prefix, &attr, &ns, TRUE, NULL );
1419 ok( hr == S_OK, "got %08x\n", hr );
1420 hr = WsWriteEndAttribute( writer, NULL );
1421 ok( hr == S_OK, "got %08x\n", hr );
1422 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1423 ok( hr == S_OK, "got %08x\n", hr );
1424 hr = WsWriteEndElement( writer, NULL );
1425 ok( hr == S_OK, "got %08x\n", hr );
1426 check_output_buffer( buffer, "<prefix:t prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__ );
1427 WsFreeHeap( heap );
1429 /* scope */
1430 prepare_xmlns_test( writer, &heap, &buffer );
1431 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1432 ok( hr == S_OK, "got %08x\n", hr );
1433 hr = WsWriteStartElement( writer, &prefix2, &localname, &ns2, NULL );
1434 ok( hr == S_OK, "got %08x\n", hr );
1435 hr = WsWriteEndElement( writer, NULL );
1436 ok( hr == S_OK, "got %08x\n", hr );
1437 hr = WsWriteEndElement( writer, NULL );
1438 ok( hr == S_OK, "got %08x\n", hr );
1439 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"><prefix2:u/></prefix:t>",
1440 __LINE__ );
1441 WsFreeHeap( heap );
1443 WsFreeWriter( writer );
1446 static void prepare_prefix_test( WS_XML_WRITER *writer )
1448 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1449 HRESULT hr;
1451 hr = set_output( writer );
1452 ok( hr == S_OK, "got %08x\n", hr );
1453 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1454 ok( hr == S_OK, "got %08x\n", hr );
1455 hr = WsWriteEndStartElement( writer, NULL );
1456 ok( hr == S_OK, "got %08x\n", hr );
1459 static void test_WsGetPrefixFromNamespace(void)
1461 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, *prefix;
1462 const WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1463 WS_XML_WRITER *writer;
1464 HRESULT hr;
1466 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1467 ok( hr == S_OK, "got %08x\n", hr );
1469 hr = set_output( writer );
1470 ok( hr == S_OK, "got %08x\n", hr );
1471 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1472 ok( hr == S_OK, "got %08x\n", hr );
1474 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, NULL, NULL );
1475 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1477 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, &prefix, NULL );
1478 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1480 hr = WsGetPrefixFromNamespace( writer, NULL, FALSE, &prefix, NULL );
1481 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1483 /* element must be committed */
1484 hr = set_output( writer );
1485 ok( hr == S_OK, "got %08x\n", hr );
1486 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1487 ok( hr == S_OK, "got %08x\n", hr );
1488 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1489 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1491 /* but writer can't be positioned on end element node */
1492 hr = set_output( writer );
1493 ok( hr == S_OK, "got %08x\n", hr );
1494 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1495 ok( hr == S_OK, "got %08x\n", hr );
1496 hr = WsWriteEndElement( writer, NULL );
1497 ok( hr == S_OK, "got %08x\n", hr );
1498 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1499 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1501 /* required = TRUE */
1502 prefix = NULL;
1503 prepare_prefix_test( writer );
1504 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1505 ok( hr == S_OK, "got %08x\n", hr );
1506 ok( prefix != NULL, "prefix not set\n" );
1507 if (prefix)
1509 ok( prefix->length == 1, "got %u\n", prefix->length );
1510 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1513 prefix = (const WS_XML_STRING *)0xdeadbeef;
1514 hr = WsGetPrefixFromNamespace( writer, &ns2, TRUE, &prefix, NULL );
1515 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1516 ok( prefix == (const WS_XML_STRING *)0xdeadbeef, "prefix set\n" );
1518 /* required = FALSE */
1519 prefix = NULL;
1520 prepare_prefix_test( writer );
1521 hr = WsGetPrefixFromNamespace( writer, &ns, FALSE, &prefix, NULL );
1522 ok( hr == S_OK, "got %08x\n", hr );
1523 ok( prefix != NULL, "prefix not set\n" );
1524 if (prefix)
1526 ok( prefix->length == 1, "got %u\n", prefix->length );
1527 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1530 prefix = (const WS_XML_STRING *)0xdeadbeef;
1531 hr = WsGetPrefixFromNamespace( writer, &ns2, FALSE, &prefix, NULL );
1532 ok( hr == S_FALSE, "got %08x\n", hr );
1533 ok( prefix == NULL, "prefix not set\n" );
1535 WsFreeWriter( writer );
1538 static void test_complex_struct_type(void)
1540 static const char expected[] =
1541 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1542 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1543 "</o:OfficeConfig>";
1544 static const WCHAR timestampW[] =
1545 {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
1546 WS_XML_STRING str_officeconfig = {12, (BYTE *)"OfficeConfig"};
1547 WS_XML_STRING str_services = {8, (BYTE *)"services"};
1548 WS_XML_STRING str_generationtime = {14, (BYTE *)"GenerationTime"};
1549 WS_XML_STRING ns = {39, (BYTE *)"urn:schemas-microsoft-com:office:office"};
1550 WS_XML_STRING prefix = {1, (BYTE *)"o"};
1551 DWORD size;
1552 HRESULT hr;
1553 WS_HEAP *heap;
1554 WS_XML_BUFFER *buffer;
1555 WS_XML_WRITER *writer;
1556 WS_STRUCT_DESCRIPTION s, s2;
1557 WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
1558 struct services
1560 const WCHAR *generationtime;
1562 struct officeconfig
1564 struct services *services;
1565 } *test;
1567 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1568 ok( hr == S_OK, "got %08x\n", hr );
1570 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1571 ok( hr == S_OK, "got %08x\n", hr );
1573 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1574 ok( hr == S_OK, "got %08x\n", hr );
1576 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1577 ok( hr == S_OK, "got %08x\n", hr );
1579 hr = WsWriteStartElement( writer, &prefix, &str_officeconfig, &ns, NULL );
1580 ok( hr == S_OK, "got %08x\n", hr );
1582 memset( &f2, 0, sizeof(f2) );
1583 f2.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
1584 f2.localName = &str_generationtime;
1585 f2.ns = &ns;
1586 f2.type = WS_WSZ_TYPE;
1587 f2.options = WS_FIELD_OPTIONAL;
1588 fields2[0] = &f2;
1590 memset( &s2, 0, sizeof(s2) );
1591 s2.size = sizeof(*test->services);
1592 s2.alignment = 4;
1593 s2.fields = fields2;
1594 s2.fieldCount = 1;
1595 s2.typeLocalName = &str_services;
1596 s2.typeNs = &ns;
1598 memset( &f, 0, sizeof(f) );
1599 f.mapping = WS_ELEMENT_FIELD_MAPPING;
1600 f.localName = &str_services;
1601 f.ns = &ns;
1602 f.type = WS_STRUCT_TYPE;
1603 f.typeDescription = &s2;
1604 f.options = WS_FIELD_POINTER;
1605 fields[0] = &f;
1607 memset( &s, 0, sizeof(s) );
1608 s.size = sizeof(*test);
1609 s.alignment = 4;
1610 s.fields = fields;
1611 s.fieldCount = 1;
1612 s.typeLocalName = &str_officeconfig;
1613 s.typeNs = &ns;
1615 size = sizeof(struct officeconfig) + sizeof(struct services);
1616 test = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
1617 test->services = (struct services *)(test + 1);
1618 test->services->generationtime = timestampW;
1619 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
1620 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1621 ok( hr == S_OK, "got %08x\n", hr );
1623 hr = WsWriteEndElement( writer, NULL );
1624 ok( hr == S_OK, "got %08x\n", hr );
1625 check_output_buffer( buffer, expected, __LINE__ );
1627 HeapFree( GetProcessHeap(), 0, test );
1628 WsFreeWriter( writer );
1629 WsFreeHeap( heap );
1632 static void test_WsMoveWriter(void)
1634 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, ns = {0, NULL};
1635 WS_HEAP *heap;
1636 WS_XML_WRITER *writer;
1637 WS_XML_BUFFER *buffer;
1638 HRESULT hr;
1640 hr = WsMoveWriter( NULL, WS_MOVE_TO_EOF, NULL, NULL );
1641 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1643 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1644 ok( hr == S_OK, "got %08x\n", hr );
1646 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1647 ok( hr == S_OK, "got %08x\n", hr );
1649 hr = set_output( writer );
1650 ok( hr == S_OK, "got %08x\n", hr );
1652 /* writer must be set to an XML buffer */
1653 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1654 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1656 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1657 ok( hr == S_OK, "got %08x\n", hr );
1659 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1660 ok( hr == S_OK, "got %08x\n", hr );
1662 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1663 ok( hr == S_OK, "got %08x\n", hr );
1665 /* <a><b/></a> */
1666 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1667 ok( hr == S_OK, "got %08x\n", hr );
1669 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1670 ok( hr == S_OK, "got %08x\n", hr );
1672 hr = WsWriteEndElement( writer, NULL );
1673 ok( hr == S_OK, "got %08x\n", hr );
1675 hr = WsWriteEndElement( writer, NULL );
1676 ok( hr == S_OK, "got %08x\n", hr );
1678 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1679 ok( hr == S_OK, "got %08x\n", hr );
1681 hr = WsMoveWriter( writer, WS_MOVE_TO_ROOT_ELEMENT, NULL, NULL );
1682 ok( hr == S_OK, "got %08x\n", hr );
1684 hr = WsMoveWriter( writer, WS_MOVE_TO_CHILD_ELEMENT, NULL, NULL );
1685 ok( hr == S_OK, "got %08x\n", hr );
1687 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1688 ok( hr == S_OK, "got %08x\n", hr );
1690 hr = WsMoveWriter( writer, WS_MOVE_TO_PARENT_ELEMENT, NULL, NULL );
1691 ok( hr == S_OK, "got %08x\n", hr );
1693 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1694 ok( hr == S_OK, "got %08x\n", hr );
1696 hr = WsMoveWriter( writer, WS_MOVE_TO_BOF, NULL, NULL );
1697 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1699 WsFreeWriter( writer );
1700 WsFreeHeap( heap );
1703 static void test_WsGetWriterPosition(void)
1705 WS_HEAP *heap;
1706 WS_XML_WRITER *writer;
1707 WS_XML_BUFFER *buffer;
1708 WS_XML_NODE_POSITION pos;
1709 HRESULT hr;
1711 hr = WsGetWriterPosition( NULL, NULL, NULL );
1712 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1714 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1715 ok( hr == S_OK, "got %08x\n", hr );
1717 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1718 ok( hr == S_OK, "got %08x\n", hr );
1720 hr = WsGetWriterPosition( writer, &pos, NULL );
1721 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1723 hr = set_output( writer );
1724 ok( hr == S_OK, "got %08x\n", hr );
1726 /* writer must be set to an XML buffer */
1727 hr = WsGetWriterPosition( writer, &pos, NULL );
1728 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1730 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1731 ok( hr == S_OK, "got %08x\n", hr );
1733 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1734 ok( hr == S_OK, "got %08x\n", hr );
1736 hr = WsGetWriterPosition( writer, NULL, NULL );
1737 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1739 pos.buffer = pos.node = NULL;
1740 hr = WsGetWriterPosition( writer, &pos, NULL );
1741 ok( hr == S_OK, "got %08x\n", hr );
1742 ok( pos.buffer != NULL, "buffer not set\n" );
1743 ok( pos.node != NULL, "node not set\n" );
1745 WsFreeWriter( writer );
1746 WsFreeHeap( heap );
1749 static void test_WsSetWriterPosition(void)
1751 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1752 WS_HEAP *heap;
1753 WS_XML_WRITER *writer;
1754 WS_XML_BUFFER *buf1, *buf2;
1755 WS_XML_NODE_POSITION pos;
1756 HRESULT hr;
1758 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1759 ok( hr == S_OK, "got %08x\n", hr );
1761 hr = WsSetWriterPosition( NULL, NULL, NULL );
1762 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1764 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1765 ok( hr == S_OK, "got %08x\n", hr );
1767 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf1, NULL );
1768 ok( hr == S_OK, "got %08x\n", hr );
1770 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1771 ok( hr == S_OK, "got %08x\n", hr );
1773 hr = WsSetWriterPosition( writer, NULL, NULL );
1774 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1776 pos.buffer = pos.node = NULL;
1777 hr = WsGetWriterPosition( writer, &pos, NULL );
1778 ok( hr == S_OK, "got %08x\n", hr );
1779 ok( pos.buffer == buf1, "wrong buffer\n" );
1780 ok( pos.node != NULL, "node not set\n" );
1782 hr = WsSetWriterPosition( writer, &pos, NULL );
1783 ok( hr == S_OK, "got %08x\n", hr );
1785 /* different buffer */
1786 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf2, NULL );
1787 ok( hr == S_OK, "got %08x\n", hr );
1789 pos.buffer = buf2;
1790 hr = WsSetWriterPosition( writer, &pos, NULL );
1791 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1793 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1794 ok( hr == S_OK, "got %08x\n", hr );
1796 /* try to write at non-final position */
1797 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1798 ok( hr == S_OK, "got %08x\n", hr );
1800 pos.buffer = pos.node = NULL;
1801 hr = WsGetWriterPosition( writer, &pos, NULL );
1802 ok( hr == S_OK, "got %08x\n", hr );
1803 ok( pos.buffer == buf1, "wrong buffer\n" );
1804 ok( pos.node != NULL, "node not set\n" );
1806 hr = WsWriteEndElement( writer, NULL );
1807 ok( hr == S_OK, "got %08x\n", hr );
1808 check_output_buffer( buf1, "<t/>", __LINE__ );
1810 hr = WsSetWriterPosition( writer, &pos, NULL );
1811 ok( hr == S_OK, "got %08x\n", hr );
1813 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1814 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1816 WsFreeWriter( writer );
1817 WsFreeHeap( heap );
1820 static void test_WsWriteXmlBuffer(void)
1822 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1823 WS_XML_WRITER *writer1, *writer2;
1824 WS_XML_BUFFER *buffer1, *buffer2;
1825 WS_HEAP *heap;
1826 HRESULT hr;
1828 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1829 ok( hr == S_OK, "got %08x\n", hr );
1831 hr = WsCreateXmlBuffer( NULL, NULL, 0, NULL, NULL );
1832 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1834 hr = WsCreateWriter( NULL, 0, &writer1, NULL );
1835 ok( hr == S_OK, "got %08x\n", hr );
1837 hr = WsCreateXmlBuffer( heap, NULL, 0, NULL, NULL );
1838 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1840 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer1, NULL );
1841 ok( hr == S_OK, "got %08x\n", hr );
1843 hr = WsSetOutputToBuffer( writer1, buffer1, NULL, 0, NULL );
1844 ok( hr == S_OK, "got %08x\n", hr );
1846 hr = WsWriteStartElement( writer1, NULL, &localname, &ns, NULL );
1847 ok( hr == S_OK, "got %08x\n", hr );
1849 hr = WsWriteEndElement( writer1, NULL );
1850 ok( hr == S_OK, "got %08x\n", hr );
1851 check_output_buffer( buffer1, "<t/>", __LINE__ );
1853 hr = WsCreateWriter( NULL, 0, &writer2, NULL );
1854 ok( hr == S_OK, "got %08x\n", hr );
1856 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer2, NULL );
1857 ok( hr == S_OK, "got %08x\n", hr );
1859 hr = WsSetOutputToBuffer( writer2, buffer2, NULL, 0, NULL );
1860 ok( hr == S_OK, "got %08x\n", hr );
1862 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1863 ok( hr == S_OK, "got %08x\n", hr );
1864 check_output_buffer( buffer2, "<t/>", __LINE__ );
1866 hr = WsMoveWriter( writer2, WS_MOVE_TO_PREVIOUS_ELEMENT, NULL, NULL );
1867 todo_wine ok( hr == S_OK, "got %08x\n", hr );
1869 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1870 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1872 WsFreeWriter( writer1 );
1873 WsFreeWriter( writer2 );
1874 WsFreeHeap( heap );
1877 static void test_WsWriteNode(void)
1879 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {4, (BYTE *)"attr"}, ns = {0, NULL};
1880 WS_XML_WRITER *writer;
1881 WS_XML_BUFFER *buffer;
1882 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
1883 WS_XML_ATTRIBUTE attr, *attrs[1];
1884 WS_XML_ELEMENT_NODE elem;
1885 WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
1886 WS_XML_NODE node;
1887 WS_XML_TEXT_NODE text = {{WS_XML_NODE_TYPE_TEXT}};
1888 WS_HEAP *heap;
1889 HRESULT hr;
1891 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1892 ok( hr == S_OK, "got %08x\n", hr );
1894 hr = WsWriteNode( NULL, NULL, NULL );
1895 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1897 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1898 ok( hr == S_OK, "got %08x\n", hr );
1900 hr = WsWriteNode( writer, NULL, NULL );
1901 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1903 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1904 ok( hr == S_OK, "got %08x\n", hr );
1906 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1907 ok( hr == S_OK, "got %08x\n", hr );
1909 utf8.value.bytes = (BYTE *)"value";
1910 utf8.value.length = sizeof("value") - 1;
1912 attr.singleQuote = TRUE;
1913 attr.isXmlNs = FALSE;
1914 attr.prefix = NULL;
1915 attr.localName = &localname2;
1916 attr.ns = &ns;
1917 attr.value = &utf8.text;
1918 attrs[0] = &attr;
1920 elem.node.nodeType = WS_XML_NODE_TYPE_ELEMENT;
1921 elem.prefix = NULL;
1922 elem.localName = &localname;
1923 elem.ns = &ns;
1924 elem.attributeCount = 1;
1925 elem.attributes = attrs;
1926 elem.isEmpty = FALSE;
1927 hr = WsWriteNode( writer, &elem.node, NULL );
1928 ok( hr == S_OK, "got %08x\n", hr );
1930 comment.value.bytes = (BYTE *)"comment";
1931 comment.value.length = sizeof("comment") - 1;
1932 hr = WsWriteNode( writer, &comment.node, NULL );
1933 ok( hr == S_OK, "got %08x\n", hr );
1935 node.nodeType = WS_XML_NODE_TYPE_EOF;
1936 hr = WsWriteNode( writer, &node, NULL );
1937 ok( hr == S_OK, "got %08x\n", hr );
1939 node.nodeType = WS_XML_NODE_TYPE_BOF;
1940 hr = WsWriteNode( writer, &node, NULL );
1941 ok( hr == S_OK, "got %08x\n", hr );
1943 node.nodeType = WS_XML_NODE_TYPE_CDATA;
1944 hr = WsWriteNode( writer, &node, NULL );
1945 ok( hr == S_OK, "got %08x\n", hr );
1947 utf8.value.bytes = (BYTE *)"cdata";
1948 utf8.value.length = sizeof("cdata") - 1;
1949 text.text = &utf8.text;
1950 hr = WsWriteNode( writer, &text.node, NULL );
1951 ok( hr == S_OK, "got %08x\n", hr );
1953 node.nodeType = WS_XML_NODE_TYPE_END_CDATA;
1954 hr = WsWriteNode( writer, &node, NULL );
1955 ok( hr == S_OK, "got %08x\n", hr );
1957 utf8.value.bytes = (BYTE *)"text";
1958 utf8.value.length = sizeof("text") - 1;
1959 hr = WsWriteNode( writer, &text.node, NULL );
1960 ok( hr == S_OK, "got %08x\n", hr );
1962 node.nodeType = WS_XML_NODE_TYPE_END_ELEMENT;
1963 hr = WsWriteNode( writer, &node, NULL );
1964 ok( hr == S_OK, "got %08x\n", hr );
1965 check_output_buffer( buffer, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__ );
1967 WsFreeWriter( writer );
1968 WsFreeHeap( heap );
1971 static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
1973 WS_XML_READER_TEXT_ENCODING enc;
1974 WS_XML_READER_BUFFER_INPUT input;
1976 enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
1977 enc.charSet = WS_CHARSET_AUTO;
1979 input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
1980 input.encodedData = (void *)data;
1981 input.encodedDataSize = size;
1983 return WsSetInput( reader, &enc.encoding, &input.input, NULL, 0, NULL );
1986 static void test_WsCopyNode(void)
1988 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
1989 WS_XML_NODE_POSITION pos, pos2;
1990 const WS_XML_NODE *node;
1991 WS_XML_WRITER *writer;
1992 WS_XML_READER *reader;
1993 WS_XML_BUFFER *buffer;
1994 WS_BUFFERS bufs;
1995 WS_HEAP *heap;
1996 HRESULT hr;
1998 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1999 ok( hr == S_OK, "got %08x\n", hr );
2001 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2002 ok( hr == S_OK, "got %08x\n", hr );
2004 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
2005 ok( hr == S_OK, "got %08x\n", hr );
2007 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
2008 ok( hr == S_OK, "got %08x\n", hr );
2010 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2011 ok( hr == S_OK, "got %08x\n", hr );
2013 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
2014 ok( hr == S_OK, "got %08x\n", hr );
2016 hr = WsWriteEndElement( writer, NULL );
2017 ok( hr == S_OK, "got %08x\n", hr );
2019 hr = WsGetWriterPosition( writer, &pos, NULL );
2020 ok( hr == S_OK, "got %08x\n", hr );
2022 hr = WsWriteEndElement( writer, NULL );
2023 ok( hr == S_OK, "got %08x\n", hr );
2024 check_output_buffer( buffer, "<t><u/></t>", __LINE__ );
2026 hr = WsCreateReader( NULL, 0, &reader, NULL );
2027 ok( hr == S_OK, "got %08x\n", hr );
2029 hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
2030 ok( hr == S_OK, "got %08x\n", hr );
2032 hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
2033 ok( hr == S_OK, "got %08x\n", hr );
2035 hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
2036 ok( hr == S_OK, "got %08x\n", hr );
2038 hr = WsSetWriterPosition( writer, &pos, NULL );
2039 ok( hr == S_OK, "got %08x\n", hr );
2041 hr = WsCopyNode( writer, reader, NULL );
2042 ok( hr == S_OK, "got %08x\n", hr );
2043 check_output_buffer( buffer, "<t><u/><v/></t>", __LINE__ );
2045 hr = WsGetWriterPosition( writer, &pos2, NULL );
2046 ok( hr == S_OK, "got %08x\n", hr );
2047 ok( pos2.buffer == pos.buffer, "wrong buffer\n" );
2048 ok( pos2.node == pos.node, "wrong node\n" );
2050 hr = WsGetReaderNode( reader, &node, NULL );
2051 ok( hr == S_OK, "got %08x\n", hr );
2052 ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
2054 /* reader positioned at EOF */
2055 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
2056 ok( hr == S_OK, "got %08x\n", hr );
2058 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
2059 ok( hr == S_OK, "got %08x\n", hr );
2061 hr = WsCopyNode( writer, reader, NULL );
2062 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2064 /* reader positioned at BOF */
2065 hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
2066 ok( hr == S_OK, "got %08x\n", hr );
2068 hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
2069 ok( hr == S_OK, "got %08x\n", hr );
2071 hr = WsGetReaderNode( reader, &node, NULL );
2072 ok( hr == S_OK, "got %08x\n", hr );
2073 ok( node->nodeType == WS_XML_NODE_TYPE_BOF, "got %u\n", node->nodeType );
2075 hr = set_output( writer );
2076 ok( hr == S_OK, "got %08x\n", hr );
2078 hr = WsCopyNode( writer, reader, NULL );
2079 ok( hr == S_OK, "got %08x\n", hr );
2080 check_output( writer, "<v/>", __LINE__ );
2082 hr = WsGetReaderNode( reader, &node, NULL );
2083 ok( hr == S_OK, "got %08x\n", hr );
2084 ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
2086 memset( &bufs, 0, sizeof(bufs) );
2087 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BUFFERS, &bufs, sizeof(bufs), NULL );
2088 ok( hr == S_OK, "got %08x\n", hr );
2089 ok( bufs.bufferCount == 1, "got %u\n", bufs.bufferCount );
2090 ok( bufs.buffers != NULL, "buffers not set\n" );
2092 WsFreeReader( reader );
2093 WsFreeWriter( writer );
2094 WsFreeHeap( heap );
2097 static void test_text_types(void)
2099 static const WCHAR utf16W[] = {'u','t','f','1','6'};
2100 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2101 WS_XML_WRITER *writer;
2102 static const WS_XML_UTF8_TEXT val_utf8 = { {WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"utf8"} };
2103 static WS_XML_UTF16_TEXT val_utf16 = { {WS_XML_TEXT_TYPE_UTF16} };
2104 static const WS_XML_GUID_TEXT val_guid = { {WS_XML_TEXT_TYPE_GUID} };
2105 static const WS_XML_UNIQUE_ID_TEXT val_urn = { {WS_XML_TEXT_TYPE_UNIQUE_ID} };
2106 static const WS_XML_BOOL_TEXT val_bool = { {WS_XML_TEXT_TYPE_BOOL}, TRUE };
2107 static const WS_XML_INT32_TEXT val_int32 = { {WS_XML_TEXT_TYPE_INT32}, -2147483647 - 1 };
2108 static const WS_XML_INT64_TEXT val_int64 = { {WS_XML_TEXT_TYPE_INT64}, -9223372036854775807 - 1 };
2109 static const WS_XML_UINT64_TEXT val_uint64 = { {WS_XML_TEXT_TYPE_UINT64}, ~0 };
2110 static const WS_XML_DATETIME_TEXT val_datetime = { {WS_XML_TEXT_TYPE_DATETIME}, {0, WS_DATETIME_FORMAT_UTC} };
2111 static const WS_XML_DOUBLE_TEXT val_double = { {WS_XML_TEXT_TYPE_DOUBLE}, 1.1 };
2112 static const WS_XML_BASE64_TEXT val_base64 = { {WS_XML_TEXT_TYPE_BASE64}, (BYTE *)"test", 4 };
2113 static const struct
2115 const WS_XML_TEXT *text;
2116 const char *result;
2118 tests[] =
2120 { &val_utf8.text, "<t>utf8</t>" },
2121 { &val_utf16.text, "<t>utf16</t>" },
2122 { &val_guid.text, "<t>00000000-0000-0000-0000-000000000000</t>" },
2123 { &val_urn.text, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
2124 { &val_bool.text, "<t>true</t>" },
2125 { &val_int32.text, "<t>-2147483648</t>" },
2126 { &val_int64.text, "<t>-9223372036854775808</t>" },
2127 { &val_uint64.text, "<t>18446744073709551615</t>" },
2128 { &val_datetime.text, "<t>0001-01-01T00:00:00Z</t>" },
2129 { &val_double.text, "<t>1.1</t>" },
2130 { &val_base64.text, "<t>dGVzdA==</t>" },
2132 HRESULT hr;
2133 ULONG i;
2135 val_utf16.bytes = (BYTE *)utf16W;
2136 val_utf16.byteCount = sizeof(utf16W);
2138 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2139 ok( hr == S_OK, "got %08x\n", hr );
2141 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2143 hr = set_output( writer );
2144 ok( hr == S_OK, "got %08x\n", hr );
2145 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2146 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2148 hr = WsWriteText( writer, tests[i].text, NULL );
2149 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2151 hr = WsWriteEndElement( writer, NULL );
2152 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2153 check_output( writer, tests[i].result, __LINE__ );
2156 WsFreeWriter( writer );
2159 static BOOL get_fpword( unsigned short *ret )
2161 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2162 unsigned short fpword;
2163 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
2164 *ret = fpword;
2165 return TRUE;
2166 #endif
2167 return FALSE;
2170 static void set_fpword( unsigned short fpword )
2172 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2173 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
2174 #endif
2177 static void test_double(void)
2179 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2180 unsigned short fpword;
2181 static const struct
2183 double val;
2184 const char *result;
2186 tests[] =
2188 {0.0, "<t>0</t>"},
2189 {1.0, "<t>1</t>"},
2190 {-1.0, "<t>-1</t>"},
2191 {1.0000000000000001, "<t>1</t>"},
2192 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2193 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2194 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2195 {100000000000000, "<t>100000000000000</t>"},
2196 {1000000000000000, "<t>1E+15</t>"},
2197 {0.1, "<t>0.1</t>"},
2198 {0.01, "<t>1E-2</t>"},
2199 {-0.1, "<t>-0.1</t>"},
2200 {-0.01, "<t>-1E-2</t>"},
2201 {1.7976931348623158e308, "<t>1.7976931348623157E+308</t>"},
2202 {-1.7976931348623158e308, "<t>-1.7976931348623157E+308</t>"},
2204 HRESULT hr;
2205 WS_XML_WRITER *writer;
2206 WS_XML_DOUBLE_TEXT text;
2207 ULONG i;
2209 hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
2210 ok( hr == S_OK, "got %08x\n", hr );
2212 text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
2213 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2215 hr = set_output( writer );
2216 ok( hr == S_OK, "got %08x\n", hr );
2217 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2218 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2220 text.value = tests[i].val;
2221 hr = WsWriteText( writer, &text.text, NULL );
2222 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2224 hr = WsWriteEndElement( writer, NULL );
2225 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2226 check_output( writer, tests[i].result, __LINE__ );
2229 hr = set_output( writer );
2230 ok( hr == S_OK, "got %08x\n", hr );
2231 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2232 ok( hr == S_OK, "got %08x\n", hr );
2234 text.value = NAN;
2235 hr = WsWriteText( writer, &text.text, NULL );
2236 ok( hr == S_OK, "got %08x\n", hr );
2238 hr = WsWriteEndElement( writer, NULL );
2239 ok( hr == S_OK, "got %08x\n", hr );
2240 check_output( writer, "<t>NaN</t>", __LINE__ );
2242 hr = set_output( writer );
2243 ok( hr == S_OK, "got %08x\n", hr );
2244 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2245 ok( hr == S_OK, "got %08x\n", hr );
2247 text.value = INFINITY;
2248 hr = WsWriteText( writer, &text.text, NULL );
2249 ok( hr == S_OK, "got %08x\n", hr );
2251 hr = WsWriteEndElement( writer, NULL );
2252 ok( hr == S_OK, "got %08x\n", hr );
2253 check_output( writer, "<t>INF</t>", __LINE__ );
2255 hr = set_output( writer );
2256 ok( hr == S_OK, "got %08x\n", hr );
2257 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2258 ok( hr == S_OK, "got %08x\n", hr );
2260 text.value = -INFINITY;
2261 hr = WsWriteText( writer, &text.text, NULL );
2262 ok( hr == S_OK, "got %08x\n", hr );
2264 hr = WsWriteEndElement( writer, NULL );
2265 ok( hr == S_OK, "got %08x\n", hr );
2266 check_output( writer, "<t>-INF</t>", __LINE__ );
2268 if (!get_fpword( &fpword ))
2270 skip( "can't get floating point control word\n" );
2271 WsFreeWriter( writer );
2272 return;
2274 ok( fpword == 0x27f, "got %04x\n", fpword );
2275 set_fpword( 0x1f7f );
2276 get_fpword( &fpword );
2277 ok( fpword == 0x1f7f, "got %04x\n", fpword );
2279 hr = set_output( writer );
2280 ok( hr == S_OK, "got %08x\n", hr );
2281 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2282 ok( hr == S_OK, "got %08x\n", hr );
2284 text.value = 100000000000000;
2285 hr = WsWriteText( writer, &text.text, NULL );
2286 ok( hr == S_OK, "got %08x\n", hr );
2288 hr = WsWriteEndElement( writer, NULL );
2289 ok( hr == S_OK, "got %08x\n", hr );
2290 check_output( writer, "<t>100000000000000</t>", __LINE__ );
2292 get_fpword( &fpword );
2293 ok( fpword == 0x1f7f, "got %04x\n", fpword );
2294 set_fpword( 0x27f );
2296 WsFreeWriter( writer );
2299 static void test_field_options(void)
2301 static const char expected[] =
2302 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2303 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2304 HRESULT hr;
2305 WS_XML_WRITER *writer;
2306 WS_STRUCT_DESCRIPTION s;
2307 WS_FIELD_DESCRIPTION f, f2, f3, f4, f5, *fields[5];
2308 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, str_guid = {4, (BYTE *)"guid"};
2309 WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_bool = {4, (BYTE *)"bool"};
2310 WS_XML_STRING str_xmlstr = {6, (BYTE *)"xmlstr"}, str_str = {3, (BYTE *)"str"};
2311 INT32 val = -1;
2312 struct test
2314 GUID guid;
2315 BOOL *bool_ptr;
2316 INT32 *int32_ptr;
2317 WS_XML_STRING xmlstr;
2318 WCHAR *str;
2319 } test;
2321 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2322 ok( hr == S_OK, "got %08x\n", hr );
2324 hr = set_output( writer );
2325 ok( hr == S_OK, "got %08x\n", hr );
2327 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2328 ok( hr == S_OK, "got %08x\n", hr );
2330 memset( &f, 0, sizeof(f) );
2331 f.mapping = WS_ELEMENT_FIELD_MAPPING;
2332 f.localName = &str_guid;
2333 f.ns = &ns;
2334 f.type = WS_GUID_TYPE;
2335 f.options = WS_FIELD_OPTIONAL;
2336 fields[0] = &f;
2338 memset( &f2, 0, sizeof(f2) );
2339 f2.mapping = WS_ELEMENT_FIELD_MAPPING;
2340 f2.localName = &str_bool;
2341 f2.offset = FIELD_OFFSET(struct test, bool_ptr);
2342 f2.ns = &ns;
2343 f2.type = WS_BOOL_TYPE;
2344 f2.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2345 fields[1] = &f2;
2347 memset( &f3, 0, sizeof(f3) );
2348 f3.mapping = WS_ELEMENT_FIELD_MAPPING;
2349 f3.localName = &str_int32;
2350 f3.offset = FIELD_OFFSET(struct test, int32_ptr);
2351 f3.ns = &ns;
2352 f3.type = WS_INT32_TYPE;
2353 f3.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2354 fields[2] = &f3;
2356 memset( &f4, 0, sizeof(f4) );
2357 f4.mapping = WS_ELEMENT_FIELD_MAPPING;
2358 f4.localName = &str_xmlstr;
2359 f4.offset = FIELD_OFFSET(struct test, xmlstr);
2360 f4.ns = &ns;
2361 f4.type = WS_XML_STRING_TYPE;
2362 f4.options = WS_FIELD_NILLABLE;
2363 fields[3] = &f4;
2365 memset( &f5, 0, sizeof(f5) );
2366 f5.mapping = WS_ELEMENT_FIELD_MAPPING;
2367 f5.localName = &str_str;
2368 f5.offset = FIELD_OFFSET(struct test, str);
2369 f5.ns = &ns;
2370 f5.type = WS_WSZ_TYPE;
2371 f5.options = WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE;
2372 fields[4] = &f5;
2374 memset( &s, 0, sizeof(s) );
2375 s.size = sizeof(struct test);
2376 s.alignment = TYPE_ALIGNMENT(struct test);
2377 s.fields = fields;
2378 s.fieldCount = 5;
2380 memset( &test, 0, sizeof(test) );
2381 test.int32_ptr = &val;
2382 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE,
2383 &test, sizeof(test), NULL );
2384 ok( hr == S_OK, "got %08x\n", hr );
2386 hr = WsWriteEndElement( writer, NULL );
2387 ok( hr == S_OK, "got %08x\n", hr );
2388 check_output( writer, expected, __LINE__ );
2390 WsFreeWriter( writer );
2393 static void test_WsWriteText(void)
2395 static const WCHAR testW[] = {'t','e','s','t'};
2396 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
2397 HRESULT hr;
2398 WS_XML_WRITER *writer;
2399 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
2400 WS_XML_UTF16_TEXT utf16 = {{WS_XML_TEXT_TYPE_UTF16}};
2401 WS_XML_GUID_TEXT guid = {{WS_XML_TEXT_TYPE_GUID}};
2403 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2404 ok( hr == S_OK, "got %08x\n", hr );
2406 hr = set_output( writer );
2407 ok( hr == S_OK, "got %08x\n", hr );
2409 utf8.value.bytes = (BYTE *)"test";
2410 utf8.value.length = 4;
2411 hr = WsWriteText( writer, &utf8.text, NULL );
2412 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
2414 hr = set_output( writer );
2415 ok( hr == S_OK, "got %08x\n", hr );
2417 /* element, utf8 */
2418 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2419 ok( hr == S_OK, "got %08x\n", hr );
2421 hr = WsWriteText( writer, &utf8.text, NULL );
2422 ok( hr == S_OK, "got %08x\n", hr );
2423 check_output( writer, "<t>test", __LINE__ );
2425 utf8.value.bytes = (BYTE *)"tset";
2426 hr = WsWriteText( writer, &utf8.text, NULL );
2427 ok( hr == S_OK, "got %08x\n", hr );
2428 check_output( writer, "<t>testtset", __LINE__ );
2430 hr = WsWriteEndElement( writer, NULL );
2431 ok( hr == S_OK, "got %08x\n", hr );
2432 check_output( writer, "<t>testtset</t>", __LINE__ );
2434 hr = set_output( writer );
2435 ok( hr == S_OK, "got %08x\n", hr );
2437 /* attribute, utf8 */
2438 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2439 ok( hr == S_OK, "got %08x\n", hr );
2441 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2442 ok( hr == S_OK, "got %08x\n", hr );
2444 hr = WsWriteText( writer, &utf8.text, NULL );
2445 ok( hr == S_OK, "got %08x\n", hr );
2446 check_output( writer, "", __LINE__ );
2448 utf8.value.bytes = (BYTE *)"test";
2449 hr = WsWriteText( writer, &utf8.text, NULL );
2450 ok( hr == S_OK, "got %08x\n", hr );
2451 check_output( writer, "", __LINE__ );
2453 hr = WsWriteEndAttribute( writer, NULL );
2454 ok( hr == S_OK, "got %08x\n", hr );
2456 hr = WsWriteEndElement( writer, NULL );
2457 ok( hr == S_OK, "got %08x\n", hr );
2458 check_output( writer, "<t a=\"tsettest\"/>", __LINE__ );
2460 hr = set_output( writer );
2461 ok( hr == S_OK, "got %08x\n", hr );
2463 /* element, utf16 */
2464 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2465 ok( hr == S_OK, "got %08x\n", hr );
2467 utf16.bytes = (BYTE *)testW;
2468 utf16.byteCount = sizeof(testW);
2469 hr = WsWriteText( writer, &utf16.text, NULL );
2470 ok( hr == S_OK, "got %08x\n", hr );
2471 check_output( writer, "<t>test", __LINE__ );
2473 hr = WsWriteText( writer, &utf16.text, NULL );
2474 ok( hr == S_OK, "got %08x\n", hr );
2475 check_output( writer, "<t>testtest", __LINE__ );
2477 hr = WsWriteEndElement( writer, NULL );
2478 ok( hr == S_OK, "got %08x\n", hr );
2479 check_output( writer, "<t>testtest</t>", __LINE__ );
2481 hr = set_output( writer );
2482 ok( hr == S_OK, "got %08x\n", hr );
2484 /* attribute, utf16 */
2485 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2486 ok( hr == S_OK, "got %08x\n", hr );
2488 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2489 ok( hr == S_OK, "got %08x\n", hr );
2491 hr = WsWriteText( writer, &utf16.text, NULL );
2492 ok( hr == S_OK, "got %08x\n", hr );
2493 check_output( writer, "", __LINE__ );
2495 hr = WsWriteText( writer, &utf16.text, NULL );
2496 ok( hr == S_OK, "got %08x\n", hr );
2497 check_output( writer, "", __LINE__ );
2499 hr = WsWriteEndAttribute( writer, NULL );
2500 ok( hr == S_OK, "got %08x\n", hr );
2502 hr = WsWriteEndElement( writer, NULL );
2503 ok( hr == S_OK, "got %08x\n", hr );
2504 check_output( writer, "<t a=\"testtest\"/>", __LINE__ );
2506 hr = set_output( writer );
2507 ok( hr == S_OK, "got %08x\n", hr );
2509 /* element, guid */
2510 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2511 ok( hr == S_OK, "got %08x\n", hr );
2513 hr = WsWriteText( writer, &guid.text, NULL );
2514 ok( hr == S_OK, "got %08x\n", hr );
2515 check_output( writer, "<t>00000000-0000-0000-0000-000000000000", __LINE__ );
2517 hr = WsWriteText( writer, &guid.text, NULL );
2518 ok( hr == S_OK, "got %08x\n", hr );
2519 check_output( writer, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000",
2520 __LINE__ );
2522 /* continue with different text type */
2523 hr = WsWriteText( writer, &utf8.text, NULL );
2524 ok( hr == S_OK, "got %08x\n", hr );
2525 check_output( writer, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000test",
2526 __LINE__ );
2528 hr = WsWriteEndElement( writer, NULL );
2529 ok( hr == S_OK, "got %08x\n", hr );
2531 hr = set_output( writer );
2532 ok( hr == S_OK, "got %08x\n", hr );
2534 /* attribute, guid */
2535 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2536 ok( hr == S_OK, "got %08x\n", hr );
2538 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2539 ok( hr == S_OK, "got %08x\n", hr );
2541 hr = WsWriteText( writer, &guid.text, NULL );
2542 ok( hr == S_OK, "got %08x\n", hr );
2543 check_output( writer, "", __LINE__ );
2545 hr = WsWriteText( writer, &guid.text, NULL );
2546 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2548 hr = set_output( writer );
2549 ok( hr == S_OK, "got %08x\n", hr );
2551 /* attribute, mix allowed text types */
2552 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2553 ok( hr == S_OK, "got %08x\n", hr );
2555 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2556 ok( hr == S_OK, "got %08x\n", hr );
2558 hr = WsWriteText( writer, &utf8.text, NULL );
2559 ok( hr == S_OK, "got %08x\n", hr );
2561 hr = WsWriteText( writer, &utf16.text, NULL );
2562 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2564 hr = set_output( writer );
2565 ok( hr == S_OK, "got %08x\n", hr );
2567 /* cdata */
2568 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2569 ok( hr == S_OK, "got %08x\n", hr );
2570 hr = WsWriteStartCData( writer, NULL );
2571 ok( hr == S_OK, "got %08x\n", hr );
2573 hr = WsWriteText( writer, &utf8.text, NULL );
2574 ok( hr == S_OK, "got %08x\n", hr );
2576 hr = WsWriteText( writer, &guid.text, NULL );
2577 ok( hr == S_OK, "got %08x\n", hr );
2579 hr = WsWriteEndCData( writer, NULL );
2580 ok( hr == S_OK, "got %08x\n", hr );
2581 hr = WsWriteEndElement( writer, NULL );
2582 ok( hr == S_OK, "got %08x\n", hr );
2583 check_output( writer, "<t><![CDATA[test00000000-0000-0000-0000-000000000000]]></t>", __LINE__ );
2585 WsFreeWriter( writer );
2588 static void test_WsWriteArray(void)
2590 static const WS_XML_STRING localname = {4, (BYTE *)"item"}, localname2 = {5, (BYTE *)"array"};
2591 static const WS_XML_STRING ns = {0, NULL};
2592 WS_XML_WRITER *writer;
2593 BOOL array_bool[2];
2594 HRESULT hr;
2596 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2597 ok( hr == S_OK, "got %08x\n", hr );
2599 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2600 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2602 hr = set_output( writer );
2603 ok( hr == S_OK, "got %08x\n", hr );
2604 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2605 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2607 hr = set_output( writer );
2608 ok( hr == S_OK, "got %08x\n", hr );
2609 hr = WsWriteArray( writer, &localname, NULL, 0, NULL, 0, 0, 0, NULL );
2610 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2612 hr = set_output( writer );
2613 ok( hr == S_OK, "got %08x\n", hr );
2614 hr = WsWriteArray( writer, &localname, &ns, 0, NULL, 0, 0, 0, NULL );
2615 ok( hr == S_OK, "got %08x\n", hr );
2616 check_output( writer, "", __LINE__ );
2618 hr = WsWriteArray( writer, &localname, &ns, ~0u, NULL, 0, 0, 0, NULL );
2619 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2621 hr = set_output( writer );
2622 ok( hr == S_OK, "got %08x\n", hr );
2623 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, 0, 0, 0, NULL );
2624 ok( hr == S_OK, "got %08x\n", hr );
2625 check_output( writer, "", __LINE__ );
2627 array_bool[0] = FALSE;
2628 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, 0, 0, 0, NULL );
2629 ok( hr == S_OK, "got %08x\n", hr );
2630 check_output( writer, "", __LINE__ );
2632 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 0, NULL );
2633 ok( hr == S_OK, "got %08x\n", hr );
2634 check_output( writer, "", __LINE__ );
2636 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 0, NULL );
2637 ok( hr == S_OK, "got %08x\n", hr );
2638 check_output( writer, "", __LINE__ );
2640 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 1, NULL );
2641 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2643 hr = set_output( writer );
2644 ok( hr == S_OK, "got %08x\n", hr );
2645 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 1, NULL );
2646 ok( hr == S_OK, "got %08x\n", hr );
2647 check_output( writer, "<item>false</item>", __LINE__ );
2649 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool) - 1, 0, 2, NULL );
2650 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2652 hr = set_output( writer );
2653 ok( hr == S_OK, "got %08x\n", hr );
2654 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 3, NULL );
2655 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2657 hr = set_output( writer );
2658 ok( hr == S_OK, "got %08x\n", hr );
2660 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
2661 ok( hr == S_OK, "got %08x\n", hr );
2663 array_bool[1] = TRUE;
2664 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 2, NULL );
2665 ok( hr == S_OK, "got %08x\n", hr );
2667 hr = WsWriteEndElement( writer, NULL );
2668 ok( hr == S_OK, "got %08x\n", hr );
2669 check_output( writer, "<array><item>false</item><item>true</item></array>", __LINE__ );
2671 WsFreeWriter( writer );
2674 static void test_escapes(void)
2676 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2677 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
2678 WS_XML_WRITER *writer;
2679 struct test
2681 const char *text;
2682 const char *result;
2683 BOOL single;
2685 static const struct test tests_elem[] =
2687 { "<", "<t>&lt;</t>" },
2688 { ">", "<t>&gt;</t>" },
2689 { "\"", "<t>\"</t>" },
2690 { "&", "<t>&amp;</t>" },
2691 { "&&", "<t>&amp;&amp;</t>" },
2692 { "'", "<t>'</t>" },
2694 static const struct test tests_attr[] =
2696 { "<", "<t t=\"&lt;\"/>" },
2697 { ">", "<t t=\">\"/>" },
2698 { "\"", "<t t=\"&quot;\"/>" },
2699 { "&", "<t t=\"&amp;\"/>" },
2700 { "'", "<t t=\"'\"/>" },
2701 { "\"", "<t t='\"'/>", TRUE },
2702 { "'", "<t t='&apos;'/>", TRUE },
2704 static const struct test tests_cdata[] =
2706 { "<", "<t><![CDATA[<]]></t>" },
2707 { ">", "<t><![CDATA[>]]></t>" },
2708 { "\"", "<t><![CDATA[\"]]></t>" },
2709 { "&", "<t><![CDATA[&]]></t>" },
2710 { "[", "<t><![CDATA[[]]></t>" },
2711 { "]", "<t><![CDATA[]]]></t>" },
2712 { "'", "<t><![CDATA[']]></t>" },
2714 static const struct test tests_comment[] =
2716 { "<", "<t><!--<--></t>" },
2717 { ">", "<t><!-->--></t>" },
2718 { "\"", "<t><!--\"--></t>" },
2719 { "&", "<t><!--&--></t>" },
2720 { "'", "<t><!--'--></t>" },
2722 HRESULT hr;
2723 ULONG i;
2725 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2726 ok( hr == S_OK, "got %08x\n", hr );
2728 for (i = 0; i < sizeof(tests_elem)/sizeof(tests_elem[0]); i++)
2730 hr = set_output( writer );
2731 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2732 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2733 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2735 utf8.value.bytes = (BYTE *)tests_elem[i].text;
2736 utf8.value.length = strlen( tests_elem[i].text );
2737 hr = WsWriteText( writer, &utf8.text, NULL );
2738 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2740 hr = WsWriteEndElement( writer, NULL );
2741 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2742 check_output( writer, tests_elem[i].result, __LINE__ );
2745 for (i = 0; i < sizeof(tests_attr)/sizeof(tests_attr[0]); i++)
2747 hr = set_output( writer );
2748 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2749 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2750 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2752 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, tests_attr[i].single, NULL );
2753 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2755 utf8.value.bytes = (BYTE *)tests_attr[i].text;
2756 utf8.value.length = strlen( tests_attr[i].text );
2757 hr = WsWriteText( writer, &utf8.text, NULL );
2758 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2760 hr = WsWriteEndAttribute( writer, NULL );
2761 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2763 hr = WsWriteEndElement( writer, NULL );
2764 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2765 check_output( writer, tests_attr[i].result, __LINE__ );
2768 for (i = 0; i < sizeof(tests_cdata)/sizeof(tests_cdata[0]); i++)
2770 hr = set_output( writer );
2771 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2772 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2773 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2775 hr = WsWriteStartCData( writer, NULL );
2776 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2778 utf8.value.bytes = (BYTE *)tests_cdata[i].text;
2779 utf8.value.length = strlen( tests_cdata[i].text );
2780 hr = WsWriteText( writer, &utf8.text, NULL );
2781 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2783 hr = WsWriteEndCData( writer, NULL );
2784 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2786 hr = WsWriteEndElement( writer, NULL );
2787 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2788 check_output( writer, tests_cdata[i].result, __LINE__ );
2791 for (i = 0; i < sizeof(tests_comment)/sizeof(tests_comment[0]); i++)
2793 WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
2795 hr = set_output( writer );
2796 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2797 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2798 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2800 comment.value.bytes = (BYTE *)tests_comment[i].text;
2801 comment.value.length = strlen( tests_comment[i].text );
2802 hr = WsWriteNode( writer, &comment.node, NULL );
2803 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2805 hr = WsWriteEndElement( writer, NULL );
2806 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2807 check_output( writer, tests_comment[i].result, __LINE__ );
2810 WsFreeWriter( writer );
2813 static void test_write_option(void)
2815 static const WCHAR sW[] = {'s',0};
2816 static const WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2817 WS_XML_WRITER *writer;
2818 int val_int = -1, val_int_zero = 0, *ptr_int = &val_int, *ptr_int_null = NULL;
2819 const WCHAR *ptr_wsz = sW, *ptr_wsz_null = NULL;
2820 static const WS_XML_STRING val_xmlstr = {1, (BYTE *)"x"}, val_xmlstr_zero = {0, NULL};
2821 const WS_XML_STRING *ptr_xmlstr = &val_xmlstr, *ptr_xmlstr_null = NULL;
2822 struct
2824 WS_TYPE type;
2825 WS_WRITE_OPTION option;
2826 const void *value;
2827 ULONG size;
2828 HRESULT hr;
2829 const char *result;
2831 tests[] =
2833 { WS_INT32_TYPE, 0, NULL, 0, E_INVALIDARG },
2834 { WS_INT32_TYPE, 0, "str", 0, E_INVALIDARG },
2835 { WS_INT32_TYPE, 0, NULL, sizeof(val_int), E_INVALIDARG },
2836 { WS_INT32_TYPE, 0, &val_int, sizeof(val_int), E_INVALIDARG },
2837 { WS_INT32_TYPE, 0, &val_int_zero, sizeof(val_int_zero), E_INVALIDARG },
2838 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, 0, E_INVALIDARG },
2839 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int, 0, E_INVALIDARG },
2840 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, sizeof(val_int), E_INVALIDARG },
2841 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int, sizeof(val_int), S_OK, "<t>-1</t>" },
2842 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int_zero, sizeof(val_int_zero), S_OK, "<t>0</t>" },
2843 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, 0, E_INVALIDARG },
2844 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int, 0, E_INVALIDARG },
2845 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, sizeof(val_int), E_INVALIDARG },
2846 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int, sizeof(val_int), E_INVALIDARG },
2847 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int_zero, sizeof(val_int_zero), E_INVALIDARG },
2848 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
2849 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int, 0, E_INVALIDARG },
2850 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_int), E_INVALIDARG },
2851 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int, sizeof(ptr_int), S_OK, "<t>-1</t>" },
2852 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int_null, sizeof(ptr_int_null), E_INVALIDARG },
2853 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
2854 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int, 0, E_INVALIDARG },
2855 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_int), E_INVALIDARG },
2856 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int, sizeof(ptr_int), S_OK, "<t>-1</t>" },
2857 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int_null, sizeof(ptr_int_null), S_OK,
2858 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2859 { WS_XML_STRING_TYPE, 0, NULL, 0, E_INVALIDARG },
2860 { WS_XML_STRING_TYPE, 0, &val_xmlstr, 0, E_INVALIDARG },
2861 { WS_XML_STRING_TYPE, 0, NULL, sizeof(val_xmlstr), E_INVALIDARG },
2862 { WS_XML_STRING_TYPE, 0, &val_xmlstr, sizeof(val_xmlstr), E_INVALIDARG },
2863 { WS_XML_STRING_TYPE, 0, &val_xmlstr_zero, sizeof(val_xmlstr_zero), E_INVALIDARG },
2864 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, 0, E_INVALIDARG },
2865 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr, 0, E_INVALIDARG },
2866 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, sizeof(&val_xmlstr), E_INVALIDARG },
2867 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr, sizeof(val_xmlstr), S_OK, "<t>x</t>" },
2868 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr_zero, sizeof(val_xmlstr_zero), S_OK, "<t/>" },
2869 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr, 0, E_INVALIDARG },
2870 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, sizeof(&val_xmlstr), E_INVALIDARG },
2871 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr, sizeof(&val_xmlstr), E_INVALIDARG },
2872 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr_zero, sizeof(val_xmlstr_zero), S_OK,
2873 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2874 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
2875 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr, 0, E_INVALIDARG },
2876 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_xmlstr), E_INVALIDARG },
2877 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr, sizeof(ptr_xmlstr), S_OK, "<t>x</t>" },
2878 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr_null, sizeof(ptr_xmlstr_null), E_INVALIDARG },
2879 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
2880 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr, 0, E_INVALIDARG },
2881 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_xmlstr), E_INVALIDARG },
2882 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr, sizeof(ptr_xmlstr), S_OK, "<t>x</t>" },
2883 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr_null, sizeof(ptr_xmlstr_null), S_OK,
2884 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2885 { WS_WSZ_TYPE, 0, NULL, 0, E_INVALIDARG },
2886 { WS_WSZ_TYPE, 0, &ptr_wsz, 0, E_INVALIDARG },
2887 { WS_WSZ_TYPE, 0, NULL, sizeof(ptr_wsz), E_INVALIDARG },
2888 { WS_WSZ_TYPE, 0, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
2889 { WS_WSZ_TYPE, 0, &ptr_wsz_null, sizeof(ptr_wsz_null), E_INVALIDARG },
2890 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_VALUE, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
2891 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_VALUE, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
2892 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
2893 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz, 0, E_INVALIDARG },
2894 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_wsz), E_INVALIDARG },
2895 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz, sizeof(ptr_wsz), S_OK, "<t>s</t>" },
2896 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz_null, sizeof(ptr_wsz_null), E_INVALIDARG },
2897 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
2898 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz, 0, E_INVALIDARG },
2899 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_wsz), E_INVALIDARG },
2900 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz, sizeof(ptr_wsz), S_OK, "<t>s</t>" },
2901 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz_null, sizeof(ptr_wsz_null), S_OK,
2902 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2904 HRESULT hr;
2905 ULONG i;
2907 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2908 ok( hr == S_OK, "got %08x\n", hr );
2910 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2912 hr = set_output( writer );
2913 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2914 WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2915 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL, tests[i].option, tests[i].value,
2916 tests[i].size, NULL );
2917 ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
2918 WsWriteEndElement( writer, NULL );
2919 if (hr == S_OK) check_output( writer, tests[i].result, __LINE__ );
2922 WsFreeWriter( writer );
2925 static BOOL check_result( WS_XML_WRITER *writer, const char *expected )
2927 WS_BYTES bytes;
2928 ULONG size = sizeof(bytes);
2929 int len = strlen( expected );
2931 memset( &bytes, 0, sizeof(bytes) );
2932 WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
2933 if (bytes.length != len) return FALSE;
2934 return !memcmp( bytes.bytes, expected, len );
2937 static void test_datetime(void)
2939 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2940 static const struct
2942 unsigned __int64 ticks;
2943 WS_DATETIME_FORMAT format;
2944 HRESULT hr;
2945 const char *result;
2946 const char *result2;
2947 HRESULT hr_broken;
2949 tests[] =
2951 { 0, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0001-01-01T00:00:00Z</t>" },
2952 { 0, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T00:00:00+00:00</t>" },
2953 { 0, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00</t>" },
2954 { 1, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0001-01-01T00:00:00.0000001Z</t>" },
2955 { 1, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T00:00:00.0000001+00:00</t>" },
2956 { 1, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00.0000001</t>" },
2957 { 10, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00.000001</t>" },
2958 { 1000000, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00.1</t>" },
2959 { 0x23c34600, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T00:01:00+00:00</t>" },
2960 { 0x861c46800, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T01:00:00+00:00</t>" },
2961 { 0x430e234000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T08:00:00+00:00</t>" },
2962 { 0x4b6fe7a800, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T09:00:00+00:00</t>" },
2963 { 0x989680, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:01</t>" },
2964 { 0x23c34600, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:01:00</t>" },
2965 { 0x861c46800, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T01:00:00</t>" },
2966 { 0xc92a69c000, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-02T00:00:00</t>" },
2967 { 0x11ed178c6c000, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0002-01-01T00:00:00</t>" },
2968 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_UTC, S_OK, "<t>9999-12-31T23:59:59.9999999Z</t>" },
2969 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>9999-12-31T15:59:59.9999999-08:00</t>",
2970 "<t>9999-12-31T17:59:59.9999999-06:00</t>" /* win7 */, WS_E_INVALID_FORMAT },
2971 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_NONE, S_OK, "<t>9999-12-31T23:59:59.9999999</t>" },
2972 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_UTC, WS_E_INVALID_FORMAT },
2973 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_LOCAL, WS_E_INVALID_FORMAT },
2974 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_NONE, WS_E_INVALID_FORMAT },
2975 { 0x8d3123e7df74000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>2015-12-31T16:00:00-08:00</t>",
2976 "<t>2015-12-31T18:00:00-06:00</t>" /* win7 */ },
2977 { 0x701ce1722770000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T00:00:00+00:00</t>" },
2978 { 0x701ce5a309a4000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T00:00:00-08:00</t>",
2979 "<t>1601-01-01T02:00:00-06:00</t>" /* win7 */ },
2980 { 0x701ce5e617c7400, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T00:30:00-08:00</t>",
2981 "<t>1601-01-01T02:30:00-06:00</t>" /* win7 */ },
2982 { 0x701ce51ced5d800, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T07:00:00+00:00</t>",
2983 "<t>1601-01-01T01:00:00-06:00</t>" /* win7 */ },
2984 { 0, WS_DATETIME_FORMAT_NONE + 1, WS_E_INVALID_FORMAT },
2985 { 0x38a080649c000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0004-02-28T00:00:00Z</t>" },
2986 { 0x38ad130b38000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0004-02-29T00:00:00Z</t>" },
2987 { 0x8c1505f0e438000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>2000-02-29T00:00:00Z</t>" },
2988 { 0x8d46035e7870000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>2017-03-01T00:00:00Z</t>" },
2990 HRESULT hr;
2991 WS_XML_WRITER *writer;
2992 WS_DATETIME date;
2993 ULONG i;
2995 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2996 ok( hr == S_OK, "got %08x\n", hr );
2997 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2999 hr = set_output( writer );
3000 ok( hr == S_OK, "got %08x\n", hr );
3002 date.ticks = tests[i].ticks;
3003 date.format = tests[i].format;
3004 WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3005 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_DATETIME_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
3006 &date, sizeof(date), NULL );
3007 WsWriteEndElement( writer, NULL );
3008 ok( hr == tests[i].hr || broken(hr == tests[i].hr_broken), "%u: got %08x\n", i, hr );
3009 if (hr != tests[i].hr && hr == tests[i].hr_broken) break;
3010 if (hr == S_OK)
3012 ok( check_result( writer, tests[i].result ) ||
3013 (tests[i].result2 && broken(check_result( writer, tests[i].result2 ))),
3014 "%u: wrong result\n", i );
3018 WsFreeWriter( writer );
3021 static void test_repeating_element(void)
3023 static const WCHAR oneW[] = {'1',0}, twoW[] = {'2',0};
3024 WS_XML_STRING localname = {4, (BYTE *)"test"}, ns = {0, NULL};
3025 WS_XML_STRING val = {3, (BYTE *)"val"}, wrapper = {7, (BYTE *)"wrapper"};
3026 HRESULT hr;
3027 WS_XML_WRITER *writer;
3028 WS_STRUCT_DESCRIPTION s;
3029 WS_FIELD_DESCRIPTION f, *fields[1];
3030 WS_ITEM_RANGE range;
3031 struct test
3033 const WCHAR **val;
3034 ULONG count;
3035 } *test;
3036 struct test2
3038 INT32 *val;
3039 ULONG count;
3040 } *test2;
3042 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3043 ok( hr == S_OK, "got %08x\n", hr );
3045 /* array of strings, wrapper */
3046 hr = set_output( writer );
3047 ok( hr == S_OK, "got %08x\n", hr );
3048 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3049 ok( hr == S_OK, "got %08x\n", hr );
3051 memset( &f, 0, sizeof(f) );
3052 f.mapping = WS_REPEATING_ELEMENT_FIELD_MAPPING;
3053 f.localName = &wrapper;
3054 f.ns = &ns;
3055 f.type = WS_WSZ_TYPE;
3056 f.countOffset = FIELD_OFFSET(struct test, count);
3057 f.itemLocalName = &val;
3058 f.itemNs = &ns;
3059 fields[0] = &f;
3061 memset( &s, 0, sizeof(s) );
3062 s.size = sizeof(struct test);
3063 s.alignment = TYPE_ALIGNMENT(struct test);
3064 s.typeLocalName = &localname;
3065 s.typeNs = &ns;
3066 s.fields = fields;
3067 s.fieldCount = 1;
3069 hr = set_output( writer );
3070 ok( hr == S_OK, "got %08x\n", hr );
3071 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3072 ok( hr == S_OK, "got %08x\n", hr );
3074 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) + 2 * sizeof(const WCHAR *) );
3075 test->val = (const WCHAR **)(test + 1);
3076 test->val[0] = oneW;
3077 test->val[1] = twoW;
3078 test->count = 2;
3079 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
3080 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
3081 ok( hr == S_OK, "got %08x\n", hr );
3082 hr = WsWriteEndElement( writer, NULL );
3083 ok( hr == S_OK, "got %08x\n", hr );
3084 check_output( writer, "<test><wrapper><val>1</val><val>2</val></wrapper></test>", __LINE__ );
3085 HeapFree( GetProcessHeap(), 0, test );
3087 /* array of integers, no wrapper */
3088 hr = set_output( writer );
3089 ok( hr == S_OK, "got %08x\n", hr );
3090 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3091 ok( hr == S_OK, "got %08x\n", hr );
3093 f.type = WS_INT32_TYPE;
3094 f.localName = NULL;
3095 f.ns = NULL;
3097 test2 = HeapAlloc( GetProcessHeap(), 0, sizeof(*test2) + 2 * sizeof(INT32) );
3098 test2->val = (INT32 *)(test2 + 1);
3099 test2->val[0] = 1;
3100 test2->val[1] = 2;
3101 test2->count = 2;
3102 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
3103 WS_WRITE_REQUIRED_POINTER, &test2, sizeof(test2), NULL );
3104 ok( hr == S_OK, "got %08x\n", hr );
3105 hr = WsWriteEndElement( writer, NULL );
3106 ok( hr == S_OK, "got %08x\n", hr );
3107 check_output( writer, "<test><val>1</val><val>2</val></test>", __LINE__ );
3109 /* item range has no effect */
3110 hr = set_output( writer );
3111 ok( hr == S_OK, "got %08x\n", hr );
3112 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3113 ok( hr == S_OK, "got %08x\n", hr );
3115 range.minItemCount = 0;
3116 range.maxItemCount = 0;
3117 f.itemRange = &range;
3119 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
3120 WS_WRITE_REQUIRED_POINTER, &test2, sizeof(test2), NULL );
3121 ok( hr == S_OK, "got %08x\n", hr );
3122 hr = WsWriteEndElement( writer, NULL );
3123 ok( hr == S_OK, "got %08x\n", hr );
3124 check_output( writer, "<test><val>1</val><val>2</val></test>", __LINE__ );
3125 HeapFree( GetProcessHeap(), 0, test2 );
3127 WsFreeWriter( writer );
3130 static const WS_XML_STRING *init_xmlstring( const char *src, WS_XML_STRING *str )
3132 if (!src) return NULL;
3133 str->length = strlen( src );
3134 str->bytes = (BYTE *)src;
3135 return str;
3138 static void test_WsWriteQualifiedName(void)
3140 WS_XML_STRING prefix = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
3141 WS_XML_WRITER *writer;
3142 HRESULT hr;
3143 ULONG i;
3144 static const struct
3146 const char *prefix;
3147 const char *localname;
3148 const char *ns;
3149 HRESULT hr;
3150 const char *result;
3151 } tests[] =
3153 { NULL, NULL, NULL, E_INVALIDARG, NULL },
3154 { NULL, "t2", NULL, E_INVALIDARG, NULL },
3155 { "p2", "t2", NULL, S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3156 { NULL, "t2", "ns2", WS_E_INVALID_FORMAT, NULL },
3157 { NULL, "t2", "ns", S_OK, "<p:t xmlns:p=\"ns\">p:t2" },
3158 { "p2", "t2", "ns2", S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3159 { "p2", "t2", "ns", S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3160 { "p", "t", NULL, S_OK, "<p:t xmlns:p=\"ns\">p:t" },
3161 { NULL, "t", "ns", S_OK, "<p:t xmlns:p=\"ns\">p:t" },
3162 { "p2", "", "", S_OK, "<p:t xmlns:p=\"ns\">p2:" },
3163 { "p2", "", "ns2", S_OK, "<p:t xmlns:p=\"ns\">p2:" },
3164 { "p2", "t2", "", S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3165 { "", "t2", "", S_OK, "<p:t xmlns:p=\"ns\">t2" },
3166 { "", "", "ns2", S_OK, "<p:t xmlns:p=\"ns\">" },
3167 { "", "", "", S_OK, "<p:t xmlns:p=\"ns\">" },
3170 hr = WsWriteQualifiedName( NULL, NULL, NULL, NULL, NULL );
3171 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3173 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3174 ok( hr == S_OK, "got %08x\n", hr );
3176 hr = WsWriteQualifiedName( writer, NULL, NULL, NULL, NULL );
3177 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3179 hr = set_output( writer );
3180 ok( hr == S_OK, "got %08x\n", hr );
3182 hr = WsWriteQualifiedName( writer, NULL, NULL, NULL, NULL );
3183 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3185 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
3187 WS_XML_STRING prefix2, localname2, ns2;
3188 const WS_XML_STRING *prefix_ptr, *localname_ptr, *ns_ptr;
3190 hr = set_output( writer );
3191 ok( hr == S_OK, "%u: got %08x\n", i, hr );
3193 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
3194 ok( hr == S_OK, "%u: got %08x\n", i, hr );
3196 prefix_ptr = init_xmlstring( tests[i].prefix, &prefix2 );
3197 localname_ptr = init_xmlstring( tests[i].localname, &localname2 );
3198 ns_ptr = init_xmlstring( tests[i].ns, &ns2 );
3200 hr = WsWriteQualifiedName( writer, prefix_ptr, localname_ptr, ns_ptr, NULL );
3201 ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
3202 if (tests[i].hr == S_OK && hr == S_OK) check_output( writer, tests[i].result, __LINE__ );
3205 WsFreeWriter( writer );
3208 static void test_WsWriteBytes(void)
3210 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
3211 WS_XML_WRITER *writer;
3212 HRESULT hr;
3214 hr = WsWriteBytes( NULL, NULL, 0, NULL );
3215 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3217 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3218 ok( hr == S_OK, "got %08x\n", hr );
3220 hr = WsWriteBytes( writer, NULL, 0, NULL );
3221 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3223 hr = WsWriteBytes( writer, "test", 0, NULL );
3224 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3226 hr = WsWriteBytes( writer, NULL, 1, NULL );
3227 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3229 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3230 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3232 hr = set_output( writer );
3233 ok( hr == S_OK, "got %08x\n", hr );
3235 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3236 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3238 hr = set_output( writer );
3239 ok( hr == S_OK, "got %08x\n", hr );
3241 /* element */
3242 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3243 ok( hr == S_OK, "got %08x\n", hr );
3245 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3246 ok( hr == S_OK, "got %08x\n", hr );
3248 hr = WsWriteEndElement( writer, NULL );
3249 ok( hr == S_OK, "got %08x\n", hr );
3250 check_output( writer, "<t>dGVzdAA=</t>", __LINE__ );
3252 hr = set_output( writer );
3253 ok( hr == S_OK, "got %08x\n", hr );
3255 /* attribute */
3256 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3257 ok( hr == S_OK, "got %08x\n", hr );
3259 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
3260 ok( hr == S_OK, "got %08x\n", hr );
3262 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3263 ok( hr == S_OK, "got %08x\n", hr );
3265 hr = WsWriteEndAttribute( writer, NULL );
3266 ok( hr == S_OK, "got %08x\n", hr );
3268 hr = WsWriteEndElement( writer, NULL );
3269 ok( hr == S_OK, "got %08x\n", hr );
3270 check_output( writer, "<t a=\"dGVzdAA=\"/>", __LINE__ );
3272 WsFreeWriter( writer );
3275 static void test_WsWriteChars(void)
3277 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
3278 static const WCHAR testW[] = {'t','e','s','t'};
3279 WS_XML_WRITER *writer;
3280 HRESULT hr;
3282 hr = WsWriteChars( NULL, NULL, 0, NULL );
3283 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3285 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3286 ok( hr == S_OK, "got %08x\n", hr );
3288 hr = WsWriteChars( writer, NULL, 0, NULL );
3289 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3291 hr = WsWriteChars( writer, testW, 0, NULL );
3292 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3294 hr = WsWriteChars( writer, NULL, 1, NULL );
3295 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3297 hr = WsWriteChars( writer, testW, 4, NULL );
3298 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3300 hr = set_output( writer );
3301 ok( hr == S_OK, "got %08x\n", hr );
3303 hr = WsWriteChars( writer, testW, 4, NULL );
3304 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3306 hr = set_output( writer );
3307 ok( hr == S_OK, "got %08x\n", hr );
3309 /* element */
3310 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3311 ok( hr == S_OK, "got %08x\n", hr );
3313 hr = WsWriteChars( writer, testW, 4, NULL );
3314 ok( hr == S_OK, "got %08x\n", hr );
3316 hr = WsWriteChars( writer, testW, 4, NULL );
3317 ok( hr == S_OK, "got %08x\n", hr );
3319 hr = WsWriteEndElement( writer, NULL );
3320 ok( hr == S_OK, "got %08x\n", hr );
3321 check_output( writer, "<t>testtest</t>", __LINE__ );
3323 hr = set_output( writer );
3324 ok( hr == S_OK, "got %08x\n", hr );
3326 /* attribute */
3327 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3328 ok( hr == S_OK, "got %08x\n", hr );
3330 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
3331 ok( hr == S_OK, "got %08x\n", hr );
3333 hr = WsWriteChars( writer, testW, 4, NULL );
3334 ok( hr == S_OK, "got %08x\n", hr );
3336 hr = WsWriteChars( writer, testW, 4, NULL );
3337 ok( hr == S_OK, "got %08x\n", hr );
3339 hr = WsWriteEndAttribute( writer, NULL );
3340 ok( hr == S_OK, "got %08x\n", hr );
3342 hr = WsWriteEndElement( writer, NULL );
3343 ok( hr == S_OK, "got %08x\n", hr );
3344 check_output( writer, "<t a=\"testtest\"/>", __LINE__ );
3346 WsFreeWriter( writer );
3349 static void test_WsWriteCharsUtf8(void)
3351 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
3352 static const BYTE test[] = {'t','e','s','t'};
3353 WS_XML_WRITER *writer;
3354 HRESULT hr;
3356 hr = WsWriteCharsUtf8( NULL, NULL, 0, NULL );
3357 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3359 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3360 ok( hr == S_OK, "got %08x\n", hr );
3362 hr = WsWriteCharsUtf8( writer, NULL, 0, NULL );
3363 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3365 hr = WsWriteCharsUtf8( writer, test, 0, NULL );
3366 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3368 hr = WsWriteCharsUtf8( writer, NULL, 1, NULL );
3369 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3371 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3372 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3374 hr = set_output( writer );
3375 ok( hr == S_OK, "got %08x\n", hr );
3377 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3378 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3380 hr = set_output( writer );
3381 ok( hr == S_OK, "got %08x\n", hr );
3383 /* element */
3384 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3385 ok( hr == S_OK, "got %08x\n", hr );
3387 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3388 ok( hr == S_OK, "got %08x\n", hr );
3390 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3391 ok( hr == S_OK, "got %08x\n", hr );
3393 hr = WsWriteEndElement( writer, NULL );
3394 ok( hr == S_OK, "got %08x\n", hr );
3395 check_output( writer, "<t>testtest</t>", __LINE__ );
3397 hr = set_output( writer );
3398 ok( hr == S_OK, "got %08x\n", hr );
3400 /* attribute */
3401 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3402 ok( hr == S_OK, "got %08x\n", hr );
3404 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
3405 ok( hr == S_OK, "got %08x\n", hr );
3407 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3408 ok( hr == S_OK, "got %08x\n", hr );
3410 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3411 ok( hr == S_OK, "got %08x\n", hr );
3413 hr = WsWriteEndAttribute( writer, NULL );
3414 ok( hr == S_OK, "got %08x\n", hr );
3416 hr = WsWriteEndElement( writer, NULL );
3417 ok( hr == S_OK, "got %08x\n", hr );
3418 check_output( writer, "<t a=\"testtest\"/>", __LINE__ );
3420 WsFreeWriter( writer );
3423 START_TEST(writer)
3425 test_WsCreateWriter();
3426 test_WsCreateXmlBuffer();
3427 test_WsSetOutput();
3428 test_WsSetOutputToBuffer();
3429 test_WsWriteStartElement();
3430 test_WsWriteStartAttribute();
3431 test_WsWriteType();
3432 test_basic_type();
3433 test_simple_struct_type();
3434 test_WsWriteElement();
3435 test_WsWriteValue();
3436 test_WsWriteAttribute();
3437 test_WsWriteStartCData();
3438 test_WsWriteXmlnsAttribute();
3439 test_WsGetPrefixFromNamespace();
3440 test_complex_struct_type();
3441 test_WsMoveWriter();
3442 test_WsGetWriterPosition();
3443 test_WsSetWriterPosition();
3444 test_WsWriteXmlBuffer();
3445 test_WsWriteNode();
3446 test_WsCopyNode();
3447 test_text_types();
3448 test_double();
3449 test_field_options();
3450 test_WsWriteText();
3451 test_WsWriteArray();
3452 test_escapes();
3453 test_write_option();
3454 test_datetime();
3455 test_repeating_element();
3456 test_WsWriteQualifiedName();
3457 test_WsWriteBytes();
3458 test_WsWriteChars();
3459 test_WsWriteCharsUtf8();