webservices: Move the reader to the next node in WsCopyNode.
[wine.git] / dlls / webservices / tests / writer.c
blob531976999cc23d3cacc27082754d1d26dcc5f418
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"};
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 WsFreeWriter( writer );
475 static void test_WsWriteStartAttribute(void)
477 HRESULT hr;
478 WS_XML_WRITER *writer;
479 WS_XML_STRING prefix = {1, (BYTE *)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
480 WS_XML_UTF8_TEXT text = {{WS_XML_TEXT_TYPE_UTF8}};
482 hr = WsCreateWriter( NULL, 0, &writer, NULL );
483 ok( hr == S_OK, "got %08x\n", hr );
485 hr = set_output( writer );
486 ok( hr == S_OK, "got %08x\n", hr );
488 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
489 ok( hr == S_OK, "got %08x\n", hr );
491 hr = WsWriteStartAttribute( NULL, &prefix, &localname, &ns, FALSE, NULL );
492 ok( hr == E_INVALIDARG, "got %08x\n", hr );
494 /* WsWriteStartAttribute doesn't output anything */
495 localname.length = 3;
496 localname.bytes = (BYTE *)"len";
497 hr = WsWriteStartAttribute( writer, &prefix, &localname, &ns, FALSE, NULL );
498 ok( hr == S_OK, "got %08x\n", hr );
499 check_output( writer, "", __LINE__ );
501 text.value.length = 1;
502 text.value.bytes = (BYTE *)"0";
503 hr = WsWriteText( writer, &text.text, NULL );
504 ok( hr == S_OK, "got %08x\n", hr );
505 check_output( writer, "", __LINE__ );
507 /* WsWriteEndAttribute doesn't output anything */
508 hr = WsWriteEndAttribute( writer, NULL );
509 ok( hr == S_OK, "got %08x\n", hr );
510 check_output( writer, "", __LINE__ );
512 hr = WsWriteEndElement( writer, NULL );
513 ok( hr == S_OK, "got %08x\n", hr );
514 check_output( writer, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__ );
516 WsFreeWriter( writer );
519 static void test_WsWriteType(void)
521 static const WCHAR testW[] = {'t','e','s','t',0};
522 HRESULT hr;
523 WS_XML_WRITER *writer;
524 WS_XML_STRING prefix = {1, (BYTE*)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
525 const WCHAR *val_str;
527 hr = WsCreateWriter( NULL, 0, &writer, NULL );
528 ok( hr == S_OK, "got %08x\n", hr );
530 hr = set_output( writer );
531 ok( hr == S_OK, "got %08x\n", hr );
533 val_str = testW;
534 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
535 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
536 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
538 hr = set_output( writer );
539 ok( hr == S_OK, "got %08x\n", hr );
541 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
542 ok( hr == S_OK, "got %08x\n", hr );
544 /* required value */
545 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
546 WS_WRITE_REQUIRED_VALUE, NULL, sizeof(testW), NULL );
547 ok( hr == E_INVALIDARG, "got %08x\n", hr );
549 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
550 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
551 ok( hr == E_INVALIDARG, "got %08x\n", hr );
553 /* required pointer */
554 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
555 WS_WRITE_REQUIRED_POINTER, NULL, sizeof(val_str), NULL );
556 ok( hr == E_INVALIDARG, "got %08x\n", hr );
558 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
559 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
560 ok( hr == E_INVALIDARG, "got %08x\n", hr );
562 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
563 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(WCHAR **), NULL );
564 ok( hr == S_OK, "got %08x\n", hr );
565 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
567 hr = WsWriteEndElement( writer, NULL );
568 ok( hr == S_OK, "got %08x\n", hr );
569 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
571 hr = set_output( writer );
572 ok( hr == S_OK, "got %08x\n", hr );
574 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
575 ok( hr == S_OK, "got %08x\n", hr );
577 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
578 ok( hr == S_OK, "got %08x\n", hr );
580 val_str = testW;
581 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
582 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
583 ok( hr == S_OK, "got %08x\n", hr );
584 check_output( writer, "", __LINE__ );
586 hr = WsWriteEndAttribute( writer, NULL );
587 ok( hr == S_OK, "got %08x\n", hr );
588 check_output( writer, "", __LINE__ );
590 hr = WsWriteEndElement( writer, NULL );
591 ok( hr == S_OK, "got %08x\n", hr );
592 check_output( writer, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__ );
594 hr = set_output( writer );
595 ok( hr == S_OK, "got %08x\n", hr );
597 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
598 ok( hr == S_OK, "got %08x\n", hr );
600 val_str = testW;
601 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
602 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
603 ok( hr == S_OK, "got %08x\n", hr );
604 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
606 hr = WsWriteEndElement( writer, NULL );
607 ok( hr == S_OK, "got %08x\n", hr );
608 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
610 WsFreeWriter( writer );
613 static void prepare_basic_type_test( WS_XML_WRITER *writer )
615 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
616 HRESULT hr;
618 hr = set_output( writer );
619 ok( hr == S_OK, "got %08x\n", hr );
620 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
621 ok( hr == S_OK, "got %08x\n", hr );
624 static void test_basic_type(void)
626 static WCHAR testW[] = {'t','e','s','t',0};
627 HRESULT hr;
628 WS_XML_WRITER *writer;
629 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, xmlstr;
630 GUID guid;
631 WCHAR *str;
632 WS_STRING string;
633 WS_BYTES bytes;
634 ULONG i;
635 static const struct
637 WS_TYPE type;
638 INT64 val;
639 ULONG size;
640 const char *result;
641 const char *result2;
643 tests[] =
645 { WS_BOOL_TYPE, TRUE, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
646 { WS_BOOL_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
647 { WS_INT8_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
648 { WS_INT16_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
649 { WS_INT32_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
650 "<t t=\"-2147483648\"/>" },
651 { WS_INT64_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
652 "<t t=\"-9223372036854775808\"/>" },
653 { WS_UINT8_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
654 { WS_UINT16_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
655 { WS_UINT32_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
656 { WS_UINT64_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
657 "<t t=\"18446744073709551615\"/>" },
660 hr = WsCreateWriter( NULL, 0, &writer, NULL );
661 ok( hr == S_OK, "got %08x\n", hr );
663 /* element content type mapping */
664 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
666 prepare_basic_type_test( writer );
667 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
668 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
669 ok( hr == S_OK, "%u: got %08x\n", i, hr );
671 hr = WsWriteEndElement( writer, NULL );
672 ok( hr == S_OK, "got %08x\n", hr );
673 check_output( writer, tests[i].result, __LINE__ );
676 /* element type mapping is the same as element content type mapping for basic types */
677 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
679 const INT64 *ptr = &tests[i].val;
681 prepare_basic_type_test( writer );
682 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
683 WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
684 ok( hr == S_OK, "%u: got %08x\n", i, hr );
686 hr = WsWriteEndElement( writer, NULL );
687 ok( hr == S_OK, "got %08x\n", hr );
688 check_output( writer, tests[i].result, __LINE__ );
691 /* attribute type mapping */
692 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
694 prepare_basic_type_test( writer );
695 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
696 ok( hr == S_OK, "got %08x\n", hr );
698 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, tests[i].type, NULL,
699 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
700 ok( hr == S_OK, "%u: got %08x\n", i, hr );
702 hr = WsWriteEndAttribute( writer, NULL );
703 ok( hr == S_OK, "got %08x\n", hr );
705 hr = WsWriteEndElement( writer, NULL );
706 ok( hr == S_OK, "got %08x\n", hr );
707 check_output( writer, tests[i].result2, __LINE__ );
710 prepare_basic_type_test( writer );
711 memset( &guid, 0, sizeof(guid) );
712 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
713 &guid, sizeof(guid), NULL );
714 ok( hr == S_OK, "got %08x\n", hr );
715 hr = WsWriteEndElement( writer, NULL );
716 ok( hr == S_OK, "got %08x\n", hr );
717 check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
719 prepare_basic_type_test( writer );
720 string.chars = testW;
721 string.length = 4;
722 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
723 &string, sizeof(string), NULL );
724 ok( hr == S_OK, "got %08x\n", hr );
725 hr = WsWriteEndElement( writer, NULL );
726 ok( hr == S_OK, "got %08x\n", hr );
727 check_output( writer, "<t>test</t>", __LINE__ );
729 prepare_basic_type_test( writer );
730 str = testW;
731 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
732 &str, sizeof(str), NULL );
733 ok( hr == S_OK, "got %08x\n", hr );
734 hr = WsWriteEndElement( writer, NULL );
735 ok( hr == S_OK, "got %08x\n", hr );
736 check_output( writer, "<t>test</t>", __LINE__ );
738 prepare_basic_type_test( writer );
739 xmlstr.bytes = (BYTE *)"test";
740 xmlstr.length = 4;
741 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
742 &xmlstr, sizeof(xmlstr), NULL );
743 ok( hr == S_OK, "got %08x\n", hr );
744 hr = WsWriteEndElement( writer, NULL );
745 ok( hr == S_OK, "got %08x\n", hr );
746 check_output( writer, "<t>test</t>", __LINE__ );
748 prepare_basic_type_test( writer );
749 bytes.bytes = (BYTE *)"test";
750 bytes.length = 4;
751 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
752 &bytes, sizeof(bytes), NULL );
753 ok( hr == S_OK, "got %08x\n", hr );
754 hr = WsWriteEndElement( writer, NULL );
755 ok( hr == S_OK, "got %08x\n", hr );
756 check_output( writer, "<t>dGVzdA==</t>", __LINE__ );
758 prepare_basic_type_test( writer );
759 bytes.length = 0;
760 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
761 &bytes, sizeof(bytes), NULL );
762 ok( hr == S_OK, "got %08x\n", hr );
763 hr = WsWriteEndElement( writer, NULL );
764 ok( hr == S_OK, "got %08x\n", hr );
765 check_output( writer, "<t/>", __LINE__ );
767 prepare_basic_type_test( writer );
768 bytes.bytes = NULL;
769 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
770 &bytes, sizeof(bytes), 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/>", __LINE__ );
776 prepare_basic_type_test( writer );
777 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_NILLABLE_VALUE,
778 &bytes, sizeof(bytes), NULL );
779 ok( hr == S_OK, "got %08x\n", hr );
780 hr = WsWriteEndElement( writer, NULL );
781 ok( hr == S_OK, "got %08x\n", hr );
782 check_output( writer, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
783 __LINE__ );
785 WsFreeWriter( writer );
788 static void test_simple_struct_type(void)
790 static const WCHAR valueW[] = {'v','a','l','u','e',0};
791 HRESULT hr;
792 WS_XML_WRITER *writer;
793 WS_STRUCT_DESCRIPTION s;
794 WS_FIELD_DESCRIPTION f, *fields[1];
795 WS_XML_STRING localname = {6, (BYTE *)"struct"}, ns = {0, NULL};
796 struct test
798 const WCHAR *field;
799 } *test;
801 hr = WsCreateWriter( NULL, 0, &writer, NULL );
802 ok( hr == S_OK, "got %08x\n", hr );
804 hr = set_output( writer );
805 ok( hr == S_OK, "got %08x\n", hr );
807 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
808 ok( hr == S_OK, "got %08x\n", hr );
810 memset( &f, 0, sizeof(f) );
811 f.mapping = WS_TEXT_FIELD_MAPPING;
812 f.type = WS_WSZ_TYPE;
813 fields[0] = &f;
815 memset( &s, 0, sizeof(s) );
816 s.size = sizeof(struct test);
817 s.alignment = TYPE_ALIGNMENT(struct test);
818 s.fields = fields;
819 s.fieldCount = 1;
821 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
822 test->field = valueW;
823 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
824 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
825 ok( hr == E_INVALIDARG, "got %08x\n", hr );
827 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
828 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
829 ok( hr == E_INVALIDARG, "got %08x\n", hr );
831 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
832 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
833 ok( hr == S_OK, "got %08x\n", hr );
835 hr = WsWriteEndElement( writer, NULL );
836 ok( hr == S_OK, "got %08x\n", hr );
837 check_output( writer, "<struct>value</struct>", __LINE__ );
839 /* required value */
840 hr = set_output( writer );
841 ok( hr == S_OK, "got %08x\n", hr );
843 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
844 ok( hr == S_OK, "got %08x\n", hr );
846 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
847 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
848 ok( hr == S_OK, "got %08x\n", hr );
850 hr = WsWriteEndElement( writer, NULL );
851 ok( hr == S_OK, "got %08x\n", hr );
852 check_output( writer, "<struct>value</struct>", __LINE__ );
854 hr = set_output( writer );
855 ok( hr == S_OK, "got %08x\n", hr );
857 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
858 ok( hr == S_OK, "got %08x\n", hr );
860 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
861 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
862 ok( hr == S_OK, "got %08x\n", hr );
864 hr = WsWriteEndElement( writer, NULL );
865 ok( hr == S_OK, "got %08x\n", hr );
866 check_output( writer, "<struct>value</struct>", __LINE__ );
868 hr = set_output( writer );
869 ok( hr == S_OK, "got %08x\n", hr );
871 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
872 ok( hr == S_OK, "got %08x\n", hr );
874 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
875 ok( hr == S_OK, "got %08x\n", hr );
877 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
878 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
879 ok( hr == S_OK, "got %08x\n", hr );
881 hr = WsWriteEndAttribute( writer, NULL );
882 ok( hr == S_OK, "got %08x\n", hr );
884 hr = WsWriteEndElement( writer, NULL );
885 ok( hr == S_OK, "got %08x\n", hr );
886 check_output( writer, "<struct struct=\"value\"/>", __LINE__ );
888 HeapFree( GetProcessHeap(), 0, test );
889 WsFreeWriter( writer );
892 static void test_WsWriteElement(void)
894 static const WCHAR testW[] = {'t','e','s','t',0};
895 HRESULT hr;
896 WS_XML_WRITER *writer;
897 WS_STRUCT_DESCRIPTION s;
898 WS_FIELD_DESCRIPTION f, *fields[1];
899 WS_ELEMENT_DESCRIPTION desc;
900 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
901 struct test { const WCHAR *str; } *test;
903 hr = WsCreateWriter( NULL, 0, &writer, NULL );
904 ok( hr == S_OK, "got %08x\n", hr );
906 hr = set_output( writer );
907 ok( hr == S_OK, "got %08x\n", hr );
909 /* text field mapping */
910 memset( &f, 0, sizeof(f) );
911 f.mapping = WS_TEXT_FIELD_MAPPING;
912 f.type = WS_WSZ_TYPE;
913 fields[0] = &f;
915 memset( &s, 0, sizeof(s) );
916 s.size = sizeof(struct test);
917 s.alignment = TYPE_ALIGNMENT(struct test);
918 s.fields = fields;
919 s.fieldCount = 1;
921 desc.elementLocalName = &localname;
922 desc.elementNs = &ns;
923 desc.type = WS_STRUCT_TYPE;
924 desc.typeDescription = &s;
926 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
927 test->str = testW;
928 hr = WsWriteElement( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
929 ok( hr == E_INVALIDARG, "got %08x\n", hr );
931 hr = WsWriteElement( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
932 ok( hr == E_INVALIDARG, "got %08x\n", hr );
934 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
935 ok( hr == E_INVALIDARG, "got %08x\n", hr );
937 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
938 ok( hr == S_OK, "got %08x\n", hr );
939 check_output( writer, "<str>test</str>", __LINE__ );
941 hr = set_output( writer );
942 ok( hr == S_OK, "got %08x\n", hr );
944 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
945 ok( hr == S_OK, "got %08x\n", hr );
947 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
948 ok( hr == S_OK, "got %08x\n", hr );
949 check_output( writer, "<str><str>test</str>", __LINE__ );
951 hr = set_output( writer );
952 ok( hr == S_OK, "got %08x\n", hr );
954 /* attribute field mapping */
955 f.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
957 /* requires localName and ns to be set */
958 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
959 ok( hr == E_INVALIDARG, "got %08x\n", hr );
961 hr = set_output( writer );
962 ok( hr == S_OK, "got %08x\n", hr );
964 f.localName = &localname;
965 f.ns = &ns;
966 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
967 ok( hr == S_OK, "got %08x\n", hr );
968 check_output( writer, "<str str=\"test\"/>", __LINE__ );
970 HeapFree( GetProcessHeap(), 0, test );
971 WsFreeWriter( writer );
974 static void test_WsWriteValue(void)
976 HRESULT hr;
977 WS_XML_WRITER *writer;
978 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
979 ULONG i;
980 static const struct
982 WS_VALUE_TYPE type;
983 INT64 val;
984 ULONG size;
985 const char *result;
986 const char *result2;
988 tests[] =
990 { WS_BOOL_VALUE_TYPE, ~0, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
991 { WS_BOOL_VALUE_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
992 { WS_INT8_VALUE_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
993 { WS_INT16_VALUE_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
994 { WS_INT32_VALUE_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
995 "<t t=\"-2147483648\"/>" },
996 { WS_INT64_VALUE_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
997 "<t t=\"-9223372036854775808\"/>" },
998 { WS_UINT8_VALUE_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
999 { WS_UINT16_VALUE_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
1000 { WS_UINT32_VALUE_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
1001 { WS_UINT64_VALUE_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
1002 "<t t=\"18446744073709551615\"/>" },
1005 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1006 ok( hr == S_OK, "got %08x\n", hr );
1008 hr = set_output( writer );
1009 ok( hr == S_OK, "got %08x\n", hr );
1011 hr = WsWriteValue( NULL, tests[0].type, &tests[0].val, tests[0].size, NULL );
1012 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1014 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, tests[0].size, NULL );
1015 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1017 hr = set_output( writer );
1018 ok( hr == S_OK, "got %08x\n", hr );
1020 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1021 ok( hr == S_OK, "got %08x\n", hr );
1023 /* zero size */
1024 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, 0, NULL );
1025 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1027 hr = set_output( writer );
1028 ok( hr == S_OK, "got %08x\n", hr );
1030 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1031 ok( hr == S_OK, "got %08x\n", hr );
1033 /* NULL value */
1034 hr = WsWriteValue( writer, tests[0].type, NULL, 0, NULL );
1035 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1037 /* element type mapping */
1038 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1040 hr = set_output( writer );
1041 ok( hr == S_OK, "got %08x\n", hr );
1043 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1044 ok( hr == S_OK, "got %08x\n", hr );
1046 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1047 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1049 hr = WsWriteEndElement( writer, NULL );
1050 ok( hr == S_OK, "got %08x\n", hr );
1051 check_output( writer, tests[i].result, __LINE__ );
1054 /* attribute type mapping */
1055 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1057 hr = set_output( writer );
1058 ok( hr == S_OK, "got %08x\n", hr );
1060 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1061 ok( hr == S_OK, "got %08x\n", hr );
1063 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
1064 ok( hr == S_OK, "got %08x\n", hr );
1066 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1067 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1069 hr = WsWriteEndAttribute( writer, NULL );
1070 ok( hr == S_OK, "got %08x\n", hr );
1072 hr = WsWriteEndElement( writer, NULL );
1073 ok( hr == S_OK, "got %08x\n", hr );
1074 check_output( writer, tests[i].result2, __LINE__ );
1077 WsFreeWriter( writer );
1080 static void test_WsWriteAttribute(void)
1082 static const WCHAR testW[] = {'t','e','s','t',0};
1083 HRESULT hr;
1084 WS_XML_WRITER *writer;
1085 WS_STRUCT_DESCRIPTION s;
1086 WS_FIELD_DESCRIPTION f, *fields[1];
1087 WS_ATTRIBUTE_DESCRIPTION desc;
1088 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
1089 struct test { const WCHAR *str; } *test;
1091 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1092 ok( hr == S_OK, "got %08x\n", hr );
1094 hr = set_output( writer );
1095 ok( hr == S_OK, "got %08x\n", hr );
1097 /* text field mapping */
1098 memset( &f, 0, sizeof(f) );
1099 f.mapping = WS_TEXT_FIELD_MAPPING;
1100 f.type = WS_WSZ_TYPE;
1101 fields[0] = &f;
1103 memset( &s, 0, sizeof(s) );
1104 s.size = sizeof(struct test);
1105 s.alignment = TYPE_ALIGNMENT(struct test);
1106 s.fields = fields;
1107 s.fieldCount = 1;
1109 desc.attributeLocalName = &localname;
1110 desc.attributeNs = &ns;
1111 desc.type = WS_STRUCT_TYPE;
1112 desc.typeDescription = &s;
1114 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
1115 test->str = testW;
1116 hr = WsWriteAttribute( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1117 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1119 hr = WsWriteAttribute( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1120 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1122 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
1123 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1125 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1126 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1128 hr = set_output( writer );
1129 ok( hr == S_OK, "got %08x\n", hr );
1131 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1132 ok( hr == S_OK, "got %08x\n", hr );
1134 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1135 ok( hr == S_OK, "got %08x\n", hr );
1137 hr = WsWriteEndElement( writer, NULL );
1138 ok( hr == S_OK, "got %08x\n", hr );
1139 check_output( writer, "<str str=\"test\"/>", __LINE__ );
1141 HeapFree( GetProcessHeap(), 0, test );
1142 WsFreeWriter( writer );
1145 static void test_WsWriteStartCData(void)
1147 HRESULT hr;
1148 WS_XML_WRITER *writer;
1149 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1150 WS_XML_UTF8_TEXT text = {{WS_XML_TEXT_TYPE_UTF8}};
1152 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1153 ok( hr == S_OK, "got %08x\n", hr );
1155 hr = set_output( writer );
1156 ok( hr == S_OK, "got %08x\n", hr );
1158 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1159 ok( hr == S_OK, "got %08x\n", hr );
1161 hr = WsWriteEndCData( writer, NULL );
1162 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1164 hr = set_output( writer );
1165 ok( hr == S_OK, "got %08x\n", hr );
1167 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1168 ok( hr == S_OK, "got %08x\n", hr );
1169 check_output( writer, "", __LINE__ );
1171 hr = WsWriteStartCData( writer, NULL );
1172 ok( hr == S_OK, "got %08x\n", hr );
1173 check_output( writer, "<t><![CDATA[", __LINE__ );
1175 text.value.bytes = (BYTE *)"<data>";
1176 text.value.length = 6;
1177 hr = WsWriteText( writer, &text.text, NULL );
1178 ok( hr == S_OK, "got %08x\n", hr );
1179 check_output( writer, "<t><![CDATA[<data>", __LINE__ );
1181 hr = WsWriteEndCData( writer, NULL );
1182 ok( hr == S_OK, "got %08x\n", hr );
1183 check_output( writer, "<t><![CDATA[<data>]]>", __LINE__ );
1185 hr = WsWriteEndElement( writer, NULL );
1186 ok( hr == S_OK, "got %08x\n", hr );
1187 check_output( writer, "<t><![CDATA[<data>]]></t>", __LINE__ );
1189 WsFreeWriter( writer );
1192 static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
1194 WS_XML_WRITER *writer;
1195 WS_BYTES bytes;
1196 ULONG size = sizeof(bytes);
1197 int len = strlen(expected);
1198 HRESULT hr;
1200 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1201 ok( hr == S_OK, "got %08x\n", hr );
1203 hr = set_output( writer );
1204 ok( hr == S_OK, "got %08x\n", hr );
1206 hr = WsWriteXmlBuffer( writer, buffer, NULL );
1207 ok( hr == S_OK, "got %08x\n", hr );
1209 memset( &bytes, 0, sizeof(bytes) );
1210 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
1211 ok( hr == S_OK, "%u: got %08x\n", line, hr );
1212 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
1213 if (bytes.length != len) return;
1214 ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
1216 WsFreeWriter( writer );
1219 static void prepare_xmlns_test( WS_XML_WRITER *writer, WS_HEAP **heap, WS_XML_BUFFER **buffer )
1221 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1222 HRESULT hr;
1224 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, heap, NULL );
1225 ok( hr == S_OK, "got %08x\n", hr );
1227 hr = WsCreateXmlBuffer( *heap, NULL, 0, buffer, NULL );
1228 ok( hr == S_OK, "got %08x\n", hr );
1230 hr = WsSetOutputToBuffer( writer, *buffer, NULL, 0, NULL );
1231 ok( hr == S_OK, "got %08x\n", hr );
1233 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
1234 ok( hr == S_OK, "got %08x\n", hr );
1237 static void test_WsWriteXmlnsAttribute(void)
1239 WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1240 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, prefix2 = {7, (BYTE *)"prefix2"};
1241 WS_XML_STRING xmlns = {6, (BYTE *)"xmlns"}, attr = {4, (BYTE *)"attr"};
1242 WS_XML_STRING localname = {1, (BYTE *)"u"};
1243 WS_HEAP *heap;
1244 WS_XML_BUFFER *buffer;
1245 WS_XML_WRITER *writer;
1246 HRESULT hr;
1248 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1249 ok( hr == S_OK, "got %08x\n", hr );
1251 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1252 ok( hr == S_OK, "got %08x\n", hr );
1254 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1255 ok( hr == S_OK, "got %08x\n", hr );
1257 hr = WsWriteXmlnsAttribute( NULL, NULL, NULL, FALSE, NULL );
1258 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1259 WsFreeHeap( heap );
1261 prepare_xmlns_test( writer, &heap, &buffer );
1262 hr = WsWriteXmlnsAttribute( writer, NULL, NULL, FALSE, NULL );
1263 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1264 WsFreeHeap( heap );
1266 prepare_xmlns_test( writer, &heap, &buffer );
1267 hr = WsWriteXmlnsAttribute( writer, &prefix2, NULL, FALSE, NULL );
1268 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1270 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1271 ok( hr == S_OK, "got %08x\n", hr );
1272 hr = WsWriteXmlnsAttribute( writer, NULL, &ns, FALSE, NULL );
1273 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1274 WsFreeHeap( heap );
1276 /* no prefix */
1277 prepare_xmlns_test( writer, &heap, &buffer );
1278 hr = WsWriteXmlnsAttribute( writer, NULL, &ns2, FALSE, NULL );
1279 ok( hr == S_OK, "got %08x\n", hr );
1280 hr = WsWriteEndElement( writer, NULL );
1281 ok( hr == S_OK, "got %08x\n", hr );
1282 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__ );
1283 WsFreeHeap( heap );
1285 /* prefix */
1286 prepare_xmlns_test( writer, &heap, &buffer );
1287 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1288 ok( hr == S_OK, "got %08x\n", hr );
1289 hr = WsWriteEndElement( writer, NULL );
1290 ok( hr == S_OK, "got %08x\n", hr );
1291 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__ );
1292 WsFreeHeap( heap );
1294 /* implicitly set element prefix namespace */
1295 prepare_xmlns_test( writer, &heap, &buffer );
1296 hr = WsWriteEndElement( writer, NULL );
1297 ok( hr == S_OK, "got %08x\n", hr );
1298 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__ );
1299 WsFreeHeap( heap );
1301 /* explicitly set element prefix namespace */
1302 prepare_xmlns_test( writer, &heap, &buffer );
1303 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1304 ok( hr == S_OK, "got %08x\n", hr );
1305 hr = WsWriteEndElement( writer, NULL );
1306 ok( hr == S_OK, "got %08x\n", hr );
1307 check_output_buffer( buffer, "<prefix:t xmlns:prefix='ns'/>", __LINE__ );
1308 WsFreeHeap( heap );
1310 /* repeated calls, same namespace */
1311 prepare_xmlns_test( writer, &heap, &buffer );
1312 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1313 ok( hr == S_OK, "got %08x\n", hr );
1314 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1315 ok( hr == S_OK, "got %08x\n", hr );
1316 hr = WsWriteEndElement( writer, NULL );
1317 ok( hr == S_OK, "got %08x\n", hr );
1318 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__ );
1319 WsFreeHeap( heap );
1321 /* repeated calls, different namespace */
1322 prepare_xmlns_test( writer, &heap, &buffer );
1323 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1324 ok( hr == S_OK, "got %08x\n", hr );
1325 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1326 ok( hr == S_OK, "got %08x\n", hr );
1327 hr = WsWriteEndElement( writer, NULL );
1328 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1329 WsFreeHeap( heap );
1331 /* single quotes */
1332 prepare_xmlns_test( writer, &heap, &buffer );
1333 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, TRUE, NULL );
1334 ok( hr == S_OK, "got %08x\n", hr );
1335 hr = WsWriteEndElement( writer, NULL );
1336 ok( hr == S_OK, "got %08x\n", hr );
1337 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns' xmlns:prefix=\"ns\"/>", __LINE__ );
1338 WsFreeHeap( heap );
1340 /* different namespace, different prefix */
1341 prepare_xmlns_test( writer, &heap, &buffer );
1342 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1343 ok( hr == S_OK, "got %08x\n", hr );
1344 hr = WsWriteEndElement( writer, NULL );
1345 ok( hr == S_OK, "got %08x\n", hr );
1346 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__ );
1347 WsFreeHeap( heap );
1349 /* different namespace, same prefix */
1350 prepare_xmlns_test( writer, &heap, &buffer );
1351 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns2, TRUE, NULL );
1352 ok( hr == S_OK, "got %08x\n", hr );
1353 hr = WsWriteEndElement( writer, NULL );
1354 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1355 WsFreeHeap( heap );
1357 /* regular attribute */
1358 prepare_xmlns_test( writer, &heap, &buffer );
1359 hr = WsWriteStartAttribute( writer, &xmlns, &prefix2, &ns2, TRUE, NULL );
1360 ok( hr == S_OK, "got %08x\n", hr );
1361 hr = WsWriteEndAttribute( writer, NULL );
1362 ok( hr == S_OK, "got %08x\n", hr );
1363 hr = WsWriteEndElement( writer, NULL );
1364 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1365 WsFreeHeap( heap );
1367 /* attribute order */
1368 prepare_xmlns_test( writer, &heap, &buffer );
1369 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1370 ok( hr == S_OK, "got %08x\n", hr );
1371 hr = WsWriteStartAttribute( writer, &prefix, &attr, &ns, TRUE, NULL );
1372 ok( hr == S_OK, "got %08x\n", hr );
1373 hr = WsWriteEndAttribute( writer, NULL );
1374 ok( hr == S_OK, "got %08x\n", hr );
1375 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1376 ok( hr == S_OK, "got %08x\n", hr );
1377 hr = WsWriteEndElement( writer, NULL );
1378 ok( hr == S_OK, "got %08x\n", hr );
1379 check_output_buffer( buffer, "<prefix:t prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__ );
1380 WsFreeHeap( heap );
1382 /* scope */
1383 prepare_xmlns_test( writer, &heap, &buffer );
1384 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1385 ok( hr == S_OK, "got %08x\n", hr );
1386 hr = WsWriteStartElement( writer, &prefix2, &localname, &ns2, NULL );
1387 ok( hr == S_OK, "got %08x\n", hr );
1388 hr = WsWriteEndElement( writer, NULL );
1389 ok( hr == S_OK, "got %08x\n", hr );
1390 hr = WsWriteEndElement( writer, NULL );
1391 ok( hr == S_OK, "got %08x\n", hr );
1392 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"><prefix2:u/></prefix:t>",
1393 __LINE__ );
1394 WsFreeHeap( heap );
1396 WsFreeWriter( writer );
1399 static void prepare_prefix_test( WS_XML_WRITER *writer )
1401 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1402 HRESULT hr;
1404 hr = set_output( writer );
1405 ok( hr == S_OK, "got %08x\n", hr );
1406 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1407 ok( hr == S_OK, "got %08x\n", hr );
1408 hr = WsWriteEndStartElement( writer, NULL );
1409 ok( hr == S_OK, "got %08x\n", hr );
1412 static void test_WsGetPrefixFromNamespace(void)
1414 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, *prefix;
1415 const WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1416 WS_XML_WRITER *writer;
1417 HRESULT hr;
1419 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1420 ok( hr == S_OK, "got %08x\n", hr );
1422 hr = set_output( writer );
1423 ok( hr == S_OK, "got %08x\n", hr );
1424 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1425 ok( hr == S_OK, "got %08x\n", hr );
1427 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, NULL, NULL );
1428 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1430 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, &prefix, NULL );
1431 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1433 hr = WsGetPrefixFromNamespace( writer, NULL, FALSE, &prefix, NULL );
1434 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1436 /* element must be committed */
1437 hr = set_output( writer );
1438 ok( hr == S_OK, "got %08x\n", hr );
1439 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1440 ok( hr == S_OK, "got %08x\n", hr );
1441 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1442 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1444 /* but writer can't be positioned on end element node */
1445 hr = set_output( writer );
1446 ok( hr == S_OK, "got %08x\n", hr );
1447 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1448 ok( hr == S_OK, "got %08x\n", hr );
1449 hr = WsWriteEndElement( writer, NULL );
1450 ok( hr == S_OK, "got %08x\n", hr );
1451 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1452 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1454 /* required = TRUE */
1455 prefix = NULL;
1456 prepare_prefix_test( writer );
1457 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1458 ok( hr == S_OK, "got %08x\n", hr );
1459 ok( prefix != NULL, "prefix not set\n" );
1460 if (prefix)
1462 ok( prefix->length == 1, "got %u\n", prefix->length );
1463 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1466 prefix = (const WS_XML_STRING *)0xdeadbeef;
1467 hr = WsGetPrefixFromNamespace( writer, &ns2, TRUE, &prefix, NULL );
1468 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1469 ok( prefix == (const WS_XML_STRING *)0xdeadbeef, "prefix set\n" );
1471 /* required = FALSE */
1472 prefix = NULL;
1473 prepare_prefix_test( writer );
1474 hr = WsGetPrefixFromNamespace( writer, &ns, FALSE, &prefix, NULL );
1475 ok( hr == S_OK, "got %08x\n", hr );
1476 ok( prefix != NULL, "prefix not set\n" );
1477 if (prefix)
1479 ok( prefix->length == 1, "got %u\n", prefix->length );
1480 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1483 prefix = (const WS_XML_STRING *)0xdeadbeef;
1484 hr = WsGetPrefixFromNamespace( writer, &ns2, FALSE, &prefix, NULL );
1485 ok( hr == S_FALSE, "got %08x\n", hr );
1486 ok( prefix == NULL, "prefix not set\n" );
1488 WsFreeWriter( writer );
1491 static void test_complex_struct_type(void)
1493 static const char expected[] =
1494 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1495 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1496 "</o:OfficeConfig>";
1497 static const WCHAR timestampW[] =
1498 {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
1499 WS_XML_STRING str_officeconfig = {12, (BYTE *)"OfficeConfig"};
1500 WS_XML_STRING str_services = {8, (BYTE *)"services"};
1501 WS_XML_STRING str_generationtime = {14, (BYTE *)"GenerationTime"};
1502 WS_XML_STRING ns = {39, (BYTE *)"urn:schemas-microsoft-com:office:office"};
1503 WS_XML_STRING prefix = {1, (BYTE *)"o"};
1504 DWORD size;
1505 HRESULT hr;
1506 WS_HEAP *heap;
1507 WS_XML_BUFFER *buffer;
1508 WS_XML_WRITER *writer;
1509 WS_STRUCT_DESCRIPTION s, s2;
1510 WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
1511 struct services
1513 const WCHAR *generationtime;
1515 struct officeconfig
1517 struct services *services;
1518 } *test;
1520 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1521 ok( hr == S_OK, "got %08x\n", hr );
1523 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1524 ok( hr == S_OK, "got %08x\n", hr );
1526 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1527 ok( hr == S_OK, "got %08x\n", hr );
1529 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1530 ok( hr == S_OK, "got %08x\n", hr );
1532 hr = WsWriteStartElement( writer, &prefix, &str_officeconfig, &ns, NULL );
1533 ok( hr == S_OK, "got %08x\n", hr );
1535 memset( &f2, 0, sizeof(f2) );
1536 f2.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
1537 f2.localName = &str_generationtime;
1538 f2.ns = &ns;
1539 f2.type = WS_WSZ_TYPE;
1540 f2.options = WS_FIELD_OPTIONAL;
1541 fields2[0] = &f2;
1543 memset( &s2, 0, sizeof(s2) );
1544 s2.size = sizeof(*test->services);
1545 s2.alignment = 4;
1546 s2.fields = fields2;
1547 s2.fieldCount = 1;
1548 s2.typeLocalName = &str_services;
1549 s2.typeNs = &ns;
1551 memset( &f, 0, sizeof(f) );
1552 f.mapping = WS_ELEMENT_FIELD_MAPPING;
1553 f.localName = &str_services;
1554 f.ns = &ns;
1555 f.type = WS_STRUCT_TYPE;
1556 f.typeDescription = &s2;
1557 f.options = WS_FIELD_POINTER;
1558 fields[0] = &f;
1560 memset( &s, 0, sizeof(s) );
1561 s.size = sizeof(*test);
1562 s.alignment = 4;
1563 s.fields = fields;
1564 s.fieldCount = 1;
1565 s.typeLocalName = &str_officeconfig;
1566 s.typeNs = &ns;
1568 size = sizeof(struct officeconfig) + sizeof(struct services);
1569 test = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
1570 test->services = (struct services *)(test + 1);
1571 test->services->generationtime = timestampW;
1572 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
1573 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1574 ok( hr == S_OK, "got %08x\n", hr );
1576 hr = WsWriteEndElement( writer, NULL );
1577 ok( hr == S_OK, "got %08x\n", hr );
1578 check_output_buffer( buffer, expected, __LINE__ );
1580 HeapFree( GetProcessHeap(), 0, test );
1581 WsFreeWriter( writer );
1582 WsFreeHeap( heap );
1585 static void test_WsMoveWriter(void)
1587 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, ns = {0, NULL};
1588 WS_HEAP *heap;
1589 WS_XML_WRITER *writer;
1590 WS_XML_BUFFER *buffer;
1591 HRESULT hr;
1593 hr = WsMoveWriter( NULL, WS_MOVE_TO_EOF, NULL, NULL );
1594 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1596 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1597 ok( hr == S_OK, "got %08x\n", hr );
1599 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1600 ok( hr == S_OK, "got %08x\n", hr );
1602 hr = set_output( writer );
1603 ok( hr == S_OK, "got %08x\n", hr );
1605 /* writer must be set to an XML buffer */
1606 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1607 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1609 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1610 ok( hr == S_OK, "got %08x\n", hr );
1612 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1613 ok( hr == S_OK, "got %08x\n", hr );
1615 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1616 ok( hr == S_OK, "got %08x\n", hr );
1618 /* <a><b/></a> */
1619 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1620 ok( hr == S_OK, "got %08x\n", hr );
1622 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1623 ok( hr == S_OK, "got %08x\n", hr );
1625 hr = WsWriteEndElement( writer, NULL );
1626 ok( hr == S_OK, "got %08x\n", hr );
1628 hr = WsWriteEndElement( writer, NULL );
1629 ok( hr == S_OK, "got %08x\n", hr );
1631 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1632 ok( hr == S_OK, "got %08x\n", hr );
1634 hr = WsMoveWriter( writer, WS_MOVE_TO_ROOT_ELEMENT, NULL, NULL );
1635 ok( hr == S_OK, "got %08x\n", hr );
1637 hr = WsMoveWriter( writer, WS_MOVE_TO_CHILD_ELEMENT, NULL, NULL );
1638 ok( hr == S_OK, "got %08x\n", hr );
1640 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1641 ok( hr == S_OK, "got %08x\n", hr );
1643 hr = WsMoveWriter( writer, WS_MOVE_TO_PARENT_ELEMENT, NULL, NULL );
1644 ok( hr == S_OK, "got %08x\n", hr );
1646 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1647 ok( hr == S_OK, "got %08x\n", hr );
1649 hr = WsMoveWriter( writer, WS_MOVE_TO_BOF, NULL, NULL );
1650 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1652 WsFreeWriter( writer );
1653 WsFreeHeap( heap );
1656 static void test_WsGetWriterPosition(void)
1658 WS_HEAP *heap;
1659 WS_XML_WRITER *writer;
1660 WS_XML_BUFFER *buffer;
1661 WS_XML_NODE_POSITION pos;
1662 HRESULT hr;
1664 hr = WsGetWriterPosition( NULL, NULL, NULL );
1665 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1667 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1668 ok( hr == S_OK, "got %08x\n", hr );
1670 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1671 ok( hr == S_OK, "got %08x\n", hr );
1673 hr = WsGetWriterPosition( writer, &pos, NULL );
1674 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1676 hr = set_output( writer );
1677 ok( hr == S_OK, "got %08x\n", hr );
1679 /* writer must be set to an XML buffer */
1680 hr = WsGetWriterPosition( writer, &pos, NULL );
1681 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1683 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1684 ok( hr == S_OK, "got %08x\n", hr );
1686 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1687 ok( hr == S_OK, "got %08x\n", hr );
1689 hr = WsGetWriterPosition( writer, NULL, NULL );
1690 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1692 pos.buffer = pos.node = NULL;
1693 hr = WsGetWriterPosition( writer, &pos, NULL );
1694 ok( hr == S_OK, "got %08x\n", hr );
1695 ok( pos.buffer != NULL, "buffer not set\n" );
1696 ok( pos.node != NULL, "node not set\n" );
1698 WsFreeWriter( writer );
1699 WsFreeHeap( heap );
1702 static void test_WsSetWriterPosition(void)
1704 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1705 WS_HEAP *heap;
1706 WS_XML_WRITER *writer;
1707 WS_XML_BUFFER *buf1, *buf2;
1708 WS_XML_NODE_POSITION pos;
1709 HRESULT hr;
1711 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1712 ok( hr == S_OK, "got %08x\n", hr );
1714 hr = WsSetWriterPosition( NULL, NULL, NULL );
1715 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1717 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1718 ok( hr == S_OK, "got %08x\n", hr );
1720 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf1, NULL );
1721 ok( hr == S_OK, "got %08x\n", hr );
1723 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1724 ok( hr == S_OK, "got %08x\n", hr );
1726 hr = WsSetWriterPosition( writer, NULL, NULL );
1727 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1729 pos.buffer = pos.node = NULL;
1730 hr = WsGetWriterPosition( writer, &pos, NULL );
1731 ok( hr == S_OK, "got %08x\n", hr );
1732 ok( pos.buffer == buf1, "wrong buffer\n" );
1733 ok( pos.node != NULL, "node not set\n" );
1735 hr = WsSetWriterPosition( writer, &pos, NULL );
1736 ok( hr == S_OK, "got %08x\n", hr );
1738 /* different buffer */
1739 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf2, NULL );
1740 ok( hr == S_OK, "got %08x\n", hr );
1742 pos.buffer = buf2;
1743 hr = WsSetWriterPosition( writer, &pos, NULL );
1744 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1746 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1747 ok( hr == S_OK, "got %08x\n", hr );
1749 /* try to write at non-final position */
1750 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1751 ok( hr == S_OK, "got %08x\n", hr );
1753 pos.buffer = pos.node = NULL;
1754 hr = WsGetWriterPosition( writer, &pos, NULL );
1755 ok( hr == S_OK, "got %08x\n", hr );
1756 ok( pos.buffer == buf1, "wrong buffer\n" );
1757 ok( pos.node != NULL, "node not set\n" );
1759 hr = WsWriteEndElement( writer, NULL );
1760 ok( hr == S_OK, "got %08x\n", hr );
1761 check_output_buffer( buf1, "<t/>", __LINE__ );
1763 hr = WsSetWriterPosition( writer, &pos, NULL );
1764 ok( hr == S_OK, "got %08x\n", hr );
1766 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1767 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1769 WsFreeWriter( writer );
1770 WsFreeHeap( heap );
1773 static void test_WsWriteXmlBuffer(void)
1775 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1776 WS_XML_WRITER *writer1, *writer2;
1777 WS_XML_BUFFER *buffer1, *buffer2;
1778 WS_HEAP *heap;
1779 HRESULT hr;
1781 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1782 ok( hr == S_OK, "got %08x\n", hr );
1784 hr = WsCreateXmlBuffer( NULL, NULL, 0, NULL, NULL );
1785 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1787 hr = WsCreateWriter( NULL, 0, &writer1, NULL );
1788 ok( hr == S_OK, "got %08x\n", hr );
1790 hr = WsCreateXmlBuffer( heap, NULL, 0, NULL, NULL );
1791 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1793 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer1, NULL );
1794 ok( hr == S_OK, "got %08x\n", hr );
1796 hr = WsSetOutputToBuffer( writer1, buffer1, NULL, 0, NULL );
1797 ok( hr == S_OK, "got %08x\n", hr );
1799 hr = WsWriteStartElement( writer1, NULL, &localname, &ns, NULL );
1800 ok( hr == S_OK, "got %08x\n", hr );
1802 hr = WsWriteEndElement( writer1, NULL );
1803 ok( hr == S_OK, "got %08x\n", hr );
1804 check_output_buffer( buffer1, "<t/>", __LINE__ );
1806 hr = WsCreateWriter( NULL, 0, &writer2, NULL );
1807 ok( hr == S_OK, "got %08x\n", hr );
1809 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer2, NULL );
1810 ok( hr == S_OK, "got %08x\n", hr );
1812 hr = WsSetOutputToBuffer( writer2, buffer2, NULL, 0, NULL );
1813 ok( hr == S_OK, "got %08x\n", hr );
1815 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1816 ok( hr == S_OK, "got %08x\n", hr );
1817 check_output_buffer( buffer2, "<t/>", __LINE__ );
1819 hr = WsMoveWriter( writer2, WS_MOVE_TO_PREVIOUS_ELEMENT, NULL, NULL );
1820 todo_wine ok( hr == S_OK, "got %08x\n", hr );
1822 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1823 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1825 WsFreeWriter( writer1 );
1826 WsFreeWriter( writer2 );
1827 WsFreeHeap( heap );
1830 static void test_WsWriteNode(void)
1832 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {4, (BYTE *)"attr"}, ns = {0, NULL};
1833 WS_XML_WRITER *writer;
1834 WS_XML_BUFFER *buffer;
1835 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
1836 WS_XML_ATTRIBUTE attr, *attrs[1];
1837 WS_XML_ELEMENT_NODE elem;
1838 WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
1839 WS_XML_NODE node;
1840 WS_XML_TEXT_NODE text = {{WS_XML_NODE_TYPE_TEXT}};
1841 WS_HEAP *heap;
1842 HRESULT hr;
1844 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1845 ok( hr == S_OK, "got %08x\n", hr );
1847 hr = WsWriteNode( NULL, NULL, NULL );
1848 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1850 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1851 ok( hr == S_OK, "got %08x\n", hr );
1853 hr = WsWriteNode( writer, NULL, NULL );
1854 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1856 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1857 ok( hr == S_OK, "got %08x\n", hr );
1859 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1860 ok( hr == S_OK, "got %08x\n", hr );
1862 utf8.value.bytes = (BYTE *)"value";
1863 utf8.value.length = sizeof("value") - 1;
1865 attr.singleQuote = TRUE;
1866 attr.isXmlNs = FALSE;
1867 attr.prefix = NULL;
1868 attr.localName = &localname2;
1869 attr.ns = &ns;
1870 attr.value = &utf8.text;
1871 attrs[0] = &attr;
1873 elem.node.nodeType = WS_XML_NODE_TYPE_ELEMENT;
1874 elem.prefix = NULL;
1875 elem.localName = &localname;
1876 elem.ns = &ns;
1877 elem.attributeCount = 1;
1878 elem.attributes = attrs;
1879 elem.isEmpty = FALSE;
1880 hr = WsWriteNode( writer, &elem.node, NULL );
1881 ok( hr == S_OK, "got %08x\n", hr );
1883 comment.value.bytes = (BYTE *)"comment";
1884 comment.value.length = sizeof("comment") - 1;
1885 hr = WsWriteNode( writer, &comment.node, NULL );
1886 ok( hr == S_OK, "got %08x\n", hr );
1888 node.nodeType = WS_XML_NODE_TYPE_EOF;
1889 hr = WsWriteNode( writer, &node, NULL );
1890 ok( hr == S_OK, "got %08x\n", hr );
1892 node.nodeType = WS_XML_NODE_TYPE_BOF;
1893 hr = WsWriteNode( writer, &node, NULL );
1894 ok( hr == S_OK, "got %08x\n", hr );
1896 node.nodeType = WS_XML_NODE_TYPE_CDATA;
1897 hr = WsWriteNode( writer, &node, NULL );
1898 ok( hr == S_OK, "got %08x\n", hr );
1900 utf8.value.bytes = (BYTE *)"cdata";
1901 utf8.value.length = sizeof("cdata") - 1;
1902 text.text = &utf8.text;
1903 hr = WsWriteNode( writer, &text.node, NULL );
1904 ok( hr == S_OK, "got %08x\n", hr );
1906 node.nodeType = WS_XML_NODE_TYPE_END_CDATA;
1907 hr = WsWriteNode( writer, &node, NULL );
1908 ok( hr == S_OK, "got %08x\n", hr );
1910 utf8.value.bytes = (BYTE *)"text";
1911 utf8.value.length = sizeof("text") - 1;
1912 hr = WsWriteNode( writer, &text.node, NULL );
1913 ok( hr == S_OK, "got %08x\n", hr );
1915 node.nodeType = WS_XML_NODE_TYPE_END_ELEMENT;
1916 hr = WsWriteNode( writer, &node, NULL );
1917 ok( hr == S_OK, "got %08x\n", hr );
1918 check_output_buffer( buffer, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__ );
1920 WsFreeWriter( writer );
1921 WsFreeHeap( heap );
1924 static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
1926 WS_XML_READER_TEXT_ENCODING enc;
1927 WS_XML_READER_BUFFER_INPUT input;
1929 enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
1930 enc.charSet = WS_CHARSET_AUTO;
1932 input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
1933 input.encodedData = (void *)data;
1934 input.encodedDataSize = size;
1936 return WsSetInput( reader, &enc.encoding, &input.input, NULL, 0, NULL );
1939 static void test_WsCopyNode(void)
1941 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
1942 WS_XML_NODE_POSITION pos, pos2;
1943 const WS_XML_NODE *node;
1944 WS_XML_WRITER *writer;
1945 WS_XML_READER *reader;
1946 WS_XML_BUFFER *buffer;
1947 WS_HEAP *heap;
1948 HRESULT hr;
1950 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1951 ok( hr == S_OK, "got %08x\n", hr );
1953 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1954 ok( hr == S_OK, "got %08x\n", hr );
1956 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1957 ok( hr == S_OK, "got %08x\n", hr );
1959 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1960 ok( hr == S_OK, "got %08x\n", hr );
1962 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1963 ok( hr == S_OK, "got %08x\n", hr );
1965 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1966 ok( hr == S_OK, "got %08x\n", hr );
1968 hr = WsWriteEndElement( writer, NULL );
1969 ok( hr == S_OK, "got %08x\n", hr );
1971 hr = WsGetWriterPosition( writer, &pos, NULL );
1972 ok( hr == S_OK, "got %08x\n", hr );
1974 hr = WsWriteEndElement( writer, NULL );
1975 ok( hr == S_OK, "got %08x\n", hr );
1976 check_output_buffer( buffer, "<t><u/></t>", __LINE__ );
1978 hr = WsCreateReader( NULL, 0, &reader, NULL );
1979 ok( hr == S_OK, "got %08x\n", hr );
1981 hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
1982 ok( hr == S_OK, "got %08x\n", hr );
1984 hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
1985 ok( hr == S_OK, "got %08x\n", hr );
1987 hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
1988 ok( hr == S_OK, "got %08x\n", hr );
1990 hr = WsSetWriterPosition( writer, &pos, NULL );
1991 ok( hr == S_OK, "got %08x\n", hr );
1993 hr = WsCopyNode( writer, reader, NULL );
1994 ok( hr == S_OK, "got %08x\n", hr );
1995 check_output_buffer( buffer, "<t><u/><v/></t>", __LINE__ );
1997 hr = WsGetWriterPosition( writer, &pos2, NULL );
1998 ok( hr == S_OK, "got %08x\n", hr );
1999 ok( pos2.buffer == pos.buffer, "wrong buffer\n" );
2000 ok( pos2.node == pos.node, "wrong node\n" );
2002 hr = WsGetReaderNode( reader, &node, NULL );
2003 ok( hr == S_OK, "got %08x\n", hr );
2004 ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
2006 WsFreeReader( reader );
2007 WsFreeWriter( writer );
2008 WsFreeHeap( heap );
2011 static void test_text_types(void)
2013 static const WCHAR utf16W[] = {'u','t','f','1','6'};
2014 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2015 WS_XML_WRITER *writer;
2016 static const WS_XML_UTF8_TEXT val_utf8 = { {WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"utf8"} };
2017 static WS_XML_UTF16_TEXT val_utf16 = { {WS_XML_TEXT_TYPE_UTF16} };
2018 static const WS_XML_GUID_TEXT val_guid = { {WS_XML_TEXT_TYPE_GUID} };
2019 static const WS_XML_UNIQUE_ID_TEXT val_urn = { {WS_XML_TEXT_TYPE_UNIQUE_ID} };
2020 static const WS_XML_BOOL_TEXT val_bool = { {WS_XML_TEXT_TYPE_BOOL}, TRUE };
2021 static const WS_XML_INT32_TEXT val_int32 = { {WS_XML_TEXT_TYPE_INT32}, -2147483647 - 1 };
2022 static const WS_XML_INT64_TEXT val_int64 = { {WS_XML_TEXT_TYPE_INT64}, -9223372036854775807 - 1 };
2023 static const WS_XML_UINT64_TEXT val_uint64 = { {WS_XML_TEXT_TYPE_UINT64}, ~0 };
2024 static const WS_XML_DATETIME_TEXT val_datetime = { {WS_XML_TEXT_TYPE_DATETIME}, {0, WS_DATETIME_FORMAT_UTC} };
2025 static const WS_XML_DOUBLE_TEXT val_double = { {WS_XML_TEXT_TYPE_DOUBLE}, 1.1 };
2026 static const WS_XML_BASE64_TEXT val_base64 = { {WS_XML_TEXT_TYPE_BASE64}, (BYTE *)"test", 4 };
2027 static const struct
2029 const WS_XML_TEXT *text;
2030 const char *result;
2032 tests[] =
2034 { &val_utf8.text, "<t>utf8</t>" },
2035 { &val_utf16.text, "<t>utf16</t>" },
2036 { &val_guid.text, "<t>00000000-0000-0000-0000-000000000000</t>" },
2037 { &val_urn.text, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
2038 { &val_bool.text, "<t>true</t>" },
2039 { &val_int32.text, "<t>-2147483648</t>" },
2040 { &val_int64.text, "<t>-9223372036854775808</t>" },
2041 { &val_uint64.text, "<t>18446744073709551615</t>" },
2042 { &val_datetime.text, "<t>0001-01-01T00:00:00Z</t>" },
2043 { &val_double.text, "<t>1.1</t>" },
2044 { &val_base64.text, "<t>dGVzdA==</t>" },
2046 HRESULT hr;
2047 ULONG i;
2049 val_utf16.bytes = (BYTE *)utf16W;
2050 val_utf16.byteCount = sizeof(utf16W);
2052 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2053 ok( hr == S_OK, "got %08x\n", hr );
2055 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2057 hr = set_output( writer );
2058 ok( hr == S_OK, "got %08x\n", hr );
2059 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2060 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2062 hr = WsWriteText( writer, tests[i].text, NULL );
2063 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2065 hr = WsWriteEndElement( writer, NULL );
2066 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2067 check_output( writer, tests[i].result, __LINE__ );
2070 WsFreeWriter( writer );
2073 static BOOL get_fpword( unsigned short *ret )
2075 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2076 unsigned short fpword;
2077 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
2078 *ret = fpword;
2079 return TRUE;
2080 #endif
2081 return FALSE;
2084 static void set_fpword( unsigned short fpword )
2086 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2087 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
2088 #endif
2091 static void test_double(void)
2093 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2094 unsigned short fpword;
2095 static const struct
2097 double val;
2098 const char *result;
2100 tests[] =
2102 {0.0, "<t>0</t>"},
2103 {1.0, "<t>1</t>"},
2104 {-1.0, "<t>-1</t>"},
2105 {1.0000000000000001, "<t>1</t>"},
2106 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2107 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2108 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2109 {100000000000000, "<t>100000000000000</t>"},
2110 {1000000000000000, "<t>1E+15</t>"},
2111 {0.1, "<t>0.1</t>"},
2112 {0.01, "<t>1E-2</t>"},
2113 {-0.1, "<t>-0.1</t>"},
2114 {-0.01, "<t>-1E-2</t>"},
2115 {1.7976931348623158e308, "<t>1.7976931348623157E+308</t>"},
2116 {-1.7976931348623158e308, "<t>-1.7976931348623157E+308</t>"},
2118 HRESULT hr;
2119 WS_XML_WRITER *writer;
2120 WS_XML_DOUBLE_TEXT text;
2121 ULONG i;
2123 hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
2124 ok( hr == S_OK, "got %08x\n", hr );
2126 text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
2127 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2129 hr = set_output( writer );
2130 ok( hr == S_OK, "got %08x\n", hr );
2131 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2132 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2134 text.value = tests[i].val;
2135 hr = WsWriteText( writer, &text.text, NULL );
2136 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2138 hr = WsWriteEndElement( writer, NULL );
2139 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2140 check_output( writer, tests[i].result, __LINE__ );
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, "got %08x\n", hr );
2148 text.value = NAN;
2149 hr = WsWriteText( writer, &text.text, NULL );
2150 ok( hr == S_OK, "got %08x\n", hr );
2152 hr = WsWriteEndElement( writer, NULL );
2153 ok( hr == S_OK, "got %08x\n", hr );
2154 check_output( writer, "<t>NaN</t>", __LINE__ );
2156 hr = set_output( writer );
2157 ok( hr == S_OK, "got %08x\n", hr );
2158 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2159 ok( hr == S_OK, "got %08x\n", hr );
2161 text.value = INFINITY;
2162 hr = WsWriteText( writer, &text.text, NULL );
2163 ok( hr == S_OK, "got %08x\n", hr );
2165 hr = WsWriteEndElement( writer, NULL );
2166 ok( hr == S_OK, "got %08x\n", hr );
2167 check_output( writer, "<t>INF</t>", __LINE__ );
2169 hr = set_output( writer );
2170 ok( hr == S_OK, "got %08x\n", hr );
2171 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2172 ok( hr == S_OK, "got %08x\n", hr );
2174 text.value = -INFINITY;
2175 hr = WsWriteText( writer, &text.text, NULL );
2176 ok( hr == S_OK, "got %08x\n", hr );
2178 hr = WsWriteEndElement( writer, NULL );
2179 ok( hr == S_OK, "got %08x\n", hr );
2180 check_output( writer, "<t>-INF</t>", __LINE__ );
2182 if (!get_fpword( &fpword ))
2184 skip( "can't get floating point control word\n" );
2185 WsFreeWriter( writer );
2186 return;
2188 ok( fpword == 0x27f, "got %04x\n", fpword );
2189 set_fpword( 0x1f7f );
2190 get_fpword( &fpword );
2191 ok( fpword == 0x1f7f, "got %04x\n", fpword );
2193 hr = set_output( writer );
2194 ok( hr == S_OK, "got %08x\n", hr );
2195 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2196 ok( hr == S_OK, "got %08x\n", hr );
2198 text.value = 100000000000000;
2199 hr = WsWriteText( writer, &text.text, NULL );
2200 ok( hr == S_OK, "got %08x\n", hr );
2202 hr = WsWriteEndElement( writer, NULL );
2203 ok( hr == S_OK, "got %08x\n", hr );
2204 check_output( writer, "<t>100000000000000</t>", __LINE__ );
2206 get_fpword( &fpword );
2207 ok( fpword == 0x1f7f, "got %04x\n", fpword );
2208 set_fpword( 0x27f );
2210 WsFreeWriter( writer );
2213 static void test_field_options(void)
2215 static const char expected[] =
2216 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2217 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2218 HRESULT hr;
2219 WS_XML_WRITER *writer;
2220 WS_STRUCT_DESCRIPTION s;
2221 WS_FIELD_DESCRIPTION f, f2, f3, f4, f5, *fields[5];
2222 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, str_guid = {4, (BYTE *)"guid"};
2223 WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_bool = {4, (BYTE *)"bool"};
2224 WS_XML_STRING str_xmlstr = {6, (BYTE *)"xmlstr"}, str_str = {3, (BYTE *)"str"};
2225 INT32 val = -1;
2226 struct test
2228 GUID guid;
2229 BOOL *bool_ptr;
2230 INT32 *int32_ptr;
2231 WS_XML_STRING xmlstr;
2232 WCHAR *str;
2233 } test;
2235 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2236 ok( hr == S_OK, "got %08x\n", hr );
2238 hr = set_output( writer );
2239 ok( hr == S_OK, "got %08x\n", hr );
2241 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2242 ok( hr == S_OK, "got %08x\n", hr );
2244 memset( &f, 0, sizeof(f) );
2245 f.mapping = WS_ELEMENT_FIELD_MAPPING;
2246 f.localName = &str_guid;
2247 f.ns = &ns;
2248 f.type = WS_GUID_TYPE;
2249 f.options = WS_FIELD_OPTIONAL;
2250 fields[0] = &f;
2252 memset( &f2, 0, sizeof(f2) );
2253 f2.mapping = WS_ELEMENT_FIELD_MAPPING;
2254 f2.localName = &str_bool;
2255 f2.offset = FIELD_OFFSET(struct test, bool_ptr);
2256 f2.ns = &ns;
2257 f2.type = WS_BOOL_TYPE;
2258 f2.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2259 fields[1] = &f2;
2261 memset( &f3, 0, sizeof(f3) );
2262 f3.mapping = WS_ELEMENT_FIELD_MAPPING;
2263 f3.localName = &str_int32;
2264 f3.offset = FIELD_OFFSET(struct test, int32_ptr);
2265 f3.ns = &ns;
2266 f3.type = WS_INT32_TYPE;
2267 f3.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2268 fields[2] = &f3;
2270 memset( &f4, 0, sizeof(f4) );
2271 f4.mapping = WS_ELEMENT_FIELD_MAPPING;
2272 f4.localName = &str_xmlstr;
2273 f4.offset = FIELD_OFFSET(struct test, xmlstr);
2274 f4.ns = &ns;
2275 f4.type = WS_XML_STRING_TYPE;
2276 f4.options = WS_FIELD_NILLABLE;
2277 fields[3] = &f4;
2279 memset( &f5, 0, sizeof(f5) );
2280 f5.mapping = WS_ELEMENT_FIELD_MAPPING;
2281 f5.localName = &str_str;
2282 f5.offset = FIELD_OFFSET(struct test, str);
2283 f5.ns = &ns;
2284 f5.type = WS_WSZ_TYPE;
2285 f5.options = WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE;
2286 fields[4] = &f5;
2288 memset( &s, 0, sizeof(s) );
2289 s.size = sizeof(struct test);
2290 s.alignment = TYPE_ALIGNMENT(struct test);
2291 s.fields = fields;
2292 s.fieldCount = 5;
2294 memset( &test, 0, sizeof(test) );
2295 test.int32_ptr = &val;
2296 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE,
2297 &test, sizeof(test), NULL );
2298 ok( hr == S_OK, "got %08x\n", hr );
2300 hr = WsWriteEndElement( writer, NULL );
2301 ok( hr == S_OK, "got %08x\n", hr );
2302 check_output( writer, expected, __LINE__ );
2304 WsFreeWriter( writer );
2307 static void test_WsWriteText(void)
2309 static const WCHAR testW[] = {'t','e','s','t'};
2310 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
2311 HRESULT hr;
2312 WS_XML_WRITER *writer;
2313 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
2314 WS_XML_UTF16_TEXT utf16 = {{WS_XML_TEXT_TYPE_UTF16}};
2315 WS_XML_GUID_TEXT guid = {{WS_XML_TEXT_TYPE_GUID}};
2317 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2318 ok( hr == S_OK, "got %08x\n", hr );
2320 hr = set_output( writer );
2321 ok( hr == S_OK, "got %08x\n", hr );
2323 utf8.value.bytes = (BYTE *)"test";
2324 utf8.value.length = 4;
2325 hr = WsWriteText( writer, &utf8.text, NULL );
2326 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
2328 hr = set_output( writer );
2329 ok( hr == S_OK, "got %08x\n", hr );
2331 /* element, utf8 */
2332 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2333 ok( hr == S_OK, "got %08x\n", hr );
2335 hr = WsWriteText( writer, &utf8.text, NULL );
2336 ok( hr == S_OK, "got %08x\n", hr );
2337 check_output( writer, "<t>test", __LINE__ );
2339 utf8.value.bytes = (BYTE *)"tset";
2340 hr = WsWriteText( writer, &utf8.text, NULL );
2341 ok( hr == S_OK, "got %08x\n", hr );
2342 check_output( writer, "<t>testtset", __LINE__ );
2344 hr = WsWriteEndElement( writer, NULL );
2345 ok( hr == S_OK, "got %08x\n", hr );
2346 check_output( writer, "<t>testtset</t>", __LINE__ );
2348 hr = set_output( writer );
2349 ok( hr == S_OK, "got %08x\n", hr );
2351 /* attribute, utf8 */
2352 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2353 ok( hr == S_OK, "got %08x\n", hr );
2355 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2356 ok( hr == S_OK, "got %08x\n", hr );
2358 hr = WsWriteText( writer, &utf8.text, NULL );
2359 ok( hr == S_OK, "got %08x\n", hr );
2360 check_output( writer, "", __LINE__ );
2362 utf8.value.bytes = (BYTE *)"test";
2363 hr = WsWriteText( writer, &utf8.text, NULL );
2364 ok( hr == S_OK, "got %08x\n", hr );
2365 check_output( writer, "", __LINE__ );
2367 hr = WsWriteEndAttribute( writer, NULL );
2368 ok( hr == S_OK, "got %08x\n", hr );
2370 hr = WsWriteEndElement( writer, NULL );
2371 ok( hr == S_OK, "got %08x\n", hr );
2372 check_output( writer, "<t a=\"tsettest\"/>", __LINE__ );
2374 hr = set_output( writer );
2375 ok( hr == S_OK, "got %08x\n", hr );
2377 /* element, utf16 */
2378 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2379 ok( hr == S_OK, "got %08x\n", hr );
2381 utf16.bytes = (BYTE *)testW;
2382 utf16.byteCount = sizeof(testW);
2383 hr = WsWriteText( writer, &utf16.text, NULL );
2384 ok( hr == S_OK, "got %08x\n", hr );
2385 check_output( writer, "<t>test", __LINE__ );
2387 hr = WsWriteText( writer, &utf16.text, NULL );
2388 ok( hr == S_OK, "got %08x\n", hr );
2389 check_output( writer, "<t>testtest", __LINE__ );
2391 hr = WsWriteEndElement( writer, NULL );
2392 ok( hr == S_OK, "got %08x\n", hr );
2393 check_output( writer, "<t>testtest</t>", __LINE__ );
2395 hr = set_output( writer );
2396 ok( hr == S_OK, "got %08x\n", hr );
2398 /* attribute, utf16 */
2399 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2400 ok( hr == S_OK, "got %08x\n", hr );
2402 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2403 ok( hr == S_OK, "got %08x\n", hr );
2405 hr = WsWriteText( writer, &utf16.text, NULL );
2406 ok( hr == S_OK, "got %08x\n", hr );
2407 check_output( writer, "", __LINE__ );
2409 hr = WsWriteText( writer, &utf16.text, NULL );
2410 ok( hr == S_OK, "got %08x\n", hr );
2411 check_output( writer, "", __LINE__ );
2413 hr = WsWriteEndAttribute( writer, NULL );
2414 ok( hr == S_OK, "got %08x\n", hr );
2416 hr = WsWriteEndElement( writer, NULL );
2417 ok( hr == S_OK, "got %08x\n", hr );
2418 check_output( writer, "<t a=\"testtest\"/>", __LINE__ );
2420 hr = set_output( writer );
2421 ok( hr == S_OK, "got %08x\n", hr );
2423 /* element, guid */
2424 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2425 ok( hr == S_OK, "got %08x\n", hr );
2427 hr = WsWriteText( writer, &guid.text, NULL );
2428 ok( hr == S_OK, "got %08x\n", hr );
2429 check_output( writer, "<t>00000000-0000-0000-0000-000000000000", __LINE__ );
2431 hr = WsWriteText( writer, &guid.text, NULL );
2432 ok( hr == S_OK, "got %08x\n", hr );
2433 check_output( writer, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000",
2434 __LINE__ );
2436 /* continue with different text type */
2437 hr = WsWriteText( writer, &utf8.text, NULL );
2438 ok( hr == S_OK, "got %08x\n", hr );
2439 check_output( writer, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000test",
2440 __LINE__ );
2442 hr = WsWriteEndElement( writer, NULL );
2443 ok( hr == S_OK, "got %08x\n", hr );
2445 hr = set_output( writer );
2446 ok( hr == S_OK, "got %08x\n", hr );
2448 /* attribute, guid */
2449 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2450 ok( hr == S_OK, "got %08x\n", hr );
2452 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2453 ok( hr == S_OK, "got %08x\n", hr );
2455 hr = WsWriteText( writer, &guid.text, NULL );
2456 ok( hr == S_OK, "got %08x\n", hr );
2457 check_output( writer, "", __LINE__ );
2459 hr = WsWriteText( writer, &guid.text, NULL );
2460 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2462 hr = set_output( writer );
2463 ok( hr == S_OK, "got %08x\n", hr );
2465 /* attribute, mix allowed text types */
2466 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2467 ok( hr == S_OK, "got %08x\n", hr );
2469 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
2470 ok( hr == S_OK, "got %08x\n", hr );
2472 hr = WsWriteText( writer, &utf8.text, NULL );
2473 ok( hr == S_OK, "got %08x\n", hr );
2475 hr = WsWriteText( writer, &utf16.text, NULL );
2476 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2478 hr = set_output( writer );
2479 ok( hr == S_OK, "got %08x\n", hr );
2481 /* cdata */
2482 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2483 ok( hr == S_OK, "got %08x\n", hr );
2484 hr = WsWriteStartCData( writer, NULL );
2485 ok( hr == S_OK, "got %08x\n", hr );
2487 hr = WsWriteText( writer, &utf8.text, NULL );
2488 ok( hr == S_OK, "got %08x\n", hr );
2490 hr = WsWriteText( writer, &guid.text, NULL );
2491 ok( hr == S_OK, "got %08x\n", hr );
2493 hr = WsWriteEndCData( writer, NULL );
2494 ok( hr == S_OK, "got %08x\n", hr );
2495 hr = WsWriteEndElement( writer, NULL );
2496 ok( hr == S_OK, "got %08x\n", hr );
2497 check_output( writer, "<t><![CDATA[test00000000-0000-0000-0000-000000000000]]></t>", __LINE__ );
2499 WsFreeWriter( writer );
2502 static void test_WsWriteArray(void)
2504 static const WS_XML_STRING localname = {4, (BYTE *)"item"}, localname2 = {5, (BYTE *)"array"};
2505 static const WS_XML_STRING ns = {0, NULL};
2506 WS_XML_WRITER *writer;
2507 BOOL array_bool[2];
2508 HRESULT hr;
2510 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2511 ok( hr == S_OK, "got %08x\n", hr );
2513 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2514 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2516 hr = set_output( writer );
2517 ok( hr == S_OK, "got %08x\n", hr );
2518 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2519 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2521 hr = set_output( writer );
2522 ok( hr == S_OK, "got %08x\n", hr );
2523 hr = WsWriteArray( writer, &localname, NULL, 0, NULL, 0, 0, 0, NULL );
2524 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2526 hr = set_output( writer );
2527 ok( hr == S_OK, "got %08x\n", hr );
2528 hr = WsWriteArray( writer, &localname, &ns, 0, NULL, 0, 0, 0, NULL );
2529 ok( hr == S_OK, "got %08x\n", hr );
2530 check_output( writer, "", __LINE__ );
2532 hr = WsWriteArray( writer, &localname, &ns, ~0u, NULL, 0, 0, 0, NULL );
2533 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2535 hr = set_output( writer );
2536 ok( hr == S_OK, "got %08x\n", hr );
2537 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, 0, 0, 0, NULL );
2538 ok( hr == S_OK, "got %08x\n", hr );
2539 check_output( writer, "", __LINE__ );
2541 array_bool[0] = FALSE;
2542 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, 0, 0, 0, NULL );
2543 ok( hr == S_OK, "got %08x\n", hr );
2544 check_output( writer, "", __LINE__ );
2546 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 0, NULL );
2547 ok( hr == S_OK, "got %08x\n", hr );
2548 check_output( writer, "", __LINE__ );
2550 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 0, NULL );
2551 ok( hr == S_OK, "got %08x\n", hr );
2552 check_output( writer, "", __LINE__ );
2554 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 1, NULL );
2555 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2557 hr = set_output( writer );
2558 ok( hr == S_OK, "got %08x\n", hr );
2559 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 1, NULL );
2560 ok( hr == S_OK, "got %08x\n", hr );
2561 check_output( writer, "<item>false</item>", __LINE__ );
2563 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool) - 1, 0, 2, NULL );
2564 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2566 hr = set_output( writer );
2567 ok( hr == S_OK, "got %08x\n", hr );
2568 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 3, NULL );
2569 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2571 hr = set_output( writer );
2572 ok( hr == S_OK, "got %08x\n", hr );
2574 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
2575 ok( hr == S_OK, "got %08x\n", hr );
2577 array_bool[1] = TRUE;
2578 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 2, NULL );
2579 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, "<array><item>false</item><item>true</item></array>", __LINE__ );
2585 WsFreeWriter( writer );
2588 static void test_escapes(void)
2590 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2591 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
2592 WS_XML_WRITER *writer;
2593 struct test
2595 const char *text;
2596 const char *result;
2597 BOOL single;
2599 static const struct test tests_elem[] =
2601 { "<", "<t>&lt;</t>" },
2602 { ">", "<t>&gt;</t>" },
2603 { "\"", "<t>\"</t>" },
2604 { "&", "<t>&amp;</t>" },
2605 { "&&", "<t>&amp;&amp;</t>" },
2606 { "'", "<t>'</t>" },
2608 static const struct test tests_attr[] =
2610 { "<", "<t t=\"&lt;\"/>" },
2611 { ">", "<t t=\">\"/>" },
2612 { "\"", "<t t=\"&quot;\"/>" },
2613 { "&", "<t t=\"&amp;\"/>" },
2614 { "'", "<t t=\"'\"/>" },
2615 { "\"", "<t t='\"'/>", TRUE },
2616 { "'", "<t t='&apos;'/>", TRUE },
2618 static const struct test tests_cdata[] =
2620 { "<", "<t><![CDATA[<]]></t>" },
2621 { ">", "<t><![CDATA[>]]></t>" },
2622 { "\"", "<t><![CDATA[\"]]></t>" },
2623 { "&", "<t><![CDATA[&]]></t>" },
2624 { "[", "<t><![CDATA[[]]></t>" },
2625 { "]", "<t><![CDATA[]]]></t>" },
2626 { "'", "<t><![CDATA[']]></t>" },
2628 static const struct test tests_comment[] =
2630 { "<", "<t><!--<--></t>" },
2631 { ">", "<t><!-->--></t>" },
2632 { "\"", "<t><!--\"--></t>" },
2633 { "&", "<t><!--&--></t>" },
2634 { "'", "<t><!--'--></t>" },
2636 HRESULT hr;
2637 ULONG i;
2639 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2640 ok( hr == S_OK, "got %08x\n", hr );
2642 for (i = 0; i < sizeof(tests_elem)/sizeof(tests_elem[0]); i++)
2644 hr = set_output( writer );
2645 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2646 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2647 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2649 utf8.value.bytes = (BYTE *)tests_elem[i].text;
2650 utf8.value.length = strlen( tests_elem[i].text );
2651 hr = WsWriteText( writer, &utf8.text, NULL );
2652 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2654 hr = WsWriteEndElement( writer, NULL );
2655 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2656 check_output( writer, tests_elem[i].result, __LINE__ );
2659 for (i = 0; i < sizeof(tests_attr)/sizeof(tests_attr[0]); i++)
2661 hr = set_output( writer );
2662 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2663 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2664 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2666 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, tests_attr[i].single, NULL );
2667 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2669 utf8.value.bytes = (BYTE *)tests_attr[i].text;
2670 utf8.value.length = strlen( tests_attr[i].text );
2671 hr = WsWriteText( writer, &utf8.text, NULL );
2672 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2674 hr = WsWriteEndAttribute( writer, NULL );
2675 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2677 hr = WsWriteEndElement( writer, NULL );
2678 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2679 check_output( writer, tests_attr[i].result, __LINE__ );
2682 for (i = 0; i < sizeof(tests_cdata)/sizeof(tests_cdata[0]); i++)
2684 hr = set_output( writer );
2685 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2686 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2687 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2689 hr = WsWriteStartCData( writer, NULL );
2690 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2692 utf8.value.bytes = (BYTE *)tests_cdata[i].text;
2693 utf8.value.length = strlen( tests_cdata[i].text );
2694 hr = WsWriteText( writer, &utf8.text, NULL );
2695 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2697 hr = WsWriteEndCData( writer, NULL );
2698 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2700 hr = WsWriteEndElement( writer, NULL );
2701 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2702 check_output( writer, tests_cdata[i].result, __LINE__ );
2705 for (i = 0; i < sizeof(tests_comment)/sizeof(tests_comment[0]); i++)
2707 WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
2709 hr = set_output( writer );
2710 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2711 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2712 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2714 comment.value.bytes = (BYTE *)tests_comment[i].text;
2715 comment.value.length = strlen( tests_comment[i].text );
2716 hr = WsWriteNode( writer, &comment.node, NULL );
2717 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2719 hr = WsWriteEndElement( writer, NULL );
2720 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2721 check_output( writer, tests_comment[i].result, __LINE__ );
2724 WsFreeWriter( writer );
2727 static void test_write_option(void)
2729 static const WCHAR sW[] = {'s',0};
2730 static const WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2731 WS_XML_WRITER *writer;
2732 int val_int = -1, val_int_zero = 0, *ptr_int = &val_int, *ptr_int_null = NULL;
2733 const WCHAR *ptr_wsz = sW, *ptr_wsz_null = NULL;
2734 static const WS_XML_STRING val_xmlstr = {1, (BYTE *)"x"}, val_xmlstr_zero = {0, NULL};
2735 const WS_XML_STRING *ptr_xmlstr = &val_xmlstr, *ptr_xmlstr_null = NULL;
2736 struct
2738 WS_TYPE type;
2739 WS_WRITE_OPTION option;
2740 const void *value;
2741 ULONG size;
2742 HRESULT hr;
2743 const char *result;
2745 tests[] =
2747 { WS_INT32_TYPE, 0, NULL, 0, E_INVALIDARG },
2748 { WS_INT32_TYPE, 0, "str", 0, E_INVALIDARG },
2749 { WS_INT32_TYPE, 0, NULL, sizeof(val_int), E_INVALIDARG },
2750 { WS_INT32_TYPE, 0, &val_int, sizeof(val_int), E_INVALIDARG },
2751 { WS_INT32_TYPE, 0, &val_int_zero, sizeof(val_int_zero), E_INVALIDARG },
2752 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, 0, E_INVALIDARG },
2753 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int, 0, E_INVALIDARG },
2754 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, sizeof(val_int), E_INVALIDARG },
2755 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int, sizeof(val_int), S_OK, "<t>-1</t>" },
2756 { WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int_zero, sizeof(val_int_zero), S_OK, "<t>0</t>" },
2757 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, 0, E_INVALIDARG },
2758 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int, 0, E_INVALIDARG },
2759 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, sizeof(val_int), E_INVALIDARG },
2760 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int, sizeof(val_int), E_INVALIDARG },
2761 { WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int_zero, sizeof(val_int_zero), E_INVALIDARG },
2762 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
2763 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int, 0, E_INVALIDARG },
2764 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_int), E_INVALIDARG },
2765 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int, sizeof(ptr_int), S_OK, "<t>-1</t>" },
2766 { WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int_null, sizeof(ptr_int_null), E_INVALIDARG },
2767 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
2768 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int, 0, E_INVALIDARG },
2769 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_int), E_INVALIDARG },
2770 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int, sizeof(ptr_int), S_OK, "<t>-1</t>" },
2771 { WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int_null, sizeof(ptr_int_null), S_OK,
2772 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2773 { WS_XML_STRING_TYPE, 0, NULL, 0, E_INVALIDARG },
2774 { WS_XML_STRING_TYPE, 0, &val_xmlstr, 0, E_INVALIDARG },
2775 { WS_XML_STRING_TYPE, 0, NULL, sizeof(val_xmlstr), E_INVALIDARG },
2776 { WS_XML_STRING_TYPE, 0, &val_xmlstr, sizeof(val_xmlstr), E_INVALIDARG },
2777 { WS_XML_STRING_TYPE, 0, &val_xmlstr_zero, sizeof(val_xmlstr_zero), E_INVALIDARG },
2778 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, 0, E_INVALIDARG },
2779 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr, 0, E_INVALIDARG },
2780 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, sizeof(&val_xmlstr), E_INVALIDARG },
2781 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr, sizeof(val_xmlstr), S_OK, "<t>x</t>" },
2782 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr_zero, sizeof(val_xmlstr_zero), S_OK, "<t/>" },
2783 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr, 0, E_INVALIDARG },
2784 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, sizeof(&val_xmlstr), E_INVALIDARG },
2785 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr, sizeof(&val_xmlstr), E_INVALIDARG },
2786 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr_zero, sizeof(val_xmlstr_zero), S_OK,
2787 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2788 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
2789 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr, 0, E_INVALIDARG },
2790 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_xmlstr), E_INVALIDARG },
2791 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr, sizeof(ptr_xmlstr), S_OK, "<t>x</t>" },
2792 { WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr_null, sizeof(ptr_xmlstr_null), E_INVALIDARG },
2793 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
2794 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr, 0, E_INVALIDARG },
2795 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_xmlstr), E_INVALIDARG },
2796 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr, sizeof(ptr_xmlstr), S_OK, "<t>x</t>" },
2797 { WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr_null, sizeof(ptr_xmlstr_null), S_OK,
2798 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2799 { WS_WSZ_TYPE, 0, NULL, 0, E_INVALIDARG },
2800 { WS_WSZ_TYPE, 0, &ptr_wsz, 0, E_INVALIDARG },
2801 { WS_WSZ_TYPE, 0, NULL, sizeof(ptr_wsz), E_INVALIDARG },
2802 { WS_WSZ_TYPE, 0, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
2803 { WS_WSZ_TYPE, 0, &ptr_wsz_null, sizeof(ptr_wsz_null), E_INVALIDARG },
2804 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_VALUE, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
2805 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_VALUE, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
2806 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
2807 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz, 0, E_INVALIDARG },
2808 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_wsz), E_INVALIDARG },
2809 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz, sizeof(ptr_wsz), S_OK, "<t>s</t>" },
2810 { WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz_null, sizeof(ptr_wsz_null), E_INVALIDARG },
2811 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
2812 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz, 0, E_INVALIDARG },
2813 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_wsz), E_INVALIDARG },
2814 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz, sizeof(ptr_wsz), S_OK, "<t>s</t>" },
2815 { WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz_null, sizeof(ptr_wsz_null), S_OK,
2816 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2818 HRESULT hr;
2819 ULONG i;
2821 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2822 ok( hr == S_OK, "got %08x\n", hr );
2824 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2826 hr = set_output( writer );
2827 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2828 WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2829 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL, tests[i].option, tests[i].value,
2830 tests[i].size, NULL );
2831 ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
2832 WsWriteEndElement( writer, NULL );
2833 if (hr == S_OK) check_output( writer, tests[i].result, __LINE__ );
2836 WsFreeWriter( writer );
2839 static BOOL check_result( WS_XML_WRITER *writer, const char *expected )
2841 WS_BYTES bytes;
2842 ULONG size = sizeof(bytes);
2843 int len = strlen( expected );
2845 memset( &bytes, 0, sizeof(bytes) );
2846 WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
2847 if (bytes.length != len) return FALSE;
2848 return !memcmp( bytes.bytes, expected, len );
2851 static void test_datetime(void)
2853 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2854 static const struct
2856 unsigned __int64 ticks;
2857 WS_DATETIME_FORMAT format;
2858 HRESULT hr;
2859 const char *result;
2860 const char *result2;
2861 HRESULT hr_broken;
2863 tests[] =
2865 { 0, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0001-01-01T00:00:00Z</t>" },
2866 { 0, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T00:00:00+00:00</t>" },
2867 { 0, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00</t>" },
2868 { 1, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0001-01-01T00:00:00.0000001Z</t>" },
2869 { 1, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T00:00:00.0000001+00:00</t>" },
2870 { 1, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00.0000001</t>" },
2871 { 10, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00.000001</t>" },
2872 { 1000000, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:00.1</t>" },
2873 { 0x23c34600, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T00:01:00+00:00</t>" },
2874 { 0x861c46800, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T01:00:00+00:00</t>" },
2875 { 0x430e234000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T08:00:00+00:00</t>" },
2876 { 0x4b6fe7a800, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>0001-01-01T09:00:00+00:00</t>" },
2877 { 0x989680, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:00:01</t>" },
2878 { 0x23c34600, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T00:01:00</t>" },
2879 { 0x861c46800, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-01T01:00:00</t>" },
2880 { 0xc92a69c000, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0001-01-02T00:00:00</t>" },
2881 { 0x11ed178c6c000, WS_DATETIME_FORMAT_NONE, S_OK, "<t>0002-01-01T00:00:00</t>" },
2882 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_UTC, S_OK, "<t>9999-12-31T23:59:59.9999999Z</t>" },
2883 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>9999-12-31T15:59:59.9999999-08:00</t>",
2884 "<t>9999-12-31T17:59:59.9999999-06:00</t>" /* win7 */, WS_E_INVALID_FORMAT },
2885 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_NONE, S_OK, "<t>9999-12-31T23:59:59.9999999</t>" },
2886 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_UTC, WS_E_INVALID_FORMAT },
2887 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_LOCAL, WS_E_INVALID_FORMAT },
2888 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_NONE, WS_E_INVALID_FORMAT },
2889 { 0x8d3123e7df74000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>2015-12-31T16:00:00-08:00</t>",
2890 "<t>2015-12-31T18:00:00-06:00</t>" /* win7 */ },
2891 { 0x701ce1722770000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T00:00:00+00:00</t>" },
2892 { 0x701ce5a309a4000, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T00:00:00-08:00</t>",
2893 "<t>1601-01-01T02:00:00-06:00</t>" /* win7 */ },
2894 { 0x701ce5e617c7400, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T00:30:00-08:00</t>",
2895 "<t>1601-01-01T02:30:00-06:00</t>" /* win7 */ },
2896 { 0x701ce51ced5d800, WS_DATETIME_FORMAT_LOCAL, S_OK, "<t>1601-01-01T07:00:00+00:00</t>",
2897 "<t>1601-01-01T01:00:00-06:00</t>" /* win7 */ },
2898 { 0, WS_DATETIME_FORMAT_NONE + 1, WS_E_INVALID_FORMAT },
2899 { 0x38a080649c000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0004-02-28T00:00:00Z</t>" },
2900 { 0x38ad130b38000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>0004-02-29T00:00:00Z</t>" },
2901 { 0x8c1505f0e438000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>2000-02-29T00:00:00Z</t>" },
2902 { 0x8d46035e7870000, WS_DATETIME_FORMAT_UTC, S_OK, "<t>2017-03-01T00:00:00Z</t>" },
2904 HRESULT hr;
2905 WS_XML_WRITER *writer;
2906 WS_DATETIME date;
2907 ULONG i;
2909 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2910 ok( hr == S_OK, "got %08x\n", hr );
2911 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2913 hr = set_output( writer );
2914 ok( hr == S_OK, "got %08x\n", hr );
2916 date.ticks = tests[i].ticks;
2917 date.format = tests[i].format;
2918 WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2919 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_DATETIME_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
2920 &date, sizeof(date), NULL );
2921 WsWriteEndElement( writer, NULL );
2922 ok( hr == tests[i].hr || broken(hr == tests[i].hr_broken), "%u: got %08x\n", i, hr );
2923 if (hr != tests[i].hr && hr == tests[i].hr_broken) break;
2924 if (hr == S_OK)
2926 ok( check_result( writer, tests[i].result ) ||
2927 (tests[i].result2 && broken(check_result( writer, tests[i].result2 ))),
2928 "%u: wrong result\n", i );
2932 WsFreeWriter( writer );
2935 static void test_repeating_element(void)
2937 static const WCHAR oneW[] = {'1',0}, twoW[] = {'2',0};
2938 WS_XML_STRING localname = {4, (BYTE *)"test"}, ns = {0, NULL};
2939 WS_XML_STRING val = {3, (BYTE *)"val"}, wrapper = {7, (BYTE *)"wrapper"};
2940 HRESULT hr;
2941 WS_XML_WRITER *writer;
2942 WS_STRUCT_DESCRIPTION s;
2943 WS_FIELD_DESCRIPTION f, *fields[1];
2944 WS_ITEM_RANGE range;
2945 struct test
2947 const WCHAR **val;
2948 ULONG count;
2949 } *test;
2950 struct test2
2952 INT32 *val;
2953 ULONG count;
2954 } *test2;
2956 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2957 ok( hr == S_OK, "got %08x\n", hr );
2959 /* array of strings, wrapper */
2960 hr = set_output( writer );
2961 ok( hr == S_OK, "got %08x\n", hr );
2962 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2963 ok( hr == S_OK, "got %08x\n", hr );
2965 memset( &f, 0, sizeof(f) );
2966 f.mapping = WS_REPEATING_ELEMENT_FIELD_MAPPING;
2967 f.localName = &wrapper;
2968 f.ns = &ns;
2969 f.type = WS_WSZ_TYPE;
2970 f.countOffset = FIELD_OFFSET(struct test, count);
2971 f.itemLocalName = &val;
2972 f.itemNs = &ns;
2973 fields[0] = &f;
2975 memset( &s, 0, sizeof(s) );
2976 s.size = sizeof(struct test);
2977 s.alignment = TYPE_ALIGNMENT(struct test);
2978 s.typeLocalName = &localname;
2979 s.typeNs = &ns;
2980 s.fields = fields;
2981 s.fieldCount = 1;
2983 hr = set_output( writer );
2984 ok( hr == S_OK, "got %08x\n", hr );
2985 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2986 ok( hr == S_OK, "got %08x\n", hr );
2988 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) + 2 * sizeof(const WCHAR *) );
2989 test->val = (const WCHAR **)(test + 1);
2990 test->val[0] = oneW;
2991 test->val[1] = twoW;
2992 test->count = 2;
2993 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
2994 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
2995 ok( hr == S_OK, "got %08x\n", hr );
2996 hr = WsWriteEndElement( writer, NULL );
2997 ok( hr == S_OK, "got %08x\n", hr );
2998 check_output( writer, "<test><wrapper><val>1</val><val>2</val></wrapper></test>", __LINE__ );
2999 HeapFree( GetProcessHeap(), 0, test );
3001 /* array of integers, no wrapper */
3002 hr = set_output( writer );
3003 ok( hr == S_OK, "got %08x\n", hr );
3004 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3005 ok( hr == S_OK, "got %08x\n", hr );
3007 f.type = WS_INT32_TYPE;
3008 f.localName = NULL;
3009 f.ns = NULL;
3011 test2 = HeapAlloc( GetProcessHeap(), 0, sizeof(*test2) + 2 * sizeof(INT32) );
3012 test2->val = (INT32 *)(test2 + 1);
3013 test2->val[0] = 1;
3014 test2->val[1] = 2;
3015 test2->count = 2;
3016 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
3017 WS_WRITE_REQUIRED_POINTER, &test2, sizeof(test2), NULL );
3018 ok( hr == S_OK, "got %08x\n", hr );
3019 hr = WsWriteEndElement( writer, NULL );
3020 ok( hr == S_OK, "got %08x\n", hr );
3021 check_output( writer, "<test><val>1</val><val>2</val></test>", __LINE__ );
3023 /* item range has no effect */
3024 hr = set_output( writer );
3025 ok( hr == S_OK, "got %08x\n", hr );
3026 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3027 ok( hr == S_OK, "got %08x\n", hr );
3029 range.minItemCount = 0;
3030 range.maxItemCount = 0;
3031 f.itemRange = &range;
3033 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
3034 WS_WRITE_REQUIRED_POINTER, &test2, sizeof(test2), NULL );
3035 ok( hr == S_OK, "got %08x\n", hr );
3036 hr = WsWriteEndElement( writer, NULL );
3037 ok( hr == S_OK, "got %08x\n", hr );
3038 check_output( writer, "<test><val>1</val><val>2</val></test>", __LINE__ );
3039 HeapFree( GetProcessHeap(), 0, test2 );
3041 WsFreeWriter( writer );
3044 static const WS_XML_STRING *init_xmlstring( const char *src, WS_XML_STRING *str )
3046 if (!src) return NULL;
3047 str->length = strlen( src );
3048 str->bytes = (BYTE *)src;
3049 return str;
3052 static void test_WsWriteQualifiedName(void)
3054 WS_XML_STRING prefix = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
3055 WS_XML_WRITER *writer;
3056 HRESULT hr;
3057 ULONG i;
3058 static const struct
3060 const char *prefix;
3061 const char *localname;
3062 const char *ns;
3063 HRESULT hr;
3064 const char *result;
3065 } tests[] =
3067 { NULL, NULL, NULL, E_INVALIDARG, NULL },
3068 { NULL, "t2", NULL, E_INVALIDARG, NULL },
3069 { "p2", "t2", NULL, S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3070 { NULL, "t2", "ns2", WS_E_INVALID_FORMAT, NULL },
3071 { NULL, "t2", "ns", S_OK, "<p:t xmlns:p=\"ns\">p:t2" },
3072 { "p2", "t2", "ns2", S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3073 { "p2", "t2", "ns", S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3074 { "p", "t", NULL, S_OK, "<p:t xmlns:p=\"ns\">p:t" },
3075 { NULL, "t", "ns", S_OK, "<p:t xmlns:p=\"ns\">p:t" },
3076 { "p2", "", "", S_OK, "<p:t xmlns:p=\"ns\">p2:" },
3077 { "p2", "", "ns2", S_OK, "<p:t xmlns:p=\"ns\">p2:" },
3078 { "p2", "t2", "", S_OK, "<p:t xmlns:p=\"ns\">p2:t2" },
3079 { "", "t2", "", S_OK, "<p:t xmlns:p=\"ns\">t2" },
3080 { "", "", "ns2", S_OK, "<p:t xmlns:p=\"ns\">" },
3081 { "", "", "", S_OK, "<p:t xmlns:p=\"ns\">" },
3084 hr = WsWriteQualifiedName( NULL, NULL, NULL, NULL, NULL );
3085 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3087 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3088 ok( hr == S_OK, "got %08x\n", hr );
3090 hr = WsWriteQualifiedName( writer, NULL, NULL, NULL, NULL );
3091 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3093 hr = set_output( writer );
3094 ok( hr == S_OK, "got %08x\n", hr );
3096 hr = WsWriteQualifiedName( writer, NULL, NULL, NULL, NULL );
3097 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3099 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
3101 WS_XML_STRING prefix2, localname2, ns2;
3102 const WS_XML_STRING *prefix_ptr, *localname_ptr, *ns_ptr;
3104 hr = set_output( writer );
3105 ok( hr == S_OK, "%u: got %08x\n", i, hr );
3107 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
3108 ok( hr == S_OK, "%u: got %08x\n", i, hr );
3110 prefix_ptr = init_xmlstring( tests[i].prefix, &prefix2 );
3111 localname_ptr = init_xmlstring( tests[i].localname, &localname2 );
3112 ns_ptr = init_xmlstring( tests[i].ns, &ns2 );
3114 hr = WsWriteQualifiedName( writer, prefix_ptr, localname_ptr, ns_ptr, NULL );
3115 ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
3116 if (tests[i].hr == S_OK && hr == S_OK) check_output( writer, tests[i].result, __LINE__ );
3119 WsFreeWriter( writer );
3122 static void test_WsWriteBytes(void)
3124 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
3125 WS_XML_WRITER *writer;
3126 HRESULT hr;
3128 hr = WsWriteBytes( NULL, NULL, 0, NULL );
3129 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3131 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3132 ok( hr == S_OK, "got %08x\n", hr );
3134 hr = WsWriteBytes( writer, NULL, 0, NULL );
3135 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3137 hr = WsWriteBytes( writer, "test", 0, NULL );
3138 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3140 hr = WsWriteBytes( writer, NULL, 1, NULL );
3141 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3143 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3144 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3146 hr = set_output( writer );
3147 ok( hr == S_OK, "got %08x\n", hr );
3149 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3150 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3152 hr = set_output( writer );
3153 ok( hr == S_OK, "got %08x\n", hr );
3155 /* element */
3156 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3157 ok( hr == S_OK, "got %08x\n", hr );
3159 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3160 ok( hr == S_OK, "got %08x\n", hr );
3162 hr = WsWriteEndElement( writer, NULL );
3163 ok( hr == S_OK, "got %08x\n", hr );
3164 check_output( writer, "<t>dGVzdAA=</t>", __LINE__ );
3166 hr = set_output( writer );
3167 ok( hr == S_OK, "got %08x\n", hr );
3169 /* attribute */
3170 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3171 ok( hr == S_OK, "got %08x\n", hr );
3173 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
3174 ok( hr == S_OK, "got %08x\n", hr );
3176 hr = WsWriteBytes( writer, "test", sizeof("test"), NULL );
3177 ok( hr == S_OK, "got %08x\n", hr );
3179 hr = WsWriteEndAttribute( writer, NULL );
3180 ok( hr == S_OK, "got %08x\n", hr );
3182 hr = WsWriteEndElement( writer, NULL );
3183 ok( hr == S_OK, "got %08x\n", hr );
3184 check_output( writer, "<t a=\"dGVzdAA=\"/>", __LINE__ );
3186 WsFreeWriter( writer );
3189 static void test_WsWriteChars(void)
3191 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
3192 static const WCHAR testW[] = {'t','e','s','t'};
3193 WS_XML_WRITER *writer;
3194 HRESULT hr;
3196 hr = WsWriteChars( NULL, NULL, 0, NULL );
3197 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3199 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3200 ok( hr == S_OK, "got %08x\n", hr );
3202 hr = WsWriteChars( writer, NULL, 0, NULL );
3203 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3205 hr = WsWriteChars( writer, testW, 0, NULL );
3206 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3208 hr = WsWriteChars( writer, NULL, 1, NULL );
3209 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3211 hr = WsWriteChars( writer, testW, 4, NULL );
3212 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3214 hr = set_output( writer );
3215 ok( hr == S_OK, "got %08x\n", hr );
3217 hr = WsWriteChars( writer, testW, 4, NULL );
3218 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3220 hr = set_output( writer );
3221 ok( hr == S_OK, "got %08x\n", hr );
3223 /* element */
3224 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3225 ok( hr == S_OK, "got %08x\n", hr );
3227 hr = WsWriteChars( writer, testW, 4, NULL );
3228 ok( hr == S_OK, "got %08x\n", hr );
3230 hr = WsWriteChars( writer, testW, 4, NULL );
3231 ok( hr == S_OK, "got %08x\n", hr );
3233 hr = WsWriteEndElement( writer, NULL );
3234 ok( hr == S_OK, "got %08x\n", hr );
3235 check_output( writer, "<t>testtest</t>", __LINE__ );
3237 hr = set_output( writer );
3238 ok( hr == S_OK, "got %08x\n", hr );
3240 /* attribute */
3241 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3242 ok( hr == S_OK, "got %08x\n", hr );
3244 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
3245 ok( hr == S_OK, "got %08x\n", hr );
3247 hr = WsWriteChars( writer, testW, 4, NULL );
3248 ok( hr == S_OK, "got %08x\n", hr );
3250 hr = WsWriteChars( writer, testW, 4, NULL );
3251 ok( hr == S_OK, "got %08x\n", hr );
3253 hr = WsWriteEndAttribute( writer, NULL );
3254 ok( hr == S_OK, "got %08x\n", hr );
3256 hr = WsWriteEndElement( writer, NULL );
3257 ok( hr == S_OK, "got %08x\n", hr );
3258 check_output( writer, "<t a=\"testtest\"/>", __LINE__ );
3260 WsFreeWriter( writer );
3263 static void test_WsWriteCharsUtf8(void)
3265 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"a"}, ns = {0, NULL};
3266 static const BYTE test[] = {'t','e','s','t'};
3267 WS_XML_WRITER *writer;
3268 HRESULT hr;
3270 hr = WsWriteCharsUtf8( NULL, NULL, 0, NULL );
3271 ok( hr == E_INVALIDARG, "got %08x\n", hr );
3273 hr = WsCreateWriter( NULL, 0, &writer, NULL );
3274 ok( hr == S_OK, "got %08x\n", hr );
3276 hr = WsWriteCharsUtf8( writer, NULL, 0, NULL );
3277 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3279 hr = WsWriteCharsUtf8( writer, test, 0, NULL );
3280 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3282 hr = WsWriteCharsUtf8( writer, NULL, 1, NULL );
3283 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3285 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3286 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
3288 hr = set_output( writer );
3289 ok( hr == S_OK, "got %08x\n", hr );
3291 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3292 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
3294 hr = set_output( writer );
3295 ok( hr == S_OK, "got %08x\n", hr );
3297 /* element */
3298 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3299 ok( hr == S_OK, "got %08x\n", hr );
3301 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3302 ok( hr == S_OK, "got %08x\n", hr );
3304 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3305 ok( hr == S_OK, "got %08x\n", hr );
3307 hr = WsWriteEndElement( writer, NULL );
3308 ok( hr == S_OK, "got %08x\n", hr );
3309 check_output( writer, "<t>testtest</t>", __LINE__ );
3311 hr = set_output( writer );
3312 ok( hr == S_OK, "got %08x\n", hr );
3314 /* attribute */
3315 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
3316 ok( hr == S_OK, "got %08x\n", hr );
3318 hr = WsWriteStartAttribute( writer, NULL, &localname2, &ns, FALSE, NULL );
3319 ok( hr == S_OK, "got %08x\n", hr );
3321 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3322 ok( hr == S_OK, "got %08x\n", hr );
3324 hr = WsWriteCharsUtf8( writer, test, sizeof(test), NULL );
3325 ok( hr == S_OK, "got %08x\n", hr );
3327 hr = WsWriteEndAttribute( writer, NULL );
3328 ok( hr == S_OK, "got %08x\n", hr );
3330 hr = WsWriteEndElement( writer, NULL );
3331 ok( hr == S_OK, "got %08x\n", hr );
3332 check_output( writer, "<t a=\"testtest\"/>", __LINE__ );
3334 WsFreeWriter( writer );
3337 START_TEST(writer)
3339 test_WsCreateWriter();
3340 test_WsCreateXmlBuffer();
3341 test_WsSetOutput();
3342 test_WsSetOutputToBuffer();
3343 test_WsWriteStartElement();
3344 test_WsWriteStartAttribute();
3345 test_WsWriteType();
3346 test_basic_type();
3347 test_simple_struct_type();
3348 test_WsWriteElement();
3349 test_WsWriteValue();
3350 test_WsWriteAttribute();
3351 test_WsWriteStartCData();
3352 test_WsWriteXmlnsAttribute();
3353 test_WsGetPrefixFromNamespace();
3354 test_complex_struct_type();
3355 test_WsMoveWriter();
3356 test_WsGetWriterPosition();
3357 test_WsSetWriterPosition();
3358 test_WsWriteXmlBuffer();
3359 test_WsWriteNode();
3360 test_WsCopyNode();
3361 test_text_types();
3362 test_double();
3363 test_field_options();
3364 test_WsWriteText();
3365 test_WsWriteArray();
3366 test_escapes();
3367 test_write_option();
3368 test_datetime();
3369 test_repeating_element();
3370 test_WsWriteQualifiedName();
3371 test_WsWriteBytes();
3372 test_WsWriteChars();
3373 test_WsWriteCharsUtf8();