webservices: Implement WsWriteArray.
[wine.git] / dlls / webservices / tests / writer.c
blob80b9f43d98faf110326a8b0672151d6c718c8fe4
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 void check_output( WS_XML_WRITER *writer, const char *expected, unsigned int line )
344 WS_BYTES bytes;
345 ULONG size = sizeof(bytes);
346 int len = strlen( expected );
347 HRESULT hr;
349 memset( &bytes, 0, sizeof(bytes) );
350 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
351 ok( hr == S_OK, "%u: got %08x\n", line, hr );
352 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
353 if (bytes.length != len) return;
354 ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
357 static void test_WsWriteStartElement(void)
359 HRESULT hr;
360 WS_XML_WRITER *writer;
361 WS_XML_STRING prefix = {1, (BYTE *)"p"}, ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
362 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"};
364 hr = WsCreateWriter( NULL, 0, &writer, NULL );
365 ok( hr == S_OK, "got %08x\n", hr );
367 hr = set_output( writer );
368 ok( hr == S_OK, "got %08x\n", hr );
370 hr = WsWriteStartElement( NULL, &prefix, &localname, &ns, NULL );
371 ok( hr == E_INVALIDARG, "got %08x\n", hr );
373 /* first call to WsWriteStartElement doesn't output anything */
374 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
375 ok( hr == S_OK, "got %08x\n", hr );
376 check_output( writer, "", __LINE__ );
378 /* two ways to close an element */
379 hr = WsWriteEndStartElement( writer, NULL );
380 ok( hr == S_OK, "got %08x\n", hr );
381 check_output( writer, "<p:a xmlns:p=\"ns\">", __LINE__ );
383 hr = WsWriteEndElement( writer, NULL );
384 ok( hr == S_OK, "got %08x\n", hr );
385 check_output( writer, "<p:a xmlns:p=\"ns\"></p:a>", __LINE__ );
387 hr = set_output( writer );
388 ok( hr == S_OK, "got %08x\n", hr );
390 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
391 ok( hr == S_OK, "got %08x\n", hr );
393 hr = WsWriteEndElement( writer, NULL );
394 ok( hr == S_OK, "got %08x\n", hr );
395 check_output( writer, "<p:a xmlns:p=\"ns\"/>", __LINE__ );
397 /* nested elements */
398 hr = set_output( writer );
399 ok( hr == S_OK, "got %08x\n", hr );
401 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
402 ok( hr == S_OK, "got %08x\n", hr );
403 check_output( writer, "", __LINE__ );
405 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
406 ok( hr == S_OK, "got %08x\n", hr );
407 check_output( writer, "<p:a xmlns:p=\"ns\">", __LINE__ );
409 hr = WsWriteEndElement( writer, NULL );
410 ok( hr == S_OK, "got %08x\n", hr );
411 check_output( writer, "<p:a xmlns:p=\"ns\"><p:b/>", __LINE__ );
413 hr = WsWriteEndElement( writer, NULL );
414 ok( hr == S_OK, "got %08x\n", hr );
415 check_output( writer, "<p:a xmlns:p=\"ns\"><p:b/></p:a>", __LINE__ );
417 hr = set_output( writer );
418 ok( hr == S_OK, "got %08x\n", hr );
420 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
421 ok( hr == S_OK, "got %08x\n", hr );
422 check_output( writer, "", __LINE__ );
424 hr = WsWriteStartElement( writer, NULL, &localname2, &ns2, NULL );
425 ok( hr == S_OK, "got %08x\n", hr );
426 check_output( writer, "<p:a xmlns:p=\"ns\">", __LINE__ );
428 hr = WsWriteEndElement( writer, NULL );
429 ok( hr == S_OK, "got %08x\n", hr );
430 check_output( writer, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/>", __LINE__ );
432 hr = WsWriteEndElement( writer, NULL );
433 ok( hr == S_OK, "got %08x\n", hr );
434 check_output( writer, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/></p:a>", __LINE__ );
436 WsFreeWriter( writer );
439 static void test_WsWriteStartAttribute(void)
441 HRESULT hr;
442 WS_XML_WRITER *writer;
443 WS_XML_STRING prefix = {1, (BYTE *)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
444 WS_XML_UTF8_TEXT text;
446 hr = WsCreateWriter( NULL, 0, &writer, NULL );
447 ok( hr == S_OK, "got %08x\n", hr );
449 hr = set_output( writer );
450 ok( hr == S_OK, "got %08x\n", hr );
452 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
453 ok( hr == S_OK, "got %08x\n", hr );
455 hr = WsWriteStartAttribute( NULL, &prefix, &localname, &ns, FALSE, NULL );
456 ok( hr == E_INVALIDARG, "got %08x\n", hr );
458 /* WsWriteStartAttribute doesn't output anything */
459 localname.length = 3;
460 localname.bytes = (BYTE *)"len";
461 hr = WsWriteStartAttribute( writer, &prefix, &localname, &ns, FALSE, NULL );
462 ok( hr == S_OK, "got %08x\n", hr );
463 check_output( writer, "", __LINE__ );
465 text.text.textType = WS_XML_TEXT_TYPE_UTF8;
466 text.value.length = 1;
467 text.value.bytes = (BYTE *)"0";
468 text.value.dictionary = NULL;
469 hr = WsWriteText( writer, &text.text, NULL );
470 ok( hr == S_OK, "got %08x\n", hr );
471 check_output( writer, "", __LINE__ );
473 /* WsWriteEndAttribute doesn't output anything */
474 hr = WsWriteEndAttribute( writer, NULL );
475 ok( hr == S_OK, "got %08x\n", hr );
476 check_output( writer, "", __LINE__ );
478 hr = WsWriteEndElement( writer, NULL );
479 ok( hr == S_OK, "got %08x\n", hr );
480 check_output( writer, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__ );
482 WsFreeWriter( writer );
485 static void test_WsWriteType(void)
487 static const WCHAR testW[] = {'t','e','s','t',0};
488 HRESULT hr;
489 WS_XML_WRITER *writer;
490 WS_XML_STRING prefix = {1, (BYTE*)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
491 const WCHAR *val_str;
493 hr = WsCreateWriter( NULL, 0, &writer, NULL );
494 ok( hr == S_OK, "got %08x\n", hr );
496 hr = set_output( writer );
497 ok( hr == S_OK, "got %08x\n", hr );
499 val_str = testW;
500 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
501 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
502 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
504 hr = set_output( writer );
505 ok( hr == S_OK, "got %08x\n", hr );
507 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
508 ok( hr == S_OK, "got %08x\n", hr );
510 /* required value */
511 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
512 WS_WRITE_REQUIRED_VALUE, NULL, sizeof(testW), NULL );
513 ok( hr == E_INVALIDARG, "got %08x\n", hr );
515 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
516 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
517 ok( hr == E_INVALIDARG, "got %08x\n", hr );
519 /* required pointer */
520 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
521 WS_WRITE_REQUIRED_POINTER, NULL, sizeof(val_str), NULL );
522 ok( hr == E_INVALIDARG, "got %08x\n", hr );
524 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
525 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
526 ok( hr == E_INVALIDARG, "got %08x\n", hr );
528 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
529 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(WCHAR **), NULL );
530 ok( hr == S_OK, "got %08x\n", hr );
531 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
533 hr = WsWriteEndElement( writer, NULL );
534 ok( hr == S_OK, "got %08x\n", hr );
535 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
537 hr = set_output( writer );
538 ok( hr == S_OK, "got %08x\n", hr );
540 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
541 ok( hr == S_OK, "got %08x\n", hr );
543 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
544 ok( hr == S_OK, "got %08x\n", hr );
546 val_str = testW;
547 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
548 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
549 ok( hr == S_OK, "got %08x\n", hr );
550 check_output( writer, "", __LINE__ );
552 hr = WsWriteEndAttribute( writer, NULL );
553 ok( hr == S_OK, "got %08x\n", hr );
554 check_output( writer, "", __LINE__ );
556 hr = WsWriteEndElement( writer, NULL );
557 ok( hr == S_OK, "got %08x\n", hr );
558 check_output( writer, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__ );
560 hr = set_output( writer );
561 ok( hr == S_OK, "got %08x\n", hr );
563 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
564 ok( hr == S_OK, "got %08x\n", hr );
566 val_str = testW;
567 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
568 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
569 ok( hr == S_OK, "got %08x\n", hr );
570 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
572 hr = WsWriteEndElement( writer, NULL );
573 ok( hr == S_OK, "got %08x\n", hr );
574 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
576 WsFreeWriter( writer );
579 static void test_basic_type(void)
581 static WCHAR testW[] = {'t','e','s','t',0};
582 HRESULT hr;
583 WS_XML_WRITER *writer;
584 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, xmlstr;
585 GUID guid;
586 WCHAR *str;
587 WS_STRING string;
588 ULONG i;
589 static const struct
591 WS_TYPE type;
592 INT64 val;
593 ULONG size;
594 const char *result;
595 const char *result2;
597 tests[] =
599 { WS_BOOL_TYPE, TRUE, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
600 { WS_BOOL_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
601 { WS_INT8_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
602 { WS_INT16_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
603 { WS_INT32_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
604 "<t t=\"-2147483648\"/>" },
605 { WS_INT64_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
606 "<t t=\"-9223372036854775808\"/>" },
607 { WS_UINT8_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
608 { WS_UINT16_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
609 { WS_UINT32_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
610 { WS_UINT64_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
611 "<t t=\"18446744073709551615\"/>" },
614 hr = WsCreateWriter( NULL, 0, &writer, NULL );
615 ok( hr == S_OK, "got %08x\n", hr );
617 /* element content type mapping */
618 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
620 hr = set_output( writer );
621 ok( hr == S_OK, "got %08x\n", hr );
623 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
624 ok( hr == S_OK, "got %08x\n", hr );
626 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
627 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
628 ok( hr == S_OK, "%u: got %08x\n", i, hr );
630 hr = WsWriteEndElement( writer, NULL );
631 ok( hr == S_OK, "got %08x\n", hr );
632 check_output( writer, tests[i].result, __LINE__ );
635 /* element type mapping is the same as element content type mapping for basic types */
636 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
638 const INT64 *ptr = &tests[i].val;
640 hr = set_output( writer );
641 ok( hr == S_OK, "got %08x\n", hr );
643 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
644 ok( hr == S_OK, "got %08x\n", hr );
646 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
647 WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
648 ok( hr == S_OK, "%u: got %08x\n", i, hr );
650 hr = WsWriteEndElement( writer, NULL );
651 ok( hr == S_OK, "got %08x\n", hr );
652 check_output( writer, tests[i].result, __LINE__ );
655 /* attribute type mapping */
656 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
658 hr = set_output( writer );
659 ok( hr == S_OK, "got %08x\n", hr );
661 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
662 ok( hr == S_OK, "got %08x\n", hr );
664 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
665 ok( hr == S_OK, "got %08x\n", hr );
667 hr = WsWriteType( writer, WS_ATTRIBUTE_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 = WsWriteEndAttribute( writer, NULL );
672 ok( hr == S_OK, "got %08x\n", hr );
674 hr = WsWriteEndElement( writer, NULL );
675 ok( hr == S_OK, "got %08x\n", hr );
676 check_output( writer, tests[i].result2, __LINE__ );
679 hr = set_output( writer );
680 ok( hr == S_OK, "got %08x\n", hr );
682 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
683 ok( hr == S_OK, "got %08x\n", hr );
685 memset( &guid, 0, sizeof(guid) );
686 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
687 &guid, sizeof(guid), NULL );
688 ok( hr == S_OK, "got %08x\n", hr );
690 hr = WsWriteEndElement( writer, NULL );
691 ok( hr == S_OK, "got %08x\n", hr );
692 check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
694 hr = set_output( writer );
695 ok( hr == S_OK, "got %08x\n", hr );
697 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
698 ok( hr == S_OK, "got %08x\n", hr );
700 string.chars = testW;
701 string.length = 4;
702 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
703 &string, sizeof(string), NULL );
704 ok( hr == S_OK, "got %08x\n", hr );
706 hr = WsWriteEndElement( writer, NULL );
707 ok( hr == S_OK, "got %08x\n", hr );
708 check_output( writer, "<t>test</t>", __LINE__ );
710 hr = set_output( writer );
711 ok( hr == S_OK, "got %08x\n", hr );
713 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
714 ok( hr == S_OK, "got %08x\n", hr );
716 str = testW;
717 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
718 &str, sizeof(str), NULL );
719 ok( hr == S_OK, "got %08x\n", hr );
721 hr = WsWriteEndElement( writer, NULL );
722 ok( hr == S_OK, "got %08x\n", hr );
723 check_output( writer, "<t>test</t>", __LINE__ );
725 hr = set_output( writer );
726 ok( hr == S_OK, "got %08x\n", hr );
728 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
729 ok( hr == S_OK, "got %08x\n", hr );
731 xmlstr.bytes = (BYTE *)"test";
732 xmlstr.length = 4;
733 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
734 &xmlstr, sizeof(xmlstr), NULL );
735 ok( hr == S_OK, "got %08x\n", hr );
737 hr = WsWriteEndElement( writer, NULL );
738 ok( hr == S_OK, "got %08x\n", hr );
739 check_output( writer, "<t>test</t>", __LINE__ );
741 WsFreeWriter( writer );
744 static void test_simple_struct_type(void)
746 static const WCHAR valueW[] = {'v','a','l','u','e',0};
747 HRESULT hr;
748 WS_XML_WRITER *writer;
749 WS_STRUCT_DESCRIPTION s;
750 WS_FIELD_DESCRIPTION f, *fields[1];
751 WS_XML_STRING localname = {6, (BYTE *)"struct"}, ns = {0, NULL};
752 struct test
754 const WCHAR *field;
755 } *test;
757 hr = WsCreateWriter( NULL, 0, &writer, NULL );
758 ok( hr == S_OK, "got %08x\n", hr );
760 hr = set_output( writer );
761 ok( hr == S_OK, "got %08x\n", hr );
763 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
764 ok( hr == S_OK, "got %08x\n", hr );
766 memset( &f, 0, sizeof(f) );
767 f.mapping = WS_TEXT_FIELD_MAPPING;
768 f.type = WS_WSZ_TYPE;
769 fields[0] = &f;
771 memset( &s, 0, sizeof(s) );
772 s.size = sizeof(struct test);
773 s.alignment = TYPE_ALIGNMENT(struct test);
774 s.fields = fields;
775 s.fieldCount = 1;
777 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
778 test->field = valueW;
779 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
780 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
781 ok( hr == E_INVALIDARG, "got %08x\n", hr );
783 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
784 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
785 ok( hr == E_INVALIDARG, "got %08x\n", hr );
787 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
788 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
789 ok( hr == S_OK, "got %08x\n", hr );
791 hr = WsWriteEndElement( writer, NULL );
792 ok( hr == S_OK, "got %08x\n", hr );
793 check_output( writer, "<struct>value</struct>", __LINE__ );
795 /* required value */
796 hr = set_output( writer );
797 ok( hr == S_OK, "got %08x\n", hr );
799 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
800 ok( hr == S_OK, "got %08x\n", hr );
802 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
803 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
804 ok( hr == S_OK, "got %08x\n", hr );
806 hr = WsWriteEndElement( writer, NULL );
807 ok( hr == S_OK, "got %08x\n", hr );
808 check_output( writer, "<struct>value</struct>", __LINE__ );
810 hr = set_output( writer );
811 ok( hr == S_OK, "got %08x\n", hr );
813 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
814 ok( hr == S_OK, "got %08x\n", hr );
816 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
817 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
818 ok( hr == S_OK, "got %08x\n", hr );
820 hr = WsWriteEndElement( writer, NULL );
821 ok( hr == S_OK, "got %08x\n", hr );
822 check_output( writer, "<struct>value</struct>", __LINE__ );
824 hr = set_output( writer );
825 ok( hr == S_OK, "got %08x\n", hr );
827 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
828 ok( hr == S_OK, "got %08x\n", hr );
830 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
831 ok( hr == S_OK, "got %08x\n", hr );
833 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
834 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
835 ok( hr == S_OK, "got %08x\n", hr );
837 hr = WsWriteEndAttribute( writer, NULL );
838 ok( hr == S_OK, "got %08x\n", hr );
840 hr = WsWriteEndElement( writer, NULL );
841 ok( hr == S_OK, "got %08x\n", hr );
842 check_output( writer, "<struct struct=\"value\"/>", __LINE__ );
844 HeapFree( GetProcessHeap(), 0, test );
845 WsFreeWriter( writer );
848 static void test_WsWriteElement(void)
850 static const WCHAR testW[] = {'t','e','s','t',0};
851 HRESULT hr;
852 WS_XML_WRITER *writer;
853 WS_STRUCT_DESCRIPTION s;
854 WS_FIELD_DESCRIPTION f, *fields[1];
855 WS_ELEMENT_DESCRIPTION desc;
856 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
857 struct test { const WCHAR *str; } *test;
859 hr = WsCreateWriter( NULL, 0, &writer, NULL );
860 ok( hr == S_OK, "got %08x\n", hr );
862 hr = set_output( writer );
863 ok( hr == S_OK, "got %08x\n", hr );
865 /* text field mapping */
866 memset( &f, 0, sizeof(f) );
867 f.mapping = WS_TEXT_FIELD_MAPPING;
868 f.type = WS_WSZ_TYPE;
869 fields[0] = &f;
871 memset( &s, 0, sizeof(s) );
872 s.size = sizeof(struct test);
873 s.alignment = TYPE_ALIGNMENT(struct test);
874 s.fields = fields;
875 s.fieldCount = 1;
877 desc.elementLocalName = &localname;
878 desc.elementNs = &ns;
879 desc.type = WS_STRUCT_TYPE;
880 desc.typeDescription = &s;
882 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
883 test->str = testW;
884 hr = WsWriteElement( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
885 ok( hr == E_INVALIDARG, "got %08x\n", hr );
887 hr = WsWriteElement( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
888 ok( hr == E_INVALIDARG, "got %08x\n", hr );
890 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
891 ok( hr == E_INVALIDARG, "got %08x\n", hr );
893 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
894 ok( hr == S_OK, "got %08x\n", hr );
895 check_output( writer, "<str>test</str>", __LINE__ );
897 hr = set_output( writer );
898 ok( hr == S_OK, "got %08x\n", hr );
900 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
901 ok( hr == S_OK, "got %08x\n", hr );
903 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
904 ok( hr == S_OK, "got %08x\n", hr );
905 check_output( writer, "<str><str>test</str>", __LINE__ );
907 hr = set_output( writer );
908 ok( hr == S_OK, "got %08x\n", hr );
910 /* attribute field mapping */
911 f.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
913 /* requires localName and ns to be set */
914 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
915 ok( hr == E_INVALIDARG, "got %08x\n", hr );
917 hr = set_output( writer );
918 ok( hr == S_OK, "got %08x\n", hr );
920 f.localName = &localname;
921 f.ns = &ns;
922 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
923 ok( hr == S_OK, "got %08x\n", hr );
924 check_output( writer, "<str str=\"test\"/>", __LINE__ );
926 HeapFree( GetProcessHeap(), 0, test );
927 WsFreeWriter( writer );
930 static void test_WsWriteValue(void)
932 HRESULT hr;
933 WS_XML_WRITER *writer;
934 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
935 ULONG i;
936 static const struct
938 WS_VALUE_TYPE type;
939 INT64 val;
940 ULONG size;
941 const char *result;
942 const char *result2;
944 tests[] =
946 { WS_BOOL_VALUE_TYPE, ~0, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
947 { WS_BOOL_VALUE_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
948 { WS_INT8_VALUE_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
949 { WS_INT16_VALUE_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
950 { WS_INT32_VALUE_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
951 "<t t=\"-2147483648\"/>" },
952 { WS_INT64_VALUE_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
953 "<t t=\"-9223372036854775808\"/>" },
954 { WS_UINT8_VALUE_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
955 { WS_UINT16_VALUE_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
956 { WS_UINT32_VALUE_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
957 { WS_UINT64_VALUE_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
958 "<t t=\"18446744073709551615\"/>" },
961 hr = WsCreateWriter( NULL, 0, &writer, NULL );
962 ok( hr == S_OK, "got %08x\n", hr );
964 hr = set_output( writer );
965 ok( hr == S_OK, "got %08x\n", hr );
967 hr = WsWriteValue( NULL, tests[0].type, &tests[0].val, tests[0].size, NULL );
968 ok( hr == E_INVALIDARG, "got %08x\n", hr );
970 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, tests[0].size, NULL );
971 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
973 hr = set_output( writer );
974 ok( hr == S_OK, "got %08x\n", hr );
976 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
977 ok( hr == S_OK, "got %08x\n", hr );
979 /* zero size */
980 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, 0, NULL );
981 ok( hr == E_INVALIDARG, "got %08x\n", hr );
983 hr = set_output( writer );
984 ok( hr == S_OK, "got %08x\n", hr );
986 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
987 ok( hr == S_OK, "got %08x\n", hr );
989 /* NULL value */
990 hr = WsWriteValue( writer, tests[0].type, NULL, 0, NULL );
991 ok( hr == E_INVALIDARG, "got %08x\n", hr );
993 /* element type mapping */
994 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
996 hr = set_output( writer );
997 ok( hr == S_OK, "got %08x\n", hr );
999 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1000 ok( hr == S_OK, "got %08x\n", hr );
1002 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1003 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1005 hr = WsWriteEndElement( writer, NULL );
1006 ok( hr == S_OK, "got %08x\n", hr );
1007 check_output( writer, tests[i].result, __LINE__ );
1010 /* attribute type mapping */
1011 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1013 hr = set_output( writer );
1014 ok( hr == S_OK, "got %08x\n", hr );
1016 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1017 ok( hr == S_OK, "got %08x\n", hr );
1019 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
1020 ok( hr == S_OK, "got %08x\n", hr );
1022 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1023 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1025 hr = WsWriteEndAttribute( writer, NULL );
1026 ok( hr == S_OK, "got %08x\n", hr );
1028 hr = WsWriteEndElement( writer, NULL );
1029 ok( hr == S_OK, "got %08x\n", hr );
1030 check_output( writer, tests[i].result2, __LINE__ );
1033 WsFreeWriter( writer );
1036 static void test_WsWriteAttribute(void)
1038 static const WCHAR testW[] = {'t','e','s','t',0};
1039 HRESULT hr;
1040 WS_XML_WRITER *writer;
1041 WS_STRUCT_DESCRIPTION s;
1042 WS_FIELD_DESCRIPTION f, *fields[1];
1043 WS_ATTRIBUTE_DESCRIPTION desc;
1044 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
1045 struct test { const WCHAR *str; } *test;
1047 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1048 ok( hr == S_OK, "got %08x\n", hr );
1050 hr = set_output( writer );
1051 ok( hr == S_OK, "got %08x\n", hr );
1053 /* text field mapping */
1054 memset( &f, 0, sizeof(f) );
1055 f.mapping = WS_TEXT_FIELD_MAPPING;
1056 f.type = WS_WSZ_TYPE;
1057 fields[0] = &f;
1059 memset( &s, 0, sizeof(s) );
1060 s.size = sizeof(struct test);
1061 s.alignment = TYPE_ALIGNMENT(struct test);
1062 s.fields = fields;
1063 s.fieldCount = 1;
1065 desc.attributeLocalName = &localname;
1066 desc.attributeNs = &ns;
1067 desc.type = WS_STRUCT_TYPE;
1068 desc.typeDescription = &s;
1070 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
1071 test->str = testW;
1072 hr = WsWriteAttribute( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1073 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1075 hr = WsWriteAttribute( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1076 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1078 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
1079 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1081 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1082 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1084 hr = set_output( writer );
1085 ok( hr == S_OK, "got %08x\n", hr );
1087 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1088 ok( hr == S_OK, "got %08x\n", hr );
1090 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1091 ok( hr == S_OK, "got %08x\n", hr );
1093 hr = WsWriteEndElement( writer, NULL );
1094 ok( hr == S_OK, "got %08x\n", hr );
1095 check_output( writer, "<str str=\"test\"/>", __LINE__ );
1097 HeapFree( GetProcessHeap(), 0, test );
1098 WsFreeWriter( writer );
1101 static void test_WsWriteStartCData(void)
1103 HRESULT hr;
1104 WS_XML_WRITER *writer;
1105 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1106 WS_XML_UTF8_TEXT text;
1108 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1109 ok( hr == S_OK, "got %08x\n", hr );
1111 hr = set_output( writer );
1112 ok( hr == S_OK, "got %08x\n", hr );
1114 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1115 ok( hr == S_OK, "got %08x\n", hr );
1117 hr = WsWriteEndCData( writer, NULL );
1118 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1120 hr = set_output( writer );
1121 ok( hr == S_OK, "got %08x\n", hr );
1123 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1124 ok( hr == S_OK, "got %08x\n", hr );
1125 check_output( writer, "", __LINE__ );
1127 hr = WsWriteStartCData( writer, NULL );
1128 ok( hr == S_OK, "got %08x\n", hr );
1129 check_output( writer, "<t><![CDATA[", __LINE__ );
1131 text.text.textType = WS_XML_TEXT_TYPE_UTF8;
1132 text.value.bytes = (BYTE *)"<data>";
1133 text.value.length = 6;
1134 text.value.dictionary = NULL;
1135 hr = WsWriteText( writer, &text.text, NULL );
1136 ok( hr == S_OK, "got %08x\n", hr );
1137 check_output( writer, "<t><![CDATA[<data>", __LINE__ );
1139 hr = WsWriteEndCData( writer, NULL );
1140 ok( hr == S_OK, "got %08x\n", hr );
1141 check_output( writer, "<t><![CDATA[<data>]]>", __LINE__ );
1143 hr = WsWriteEndElement( writer, NULL );
1144 ok( hr == S_OK, "got %08x\n", hr );
1145 check_output( writer, "<t><![CDATA[<data>]]></t>", __LINE__ );
1147 WsFreeWriter( writer );
1150 static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
1152 WS_XML_WRITER *writer;
1153 WS_BYTES bytes;
1154 ULONG size = sizeof(bytes);
1155 int len = strlen(expected);
1156 HRESULT hr;
1158 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1159 ok( hr == S_OK, "got %08x\n", hr );
1161 hr = set_output( writer );
1162 ok( hr == S_OK, "got %08x\n", hr );
1164 hr = WsWriteXmlBuffer( writer, buffer, NULL );
1165 ok( hr == S_OK, "got %08x\n", hr );
1167 memset( &bytes, 0, sizeof(bytes) );
1168 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
1169 ok( hr == S_OK, "%u: got %08x\n", line, hr );
1170 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
1171 if (bytes.length != len) return;
1172 ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
1174 WsFreeWriter( writer );
1177 static void prepare_xmlns_test( WS_XML_WRITER *writer, WS_HEAP **heap, WS_XML_BUFFER **buffer )
1179 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1180 HRESULT hr;
1182 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, heap, NULL );
1183 ok( hr == S_OK, "got %08x\n", hr );
1185 hr = WsCreateXmlBuffer( *heap, NULL, 0, buffer, NULL );
1186 ok( hr == S_OK, "got %08x\n", hr );
1188 hr = WsSetOutputToBuffer( writer, *buffer, NULL, 0, NULL );
1189 ok( hr == S_OK, "got %08x\n", hr );
1191 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
1192 ok( hr == S_OK, "got %08x\n", hr );
1195 static void test_WsWriteXmlnsAttribute(void)
1197 WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1198 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, prefix2 = {7, (BYTE *)"prefix2"};
1199 WS_XML_STRING xmlns = {6, (BYTE *)"xmlns"}, attr = {4, (BYTE *)"attr"};
1200 WS_XML_STRING localname = {1, (BYTE *)"u"};
1201 WS_HEAP *heap;
1202 WS_XML_BUFFER *buffer;
1203 WS_XML_WRITER *writer;
1204 HRESULT hr;
1206 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1207 ok( hr == S_OK, "got %08x\n", hr );
1209 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1210 ok( hr == S_OK, "got %08x\n", hr );
1212 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1213 ok( hr == S_OK, "got %08x\n", hr );
1215 hr = WsWriteXmlnsAttribute( NULL, NULL, NULL, FALSE, NULL );
1216 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1217 WsFreeHeap( heap );
1219 prepare_xmlns_test( writer, &heap, &buffer );
1220 hr = WsWriteXmlnsAttribute( writer, NULL, NULL, FALSE, NULL );
1221 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1222 WsFreeHeap( heap );
1224 prepare_xmlns_test( writer, &heap, &buffer );
1225 hr = WsWriteXmlnsAttribute( writer, &prefix2, NULL, FALSE, NULL );
1226 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1228 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1229 ok( hr == S_OK, "got %08x\n", hr );
1230 hr = WsWriteXmlnsAttribute( writer, NULL, &ns, FALSE, NULL );
1231 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1232 WsFreeHeap( heap );
1234 /* no prefix */
1235 prepare_xmlns_test( writer, &heap, &buffer );
1236 hr = WsWriteXmlnsAttribute( writer, NULL, &ns2, FALSE, NULL );
1237 ok( hr == S_OK, "got %08x\n", hr );
1238 hr = WsWriteEndElement( writer, NULL );
1239 ok( hr == S_OK, "got %08x\n", hr );
1240 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__ );
1241 WsFreeHeap( heap );
1243 /* prefix */
1244 prepare_xmlns_test( writer, &heap, &buffer );
1245 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1246 ok( hr == S_OK, "got %08x\n", hr );
1247 hr = WsWriteEndElement( writer, NULL );
1248 ok( hr == S_OK, "got %08x\n", hr );
1249 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__ );
1250 WsFreeHeap( heap );
1252 /* implicitly set element prefix namespace */
1253 prepare_xmlns_test( writer, &heap, &buffer );
1254 hr = WsWriteEndElement( writer, NULL );
1255 ok( hr == S_OK, "got %08x\n", hr );
1256 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__ );
1257 WsFreeHeap( heap );
1259 /* explicitly set element prefix namespace */
1260 prepare_xmlns_test( writer, &heap, &buffer );
1261 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1262 ok( hr == S_OK, "got %08x\n", hr );
1263 hr = WsWriteEndElement( writer, NULL );
1264 ok( hr == S_OK, "got %08x\n", hr );
1265 check_output_buffer( buffer, "<prefix:t xmlns:prefix='ns'/>", __LINE__ );
1266 WsFreeHeap( heap );
1268 /* repeated calls, same namespace */
1269 prepare_xmlns_test( writer, &heap, &buffer );
1270 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1271 ok( hr == S_OK, "got %08x\n", hr );
1272 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1273 ok( hr == S_OK, "got %08x\n", hr );
1274 hr = WsWriteEndElement( writer, NULL );
1275 ok( hr == S_OK, "got %08x\n", hr );
1276 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__ );
1277 WsFreeHeap( heap );
1279 /* repeated calls, different namespace */
1280 prepare_xmlns_test( writer, &heap, &buffer );
1281 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1282 ok( hr == S_OK, "got %08x\n", hr );
1283 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1284 ok( hr == S_OK, "got %08x\n", hr );
1285 hr = WsWriteEndElement( writer, NULL );
1286 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1287 WsFreeHeap( heap );
1289 /* single quotes */
1290 prepare_xmlns_test( writer, &heap, &buffer );
1291 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, TRUE, NULL );
1292 ok( hr == S_OK, "got %08x\n", hr );
1293 hr = WsWriteEndElement( writer, NULL );
1294 ok( hr == S_OK, "got %08x\n", hr );
1295 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns' xmlns:prefix=\"ns\"/>", __LINE__ );
1296 WsFreeHeap( heap );
1298 /* different namespace, different prefix */
1299 prepare_xmlns_test( writer, &heap, &buffer );
1300 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1301 ok( hr == S_OK, "got %08x\n", hr );
1302 hr = WsWriteEndElement( writer, NULL );
1303 ok( hr == S_OK, "got %08x\n", hr );
1304 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__ );
1305 WsFreeHeap( heap );
1307 /* different namespace, same prefix */
1308 prepare_xmlns_test( writer, &heap, &buffer );
1309 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns2, TRUE, NULL );
1310 ok( hr == S_OK, "got %08x\n", hr );
1311 hr = WsWriteEndElement( writer, NULL );
1312 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1313 WsFreeHeap( heap );
1315 /* regular attribute */
1316 prepare_xmlns_test( writer, &heap, &buffer );
1317 hr = WsWriteStartAttribute( writer, &xmlns, &prefix2, &ns2, TRUE, NULL );
1318 ok( hr == S_OK, "got %08x\n", hr );
1319 hr = WsWriteEndAttribute( writer, NULL );
1320 ok( hr == S_OK, "got %08x\n", hr );
1321 hr = WsWriteEndElement( writer, NULL );
1322 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1323 WsFreeHeap( heap );
1325 /* attribute order */
1326 prepare_xmlns_test( writer, &heap, &buffer );
1327 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1328 ok( hr == S_OK, "got %08x\n", hr );
1329 hr = WsWriteStartAttribute( writer, &prefix, &attr, &ns, TRUE, NULL );
1330 ok( hr == S_OK, "got %08x\n", hr );
1331 hr = WsWriteEndAttribute( writer, NULL );
1332 ok( hr == S_OK, "got %08x\n", hr );
1333 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, 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 prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__ );
1338 WsFreeHeap( heap );
1340 /* scope */
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 = WsWriteStartElement( writer, &prefix2, &localname, &ns2, NULL );
1345 ok( hr == S_OK, "got %08x\n", hr );
1346 hr = WsWriteEndElement( writer, NULL );
1347 ok( hr == S_OK, "got %08x\n", hr );
1348 hr = WsWriteEndElement( writer, NULL );
1349 ok( hr == S_OK, "got %08x\n", hr );
1350 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"><prefix2:u/></prefix:t>",
1351 __LINE__ );
1352 WsFreeHeap( heap );
1354 WsFreeWriter( writer );
1357 static void prepare_prefix_test( WS_XML_WRITER *writer )
1359 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1360 HRESULT hr;
1362 hr = set_output( writer );
1363 ok( hr == S_OK, "got %08x\n", hr );
1364 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1365 ok( hr == S_OK, "got %08x\n", hr );
1366 hr = WsWriteEndStartElement( writer, NULL );
1367 ok( hr == S_OK, "got %08x\n", hr );
1370 static void test_WsGetPrefixFromNamespace(void)
1372 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, *prefix;
1373 const WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1374 WS_XML_WRITER *writer;
1375 HRESULT hr;
1377 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1378 ok( hr == S_OK, "got %08x\n", hr );
1380 hr = set_output( writer );
1381 ok( hr == S_OK, "got %08x\n", hr );
1382 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1383 ok( hr == S_OK, "got %08x\n", hr );
1385 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, NULL, NULL );
1386 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1388 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, &prefix, NULL );
1389 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1391 hr = WsGetPrefixFromNamespace( writer, NULL, FALSE, &prefix, NULL );
1392 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1394 /* element must be committed */
1395 hr = set_output( writer );
1396 ok( hr == S_OK, "got %08x\n", hr );
1397 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1398 ok( hr == S_OK, "got %08x\n", hr );
1399 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1400 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1402 /* but writer can't be positioned on end element node */
1403 hr = set_output( writer );
1404 ok( hr == S_OK, "got %08x\n", hr );
1405 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1406 ok( hr == S_OK, "got %08x\n", hr );
1407 hr = WsWriteEndElement( writer, NULL );
1408 ok( hr == S_OK, "got %08x\n", hr );
1409 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1410 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1412 /* required = TRUE */
1413 prefix = NULL;
1414 prepare_prefix_test( writer );
1415 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1416 ok( hr == S_OK, "got %08x\n", hr );
1417 ok( prefix != NULL, "prefix not set\n" );
1418 if (prefix)
1420 ok( prefix->length == 1, "got %u\n", prefix->length );
1421 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1424 prefix = (const WS_XML_STRING *)0xdeadbeef;
1425 hr = WsGetPrefixFromNamespace( writer, &ns2, TRUE, &prefix, NULL );
1426 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1427 ok( prefix == (const WS_XML_STRING *)0xdeadbeef, "prefix set\n" );
1429 /* required = FALSE */
1430 prefix = NULL;
1431 prepare_prefix_test( writer );
1432 hr = WsGetPrefixFromNamespace( writer, &ns, FALSE, &prefix, NULL );
1433 ok( hr == S_OK, "got %08x\n", hr );
1434 ok( prefix != NULL, "prefix not set\n" );
1435 if (prefix)
1437 ok( prefix->length == 1, "got %u\n", prefix->length );
1438 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1441 prefix = (const WS_XML_STRING *)0xdeadbeef;
1442 hr = WsGetPrefixFromNamespace( writer, &ns2, FALSE, &prefix, NULL );
1443 ok( hr == S_FALSE, "got %08x\n", hr );
1444 ok( prefix == NULL, "prefix not set\n" );
1446 WsFreeWriter( writer );
1449 static void test_complex_struct_type(void)
1451 static const char expected[] =
1452 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1453 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1454 "</o:OfficeConfig>";
1455 static const WCHAR timestampW[] =
1456 {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
1457 WS_XML_STRING str_officeconfig = {12, (BYTE *)"OfficeConfig"};
1458 WS_XML_STRING str_services = {8, (BYTE *)"services"};
1459 WS_XML_STRING str_generationtime = {14, (BYTE *)"GenerationTime"};
1460 WS_XML_STRING ns = {39, (BYTE *)"urn:schemas-microsoft-com:office:office"};
1461 WS_XML_STRING prefix = {1, (BYTE *)"o"};
1462 DWORD size;
1463 HRESULT hr;
1464 WS_HEAP *heap;
1465 WS_XML_BUFFER *buffer;
1466 WS_XML_WRITER *writer;
1467 WS_STRUCT_DESCRIPTION s, s2;
1468 WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
1469 struct services
1471 const WCHAR *generationtime;
1473 struct officeconfig
1475 struct services *services;
1476 } *test;
1478 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1479 ok( hr == S_OK, "got %08x\n", hr );
1481 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1482 ok( hr == S_OK, "got %08x\n", hr );
1484 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1485 ok( hr == S_OK, "got %08x\n", hr );
1487 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1488 ok( hr == S_OK, "got %08x\n", hr );
1490 hr = WsWriteStartElement( writer, &prefix, &str_officeconfig, &ns, NULL );
1491 ok( hr == S_OK, "got %08x\n", hr );
1493 memset( &f2, 0, sizeof(f2) );
1494 f2.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
1495 f2.localName = &str_generationtime;
1496 f2.ns = &ns;
1497 f2.type = WS_WSZ_TYPE;
1498 f2.options = WS_FIELD_OPTIONAL;
1499 fields2[0] = &f2;
1501 memset( &s2, 0, sizeof(s2) );
1502 s2.size = sizeof(*test->services);
1503 s2.alignment = 4;
1504 s2.fields = fields2;
1505 s2.fieldCount = 1;
1506 s2.typeLocalName = &str_services;
1507 s2.typeNs = &ns;
1509 memset( &f, 0, sizeof(f) );
1510 f.mapping = WS_ELEMENT_FIELD_MAPPING;
1511 f.localName = &str_services;
1512 f.ns = &ns;
1513 f.type = WS_STRUCT_TYPE;
1514 f.typeDescription = &s2;
1515 f.options = WS_FIELD_POINTER;
1516 fields[0] = &f;
1518 memset( &s, 0, sizeof(s) );
1519 s.size = sizeof(*test);
1520 s.alignment = 4;
1521 s.fields = fields;
1522 s.fieldCount = 1;
1523 s.typeLocalName = &str_officeconfig;
1524 s.typeNs = &ns;
1526 size = sizeof(struct officeconfig) + sizeof(struct services);
1527 test = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
1528 test->services = (struct services *)(test + 1);
1529 test->services->generationtime = timestampW;
1530 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
1531 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1532 ok( hr == S_OK, "got %08x\n", hr );
1534 hr = WsWriteEndElement( writer, NULL );
1535 ok( hr == S_OK, "got %08x\n", hr );
1536 check_output_buffer( buffer, expected, __LINE__ );
1538 HeapFree( GetProcessHeap(), 0, test );
1539 WsFreeWriter( writer );
1540 WsFreeHeap( heap );
1543 static void test_WsMoveWriter(void)
1545 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, ns = {0, NULL};
1546 WS_HEAP *heap;
1547 WS_XML_WRITER *writer;
1548 WS_XML_BUFFER *buffer;
1549 HRESULT hr;
1551 hr = WsMoveWriter( NULL, WS_MOVE_TO_EOF, NULL, NULL );
1552 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1554 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1555 ok( hr == S_OK, "got %08x\n", hr );
1557 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1558 ok( hr == S_OK, "got %08x\n", hr );
1560 hr = set_output( writer );
1561 ok( hr == S_OK, "got %08x\n", hr );
1563 /* writer must be set to an XML buffer */
1564 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1565 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1567 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1568 ok( hr == S_OK, "got %08x\n", hr );
1570 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1571 ok( hr == S_OK, "got %08x\n", hr );
1573 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1574 ok( hr == S_OK, "got %08x\n", hr );
1576 /* <a><b/></a> */
1577 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1578 ok( hr == S_OK, "got %08x\n", hr );
1580 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1581 ok( hr == S_OK, "got %08x\n", hr );
1583 hr = WsWriteEndElement( writer, NULL );
1584 ok( hr == S_OK, "got %08x\n", hr );
1586 hr = WsWriteEndElement( writer, NULL );
1587 ok( hr == S_OK, "got %08x\n", hr );
1589 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1590 ok( hr == S_OK, "got %08x\n", hr );
1592 hr = WsMoveWriter( writer, WS_MOVE_TO_ROOT_ELEMENT, NULL, NULL );
1593 ok( hr == S_OK, "got %08x\n", hr );
1595 hr = WsMoveWriter( writer, WS_MOVE_TO_CHILD_ELEMENT, NULL, NULL );
1596 ok( hr == S_OK, "got %08x\n", hr );
1598 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1599 ok( hr == S_OK, "got %08x\n", hr );
1601 hr = WsMoveWriter( writer, WS_MOVE_TO_PARENT_ELEMENT, NULL, NULL );
1602 ok( hr == S_OK, "got %08x\n", hr );
1604 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1605 ok( hr == S_OK, "got %08x\n", hr );
1607 hr = WsMoveWriter( writer, WS_MOVE_TO_BOF, NULL, NULL );
1608 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1610 WsFreeWriter( writer );
1611 WsFreeHeap( heap );
1614 static void test_WsGetWriterPosition(void)
1616 WS_HEAP *heap;
1617 WS_XML_WRITER *writer;
1618 WS_XML_BUFFER *buffer;
1619 WS_XML_NODE_POSITION pos;
1620 HRESULT hr;
1622 hr = WsGetWriterPosition( NULL, NULL, NULL );
1623 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1625 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1626 ok( hr == S_OK, "got %08x\n", hr );
1628 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1629 ok( hr == S_OK, "got %08x\n", hr );
1631 hr = WsGetWriterPosition( writer, &pos, NULL );
1632 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1634 hr = set_output( writer );
1635 ok( hr == S_OK, "got %08x\n", hr );
1637 /* writer must be set to an XML buffer */
1638 hr = WsGetWriterPosition( writer, &pos, NULL );
1639 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1641 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1642 ok( hr == S_OK, "got %08x\n", hr );
1644 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1645 ok( hr == S_OK, "got %08x\n", hr );
1647 hr = WsGetWriterPosition( writer, NULL, NULL );
1648 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1650 pos.buffer = pos.node = NULL;
1651 hr = WsGetWriterPosition( writer, &pos, NULL );
1652 ok( hr == S_OK, "got %08x\n", hr );
1653 ok( pos.buffer != NULL, "buffer not set\n" );
1654 ok( pos.node != NULL, "node not set\n" );
1656 WsFreeWriter( writer );
1657 WsFreeHeap( heap );
1660 static void test_WsSetWriterPosition(void)
1662 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1663 WS_HEAP *heap;
1664 WS_XML_WRITER *writer;
1665 WS_XML_BUFFER *buf1, *buf2;
1666 WS_XML_NODE_POSITION pos;
1667 HRESULT hr;
1669 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1670 ok( hr == S_OK, "got %08x\n", hr );
1672 hr = WsSetWriterPosition( NULL, NULL, NULL );
1673 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1675 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1676 ok( hr == S_OK, "got %08x\n", hr );
1678 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf1, NULL );
1679 ok( hr == S_OK, "got %08x\n", hr );
1681 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1682 ok( hr == S_OK, "got %08x\n", hr );
1684 hr = WsSetWriterPosition( writer, NULL, NULL );
1685 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1687 pos.buffer = pos.node = NULL;
1688 hr = WsGetWriterPosition( writer, &pos, NULL );
1689 ok( hr == S_OK, "got %08x\n", hr );
1690 ok( pos.buffer == buf1, "wrong buffer\n" );
1691 ok( pos.node != NULL, "node not set\n" );
1693 hr = WsSetWriterPosition( writer, &pos, NULL );
1694 ok( hr == S_OK, "got %08x\n", hr );
1696 /* different buffer */
1697 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf2, NULL );
1698 ok( hr == S_OK, "got %08x\n", hr );
1700 pos.buffer = buf2;
1701 hr = WsSetWriterPosition( writer, &pos, NULL );
1702 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1704 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1705 ok( hr == S_OK, "got %08x\n", hr );
1707 /* try to write at non-final position */
1708 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1709 ok( hr == S_OK, "got %08x\n", hr );
1711 pos.buffer = pos.node = NULL;
1712 hr = WsGetWriterPosition( writer, &pos, NULL );
1713 ok( hr == S_OK, "got %08x\n", hr );
1714 ok( pos.buffer == buf1, "wrong buffer\n" );
1715 ok( pos.node != NULL, "node not set\n" );
1717 hr = WsWriteEndElement( writer, NULL );
1718 ok( hr == S_OK, "got %08x\n", hr );
1719 check_output_buffer( buf1, "<t/>", __LINE__ );
1721 hr = WsSetWriterPosition( writer, &pos, NULL );
1722 ok( hr == S_OK, "got %08x\n", hr );
1724 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1725 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1727 WsFreeWriter( writer );
1728 WsFreeHeap( heap );
1731 static void test_WsWriteXmlBuffer(void)
1733 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1734 WS_XML_WRITER *writer1, *writer2;
1735 WS_XML_BUFFER *buffer1, *buffer2;
1736 WS_HEAP *heap;
1737 HRESULT hr;
1739 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1740 ok( hr == S_OK, "got %08x\n", hr );
1742 hr = WsCreateXmlBuffer( NULL, NULL, 0, NULL, NULL );
1743 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1745 hr = WsCreateWriter( NULL, 0, &writer1, NULL );
1746 ok( hr == S_OK, "got %08x\n", hr );
1748 hr = WsCreateXmlBuffer( heap, NULL, 0, NULL, NULL );
1749 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1751 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer1, NULL );
1752 ok( hr == S_OK, "got %08x\n", hr );
1754 hr = WsSetOutputToBuffer( writer1, buffer1, NULL, 0, NULL );
1755 ok( hr == S_OK, "got %08x\n", hr );
1757 hr = WsWriteStartElement( writer1, NULL, &localname, &ns, NULL );
1758 ok( hr == S_OK, "got %08x\n", hr );
1760 hr = WsWriteEndElement( writer1, NULL );
1761 ok( hr == S_OK, "got %08x\n", hr );
1762 check_output_buffer( buffer1, "<t/>", __LINE__ );
1764 hr = WsCreateWriter( NULL, 0, &writer2, NULL );
1765 ok( hr == S_OK, "got %08x\n", hr );
1767 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer2, NULL );
1768 ok( hr == S_OK, "got %08x\n", hr );
1770 hr = WsSetOutputToBuffer( writer2, buffer2, NULL, 0, NULL );
1771 ok( hr == S_OK, "got %08x\n", hr );
1773 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1774 ok( hr == S_OK, "got %08x\n", hr );
1775 check_output_buffer( buffer2, "<t/>", __LINE__ );
1777 hr = WsMoveWriter( writer2, WS_MOVE_TO_PREVIOUS_ELEMENT, NULL, NULL );
1778 todo_wine ok( hr == S_OK, "got %08x\n", hr );
1780 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1781 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1783 WsFreeWriter( writer1 );
1784 WsFreeWriter( writer2 );
1785 WsFreeHeap( heap );
1788 static void test_WsWriteNode(void)
1790 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {4, (BYTE *)"attr"}, ns = {0, NULL};
1791 WS_XML_WRITER *writer;
1792 WS_XML_BUFFER *buffer;
1793 WS_XML_UTF8_TEXT utf8;
1794 WS_XML_ATTRIBUTE attr, *attrs[1];
1795 WS_XML_ELEMENT_NODE elem;
1796 WS_XML_COMMENT_NODE comment;
1797 WS_XML_NODE node;
1798 WS_XML_TEXT_NODE text;
1799 WS_HEAP *heap;
1800 HRESULT hr;
1802 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1803 ok( hr == S_OK, "got %08x\n", hr );
1805 hr = WsWriteNode( NULL, NULL, NULL );
1806 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1808 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1809 ok( hr == S_OK, "got %08x\n", hr );
1811 hr = WsWriteNode( writer, NULL, NULL );
1812 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1814 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1815 ok( hr == S_OK, "got %08x\n", hr );
1817 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1818 ok( hr == S_OK, "got %08x\n", hr );
1820 utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
1821 utf8.value.bytes = (BYTE *)"value";
1822 utf8.value.length = sizeof("value") - 1;
1823 utf8.value.dictionary = NULL;
1825 attr.singleQuote = TRUE;
1826 attr.isXmlNs = FALSE;
1827 attr.prefix = NULL;
1828 attr.localName = &localname2;
1829 attr.ns = &ns;
1830 attr.value = &utf8.text;
1831 attrs[0] = &attr;
1833 elem.node.nodeType = WS_XML_NODE_TYPE_ELEMENT;
1834 elem.prefix = NULL;
1835 elem.localName = &localname;
1836 elem.ns = &ns;
1837 elem.attributeCount = 1;
1838 elem.attributes = attrs;
1839 elem.isEmpty = FALSE;
1840 hr = WsWriteNode( writer, (const WS_XML_NODE *)&elem, NULL );
1841 ok( hr == S_OK, "got %08x\n", hr );
1843 comment.node.nodeType = WS_XML_NODE_TYPE_COMMENT;
1844 comment.value.bytes = (BYTE *)"comment";
1845 comment.value.length = sizeof("comment") - 1;
1846 comment.value.dictionary = NULL;
1847 hr = WsWriteNode( writer, (const WS_XML_NODE *)&comment, NULL );
1848 ok( hr == S_OK, "got %08x\n", hr );
1850 node.nodeType = WS_XML_NODE_TYPE_EOF;
1851 hr = WsWriteNode( writer, &node, NULL );
1852 ok( hr == S_OK, "got %08x\n", hr );
1854 node.nodeType = WS_XML_NODE_TYPE_BOF;
1855 hr = WsWriteNode( writer, &node, NULL );
1856 ok( hr == S_OK, "got %08x\n", hr );
1858 node.nodeType = WS_XML_NODE_TYPE_CDATA;
1859 hr = WsWriteNode( writer, &node, NULL );
1860 ok( hr == S_OK, "got %08x\n", hr );
1862 utf8.value.bytes = (BYTE *)"cdata";
1863 utf8.value.length = sizeof("cdata") - 1;
1864 utf8.value.dictionary = NULL;
1865 text.node.nodeType = WS_XML_NODE_TYPE_TEXT;
1866 text.text = &utf8.text;
1867 hr = WsWriteNode( writer, (const WS_XML_NODE *)&text, NULL );
1868 ok( hr == S_OK, "got %08x\n", hr );
1870 node.nodeType = WS_XML_NODE_TYPE_END_CDATA;
1871 hr = WsWriteNode( writer, &node, NULL );
1872 ok( hr == S_OK, "got %08x\n", hr );
1874 utf8.value.bytes = (BYTE *)"text";
1875 utf8.value.length = sizeof("text") - 1;
1876 utf8.value.dictionary = NULL;
1877 hr = WsWriteNode( writer, (const WS_XML_NODE *)&text, NULL );
1878 ok( hr == S_OK, "got %08x\n", hr );
1880 node.nodeType = WS_XML_NODE_TYPE_END_ELEMENT;
1881 hr = WsWriteNode( writer, &node, NULL );
1882 ok( hr == S_OK, "got %08x\n", hr );
1883 check_output_buffer( buffer, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__ );
1885 WsFreeWriter( writer );
1886 WsFreeHeap( heap );
1889 static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
1891 WS_XML_READER_TEXT_ENCODING enc;
1892 WS_XML_READER_BUFFER_INPUT input;
1894 enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
1895 enc.charSet = WS_CHARSET_AUTO;
1897 input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
1898 input.encodedData = (void *)data;
1899 input.encodedDataSize = size;
1901 return WsSetInput( reader, &enc.encoding, &input.input, NULL, 0, NULL );
1904 static void test_WsCopyNode(void)
1906 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
1907 WS_XML_NODE_POSITION pos, pos2;
1908 WS_XML_WRITER *writer;
1909 WS_XML_READER *reader;
1910 WS_XML_BUFFER *buffer;
1911 WS_HEAP *heap;
1912 HRESULT hr;
1914 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1915 ok( hr == S_OK, "got %08x\n", hr );
1917 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1918 ok( hr == S_OK, "got %08x\n", hr );
1920 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1921 ok( hr == S_OK, "got %08x\n", hr );
1923 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1924 ok( hr == S_OK, "got %08x\n", hr );
1926 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1927 ok( hr == S_OK, "got %08x\n", hr );
1929 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1930 ok( hr == S_OK, "got %08x\n", hr );
1932 hr = WsWriteEndElement( writer, NULL );
1933 ok( hr == S_OK, "got %08x\n", hr );
1935 hr = WsGetWriterPosition( writer, &pos, NULL );
1936 ok( hr == S_OK, "got %08x\n", hr );
1938 hr = WsWriteEndElement( writer, NULL );
1939 ok( hr == S_OK, "got %08x\n", hr );
1940 check_output_buffer( buffer, "<t><u/></t>", __LINE__ );
1942 hr = WsCreateReader( NULL, 0, &reader, NULL );
1943 ok( hr == S_OK, "got %08x\n", hr );
1945 hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
1946 ok( hr == S_OK, "got %08x\n", hr );
1948 hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
1949 ok( hr == S_OK, "got %08x\n", hr );
1951 hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
1952 ok( hr == S_OK, "got %08x\n", hr );
1954 hr = WsSetWriterPosition( writer, &pos, NULL );
1955 ok( hr == S_OK, "got %08x\n", hr );
1957 hr = WsCopyNode( writer, reader, NULL );
1958 ok( hr == S_OK, "got %08x\n", hr );
1959 check_output_buffer( buffer, "<t><u/><v/></t>", __LINE__ );
1961 hr = WsGetWriterPosition( writer, &pos2, NULL );
1962 ok( hr == S_OK, "got %08x\n", hr );
1963 ok( pos2.buffer == pos.buffer, "wrong buffer\n" );
1964 ok( pos2.node == pos.node, "wrong node\n" );
1966 WsFreeReader( reader );
1967 WsFreeWriter( writer );
1968 WsFreeHeap( heap );
1971 static void test_text_types(void)
1973 static const WCHAR utf16W[] = {'u','t','f','1','6'};
1974 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1975 WS_XML_WRITER *writer;
1976 static const WS_XML_UTF8_TEXT val_utf8 = { {WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"utf8"} };
1977 static WS_XML_UTF16_TEXT val_utf16 = { {WS_XML_TEXT_TYPE_UTF16} };
1978 static const WS_XML_GUID_TEXT val_guid = { {WS_XML_TEXT_TYPE_GUID} };
1979 static const WS_XML_UNIQUE_ID_TEXT val_urn = { {WS_XML_TEXT_TYPE_UNIQUE_ID} };
1980 static const WS_XML_BOOL_TEXT val_bool = { {WS_XML_TEXT_TYPE_BOOL}, TRUE };
1981 static const WS_XML_INT32_TEXT val_int32 = { {WS_XML_TEXT_TYPE_INT32}, -2147483647 - 1 };
1982 static const WS_XML_INT64_TEXT val_int64 = { {WS_XML_TEXT_TYPE_INT64}, -9223372036854775807 - 1 };
1983 static const WS_XML_UINT64_TEXT val_uint64 = { {WS_XML_TEXT_TYPE_UINT64}, ~0 };
1984 static const struct
1986 const WS_XML_TEXT *text;
1987 const char *result;
1989 tests[] =
1991 { &val_utf8.text, "<t>utf8</t>" },
1992 { &val_utf16.text, "<t>utf16</t>" },
1993 { &val_guid.text, "<t>00000000-0000-0000-0000-000000000000</t>" },
1994 { &val_urn.text, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
1995 { &val_bool.text, "<t>true</t>" },
1996 { &val_int32.text, "<t>-2147483648</t>" },
1997 { &val_int64.text, "<t>-9223372036854775808</t>" },
1998 { &val_uint64.text, "<t>18446744073709551615</t>" },
2000 HRESULT hr;
2001 ULONG i;
2003 val_utf16.bytes = (BYTE *)utf16W;
2004 val_utf16.byteCount = sizeof(utf16W);
2006 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2007 ok( hr == S_OK, "got %08x\n", hr );
2009 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2011 hr = set_output( writer );
2012 ok( hr == S_OK, "got %08x\n", hr );
2013 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2014 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2016 hr = WsWriteText( writer, tests[i].text, NULL );
2017 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2019 hr = WsWriteEndElement( writer, NULL );
2020 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2021 check_output( writer, tests[i].result, __LINE__ );
2024 WsFreeWriter( writer );
2027 static void test_double(void)
2029 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2030 static const struct
2032 double val;
2033 const char *result;
2035 tests[] =
2037 {0.0, "<t>0</t>"},
2038 {1.0, "<t>1</t>"},
2039 {-1.0, "<t>-1</t>"},
2040 {1.0000000000000001, "<t>1</t>"},
2041 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2042 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2043 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2044 {100000000000000, "<t>100000000000000</t>"},
2045 {1000000000000000, "<t>1E+15</t>"},
2046 {0.1, "<t>0.1</t>"},
2047 {0.01, "<t>1E-2</t>"},
2048 {-0.1, "<t>-0.1</t>"},
2049 {-0.01, "<t>-1E-2</t>"},
2050 {1.7976931348623158e308, "<t>1.7976931348623157E+308</t>"},
2051 {-1.7976931348623158e308, "<t>-1.7976931348623157E+308</t>"},
2053 HRESULT hr;
2054 WS_XML_WRITER *writer;
2055 WS_XML_DOUBLE_TEXT text;
2056 ULONG i;
2058 hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
2059 ok( hr == S_OK, "got %08x\n", hr );
2061 text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
2062 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2064 hr = set_output( writer );
2065 ok( hr == S_OK, "got %08x\n", hr );
2066 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2067 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2069 text.value = tests[i].val;
2070 hr = WsWriteText( writer, &text.text, NULL );
2071 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2073 hr = WsWriteEndElement( writer, NULL );
2074 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2075 check_output( writer, tests[i].result, __LINE__ );
2078 hr = set_output( writer );
2079 ok( hr == S_OK, "got %08x\n", hr );
2080 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2081 ok( hr == S_OK, "got %08x\n", hr );
2083 text.value = NAN;
2084 hr = WsWriteText( writer, &text.text, NULL );
2085 ok( hr == S_OK, "got %08x\n", hr );
2087 hr = WsWriteEndElement( writer, NULL );
2088 ok( hr == S_OK, "got %08x\n", hr );
2089 check_output( writer, "<t>NaN</t>", __LINE__ );
2091 hr = set_output( writer );
2092 ok( hr == S_OK, "got %08x\n", hr );
2093 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2094 ok( hr == S_OK, "got %08x\n", hr );
2096 text.value = INFINITY;
2097 hr = WsWriteText( writer, &text.text, NULL );
2098 ok( hr == S_OK, "got %08x\n", hr );
2100 hr = WsWriteEndElement( writer, NULL );
2101 ok( hr == S_OK, "got %08x\n", hr );
2102 check_output( writer, "<t>INF</t>", __LINE__ );
2104 hr = set_output( writer );
2105 ok( hr == S_OK, "got %08x\n", hr );
2106 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2107 ok( hr == S_OK, "got %08x\n", hr );
2109 text.value = -INFINITY;
2110 hr = WsWriteText( writer, &text.text, NULL );
2111 ok( hr == S_OK, "got %08x\n", hr );
2113 hr = WsWriteEndElement( writer, NULL );
2114 ok( hr == S_OK, "got %08x\n", hr );
2115 check_output( writer, "<t>-INF</t>", __LINE__ );
2117 WsFreeWriter( writer );
2120 static void test_field_flags(void)
2122 static const char expected[] =
2123 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2124 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2125 HRESULT hr;
2126 WS_XML_WRITER *writer;
2127 WS_STRUCT_DESCRIPTION s;
2128 WS_FIELD_DESCRIPTION f, f2, f3, f4, *fields[4];
2129 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, str_guid = {4, (BYTE *)"guid"};
2130 WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_bool = {4, (BYTE *)"bool"};
2131 WS_XML_STRING str_xmlstr = {6, (BYTE *)"xmlstr"};
2132 INT32 val = -1;
2133 struct test
2135 GUID guid;
2136 BOOL *bool_ptr;
2137 INT32 *int32_ptr;
2138 WS_XML_STRING xmlstr;
2139 } test;
2141 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2142 ok( hr == S_OK, "got %08x\n", hr );
2144 hr = set_output( writer );
2145 ok( hr == S_OK, "got %08x\n", hr );
2147 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2148 ok( hr == S_OK, "got %08x\n", hr );
2150 memset( &f, 0, sizeof(f) );
2151 f.mapping = WS_ELEMENT_FIELD_MAPPING;
2152 f.localName = &str_guid;
2153 f.ns = &ns;
2154 f.type = WS_GUID_TYPE;
2155 f.options = WS_FIELD_OPTIONAL;
2156 fields[0] = &f;
2158 memset( &f2, 0, sizeof(f2) );
2159 f2.mapping = WS_ELEMENT_FIELD_MAPPING;
2160 f2.localName = &str_bool;
2161 f2.offset = FIELD_OFFSET(struct test, bool_ptr);
2162 f2.ns = &ns;
2163 f2.type = WS_BOOL_TYPE;
2164 f2.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2165 fields[1] = &f2;
2167 memset( &f3, 0, sizeof(f3) );
2168 f3.mapping = WS_ELEMENT_FIELD_MAPPING;
2169 f3.localName = &str_int32;
2170 f3.offset = FIELD_OFFSET(struct test, int32_ptr);
2171 f3.ns = &ns;
2172 f3.type = WS_INT32_TYPE;
2173 f3.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2174 fields[2] = &f3;
2176 memset( &f4, 0, sizeof(f4) );
2177 f4.mapping = WS_ELEMENT_FIELD_MAPPING;
2178 f4.localName = &str_xmlstr;
2179 f4.offset = FIELD_OFFSET(struct test, xmlstr);
2180 f4.ns = &ns;
2181 f4.type = WS_XML_STRING_TYPE;
2182 f4.options = WS_FIELD_NILLABLE;
2183 fields[3] = &f4;
2185 memset( &s, 0, sizeof(s) );
2186 s.size = sizeof(struct test);
2187 s.alignment = TYPE_ALIGNMENT(struct test);
2188 s.fields = fields;
2189 s.fieldCount = 4;
2191 memset( &test, 0, sizeof(test) );
2192 test.int32_ptr = &val;
2193 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE,
2194 &test, sizeof(test), NULL );
2195 ok( hr == S_OK, "got %08x\n", hr );
2197 hr = WsWriteEndElement( writer, NULL );
2198 ok( hr == S_OK, "got %08x\n", hr );
2199 check_output( writer, expected, __LINE__ );
2201 WsFreeWriter( writer );
2204 static void test_WsWriteText(void)
2206 HRESULT hr;
2207 WS_XML_WRITER *writer;
2208 WS_XML_UTF8_TEXT utf8;
2210 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2211 ok( hr == S_OK, "got %08x\n", hr );
2213 hr = set_output( writer );
2214 ok( hr == S_OK, "got %08x\n", hr );
2216 utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
2217 utf8.value.bytes = (BYTE *)"test";
2218 utf8.value.length = 4;
2219 utf8.value.dictionary = NULL;
2220 hr = WsWriteText( writer, &utf8.text, NULL );
2221 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
2223 WsFreeWriter( writer );
2226 static void test_WsWriteArray(void)
2228 static const WS_XML_STRING localname = {4, (BYTE *)"item"}, localname2 = {5, (BYTE *)"array"};
2229 static const WS_XML_STRING ns = {0, NULL};
2230 WS_XML_WRITER *writer;
2231 BOOL array_bool[2];
2232 HRESULT hr;
2234 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2235 ok( hr == S_OK, "got %08x\n", hr );
2237 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2238 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2240 hr = set_output( writer );
2241 ok( hr == S_OK, "got %08x\n", hr );
2242 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2243 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2245 hr = set_output( writer );
2246 ok( hr == S_OK, "got %08x\n", hr );
2247 hr = WsWriteArray( writer, &localname, NULL, 0, NULL, 0, 0, 0, NULL );
2248 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2250 hr = set_output( writer );
2251 ok( hr == S_OK, "got %08x\n", hr );
2252 hr = WsWriteArray( writer, &localname, &ns, 0, NULL, 0, 0, 0, NULL );
2253 ok( hr == S_OK, "got %08x\n", hr );
2254 check_output( writer, "", __LINE__ );
2256 hr = WsWriteArray( writer, &localname, &ns, ~0u, NULL, 0, 0, 0, NULL );
2257 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2259 hr = set_output( writer );
2260 ok( hr == S_OK, "got %08x\n", hr );
2261 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, 0, 0, 0, NULL );
2262 ok( hr == S_OK, "got %08x\n", hr );
2263 check_output( writer, "", __LINE__ );
2265 array_bool[0] = FALSE;
2266 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, 0, 0, 0, NULL );
2267 ok( hr == S_OK, "got %08x\n", hr );
2268 check_output( writer, "", __LINE__ );
2270 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 0, NULL );
2271 ok( hr == S_OK, "got %08x\n", hr );
2272 check_output( writer, "", __LINE__ );
2274 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 0, NULL );
2275 ok( hr == S_OK, "got %08x\n", hr );
2276 check_output( writer, "", __LINE__ );
2278 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 1, NULL );
2279 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2281 hr = set_output( writer );
2282 ok( hr == S_OK, "got %08x\n", hr );
2283 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 1, NULL );
2284 ok( hr == S_OK, "got %08x\n", hr );
2285 check_output( writer, "<item>false</item>", __LINE__ );
2287 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool) - 1, 0, 2, NULL );
2288 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2290 hr = set_output( writer );
2291 ok( hr == S_OK, "got %08x\n", hr );
2292 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 3, NULL );
2293 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2295 hr = set_output( writer );
2296 ok( hr == S_OK, "got %08x\n", hr );
2298 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
2299 ok( hr == S_OK, "got %08x\n", hr );
2301 array_bool[1] = TRUE;
2302 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 2, NULL );
2303 ok( hr == S_OK, "got %08x\n", hr );
2305 hr = WsWriteEndElement( writer, NULL );
2306 ok( hr == S_OK, "got %08x\n", hr );
2307 check_output( writer, "<array><item>false</item><item>true</item></array>", __LINE__ );
2309 WsFreeWriter( writer );
2312 START_TEST(writer)
2314 test_WsCreateWriter();
2315 test_WsCreateXmlBuffer();
2316 test_WsSetOutput();
2317 test_WsSetOutputToBuffer();
2318 test_WsWriteStartElement();
2319 test_WsWriteStartAttribute();
2320 test_WsWriteType();
2321 test_basic_type();
2322 test_simple_struct_type();
2323 test_WsWriteElement();
2324 test_WsWriteValue();
2325 test_WsWriteAttribute();
2326 test_WsWriteStartCData();
2327 test_WsWriteXmlnsAttribute();
2328 test_WsGetPrefixFromNamespace();
2329 test_complex_struct_type();
2330 test_WsMoveWriter();
2331 test_WsGetWriterPosition();
2332 test_WsSetWriterPosition();
2333 test_WsWriteXmlBuffer();
2334 test_WsWriteNode();
2335 test_WsCopyNode();
2336 test_text_types();
2337 test_double();
2338 test_field_flags();
2339 test_WsWriteText();
2340 test_WsWriteArray();