webservices: Escape XML special characters where needed.
[wine.git] / dlls / webservices / tests / writer.c
blob326aed2698c0db91bf13784daebf1a86852655a4
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 = {{WS_XML_TEXT_TYPE_UTF8}};
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.value.length = 1;
466 text.value.bytes = (BYTE *)"0";
467 hr = WsWriteText( writer, &text.text, NULL );
468 ok( hr == S_OK, "got %08x\n", hr );
469 check_output( writer, "", __LINE__ );
471 /* WsWriteEndAttribute doesn't output anything */
472 hr = WsWriteEndAttribute( writer, NULL );
473 ok( hr == S_OK, "got %08x\n", hr );
474 check_output( writer, "", __LINE__ );
476 hr = WsWriteEndElement( writer, NULL );
477 ok( hr == S_OK, "got %08x\n", hr );
478 check_output( writer, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__ );
480 WsFreeWriter( writer );
483 static void test_WsWriteType(void)
485 static const WCHAR testW[] = {'t','e','s','t',0};
486 HRESULT hr;
487 WS_XML_WRITER *writer;
488 WS_XML_STRING prefix = {1, (BYTE*)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
489 const WCHAR *val_str;
491 hr = WsCreateWriter( NULL, 0, &writer, NULL );
492 ok( hr == S_OK, "got %08x\n", hr );
494 hr = set_output( writer );
495 ok( hr == S_OK, "got %08x\n", hr );
497 val_str = testW;
498 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
499 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
500 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
502 hr = set_output( writer );
503 ok( hr == S_OK, "got %08x\n", hr );
505 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
506 ok( hr == S_OK, "got %08x\n", hr );
508 /* required value */
509 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
510 WS_WRITE_REQUIRED_VALUE, NULL, sizeof(testW), NULL );
511 ok( hr == E_INVALIDARG, "got %08x\n", hr );
513 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
514 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
515 ok( hr == E_INVALIDARG, "got %08x\n", hr );
517 /* required pointer */
518 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
519 WS_WRITE_REQUIRED_POINTER, NULL, sizeof(val_str), NULL );
520 ok( hr == E_INVALIDARG, "got %08x\n", hr );
522 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
523 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
524 ok( hr == E_INVALIDARG, "got %08x\n", hr );
526 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
527 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(WCHAR **), NULL );
528 ok( hr == S_OK, "got %08x\n", hr );
529 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
531 hr = WsWriteEndElement( writer, NULL );
532 ok( hr == S_OK, "got %08x\n", hr );
533 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
535 hr = set_output( writer );
536 ok( hr == S_OK, "got %08x\n", hr );
538 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
539 ok( hr == S_OK, "got %08x\n", hr );
541 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
542 ok( hr == S_OK, "got %08x\n", hr );
544 val_str = testW;
545 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
546 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
547 ok( hr == S_OK, "got %08x\n", hr );
548 check_output( writer, "", __LINE__ );
550 hr = WsWriteEndAttribute( writer, NULL );
551 ok( hr == S_OK, "got %08x\n", hr );
552 check_output( writer, "", __LINE__ );
554 hr = WsWriteEndElement( writer, NULL );
555 ok( hr == S_OK, "got %08x\n", hr );
556 check_output( writer, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__ );
558 hr = set_output( writer );
559 ok( hr == S_OK, "got %08x\n", hr );
561 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
562 ok( hr == S_OK, "got %08x\n", hr );
564 val_str = testW;
565 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
566 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
567 ok( hr == S_OK, "got %08x\n", hr );
568 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
570 hr = WsWriteEndElement( writer, NULL );
571 ok( hr == S_OK, "got %08x\n", hr );
572 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
574 WsFreeWriter( writer );
577 static void test_basic_type(void)
579 static WCHAR testW[] = {'t','e','s','t',0};
580 HRESULT hr;
581 WS_XML_WRITER *writer;
582 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, xmlstr;
583 GUID guid;
584 WCHAR *str;
585 WS_STRING string;
586 ULONG i;
587 static const struct
589 WS_TYPE type;
590 INT64 val;
591 ULONG size;
592 const char *result;
593 const char *result2;
595 tests[] =
597 { WS_BOOL_TYPE, TRUE, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
598 { WS_BOOL_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
599 { WS_INT8_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
600 { WS_INT16_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
601 { WS_INT32_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
602 "<t t=\"-2147483648\"/>" },
603 { WS_INT64_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
604 "<t t=\"-9223372036854775808\"/>" },
605 { WS_UINT8_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
606 { WS_UINT16_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
607 { WS_UINT32_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
608 { WS_UINT64_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
609 "<t t=\"18446744073709551615\"/>" },
612 hr = WsCreateWriter( NULL, 0, &writer, NULL );
613 ok( hr == S_OK, "got %08x\n", hr );
615 /* element content type mapping */
616 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
618 hr = set_output( writer );
619 ok( hr == S_OK, "got %08x\n", hr );
621 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
622 ok( hr == S_OK, "got %08x\n", hr );
624 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
625 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
626 ok( hr == S_OK, "%u: got %08x\n", i, hr );
628 hr = WsWriteEndElement( writer, NULL );
629 ok( hr == S_OK, "got %08x\n", hr );
630 check_output( writer, tests[i].result, __LINE__ );
633 /* element type mapping is the same as element content type mapping for basic types */
634 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
636 const INT64 *ptr = &tests[i].val;
638 hr = set_output( writer );
639 ok( hr == S_OK, "got %08x\n", hr );
641 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
642 ok( hr == S_OK, "got %08x\n", hr );
644 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
645 WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
646 ok( hr == S_OK, "%u: got %08x\n", i, hr );
648 hr = WsWriteEndElement( writer, NULL );
649 ok( hr == S_OK, "got %08x\n", hr );
650 check_output( writer, tests[i].result, __LINE__ );
653 /* attribute type mapping */
654 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
656 hr = set_output( writer );
657 ok( hr == S_OK, "got %08x\n", hr );
659 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
660 ok( hr == S_OK, "got %08x\n", hr );
662 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
663 ok( hr == S_OK, "got %08x\n", hr );
665 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, tests[i].type, NULL,
666 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
667 ok( hr == S_OK, "%u: got %08x\n", i, hr );
669 hr = WsWriteEndAttribute( writer, NULL );
670 ok( hr == S_OK, "got %08x\n", hr );
672 hr = WsWriteEndElement( writer, NULL );
673 ok( hr == S_OK, "got %08x\n", hr );
674 check_output( writer, tests[i].result2, __LINE__ );
677 hr = set_output( writer );
678 ok( hr == S_OK, "got %08x\n", hr );
680 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
681 ok( hr == S_OK, "got %08x\n", hr );
683 memset( &guid, 0, sizeof(guid) );
684 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
685 &guid, sizeof(guid), NULL );
686 ok( hr == S_OK, "got %08x\n", hr );
688 hr = WsWriteEndElement( writer, NULL );
689 ok( hr == S_OK, "got %08x\n", hr );
690 check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
692 hr = set_output( writer );
693 ok( hr == S_OK, "got %08x\n", hr );
695 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
696 ok( hr == S_OK, "got %08x\n", hr );
698 string.chars = testW;
699 string.length = 4;
700 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
701 &string, sizeof(string), NULL );
702 ok( hr == S_OK, "got %08x\n", hr );
704 hr = WsWriteEndElement( writer, NULL );
705 ok( hr == S_OK, "got %08x\n", hr );
706 check_output( writer, "<t>test</t>", __LINE__ );
708 hr = set_output( writer );
709 ok( hr == S_OK, "got %08x\n", hr );
711 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
712 ok( hr == S_OK, "got %08x\n", hr );
714 str = testW;
715 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
716 &str, sizeof(str), NULL );
717 ok( hr == S_OK, "got %08x\n", hr );
719 hr = WsWriteEndElement( writer, NULL );
720 ok( hr == S_OK, "got %08x\n", hr );
721 check_output( writer, "<t>test</t>", __LINE__ );
723 hr = set_output( writer );
724 ok( hr == S_OK, "got %08x\n", hr );
726 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
727 ok( hr == S_OK, "got %08x\n", hr );
729 xmlstr.bytes = (BYTE *)"test";
730 xmlstr.length = 4;
731 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
732 &xmlstr, sizeof(xmlstr), NULL );
733 ok( hr == S_OK, "got %08x\n", hr );
735 hr = WsWriteEndElement( writer, NULL );
736 ok( hr == S_OK, "got %08x\n", hr );
737 check_output( writer, "<t>test</t>", __LINE__ );
739 WsFreeWriter( writer );
742 static void test_simple_struct_type(void)
744 static const WCHAR valueW[] = {'v','a','l','u','e',0};
745 HRESULT hr;
746 WS_XML_WRITER *writer;
747 WS_STRUCT_DESCRIPTION s;
748 WS_FIELD_DESCRIPTION f, *fields[1];
749 WS_XML_STRING localname = {6, (BYTE *)"struct"}, ns = {0, NULL};
750 struct test
752 const WCHAR *field;
753 } *test;
755 hr = WsCreateWriter( NULL, 0, &writer, NULL );
756 ok( hr == S_OK, "got %08x\n", hr );
758 hr = set_output( writer );
759 ok( hr == S_OK, "got %08x\n", hr );
761 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
762 ok( hr == S_OK, "got %08x\n", hr );
764 memset( &f, 0, sizeof(f) );
765 f.mapping = WS_TEXT_FIELD_MAPPING;
766 f.type = WS_WSZ_TYPE;
767 fields[0] = &f;
769 memset( &s, 0, sizeof(s) );
770 s.size = sizeof(struct test);
771 s.alignment = TYPE_ALIGNMENT(struct test);
772 s.fields = fields;
773 s.fieldCount = 1;
775 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
776 test->field = valueW;
777 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
778 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
779 ok( hr == E_INVALIDARG, "got %08x\n", hr );
781 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
782 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
783 ok( hr == E_INVALIDARG, "got %08x\n", hr );
785 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
786 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
787 ok( hr == S_OK, "got %08x\n", hr );
789 hr = WsWriteEndElement( writer, NULL );
790 ok( hr == S_OK, "got %08x\n", hr );
791 check_output( writer, "<struct>value</struct>", __LINE__ );
793 /* required value */
794 hr = set_output( writer );
795 ok( hr == S_OK, "got %08x\n", hr );
797 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
798 ok( hr == S_OK, "got %08x\n", hr );
800 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
801 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
802 ok( hr == S_OK, "got %08x\n", hr );
804 hr = WsWriteEndElement( writer, NULL );
805 ok( hr == S_OK, "got %08x\n", hr );
806 check_output( writer, "<struct>value</struct>", __LINE__ );
808 hr = set_output( writer );
809 ok( hr == S_OK, "got %08x\n", hr );
811 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
812 ok( hr == S_OK, "got %08x\n", hr );
814 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
815 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
816 ok( hr == S_OK, "got %08x\n", hr );
818 hr = WsWriteEndElement( writer, NULL );
819 ok( hr == S_OK, "got %08x\n", hr );
820 check_output( writer, "<struct>value</struct>", __LINE__ );
822 hr = set_output( writer );
823 ok( hr == S_OK, "got %08x\n", hr );
825 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
826 ok( hr == S_OK, "got %08x\n", hr );
828 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
829 ok( hr == S_OK, "got %08x\n", hr );
831 hr = WsWriteType( writer, WS_ATTRIBUTE_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 = WsWriteEndAttribute( writer, NULL );
836 ok( hr == S_OK, "got %08x\n", hr );
838 hr = WsWriteEndElement( writer, NULL );
839 ok( hr == S_OK, "got %08x\n", hr );
840 check_output( writer, "<struct struct=\"value\"/>", __LINE__ );
842 HeapFree( GetProcessHeap(), 0, test );
843 WsFreeWriter( writer );
846 static void test_WsWriteElement(void)
848 static const WCHAR testW[] = {'t','e','s','t',0};
849 HRESULT hr;
850 WS_XML_WRITER *writer;
851 WS_STRUCT_DESCRIPTION s;
852 WS_FIELD_DESCRIPTION f, *fields[1];
853 WS_ELEMENT_DESCRIPTION desc;
854 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
855 struct test { const WCHAR *str; } *test;
857 hr = WsCreateWriter( NULL, 0, &writer, NULL );
858 ok( hr == S_OK, "got %08x\n", hr );
860 hr = set_output( writer );
861 ok( hr == S_OK, "got %08x\n", hr );
863 /* text field mapping */
864 memset( &f, 0, sizeof(f) );
865 f.mapping = WS_TEXT_FIELD_MAPPING;
866 f.type = WS_WSZ_TYPE;
867 fields[0] = &f;
869 memset( &s, 0, sizeof(s) );
870 s.size = sizeof(struct test);
871 s.alignment = TYPE_ALIGNMENT(struct test);
872 s.fields = fields;
873 s.fieldCount = 1;
875 desc.elementLocalName = &localname;
876 desc.elementNs = &ns;
877 desc.type = WS_STRUCT_TYPE;
878 desc.typeDescription = &s;
880 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
881 test->str = testW;
882 hr = WsWriteElement( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
883 ok( hr == E_INVALIDARG, "got %08x\n", hr );
885 hr = WsWriteElement( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
886 ok( hr == E_INVALIDARG, "got %08x\n", hr );
888 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
889 ok( hr == E_INVALIDARG, "got %08x\n", hr );
891 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
892 ok( hr == S_OK, "got %08x\n", hr );
893 check_output( writer, "<str>test</str>", __LINE__ );
895 hr = set_output( writer );
896 ok( hr == S_OK, "got %08x\n", hr );
898 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
899 ok( hr == S_OK, "got %08x\n", hr );
901 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
902 ok( hr == S_OK, "got %08x\n", hr );
903 check_output( writer, "<str><str>test</str>", __LINE__ );
905 hr = set_output( writer );
906 ok( hr == S_OK, "got %08x\n", hr );
908 /* attribute field mapping */
909 f.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
911 /* requires localName and ns to be set */
912 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
913 ok( hr == E_INVALIDARG, "got %08x\n", hr );
915 hr = set_output( writer );
916 ok( hr == S_OK, "got %08x\n", hr );
918 f.localName = &localname;
919 f.ns = &ns;
920 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
921 ok( hr == S_OK, "got %08x\n", hr );
922 check_output( writer, "<str str=\"test\"/>", __LINE__ );
924 HeapFree( GetProcessHeap(), 0, test );
925 WsFreeWriter( writer );
928 static void test_WsWriteValue(void)
930 HRESULT hr;
931 WS_XML_WRITER *writer;
932 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
933 ULONG i;
934 static const struct
936 WS_VALUE_TYPE type;
937 INT64 val;
938 ULONG size;
939 const char *result;
940 const char *result2;
942 tests[] =
944 { WS_BOOL_VALUE_TYPE, ~0, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
945 { WS_BOOL_VALUE_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
946 { WS_INT8_VALUE_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
947 { WS_INT16_VALUE_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
948 { WS_INT32_VALUE_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
949 "<t t=\"-2147483648\"/>" },
950 { WS_INT64_VALUE_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
951 "<t t=\"-9223372036854775808\"/>" },
952 { WS_UINT8_VALUE_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
953 { WS_UINT16_VALUE_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
954 { WS_UINT32_VALUE_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
955 { WS_UINT64_VALUE_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
956 "<t t=\"18446744073709551615\"/>" },
959 hr = WsCreateWriter( NULL, 0, &writer, NULL );
960 ok( hr == S_OK, "got %08x\n", hr );
962 hr = set_output( writer );
963 ok( hr == S_OK, "got %08x\n", hr );
965 hr = WsWriteValue( NULL, tests[0].type, &tests[0].val, tests[0].size, NULL );
966 ok( hr == E_INVALIDARG, "got %08x\n", hr );
968 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, tests[0].size, NULL );
969 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
971 hr = set_output( writer );
972 ok( hr == S_OK, "got %08x\n", hr );
974 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
975 ok( hr == S_OK, "got %08x\n", hr );
977 /* zero size */
978 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, 0, NULL );
979 ok( hr == E_INVALIDARG, "got %08x\n", hr );
981 hr = set_output( writer );
982 ok( hr == S_OK, "got %08x\n", hr );
984 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
985 ok( hr == S_OK, "got %08x\n", hr );
987 /* NULL value */
988 hr = WsWriteValue( writer, tests[0].type, NULL, 0, NULL );
989 ok( hr == E_INVALIDARG, "got %08x\n", hr );
991 /* element type mapping */
992 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
994 hr = set_output( writer );
995 ok( hr == S_OK, "got %08x\n", hr );
997 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
998 ok( hr == S_OK, "got %08x\n", hr );
1000 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1001 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1003 hr = WsWriteEndElement( writer, NULL );
1004 ok( hr == S_OK, "got %08x\n", hr );
1005 check_output( writer, tests[i].result, __LINE__ );
1008 /* attribute type mapping */
1009 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1011 hr = set_output( writer );
1012 ok( hr == S_OK, "got %08x\n", hr );
1014 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1015 ok( hr == S_OK, "got %08x\n", hr );
1017 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
1018 ok( hr == S_OK, "got %08x\n", hr );
1020 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1021 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1023 hr = WsWriteEndAttribute( writer, NULL );
1024 ok( hr == S_OK, "got %08x\n", hr );
1026 hr = WsWriteEndElement( writer, NULL );
1027 ok( hr == S_OK, "got %08x\n", hr );
1028 check_output( writer, tests[i].result2, __LINE__ );
1031 WsFreeWriter( writer );
1034 static void test_WsWriteAttribute(void)
1036 static const WCHAR testW[] = {'t','e','s','t',0};
1037 HRESULT hr;
1038 WS_XML_WRITER *writer;
1039 WS_STRUCT_DESCRIPTION s;
1040 WS_FIELD_DESCRIPTION f, *fields[1];
1041 WS_ATTRIBUTE_DESCRIPTION desc;
1042 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
1043 struct test { const WCHAR *str; } *test;
1045 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1046 ok( hr == S_OK, "got %08x\n", hr );
1048 hr = set_output( writer );
1049 ok( hr == S_OK, "got %08x\n", hr );
1051 /* text field mapping */
1052 memset( &f, 0, sizeof(f) );
1053 f.mapping = WS_TEXT_FIELD_MAPPING;
1054 f.type = WS_WSZ_TYPE;
1055 fields[0] = &f;
1057 memset( &s, 0, sizeof(s) );
1058 s.size = sizeof(struct test);
1059 s.alignment = TYPE_ALIGNMENT(struct test);
1060 s.fields = fields;
1061 s.fieldCount = 1;
1063 desc.attributeLocalName = &localname;
1064 desc.attributeNs = &ns;
1065 desc.type = WS_STRUCT_TYPE;
1066 desc.typeDescription = &s;
1068 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
1069 test->str = testW;
1070 hr = WsWriteAttribute( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1071 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1073 hr = WsWriteAttribute( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1074 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1076 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
1077 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1079 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1080 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1082 hr = set_output( writer );
1083 ok( hr == S_OK, "got %08x\n", hr );
1085 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1086 ok( hr == S_OK, "got %08x\n", hr );
1088 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1089 ok( hr == S_OK, "got %08x\n", hr );
1091 hr = WsWriteEndElement( writer, NULL );
1092 ok( hr == S_OK, "got %08x\n", hr );
1093 check_output( writer, "<str str=\"test\"/>", __LINE__ );
1095 HeapFree( GetProcessHeap(), 0, test );
1096 WsFreeWriter( writer );
1099 static void test_WsWriteStartCData(void)
1101 HRESULT hr;
1102 WS_XML_WRITER *writer;
1103 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1104 WS_XML_UTF8_TEXT text = {{WS_XML_TEXT_TYPE_UTF8}};
1106 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1107 ok( hr == S_OK, "got %08x\n", hr );
1109 hr = set_output( writer );
1110 ok( hr == S_OK, "got %08x\n", hr );
1112 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1113 ok( hr == S_OK, "got %08x\n", hr );
1115 hr = WsWriteEndCData( writer, NULL );
1116 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1118 hr = set_output( writer );
1119 ok( hr == S_OK, "got %08x\n", hr );
1121 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1122 ok( hr == S_OK, "got %08x\n", hr );
1123 check_output( writer, "", __LINE__ );
1125 hr = WsWriteStartCData( writer, NULL );
1126 ok( hr == S_OK, "got %08x\n", hr );
1127 check_output( writer, "<t><![CDATA[", __LINE__ );
1129 text.value.bytes = (BYTE *)"<data>";
1130 text.value.length = 6;
1131 hr = WsWriteText( writer, &text.text, NULL );
1132 ok( hr == S_OK, "got %08x\n", hr );
1133 check_output( writer, "<t><![CDATA[<data>", __LINE__ );
1135 hr = WsWriteEndCData( writer, NULL );
1136 ok( hr == S_OK, "got %08x\n", hr );
1137 check_output( writer, "<t><![CDATA[<data>]]>", __LINE__ );
1139 hr = WsWriteEndElement( writer, NULL );
1140 ok( hr == S_OK, "got %08x\n", hr );
1141 check_output( writer, "<t><![CDATA[<data>]]></t>", __LINE__ );
1143 WsFreeWriter( writer );
1146 static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
1148 WS_XML_WRITER *writer;
1149 WS_BYTES bytes;
1150 ULONG size = sizeof(bytes);
1151 int len = strlen(expected);
1152 HRESULT hr;
1154 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1155 ok( hr == S_OK, "got %08x\n", hr );
1157 hr = set_output( writer );
1158 ok( hr == S_OK, "got %08x\n", hr );
1160 hr = WsWriteXmlBuffer( writer, buffer, NULL );
1161 ok( hr == S_OK, "got %08x\n", hr );
1163 memset( &bytes, 0, sizeof(bytes) );
1164 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
1165 ok( hr == S_OK, "%u: got %08x\n", line, hr );
1166 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
1167 if (bytes.length != len) return;
1168 ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
1170 WsFreeWriter( writer );
1173 static void prepare_xmlns_test( WS_XML_WRITER *writer, WS_HEAP **heap, WS_XML_BUFFER **buffer )
1175 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1176 HRESULT hr;
1178 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, heap, NULL );
1179 ok( hr == S_OK, "got %08x\n", hr );
1181 hr = WsCreateXmlBuffer( *heap, NULL, 0, buffer, NULL );
1182 ok( hr == S_OK, "got %08x\n", hr );
1184 hr = WsSetOutputToBuffer( writer, *buffer, NULL, 0, NULL );
1185 ok( hr == S_OK, "got %08x\n", hr );
1187 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
1188 ok( hr == S_OK, "got %08x\n", hr );
1191 static void test_WsWriteXmlnsAttribute(void)
1193 WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1194 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, prefix2 = {7, (BYTE *)"prefix2"};
1195 WS_XML_STRING xmlns = {6, (BYTE *)"xmlns"}, attr = {4, (BYTE *)"attr"};
1196 WS_XML_STRING localname = {1, (BYTE *)"u"};
1197 WS_HEAP *heap;
1198 WS_XML_BUFFER *buffer;
1199 WS_XML_WRITER *writer;
1200 HRESULT hr;
1202 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1203 ok( hr == S_OK, "got %08x\n", hr );
1205 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1206 ok( hr == S_OK, "got %08x\n", hr );
1208 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1209 ok( hr == S_OK, "got %08x\n", hr );
1211 hr = WsWriteXmlnsAttribute( NULL, NULL, NULL, FALSE, NULL );
1212 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1213 WsFreeHeap( heap );
1215 prepare_xmlns_test( writer, &heap, &buffer );
1216 hr = WsWriteXmlnsAttribute( writer, NULL, NULL, FALSE, NULL );
1217 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1218 WsFreeHeap( heap );
1220 prepare_xmlns_test( writer, &heap, &buffer );
1221 hr = WsWriteXmlnsAttribute( writer, &prefix2, NULL, FALSE, NULL );
1222 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1224 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1225 ok( hr == S_OK, "got %08x\n", hr );
1226 hr = WsWriteXmlnsAttribute( writer, NULL, &ns, FALSE, NULL );
1227 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1228 WsFreeHeap( heap );
1230 /* no prefix */
1231 prepare_xmlns_test( writer, &heap, &buffer );
1232 hr = WsWriteXmlnsAttribute( writer, NULL, &ns2, FALSE, NULL );
1233 ok( hr == S_OK, "got %08x\n", hr );
1234 hr = WsWriteEndElement( writer, NULL );
1235 ok( hr == S_OK, "got %08x\n", hr );
1236 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__ );
1237 WsFreeHeap( heap );
1239 /* prefix */
1240 prepare_xmlns_test( writer, &heap, &buffer );
1241 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1242 ok( hr == S_OK, "got %08x\n", hr );
1243 hr = WsWriteEndElement( writer, NULL );
1244 ok( hr == S_OK, "got %08x\n", hr );
1245 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__ );
1246 WsFreeHeap( heap );
1248 /* implicitly set element prefix namespace */
1249 prepare_xmlns_test( writer, &heap, &buffer );
1250 hr = WsWriteEndElement( writer, NULL );
1251 ok( hr == S_OK, "got %08x\n", hr );
1252 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__ );
1253 WsFreeHeap( heap );
1255 /* explicitly set element prefix namespace */
1256 prepare_xmlns_test( writer, &heap, &buffer );
1257 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1258 ok( hr == S_OK, "got %08x\n", hr );
1259 hr = WsWriteEndElement( writer, NULL );
1260 ok( hr == S_OK, "got %08x\n", hr );
1261 check_output_buffer( buffer, "<prefix:t xmlns:prefix='ns'/>", __LINE__ );
1262 WsFreeHeap( heap );
1264 /* repeated calls, same namespace */
1265 prepare_xmlns_test( writer, &heap, &buffer );
1266 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1267 ok( hr == S_OK, "got %08x\n", hr );
1268 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1269 ok( hr == S_OK, "got %08x\n", hr );
1270 hr = WsWriteEndElement( writer, NULL );
1271 ok( hr == S_OK, "got %08x\n", hr );
1272 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__ );
1273 WsFreeHeap( heap );
1275 /* repeated calls, different namespace */
1276 prepare_xmlns_test( writer, &heap, &buffer );
1277 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1278 ok( hr == S_OK, "got %08x\n", hr );
1279 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1280 ok( hr == S_OK, "got %08x\n", hr );
1281 hr = WsWriteEndElement( writer, NULL );
1282 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1283 WsFreeHeap( heap );
1285 /* single quotes */
1286 prepare_xmlns_test( writer, &heap, &buffer );
1287 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, TRUE, 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='ns' xmlns:prefix=\"ns\"/>", __LINE__ );
1292 WsFreeHeap( heap );
1294 /* different namespace, different prefix */
1295 prepare_xmlns_test( writer, &heap, &buffer );
1296 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1297 ok( hr == S_OK, "got %08x\n", hr );
1298 hr = WsWriteEndElement( writer, NULL );
1299 ok( hr == S_OK, "got %08x\n", hr );
1300 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__ );
1301 WsFreeHeap( heap );
1303 /* different namespace, same prefix */
1304 prepare_xmlns_test( writer, &heap, &buffer );
1305 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns2, TRUE, NULL );
1306 ok( hr == S_OK, "got %08x\n", hr );
1307 hr = WsWriteEndElement( writer, NULL );
1308 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1309 WsFreeHeap( heap );
1311 /* regular attribute */
1312 prepare_xmlns_test( writer, &heap, &buffer );
1313 hr = WsWriteStartAttribute( writer, &xmlns, &prefix2, &ns2, TRUE, NULL );
1314 ok( hr == S_OK, "got %08x\n", hr );
1315 hr = WsWriteEndAttribute( writer, NULL );
1316 ok( hr == S_OK, "got %08x\n", hr );
1317 hr = WsWriteEndElement( writer, NULL );
1318 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1319 WsFreeHeap( heap );
1321 /* attribute order */
1322 prepare_xmlns_test( writer, &heap, &buffer );
1323 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1324 ok( hr == S_OK, "got %08x\n", hr );
1325 hr = WsWriteStartAttribute( writer, &prefix, &attr, &ns, TRUE, NULL );
1326 ok( hr == S_OK, "got %08x\n", hr );
1327 hr = WsWriteEndAttribute( writer, NULL );
1328 ok( hr == S_OK, "got %08x\n", hr );
1329 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1330 ok( hr == S_OK, "got %08x\n", hr );
1331 hr = WsWriteEndElement( writer, NULL );
1332 ok( hr == S_OK, "got %08x\n", hr );
1333 check_output_buffer( buffer, "<prefix:t prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__ );
1334 WsFreeHeap( heap );
1336 /* scope */
1337 prepare_xmlns_test( writer, &heap, &buffer );
1338 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1339 ok( hr == S_OK, "got %08x\n", hr );
1340 hr = WsWriteStartElement( writer, &prefix2, &localname, &ns2, NULL );
1341 ok( hr == S_OK, "got %08x\n", hr );
1342 hr = WsWriteEndElement( writer, 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\"><prefix2:u/></prefix:t>",
1347 __LINE__ );
1348 WsFreeHeap( heap );
1350 WsFreeWriter( writer );
1353 static void prepare_prefix_test( WS_XML_WRITER *writer )
1355 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1356 HRESULT hr;
1358 hr = set_output( writer );
1359 ok( hr == S_OK, "got %08x\n", hr );
1360 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1361 ok( hr == S_OK, "got %08x\n", hr );
1362 hr = WsWriteEndStartElement( writer, NULL );
1363 ok( hr == S_OK, "got %08x\n", hr );
1366 static void test_WsGetPrefixFromNamespace(void)
1368 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, *prefix;
1369 const WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1370 WS_XML_WRITER *writer;
1371 HRESULT hr;
1373 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1374 ok( hr == S_OK, "got %08x\n", hr );
1376 hr = set_output( writer );
1377 ok( hr == S_OK, "got %08x\n", hr );
1378 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1379 ok( hr == S_OK, "got %08x\n", hr );
1381 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, NULL, NULL );
1382 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1384 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, &prefix, NULL );
1385 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1387 hr = WsGetPrefixFromNamespace( writer, NULL, FALSE, &prefix, NULL );
1388 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1390 /* element must be committed */
1391 hr = set_output( writer );
1392 ok( hr == S_OK, "got %08x\n", hr );
1393 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1394 ok( hr == S_OK, "got %08x\n", hr );
1395 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1396 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1398 /* but writer can't be positioned on end element node */
1399 hr = set_output( writer );
1400 ok( hr == S_OK, "got %08x\n", hr );
1401 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1402 ok( hr == S_OK, "got %08x\n", hr );
1403 hr = WsWriteEndElement( writer, NULL );
1404 ok( hr == S_OK, "got %08x\n", hr );
1405 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1406 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1408 /* required = TRUE */
1409 prefix = NULL;
1410 prepare_prefix_test( writer );
1411 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1412 ok( hr == S_OK, "got %08x\n", hr );
1413 ok( prefix != NULL, "prefix not set\n" );
1414 if (prefix)
1416 ok( prefix->length == 1, "got %u\n", prefix->length );
1417 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1420 prefix = (const WS_XML_STRING *)0xdeadbeef;
1421 hr = WsGetPrefixFromNamespace( writer, &ns2, TRUE, &prefix, NULL );
1422 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1423 ok( prefix == (const WS_XML_STRING *)0xdeadbeef, "prefix set\n" );
1425 /* required = FALSE */
1426 prefix = NULL;
1427 prepare_prefix_test( writer );
1428 hr = WsGetPrefixFromNamespace( writer, &ns, FALSE, &prefix, NULL );
1429 ok( hr == S_OK, "got %08x\n", hr );
1430 ok( prefix != NULL, "prefix not set\n" );
1431 if (prefix)
1433 ok( prefix->length == 1, "got %u\n", prefix->length );
1434 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1437 prefix = (const WS_XML_STRING *)0xdeadbeef;
1438 hr = WsGetPrefixFromNamespace( writer, &ns2, FALSE, &prefix, NULL );
1439 ok( hr == S_FALSE, "got %08x\n", hr );
1440 ok( prefix == NULL, "prefix not set\n" );
1442 WsFreeWriter( writer );
1445 static void test_complex_struct_type(void)
1447 static const char expected[] =
1448 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1449 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1450 "</o:OfficeConfig>";
1451 static const WCHAR timestampW[] =
1452 {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
1453 WS_XML_STRING str_officeconfig = {12, (BYTE *)"OfficeConfig"};
1454 WS_XML_STRING str_services = {8, (BYTE *)"services"};
1455 WS_XML_STRING str_generationtime = {14, (BYTE *)"GenerationTime"};
1456 WS_XML_STRING ns = {39, (BYTE *)"urn:schemas-microsoft-com:office:office"};
1457 WS_XML_STRING prefix = {1, (BYTE *)"o"};
1458 DWORD size;
1459 HRESULT hr;
1460 WS_HEAP *heap;
1461 WS_XML_BUFFER *buffer;
1462 WS_XML_WRITER *writer;
1463 WS_STRUCT_DESCRIPTION s, s2;
1464 WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
1465 struct services
1467 const WCHAR *generationtime;
1469 struct officeconfig
1471 struct services *services;
1472 } *test;
1474 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1475 ok( hr == S_OK, "got %08x\n", hr );
1477 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1478 ok( hr == S_OK, "got %08x\n", hr );
1480 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1481 ok( hr == S_OK, "got %08x\n", hr );
1483 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1484 ok( hr == S_OK, "got %08x\n", hr );
1486 hr = WsWriteStartElement( writer, &prefix, &str_officeconfig, &ns, NULL );
1487 ok( hr == S_OK, "got %08x\n", hr );
1489 memset( &f2, 0, sizeof(f2) );
1490 f2.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
1491 f2.localName = &str_generationtime;
1492 f2.ns = &ns;
1493 f2.type = WS_WSZ_TYPE;
1494 f2.options = WS_FIELD_OPTIONAL;
1495 fields2[0] = &f2;
1497 memset( &s2, 0, sizeof(s2) );
1498 s2.size = sizeof(*test->services);
1499 s2.alignment = 4;
1500 s2.fields = fields2;
1501 s2.fieldCount = 1;
1502 s2.typeLocalName = &str_services;
1503 s2.typeNs = &ns;
1505 memset( &f, 0, sizeof(f) );
1506 f.mapping = WS_ELEMENT_FIELD_MAPPING;
1507 f.localName = &str_services;
1508 f.ns = &ns;
1509 f.type = WS_STRUCT_TYPE;
1510 f.typeDescription = &s2;
1511 f.options = WS_FIELD_POINTER;
1512 fields[0] = &f;
1514 memset( &s, 0, sizeof(s) );
1515 s.size = sizeof(*test);
1516 s.alignment = 4;
1517 s.fields = fields;
1518 s.fieldCount = 1;
1519 s.typeLocalName = &str_officeconfig;
1520 s.typeNs = &ns;
1522 size = sizeof(struct officeconfig) + sizeof(struct services);
1523 test = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
1524 test->services = (struct services *)(test + 1);
1525 test->services->generationtime = timestampW;
1526 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
1527 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1528 ok( hr == S_OK, "got %08x\n", hr );
1530 hr = WsWriteEndElement( writer, NULL );
1531 ok( hr == S_OK, "got %08x\n", hr );
1532 check_output_buffer( buffer, expected, __LINE__ );
1534 HeapFree( GetProcessHeap(), 0, test );
1535 WsFreeWriter( writer );
1536 WsFreeHeap( heap );
1539 static void test_WsMoveWriter(void)
1541 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, ns = {0, NULL};
1542 WS_HEAP *heap;
1543 WS_XML_WRITER *writer;
1544 WS_XML_BUFFER *buffer;
1545 HRESULT hr;
1547 hr = WsMoveWriter( NULL, WS_MOVE_TO_EOF, NULL, NULL );
1548 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1550 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1551 ok( hr == S_OK, "got %08x\n", hr );
1553 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1554 ok( hr == S_OK, "got %08x\n", hr );
1556 hr = set_output( writer );
1557 ok( hr == S_OK, "got %08x\n", hr );
1559 /* writer must be set to an XML buffer */
1560 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1561 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1563 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1564 ok( hr == S_OK, "got %08x\n", hr );
1566 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1567 ok( hr == S_OK, "got %08x\n", hr );
1569 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1570 ok( hr == S_OK, "got %08x\n", hr );
1572 /* <a><b/></a> */
1573 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1574 ok( hr == S_OK, "got %08x\n", hr );
1576 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1577 ok( hr == S_OK, "got %08x\n", hr );
1579 hr = WsWriteEndElement( writer, NULL );
1580 ok( hr == S_OK, "got %08x\n", hr );
1582 hr = WsWriteEndElement( writer, NULL );
1583 ok( hr == S_OK, "got %08x\n", hr );
1585 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1586 ok( hr == S_OK, "got %08x\n", hr );
1588 hr = WsMoveWriter( writer, WS_MOVE_TO_ROOT_ELEMENT, NULL, NULL );
1589 ok( hr == S_OK, "got %08x\n", hr );
1591 hr = WsMoveWriter( writer, WS_MOVE_TO_CHILD_ELEMENT, NULL, NULL );
1592 ok( hr == S_OK, "got %08x\n", hr );
1594 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1595 ok( hr == S_OK, "got %08x\n", hr );
1597 hr = WsMoveWriter( writer, WS_MOVE_TO_PARENT_ELEMENT, NULL, NULL );
1598 ok( hr == S_OK, "got %08x\n", hr );
1600 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1601 ok( hr == S_OK, "got %08x\n", hr );
1603 hr = WsMoveWriter( writer, WS_MOVE_TO_BOF, NULL, NULL );
1604 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1606 WsFreeWriter( writer );
1607 WsFreeHeap( heap );
1610 static void test_WsGetWriterPosition(void)
1612 WS_HEAP *heap;
1613 WS_XML_WRITER *writer;
1614 WS_XML_BUFFER *buffer;
1615 WS_XML_NODE_POSITION pos;
1616 HRESULT hr;
1618 hr = WsGetWriterPosition( NULL, NULL, NULL );
1619 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1621 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1622 ok( hr == S_OK, "got %08x\n", hr );
1624 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1625 ok( hr == S_OK, "got %08x\n", hr );
1627 hr = WsGetWriterPosition( writer, &pos, NULL );
1628 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1630 hr = set_output( writer );
1631 ok( hr == S_OK, "got %08x\n", hr );
1633 /* writer must be set to an XML buffer */
1634 hr = WsGetWriterPosition( writer, &pos, NULL );
1635 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1637 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1638 ok( hr == S_OK, "got %08x\n", hr );
1640 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1641 ok( hr == S_OK, "got %08x\n", hr );
1643 hr = WsGetWriterPosition( writer, NULL, NULL );
1644 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1646 pos.buffer = pos.node = NULL;
1647 hr = WsGetWriterPosition( writer, &pos, NULL );
1648 ok( hr == S_OK, "got %08x\n", hr );
1649 ok( pos.buffer != NULL, "buffer not set\n" );
1650 ok( pos.node != NULL, "node not set\n" );
1652 WsFreeWriter( writer );
1653 WsFreeHeap( heap );
1656 static void test_WsSetWriterPosition(void)
1658 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1659 WS_HEAP *heap;
1660 WS_XML_WRITER *writer;
1661 WS_XML_BUFFER *buf1, *buf2;
1662 WS_XML_NODE_POSITION pos;
1663 HRESULT hr;
1665 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1666 ok( hr == S_OK, "got %08x\n", hr );
1668 hr = WsSetWriterPosition( NULL, NULL, NULL );
1669 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1671 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1672 ok( hr == S_OK, "got %08x\n", hr );
1674 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf1, NULL );
1675 ok( hr == S_OK, "got %08x\n", hr );
1677 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1678 ok( hr == S_OK, "got %08x\n", hr );
1680 hr = WsSetWriterPosition( writer, NULL, NULL );
1681 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1683 pos.buffer = pos.node = NULL;
1684 hr = WsGetWriterPosition( writer, &pos, NULL );
1685 ok( hr == S_OK, "got %08x\n", hr );
1686 ok( pos.buffer == buf1, "wrong buffer\n" );
1687 ok( pos.node != NULL, "node not set\n" );
1689 hr = WsSetWriterPosition( writer, &pos, NULL );
1690 ok( hr == S_OK, "got %08x\n", hr );
1692 /* different buffer */
1693 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf2, NULL );
1694 ok( hr == S_OK, "got %08x\n", hr );
1696 pos.buffer = buf2;
1697 hr = WsSetWriterPosition( writer, &pos, NULL );
1698 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1700 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1701 ok( hr == S_OK, "got %08x\n", hr );
1703 /* try to write at non-final position */
1704 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1705 ok( hr == S_OK, "got %08x\n", hr );
1707 pos.buffer = pos.node = NULL;
1708 hr = WsGetWriterPosition( writer, &pos, NULL );
1709 ok( hr == S_OK, "got %08x\n", hr );
1710 ok( pos.buffer == buf1, "wrong buffer\n" );
1711 ok( pos.node != NULL, "node not set\n" );
1713 hr = WsWriteEndElement( writer, NULL );
1714 ok( hr == S_OK, "got %08x\n", hr );
1715 check_output_buffer( buf1, "<t/>", __LINE__ );
1717 hr = WsSetWriterPosition( writer, &pos, NULL );
1718 ok( hr == S_OK, "got %08x\n", hr );
1720 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1721 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1723 WsFreeWriter( writer );
1724 WsFreeHeap( heap );
1727 static void test_WsWriteXmlBuffer(void)
1729 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1730 WS_XML_WRITER *writer1, *writer2;
1731 WS_XML_BUFFER *buffer1, *buffer2;
1732 WS_HEAP *heap;
1733 HRESULT hr;
1735 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1736 ok( hr == S_OK, "got %08x\n", hr );
1738 hr = WsCreateXmlBuffer( NULL, NULL, 0, NULL, NULL );
1739 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1741 hr = WsCreateWriter( NULL, 0, &writer1, NULL );
1742 ok( hr == S_OK, "got %08x\n", hr );
1744 hr = WsCreateXmlBuffer( heap, NULL, 0, NULL, NULL );
1745 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1747 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer1, NULL );
1748 ok( hr == S_OK, "got %08x\n", hr );
1750 hr = WsSetOutputToBuffer( writer1, buffer1, NULL, 0, NULL );
1751 ok( hr == S_OK, "got %08x\n", hr );
1753 hr = WsWriteStartElement( writer1, NULL, &localname, &ns, NULL );
1754 ok( hr == S_OK, "got %08x\n", hr );
1756 hr = WsWriteEndElement( writer1, NULL );
1757 ok( hr == S_OK, "got %08x\n", hr );
1758 check_output_buffer( buffer1, "<t/>", __LINE__ );
1760 hr = WsCreateWriter( NULL, 0, &writer2, NULL );
1761 ok( hr == S_OK, "got %08x\n", hr );
1763 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer2, NULL );
1764 ok( hr == S_OK, "got %08x\n", hr );
1766 hr = WsSetOutputToBuffer( writer2, buffer2, NULL, 0, NULL );
1767 ok( hr == S_OK, "got %08x\n", hr );
1769 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1770 ok( hr == S_OK, "got %08x\n", hr );
1771 check_output_buffer( buffer2, "<t/>", __LINE__ );
1773 hr = WsMoveWriter( writer2, WS_MOVE_TO_PREVIOUS_ELEMENT, NULL, NULL );
1774 todo_wine ok( hr == S_OK, "got %08x\n", hr );
1776 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1777 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1779 WsFreeWriter( writer1 );
1780 WsFreeWriter( writer2 );
1781 WsFreeHeap( heap );
1784 static void test_WsWriteNode(void)
1786 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {4, (BYTE *)"attr"}, ns = {0, NULL};
1787 WS_XML_WRITER *writer;
1788 WS_XML_BUFFER *buffer;
1789 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
1790 WS_XML_ATTRIBUTE attr, *attrs[1];
1791 WS_XML_ELEMENT_NODE elem;
1792 WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
1793 WS_XML_NODE node;
1794 WS_XML_TEXT_NODE text = {{WS_XML_NODE_TYPE_TEXT}};
1795 WS_HEAP *heap;
1796 HRESULT hr;
1798 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1799 ok( hr == S_OK, "got %08x\n", hr );
1801 hr = WsWriteNode( NULL, NULL, NULL );
1802 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1804 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1805 ok( hr == S_OK, "got %08x\n", hr );
1807 hr = WsWriteNode( writer, NULL, NULL );
1808 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1810 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1811 ok( hr == S_OK, "got %08x\n", hr );
1813 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1814 ok( hr == S_OK, "got %08x\n", hr );
1816 utf8.value.bytes = (BYTE *)"value";
1817 utf8.value.length = sizeof("value") - 1;
1819 attr.singleQuote = TRUE;
1820 attr.isXmlNs = FALSE;
1821 attr.prefix = NULL;
1822 attr.localName = &localname2;
1823 attr.ns = &ns;
1824 attr.value = &utf8.text;
1825 attrs[0] = &attr;
1827 elem.node.nodeType = WS_XML_NODE_TYPE_ELEMENT;
1828 elem.prefix = NULL;
1829 elem.localName = &localname;
1830 elem.ns = &ns;
1831 elem.attributeCount = 1;
1832 elem.attributes = attrs;
1833 elem.isEmpty = FALSE;
1834 hr = WsWriteNode( writer, &elem.node, NULL );
1835 ok( hr == S_OK, "got %08x\n", hr );
1837 comment.value.bytes = (BYTE *)"comment";
1838 comment.value.length = sizeof("comment") - 1;
1839 hr = WsWriteNode( writer, &comment.node, NULL );
1840 ok( hr == S_OK, "got %08x\n", hr );
1842 node.nodeType = WS_XML_NODE_TYPE_EOF;
1843 hr = WsWriteNode( writer, &node, NULL );
1844 ok( hr == S_OK, "got %08x\n", hr );
1846 node.nodeType = WS_XML_NODE_TYPE_BOF;
1847 hr = WsWriteNode( writer, &node, NULL );
1848 ok( hr == S_OK, "got %08x\n", hr );
1850 node.nodeType = WS_XML_NODE_TYPE_CDATA;
1851 hr = WsWriteNode( writer, &node, NULL );
1852 ok( hr == S_OK, "got %08x\n", hr );
1854 utf8.value.bytes = (BYTE *)"cdata";
1855 utf8.value.length = sizeof("cdata") - 1;
1856 text.text = &utf8.text;
1857 hr = WsWriteNode( writer, &text.node, NULL );
1858 ok( hr == S_OK, "got %08x\n", hr );
1860 node.nodeType = WS_XML_NODE_TYPE_END_CDATA;
1861 hr = WsWriteNode( writer, &node, NULL );
1862 ok( hr == S_OK, "got %08x\n", hr );
1864 utf8.value.bytes = (BYTE *)"text";
1865 utf8.value.length = sizeof("text") - 1;
1866 hr = WsWriteNode( writer, &text.node, NULL );
1867 ok( hr == S_OK, "got %08x\n", hr );
1869 node.nodeType = WS_XML_NODE_TYPE_END_ELEMENT;
1870 hr = WsWriteNode( writer, &node, NULL );
1871 ok( hr == S_OK, "got %08x\n", hr );
1872 check_output_buffer( buffer, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__ );
1874 WsFreeWriter( writer );
1875 WsFreeHeap( heap );
1878 static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
1880 WS_XML_READER_TEXT_ENCODING enc;
1881 WS_XML_READER_BUFFER_INPUT input;
1883 enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
1884 enc.charSet = WS_CHARSET_AUTO;
1886 input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
1887 input.encodedData = (void *)data;
1888 input.encodedDataSize = size;
1890 return WsSetInput( reader, &enc.encoding, &input.input, NULL, 0, NULL );
1893 static void test_WsCopyNode(void)
1895 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
1896 WS_XML_NODE_POSITION pos, pos2;
1897 WS_XML_WRITER *writer;
1898 WS_XML_READER *reader;
1899 WS_XML_BUFFER *buffer;
1900 WS_HEAP *heap;
1901 HRESULT hr;
1903 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1904 ok( hr == S_OK, "got %08x\n", hr );
1906 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1907 ok( hr == S_OK, "got %08x\n", hr );
1909 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1910 ok( hr == S_OK, "got %08x\n", hr );
1912 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1913 ok( hr == S_OK, "got %08x\n", hr );
1915 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1916 ok( hr == S_OK, "got %08x\n", hr );
1918 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1919 ok( hr == S_OK, "got %08x\n", hr );
1921 hr = WsWriteEndElement( writer, NULL );
1922 ok( hr == S_OK, "got %08x\n", hr );
1924 hr = WsGetWriterPosition( writer, &pos, NULL );
1925 ok( hr == S_OK, "got %08x\n", hr );
1927 hr = WsWriteEndElement( writer, NULL );
1928 ok( hr == S_OK, "got %08x\n", hr );
1929 check_output_buffer( buffer, "<t><u/></t>", __LINE__ );
1931 hr = WsCreateReader( NULL, 0, &reader, NULL );
1932 ok( hr == S_OK, "got %08x\n", hr );
1934 hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
1935 ok( hr == S_OK, "got %08x\n", hr );
1937 hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
1938 ok( hr == S_OK, "got %08x\n", hr );
1940 hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
1941 ok( hr == S_OK, "got %08x\n", hr );
1943 hr = WsSetWriterPosition( writer, &pos, NULL );
1944 ok( hr == S_OK, "got %08x\n", hr );
1946 hr = WsCopyNode( writer, reader, NULL );
1947 ok( hr == S_OK, "got %08x\n", hr );
1948 check_output_buffer( buffer, "<t><u/><v/></t>", __LINE__ );
1950 hr = WsGetWriterPosition( writer, &pos2, NULL );
1951 ok( hr == S_OK, "got %08x\n", hr );
1952 ok( pos2.buffer == pos.buffer, "wrong buffer\n" );
1953 ok( pos2.node == pos.node, "wrong node\n" );
1955 WsFreeReader( reader );
1956 WsFreeWriter( writer );
1957 WsFreeHeap( heap );
1960 static void test_text_types(void)
1962 static const WCHAR utf16W[] = {'u','t','f','1','6'};
1963 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1964 WS_XML_WRITER *writer;
1965 static const WS_XML_UTF8_TEXT val_utf8 = { {WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"utf8"} };
1966 static WS_XML_UTF16_TEXT val_utf16 = { {WS_XML_TEXT_TYPE_UTF16} };
1967 static const WS_XML_GUID_TEXT val_guid = { {WS_XML_TEXT_TYPE_GUID} };
1968 static const WS_XML_UNIQUE_ID_TEXT val_urn = { {WS_XML_TEXT_TYPE_UNIQUE_ID} };
1969 static const WS_XML_BOOL_TEXT val_bool = { {WS_XML_TEXT_TYPE_BOOL}, TRUE };
1970 static const WS_XML_INT32_TEXT val_int32 = { {WS_XML_TEXT_TYPE_INT32}, -2147483647 - 1 };
1971 static const WS_XML_INT64_TEXT val_int64 = { {WS_XML_TEXT_TYPE_INT64}, -9223372036854775807 - 1 };
1972 static const WS_XML_UINT64_TEXT val_uint64 = { {WS_XML_TEXT_TYPE_UINT64}, ~0 };
1973 static const struct
1975 const WS_XML_TEXT *text;
1976 const char *result;
1978 tests[] =
1980 { &val_utf8.text, "<t>utf8</t>" },
1981 { &val_utf16.text, "<t>utf16</t>" },
1982 { &val_guid.text, "<t>00000000-0000-0000-0000-000000000000</t>" },
1983 { &val_urn.text, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
1984 { &val_bool.text, "<t>true</t>" },
1985 { &val_int32.text, "<t>-2147483648</t>" },
1986 { &val_int64.text, "<t>-9223372036854775808</t>" },
1987 { &val_uint64.text, "<t>18446744073709551615</t>" },
1989 HRESULT hr;
1990 ULONG i;
1992 val_utf16.bytes = (BYTE *)utf16W;
1993 val_utf16.byteCount = sizeof(utf16W);
1995 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1996 ok( hr == S_OK, "got %08x\n", hr );
1998 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2000 hr = set_output( writer );
2001 ok( hr == S_OK, "got %08x\n", hr );
2002 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2003 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2005 hr = WsWriteText( writer, tests[i].text, NULL );
2006 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2008 hr = WsWriteEndElement( writer, NULL );
2009 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2010 check_output( writer, tests[i].result, __LINE__ );
2013 WsFreeWriter( writer );
2016 static void test_double(void)
2018 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2019 static const struct
2021 double val;
2022 const char *result;
2024 tests[] =
2026 {0.0, "<t>0</t>"},
2027 {1.0, "<t>1</t>"},
2028 {-1.0, "<t>-1</t>"},
2029 {1.0000000000000001, "<t>1</t>"},
2030 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2031 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2032 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2033 {100000000000000, "<t>100000000000000</t>"},
2034 {1000000000000000, "<t>1E+15</t>"},
2035 {0.1, "<t>0.1</t>"},
2036 {0.01, "<t>1E-2</t>"},
2037 {-0.1, "<t>-0.1</t>"},
2038 {-0.01, "<t>-1E-2</t>"},
2039 {1.7976931348623158e308, "<t>1.7976931348623157E+308</t>"},
2040 {-1.7976931348623158e308, "<t>-1.7976931348623157E+308</t>"},
2042 HRESULT hr;
2043 WS_XML_WRITER *writer;
2044 WS_XML_DOUBLE_TEXT text;
2045 ULONG i;
2047 hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
2048 ok( hr == S_OK, "got %08x\n", hr );
2050 text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
2051 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2053 hr = set_output( writer );
2054 ok( hr == S_OK, "got %08x\n", hr );
2055 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2056 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2058 text.value = tests[i].val;
2059 hr = WsWriteText( writer, &text.text, NULL );
2060 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2062 hr = WsWriteEndElement( writer, NULL );
2063 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2064 check_output( writer, tests[i].result, __LINE__ );
2067 hr = set_output( writer );
2068 ok( hr == S_OK, "got %08x\n", hr );
2069 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2070 ok( hr == S_OK, "got %08x\n", hr );
2072 text.value = NAN;
2073 hr = WsWriteText( writer, &text.text, NULL );
2074 ok( hr == S_OK, "got %08x\n", hr );
2076 hr = WsWriteEndElement( writer, NULL );
2077 ok( hr == S_OK, "got %08x\n", hr );
2078 check_output( writer, "<t>NaN</t>", __LINE__ );
2080 hr = set_output( writer );
2081 ok( hr == S_OK, "got %08x\n", hr );
2082 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2083 ok( hr == S_OK, "got %08x\n", hr );
2085 text.value = INFINITY;
2086 hr = WsWriteText( writer, &text.text, NULL );
2087 ok( hr == S_OK, "got %08x\n", hr );
2089 hr = WsWriteEndElement( writer, NULL );
2090 ok( hr == S_OK, "got %08x\n", hr );
2091 check_output( writer, "<t>INF</t>", __LINE__ );
2093 hr = set_output( writer );
2094 ok( hr == S_OK, "got %08x\n", hr );
2095 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2096 ok( hr == S_OK, "got %08x\n", hr );
2098 text.value = -INFINITY;
2099 hr = WsWriteText( writer, &text.text, NULL );
2100 ok( hr == S_OK, "got %08x\n", hr );
2102 hr = WsWriteEndElement( writer, NULL );
2103 ok( hr == S_OK, "got %08x\n", hr );
2104 check_output( writer, "<t>-INF</t>", __LINE__ );
2106 WsFreeWriter( writer );
2109 static void test_field_flags(void)
2111 static const char expected[] =
2112 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2113 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2114 HRESULT hr;
2115 WS_XML_WRITER *writer;
2116 WS_STRUCT_DESCRIPTION s;
2117 WS_FIELD_DESCRIPTION f, f2, f3, f4, *fields[4];
2118 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, str_guid = {4, (BYTE *)"guid"};
2119 WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_bool = {4, (BYTE *)"bool"};
2120 WS_XML_STRING str_xmlstr = {6, (BYTE *)"xmlstr"};
2121 INT32 val = -1;
2122 struct test
2124 GUID guid;
2125 BOOL *bool_ptr;
2126 INT32 *int32_ptr;
2127 WS_XML_STRING xmlstr;
2128 } test;
2130 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2131 ok( hr == S_OK, "got %08x\n", hr );
2133 hr = set_output( writer );
2134 ok( hr == S_OK, "got %08x\n", hr );
2136 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2137 ok( hr == S_OK, "got %08x\n", hr );
2139 memset( &f, 0, sizeof(f) );
2140 f.mapping = WS_ELEMENT_FIELD_MAPPING;
2141 f.localName = &str_guid;
2142 f.ns = &ns;
2143 f.type = WS_GUID_TYPE;
2144 f.options = WS_FIELD_OPTIONAL;
2145 fields[0] = &f;
2147 memset( &f2, 0, sizeof(f2) );
2148 f2.mapping = WS_ELEMENT_FIELD_MAPPING;
2149 f2.localName = &str_bool;
2150 f2.offset = FIELD_OFFSET(struct test, bool_ptr);
2151 f2.ns = &ns;
2152 f2.type = WS_BOOL_TYPE;
2153 f2.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2154 fields[1] = &f2;
2156 memset( &f3, 0, sizeof(f3) );
2157 f3.mapping = WS_ELEMENT_FIELD_MAPPING;
2158 f3.localName = &str_int32;
2159 f3.offset = FIELD_OFFSET(struct test, int32_ptr);
2160 f3.ns = &ns;
2161 f3.type = WS_INT32_TYPE;
2162 f3.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2163 fields[2] = &f3;
2165 memset( &f4, 0, sizeof(f4) );
2166 f4.mapping = WS_ELEMENT_FIELD_MAPPING;
2167 f4.localName = &str_xmlstr;
2168 f4.offset = FIELD_OFFSET(struct test, xmlstr);
2169 f4.ns = &ns;
2170 f4.type = WS_XML_STRING_TYPE;
2171 f4.options = WS_FIELD_NILLABLE;
2172 fields[3] = &f4;
2174 memset( &s, 0, sizeof(s) );
2175 s.size = sizeof(struct test);
2176 s.alignment = TYPE_ALIGNMENT(struct test);
2177 s.fields = fields;
2178 s.fieldCount = 4;
2180 memset( &test, 0, sizeof(test) );
2181 test.int32_ptr = &val;
2182 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE,
2183 &test, sizeof(test), NULL );
2184 ok( hr == S_OK, "got %08x\n", hr );
2186 hr = WsWriteEndElement( writer, NULL );
2187 ok( hr == S_OK, "got %08x\n", hr );
2188 check_output( writer, expected, __LINE__ );
2190 WsFreeWriter( writer );
2193 static void test_WsWriteText(void)
2195 HRESULT hr;
2196 WS_XML_WRITER *writer;
2197 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
2199 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2200 ok( hr == S_OK, "got %08x\n", hr );
2202 hr = set_output( writer );
2203 ok( hr == S_OK, "got %08x\n", hr );
2205 utf8.value.bytes = (BYTE *)"test";
2206 utf8.value.length = 4;
2207 hr = WsWriteText( writer, &utf8.text, NULL );
2208 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
2210 WsFreeWriter( writer );
2213 static void test_WsWriteArray(void)
2215 static const WS_XML_STRING localname = {4, (BYTE *)"item"}, localname2 = {5, (BYTE *)"array"};
2216 static const WS_XML_STRING ns = {0, NULL};
2217 WS_XML_WRITER *writer;
2218 BOOL array_bool[2];
2219 HRESULT hr;
2221 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2222 ok( hr == S_OK, "got %08x\n", hr );
2224 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2225 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
2227 hr = set_output( writer );
2228 ok( hr == S_OK, "got %08x\n", hr );
2229 hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL );
2230 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2232 hr = set_output( writer );
2233 ok( hr == S_OK, "got %08x\n", hr );
2234 hr = WsWriteArray( writer, &localname, NULL, 0, NULL, 0, 0, 0, NULL );
2235 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2237 hr = set_output( writer );
2238 ok( hr == S_OK, "got %08x\n", hr );
2239 hr = WsWriteArray( writer, &localname, &ns, 0, NULL, 0, 0, 0, NULL );
2240 ok( hr == S_OK, "got %08x\n", hr );
2241 check_output( writer, "", __LINE__ );
2243 hr = WsWriteArray( writer, &localname, &ns, ~0u, NULL, 0, 0, 0, NULL );
2244 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2246 hr = set_output( writer );
2247 ok( hr == S_OK, "got %08x\n", hr );
2248 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, 0, 0, 0, NULL );
2249 ok( hr == S_OK, "got %08x\n", hr );
2250 check_output( writer, "", __LINE__ );
2252 array_bool[0] = FALSE;
2253 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, 0, 0, 0, NULL );
2254 ok( hr == S_OK, "got %08x\n", hr );
2255 check_output( writer, "", __LINE__ );
2257 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 0, NULL );
2258 ok( hr == S_OK, "got %08x\n", hr );
2259 check_output( writer, "", __LINE__ );
2261 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 0, NULL );
2262 ok( hr == S_OK, "got %08x\n", hr );
2263 check_output( writer, "", __LINE__ );
2265 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 1, NULL );
2266 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2268 hr = set_output( writer );
2269 ok( hr == S_OK, "got %08x\n", hr );
2270 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 1, NULL );
2271 ok( hr == S_OK, "got %08x\n", hr );
2272 check_output( writer, "<item>false</item>", __LINE__ );
2274 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool) - 1, 0, 2, NULL );
2275 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2277 hr = set_output( writer );
2278 ok( hr == S_OK, "got %08x\n", hr );
2279 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 3, NULL );
2280 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2282 hr = set_output( writer );
2283 ok( hr == S_OK, "got %08x\n", hr );
2285 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
2286 ok( hr == S_OK, "got %08x\n", hr );
2288 array_bool[1] = TRUE;
2289 hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 2, NULL );
2290 ok( hr == S_OK, "got %08x\n", hr );
2292 hr = WsWriteEndElement( writer, NULL );
2293 ok( hr == S_OK, "got %08x\n", hr );
2294 check_output( writer, "<array><item>false</item><item>true</item></array>", __LINE__ );
2296 WsFreeWriter( writer );
2299 static void test_escapes(void)
2301 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2302 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
2303 WS_XML_WRITER *writer;
2304 struct test
2306 const char *text;
2307 const char *result;
2308 BOOL single;
2310 static const struct test tests_elem[] =
2312 { "<", "<t>&lt;</t>" },
2313 { ">", "<t>&gt;</t>" },
2314 { "\"", "<t>\"</t>" },
2315 { "&", "<t>&amp;</t>" },
2316 { "&&", "<t>&amp;&amp;</t>" },
2317 { "'", "<t>'</t>" },
2319 static const struct test tests_attr[] =
2321 { "<", "<t t=\"&lt;\"/>" },
2322 { ">", "<t t=\">\"/>" },
2323 { "\"", "<t t=\"&quot;\"/>" },
2324 { "&", "<t t=\"&amp;\"/>" },
2325 { "'", "<t t=\"'\"/>" },
2326 { "\"", "<t t='\"'/>", TRUE },
2327 { "'", "<t t='&apos;'/>", TRUE },
2329 static const struct test tests_cdata[] =
2331 { "<", "<t><![CDATA[<]]></t>" },
2332 { ">", "<t><![CDATA[>]]></t>" },
2333 { "\"", "<t><![CDATA[\"]]></t>" },
2334 { "&", "<t><![CDATA[&]]></t>" },
2335 { "[", "<t><![CDATA[[]]></t>" },
2336 { "]", "<t><![CDATA[]]]></t>" },
2337 { "'", "<t><![CDATA[']]></t>" },
2339 static const struct test tests_comment[] =
2341 { "<", "<t><!--<--></t>" },
2342 { ">", "<t><!-->--></t>" },
2343 { "\"", "<t><!--\"--></t>" },
2344 { "&", "<t><!--&--></t>" },
2345 { "'", "<t><!--'--></t>" },
2347 HRESULT hr;
2348 ULONG i;
2350 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2351 ok( hr == S_OK, "got %08x\n", hr );
2353 for (i = 0; i < sizeof(tests_elem)/sizeof(tests_elem[0]); i++)
2355 hr = set_output( writer );
2356 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2357 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2358 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2360 utf8.value.bytes = (BYTE *)tests_elem[i].text;
2361 utf8.value.length = strlen( tests_elem[i].text );
2362 hr = WsWriteText( writer, &utf8.text, NULL );
2363 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2365 hr = WsWriteEndElement( writer, NULL );
2366 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2367 check_output( writer, tests_elem[i].result, __LINE__ );
2370 for (i = 0; i < sizeof(tests_attr)/sizeof(tests_attr[0]); i++)
2372 hr = set_output( writer );
2373 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2374 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2375 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2377 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, tests_attr[i].single, NULL );
2378 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2380 utf8.value.bytes = (BYTE *)tests_attr[i].text;
2381 utf8.value.length = strlen( tests_attr[i].text );
2382 hr = WsWriteText( writer, &utf8.text, NULL );
2383 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2385 hr = WsWriteEndAttribute( writer, NULL );
2386 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2388 hr = WsWriteEndElement( writer, NULL );
2389 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2390 check_output( writer, tests_attr[i].result, __LINE__ );
2393 for (i = 0; i < sizeof(tests_cdata)/sizeof(tests_cdata[0]); i++)
2395 hr = set_output( writer );
2396 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2397 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2398 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2400 hr = WsWriteStartCData( writer, NULL );
2401 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2403 utf8.value.bytes = (BYTE *)tests_cdata[i].text;
2404 utf8.value.length = strlen( tests_cdata[i].text );
2405 hr = WsWriteText( writer, &utf8.text, NULL );
2406 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2408 hr = WsWriteEndCData( writer, NULL );
2409 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2411 hr = WsWriteEndElement( writer, NULL );
2412 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2413 check_output( writer, tests_cdata[i].result, __LINE__ );
2416 for (i = 0; i < sizeof(tests_comment)/sizeof(tests_comment[0]); i++)
2418 WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
2420 hr = set_output( writer );
2421 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2422 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2423 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2425 comment.value.bytes = (BYTE *)tests_comment[i].text;
2426 comment.value.length = strlen( tests_comment[i].text );
2427 hr = WsWriteNode( writer, &comment.node, NULL );
2428 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2430 hr = WsWriteEndElement( writer, NULL );
2431 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2432 check_output( writer, tests_comment[i].result, __LINE__ );
2435 WsFreeWriter( writer );
2438 START_TEST(writer)
2440 test_WsCreateWriter();
2441 test_WsCreateXmlBuffer();
2442 test_WsSetOutput();
2443 test_WsSetOutputToBuffer();
2444 test_WsWriteStartElement();
2445 test_WsWriteStartAttribute();
2446 test_WsWriteType();
2447 test_basic_type();
2448 test_simple_struct_type();
2449 test_WsWriteElement();
2450 test_WsWriteValue();
2451 test_WsWriteAttribute();
2452 test_WsWriteStartCData();
2453 test_WsWriteXmlnsAttribute();
2454 test_WsGetPrefixFromNamespace();
2455 test_complex_struct_type();
2456 test_WsMoveWriter();
2457 test_WsGetWriterPosition();
2458 test_WsSetWriterPosition();
2459 test_WsWriteXmlBuffer();
2460 test_WsWriteNode();
2461 test_WsCopyNode();
2462 test_text_types();
2463 test_double();
2464 test_field_flags();
2465 test_WsWriteText();
2466 test_WsWriteArray();
2467 test_escapes();