winebus.sys: Add stub driver.
[wine.git] / dlls / webservices / tests / writer.c
blobd9c3fb1fef5d2875c69f4521f502c25827734c8b
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 hr = WsWriteText( writer, &text.text, NULL );
469 ok( hr == S_OK, "got %08x\n", hr );
470 check_output( writer, "", __LINE__ );
472 /* WsWriteEndAttribute doesn't output anything */
473 hr = WsWriteEndAttribute( writer, NULL );
474 ok( hr == S_OK, "got %08x\n", hr );
475 check_output( writer, "", __LINE__ );
477 hr = WsWriteEndElement( writer, NULL );
478 ok( hr == S_OK, "got %08x\n", hr );
479 check_output( writer, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__ );
481 WsFreeWriter( writer );
484 static void test_WsWriteType(void)
486 static const WCHAR testW[] = {'t','e','s','t',0};
487 HRESULT hr;
488 WS_XML_WRITER *writer;
489 WS_XML_STRING prefix = {1, (BYTE*)"p"}, localname = {3, (BYTE *)"str"}, ns = {2, (BYTE *)"ns"};
490 const WCHAR *val_str;
492 hr = WsCreateWriter( NULL, 0, &writer, NULL );
493 ok( hr == S_OK, "got %08x\n", hr );
495 hr = set_output( writer );
496 ok( hr == S_OK, "got %08x\n", hr );
498 val_str = testW;
499 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
500 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
501 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
503 hr = set_output( writer );
504 ok( hr == S_OK, "got %08x\n", hr );
506 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
507 ok( hr == S_OK, "got %08x\n", hr );
509 /* required value */
510 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
511 WS_WRITE_REQUIRED_VALUE, NULL, sizeof(testW), NULL );
512 ok( hr == E_INVALIDARG, "got %08x\n", hr );
514 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
515 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
516 ok( hr == E_INVALIDARG, "got %08x\n", hr );
518 /* required pointer */
519 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
520 WS_WRITE_REQUIRED_POINTER, NULL, sizeof(val_str), NULL );
521 ok( hr == E_INVALIDARG, "got %08x\n", hr );
523 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
524 WS_WRITE_REQUIRED_VALUE, testW, sizeof(testW), NULL );
525 ok( hr == E_INVALIDARG, "got %08x\n", hr );
527 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
528 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(WCHAR **), NULL );
529 ok( hr == S_OK, "got %08x\n", hr );
530 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
532 hr = WsWriteEndElement( writer, NULL );
533 ok( hr == S_OK, "got %08x\n", hr );
534 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
536 hr = set_output( writer );
537 ok( hr == S_OK, "got %08x\n", hr );
539 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
540 ok( hr == S_OK, "got %08x\n", hr );
542 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
543 ok( hr == S_OK, "got %08x\n", hr );
545 val_str = testW;
546 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
547 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
548 ok( hr == S_OK, "got %08x\n", hr );
549 check_output( writer, "", __LINE__ );
551 hr = WsWriteEndAttribute( writer, NULL );
552 ok( hr == S_OK, "got %08x\n", hr );
553 check_output( writer, "", __LINE__ );
555 hr = WsWriteEndElement( writer, NULL );
556 ok( hr == S_OK, "got %08x\n", hr );
557 check_output( writer, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__ );
559 hr = set_output( writer );
560 ok( hr == S_OK, "got %08x\n", hr );
562 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
563 ok( hr == S_OK, "got %08x\n", hr );
565 val_str = testW;
566 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL,
567 WS_WRITE_REQUIRED_POINTER, &val_str, sizeof(val_str), NULL );
568 ok( hr == S_OK, "got %08x\n", hr );
569 check_output( writer, "<p:str xmlns:p=\"ns\">test", __LINE__ );
571 hr = WsWriteEndElement( writer, NULL );
572 ok( hr == S_OK, "got %08x\n", hr );
573 check_output( writer, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__ );
575 WsFreeWriter( writer );
578 static void test_basic_type(void)
580 static WCHAR testW[] = {'t','e','s','t',0};
581 HRESULT hr;
582 WS_XML_WRITER *writer;
583 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, xmlstr;
584 GUID guid;
585 WCHAR *str;
586 WS_STRING string;
587 ULONG i;
588 static const struct
590 WS_TYPE type;
591 INT64 val;
592 ULONG size;
593 const char *result;
594 const char *result2;
596 tests[] =
598 { WS_BOOL_TYPE, TRUE, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
599 { WS_BOOL_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
600 { WS_INT8_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
601 { WS_INT16_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
602 { WS_INT32_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
603 "<t t=\"-2147483648\"/>" },
604 { WS_INT64_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
605 "<t t=\"-9223372036854775808\"/>" },
606 { WS_UINT8_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
607 { WS_UINT16_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
608 { WS_UINT32_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
609 { WS_UINT64_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
610 "<t t=\"18446744073709551615\"/>" },
613 hr = WsCreateWriter( NULL, 0, &writer, NULL );
614 ok( hr == S_OK, "got %08x\n", hr );
616 /* element content type mapping */
617 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
619 hr = set_output( writer );
620 ok( hr == S_OK, "got %08x\n", hr );
622 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
623 ok( hr == S_OK, "got %08x\n", hr );
625 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
626 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
627 ok( hr == S_OK, "%u: got %08x\n", i, hr );
629 hr = WsWriteEndElement( writer, NULL );
630 ok( hr == S_OK, "got %08x\n", hr );
631 check_output( writer, tests[i].result, __LINE__ );
634 /* element type mapping is the same as element content type mapping for basic types */
635 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
637 const INT64 *ptr = &tests[i].val;
639 hr = set_output( writer );
640 ok( hr == S_OK, "got %08x\n", hr );
642 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
643 ok( hr == S_OK, "got %08x\n", hr );
645 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
646 WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
647 ok( hr == S_OK, "%u: got %08x\n", i, hr );
649 hr = WsWriteEndElement( writer, NULL );
650 ok( hr == S_OK, "got %08x\n", hr );
651 check_output( writer, tests[i].result, __LINE__ );
654 /* attribute type mapping */
655 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
657 hr = set_output( writer );
658 ok( hr == S_OK, "got %08x\n", hr );
660 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
661 ok( hr == S_OK, "got %08x\n", hr );
663 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
664 ok( hr == S_OK, "got %08x\n", hr );
666 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, tests[i].type, NULL,
667 WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
668 ok( hr == S_OK, "%u: got %08x\n", i, hr );
670 hr = WsWriteEndAttribute( writer, NULL );
671 ok( hr == S_OK, "got %08x\n", hr );
673 hr = WsWriteEndElement( writer, NULL );
674 ok( hr == S_OK, "got %08x\n", hr );
675 check_output( writer, tests[i].result2, __LINE__ );
678 hr = set_output( writer );
679 ok( hr == S_OK, "got %08x\n", hr );
681 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
682 ok( hr == S_OK, "got %08x\n", hr );
684 memset( &guid, 0, sizeof(guid) );
685 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
686 &guid, sizeof(guid), NULL );
687 ok( hr == S_OK, "got %08x\n", hr );
689 hr = WsWriteEndElement( writer, NULL );
690 ok( hr == S_OK, "got %08x\n", hr );
691 check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
693 hr = set_output( writer );
694 ok( hr == S_OK, "got %08x\n", hr );
696 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
697 ok( hr == S_OK, "got %08x\n", hr );
699 string.chars = testW;
700 string.length = 4;
701 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
702 &string, sizeof(string), NULL );
703 ok( hr == S_OK, "got %08x\n", hr );
705 hr = WsWriteEndElement( writer, NULL );
706 ok( hr == S_OK, "got %08x\n", hr );
707 check_output( writer, "<t>test</t>", __LINE__ );
709 hr = set_output( writer );
710 ok( hr == S_OK, "got %08x\n", hr );
712 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
713 ok( hr == S_OK, "got %08x\n", hr );
715 str = testW;
716 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
717 &str, sizeof(str), NULL );
718 ok( hr == S_OK, "got %08x\n", hr );
720 hr = WsWriteEndElement( writer, NULL );
721 ok( hr == S_OK, "got %08x\n", hr );
722 check_output( writer, "<t>test</t>", __LINE__ );
724 hr = set_output( writer );
725 ok( hr == S_OK, "got %08x\n", hr );
727 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
728 ok( hr == S_OK, "got %08x\n", hr );
730 xmlstr.bytes = (BYTE *)"test";
731 xmlstr.length = 4;
732 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
733 &xmlstr, sizeof(xmlstr), NULL );
734 ok( hr == S_OK, "got %08x\n", hr );
736 hr = WsWriteEndElement( writer, NULL );
737 ok( hr == S_OK, "got %08x\n", hr );
738 check_output( writer, "<t>test</t>", __LINE__ );
740 WsFreeWriter( writer );
743 static void test_simple_struct_type(void)
745 static const WCHAR valueW[] = {'v','a','l','u','e',0};
746 HRESULT hr;
747 WS_XML_WRITER *writer;
748 WS_STRUCT_DESCRIPTION s;
749 WS_FIELD_DESCRIPTION f, *fields[1];
750 WS_XML_STRING localname = {6, (BYTE *)"struct"}, ns = {0, NULL};
751 struct test
753 const WCHAR *field;
754 } *test;
756 hr = WsCreateWriter( NULL, 0, &writer, NULL );
757 ok( hr == S_OK, "got %08x\n", hr );
759 hr = set_output( writer );
760 ok( hr == S_OK, "got %08x\n", hr );
762 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
763 ok( hr == S_OK, "got %08x\n", hr );
765 memset( &f, 0, sizeof(f) );
766 f.mapping = WS_TEXT_FIELD_MAPPING;
767 f.type = WS_WSZ_TYPE;
768 fields[0] = &f;
770 memset( &s, 0, sizeof(s) );
771 s.size = sizeof(struct test);
772 s.alignment = TYPE_ALIGNMENT(struct test);
773 s.fields = fields;
774 s.fieldCount = 1;
776 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
777 test->field = valueW;
778 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
779 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
780 ok( hr == E_INVALIDARG, "got %08x\n", hr );
782 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
783 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
784 ok( hr == E_INVALIDARG, "got %08x\n", hr );
786 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
787 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
788 ok( hr == S_OK, "got %08x\n", hr );
790 hr = WsWriteEndElement( writer, NULL );
791 ok( hr == S_OK, "got %08x\n", hr );
792 check_output( writer, "<struct>value</struct>", __LINE__ );
794 /* required value */
795 hr = set_output( writer );
796 ok( hr == S_OK, "got %08x\n", hr );
798 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
799 ok( hr == S_OK, "got %08x\n", hr );
801 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
802 WS_WRITE_REQUIRED_VALUE, test, sizeof(*test), NULL );
803 ok( hr == S_OK, "got %08x\n", hr );
805 hr = WsWriteEndElement( writer, NULL );
806 ok( hr == S_OK, "got %08x\n", hr );
807 check_output( writer, "<struct>value</struct>", __LINE__ );
809 hr = set_output( writer );
810 ok( hr == S_OK, "got %08x\n", hr );
812 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
813 ok( hr == S_OK, "got %08x\n", hr );
815 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
816 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
817 ok( hr == S_OK, "got %08x\n", hr );
819 hr = WsWriteEndElement( writer, NULL );
820 ok( hr == S_OK, "got %08x\n", hr );
821 check_output( writer, "<struct>value</struct>", __LINE__ );
823 hr = set_output( writer );
824 ok( hr == S_OK, "got %08x\n", hr );
826 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
827 ok( hr == S_OK, "got %08x\n", hr );
829 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
830 ok( hr == S_OK, "got %08x\n", hr );
832 hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
833 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
834 ok( hr == S_OK, "got %08x\n", hr );
836 hr = WsWriteEndAttribute( writer, NULL );
837 ok( hr == S_OK, "got %08x\n", hr );
839 hr = WsWriteEndElement( writer, NULL );
840 ok( hr == S_OK, "got %08x\n", hr );
841 check_output( writer, "<struct struct=\"value\"/>", __LINE__ );
843 HeapFree( GetProcessHeap(), 0, test );
844 WsFreeWriter( writer );
847 static void test_WsWriteElement(void)
849 static const WCHAR testW[] = {'t','e','s','t',0};
850 HRESULT hr;
851 WS_XML_WRITER *writer;
852 WS_STRUCT_DESCRIPTION s;
853 WS_FIELD_DESCRIPTION f, *fields[1];
854 WS_ELEMENT_DESCRIPTION desc;
855 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
856 struct test { const WCHAR *str; } *test;
858 hr = WsCreateWriter( NULL, 0, &writer, NULL );
859 ok( hr == S_OK, "got %08x\n", hr );
861 hr = set_output( writer );
862 ok( hr == S_OK, "got %08x\n", hr );
864 /* text field mapping */
865 memset( &f, 0, sizeof(f) );
866 f.mapping = WS_TEXT_FIELD_MAPPING;
867 f.type = WS_WSZ_TYPE;
868 fields[0] = &f;
870 memset( &s, 0, sizeof(s) );
871 s.size = sizeof(struct test);
872 s.alignment = TYPE_ALIGNMENT(struct test);
873 s.fields = fields;
874 s.fieldCount = 1;
876 desc.elementLocalName = &localname;
877 desc.elementNs = &ns;
878 desc.type = WS_STRUCT_TYPE;
879 desc.typeDescription = &s;
881 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
882 test->str = testW;
883 hr = WsWriteElement( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
884 ok( hr == E_INVALIDARG, "got %08x\n", hr );
886 hr = WsWriteElement( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
887 ok( hr == E_INVALIDARG, "got %08x\n", hr );
889 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
890 ok( hr == E_INVALIDARG, "got %08x\n", hr );
892 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
893 ok( hr == S_OK, "got %08x\n", hr );
894 check_output( writer, "<str>test</str>", __LINE__ );
896 hr = set_output( writer );
897 ok( hr == S_OK, "got %08x\n", hr );
899 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
900 ok( hr == S_OK, "got %08x\n", hr );
902 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
903 ok( hr == S_OK, "got %08x\n", hr );
904 check_output( writer, "<str><str>test</str>", __LINE__ );
906 hr = set_output( writer );
907 ok( hr == S_OK, "got %08x\n", hr );
909 /* attribute field mapping */
910 f.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
912 /* requires localName and ns to be set */
913 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
914 ok( hr == E_INVALIDARG, "got %08x\n", hr );
916 hr = set_output( writer );
917 ok( hr == S_OK, "got %08x\n", hr );
919 f.localName = &localname;
920 f.ns = &ns;
921 hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
922 ok( hr == S_OK, "got %08x\n", hr );
923 check_output( writer, "<str str=\"test\"/>", __LINE__ );
925 HeapFree( GetProcessHeap(), 0, test );
926 WsFreeWriter( writer );
929 static void test_WsWriteValue(void)
931 HRESULT hr;
932 WS_XML_WRITER *writer;
933 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
934 ULONG i;
935 static const struct
937 WS_VALUE_TYPE type;
938 INT64 val;
939 ULONG size;
940 const char *result;
941 const char *result2;
943 tests[] =
945 { WS_BOOL_VALUE_TYPE, ~0, sizeof(BOOL), "<t>true</t>", "<t t=\"true\"/>" },
946 { WS_BOOL_VALUE_TYPE, FALSE, sizeof(BOOL), "<t>false</t>", "<t t=\"false\"/>" },
947 { WS_INT8_VALUE_TYPE, -128, sizeof(INT8), "<t>-128</t>", "<t t=\"-128\"/>" },
948 { WS_INT16_VALUE_TYPE, -32768, sizeof(INT16), "<t>-32768</t>", "<t t=\"-32768\"/>" },
949 { WS_INT32_VALUE_TYPE, -2147483647 - 1, sizeof(INT32), "<t>-2147483648</t>",
950 "<t t=\"-2147483648\"/>" },
951 { WS_INT64_VALUE_TYPE, -9223372036854775807 - 1, sizeof(INT64), "<t>-9223372036854775808</t>",
952 "<t t=\"-9223372036854775808\"/>" },
953 { WS_UINT8_VALUE_TYPE, 255, sizeof(UINT8), "<t>255</t>", "<t t=\"255\"/>" },
954 { WS_UINT16_VALUE_TYPE, 65535, sizeof(UINT16), "<t>65535</t>", "<t t=\"65535\"/>" },
955 { WS_UINT32_VALUE_TYPE, ~0u, sizeof(UINT32), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
956 { WS_UINT64_VALUE_TYPE, ~0, sizeof(UINT64), "<t>18446744073709551615</t>",
957 "<t t=\"18446744073709551615\"/>" },
960 hr = WsCreateWriter( NULL, 0, &writer, NULL );
961 ok( hr == S_OK, "got %08x\n", hr );
963 hr = set_output( writer );
964 ok( hr == S_OK, "got %08x\n", hr );
966 hr = WsWriteValue( NULL, tests[0].type, &tests[0].val, tests[0].size, NULL );
967 ok( hr == E_INVALIDARG, "got %08x\n", hr );
969 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, tests[0].size, NULL );
970 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
972 hr = set_output( writer );
973 ok( hr == S_OK, "got %08x\n", hr );
975 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
976 ok( hr == S_OK, "got %08x\n", hr );
978 /* zero size */
979 hr = WsWriteValue( writer, tests[0].type, &tests[0].val, 0, NULL );
980 ok( hr == E_INVALIDARG, "got %08x\n", hr );
982 hr = set_output( writer );
983 ok( hr == S_OK, "got %08x\n", hr );
985 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
986 ok( hr == S_OK, "got %08x\n", hr );
988 /* NULL value */
989 hr = WsWriteValue( writer, tests[0].type, NULL, 0, NULL );
990 ok( hr == E_INVALIDARG, "got %08x\n", hr );
992 /* element type mapping */
993 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
995 hr = set_output( writer );
996 ok( hr == S_OK, "got %08x\n", hr );
998 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
999 ok( hr == S_OK, "got %08x\n", hr );
1001 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1002 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1004 hr = WsWriteEndElement( writer, NULL );
1005 ok( hr == S_OK, "got %08x\n", hr );
1006 check_output( writer, tests[i].result, __LINE__ );
1009 /* attribute type mapping */
1010 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1012 hr = set_output( writer );
1013 ok( hr == S_OK, "got %08x\n", hr );
1015 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1016 ok( hr == S_OK, "got %08x\n", hr );
1018 hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
1019 ok( hr == S_OK, "got %08x\n", hr );
1021 hr = WsWriteValue( writer, tests[i].type, &tests[i].val, tests[i].size, NULL );
1022 ok( hr == S_OK, "%u: got %08x\n", i, hr );
1024 hr = WsWriteEndAttribute( writer, NULL );
1025 ok( hr == S_OK, "got %08x\n", hr );
1027 hr = WsWriteEndElement( writer, NULL );
1028 ok( hr == S_OK, "got %08x\n", hr );
1029 check_output( writer, tests[i].result2, __LINE__ );
1032 WsFreeWriter( writer );
1035 static void test_WsWriteAttribute(void)
1037 static const WCHAR testW[] = {'t','e','s','t',0};
1038 HRESULT hr;
1039 WS_XML_WRITER *writer;
1040 WS_STRUCT_DESCRIPTION s;
1041 WS_FIELD_DESCRIPTION f, *fields[1];
1042 WS_ATTRIBUTE_DESCRIPTION desc;
1043 WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
1044 struct test { const WCHAR *str; } *test;
1046 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1047 ok( hr == S_OK, "got %08x\n", hr );
1049 hr = set_output( writer );
1050 ok( hr == S_OK, "got %08x\n", hr );
1052 /* text field mapping */
1053 memset( &f, 0, sizeof(f) );
1054 f.mapping = WS_TEXT_FIELD_MAPPING;
1055 f.type = WS_WSZ_TYPE;
1056 fields[0] = &f;
1058 memset( &s, 0, sizeof(s) );
1059 s.size = sizeof(struct test);
1060 s.alignment = TYPE_ALIGNMENT(struct test);
1061 s.fields = fields;
1062 s.fieldCount = 1;
1064 desc.attributeLocalName = &localname;
1065 desc.attributeNs = &ns;
1066 desc.type = WS_STRUCT_TYPE;
1067 desc.typeDescription = &s;
1069 test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
1070 test->str = testW;
1071 hr = WsWriteAttribute( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1072 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1074 hr = WsWriteAttribute( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1075 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1077 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
1078 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1080 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1081 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1083 hr = set_output( writer );
1084 ok( hr == S_OK, "got %08x\n", hr );
1086 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1087 ok( hr == S_OK, "got %08x\n", hr );
1089 hr = WsWriteAttribute( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1090 ok( hr == S_OK, "got %08x\n", hr );
1092 hr = WsWriteEndElement( writer, NULL );
1093 ok( hr == S_OK, "got %08x\n", hr );
1094 check_output( writer, "<str str=\"test\"/>", __LINE__ );
1096 HeapFree( GetProcessHeap(), 0, test );
1097 WsFreeWriter( writer );
1100 static void test_WsWriteStartCData(void)
1102 HRESULT hr;
1103 WS_XML_WRITER *writer;
1104 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1105 WS_XML_UTF8_TEXT text;
1107 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1108 ok( hr == S_OK, "got %08x\n", hr );
1110 hr = set_output( writer );
1111 ok( hr == S_OK, "got %08x\n", hr );
1113 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1114 ok( hr == S_OK, "got %08x\n", hr );
1116 hr = WsWriteEndCData( writer, NULL );
1117 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1119 hr = set_output( writer );
1120 ok( hr == S_OK, "got %08x\n", hr );
1122 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1123 ok( hr == S_OK, "got %08x\n", hr );
1124 check_output( writer, "", __LINE__ );
1126 hr = WsWriteStartCData( writer, NULL );
1127 ok( hr == S_OK, "got %08x\n", hr );
1128 check_output( writer, "<t><![CDATA[", __LINE__ );
1130 text.text.textType = WS_XML_TEXT_TYPE_UTF8;
1131 text.value.bytes = (BYTE *)"<data>";
1132 text.value.length = 6;
1133 hr = WsWriteText( writer, &text.text, NULL );
1134 ok( hr == S_OK, "got %08x\n", hr );
1135 check_output( writer, "<t><![CDATA[<data>", __LINE__ );
1137 hr = WsWriteEndCData( writer, NULL );
1138 ok( hr == S_OK, "got %08x\n", hr );
1139 check_output( writer, "<t><![CDATA[<data>]]>", __LINE__ );
1141 hr = WsWriteEndElement( writer, NULL );
1142 ok( hr == S_OK, "got %08x\n", hr );
1143 check_output( writer, "<t><![CDATA[<data>]]></t>", __LINE__ );
1145 WsFreeWriter( writer );
1148 static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
1150 WS_XML_WRITER *writer;
1151 WS_BYTES bytes;
1152 ULONG size = sizeof(bytes);
1153 int len = strlen(expected);
1154 HRESULT hr;
1156 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1157 ok( hr == S_OK, "got %08x\n", hr );
1159 hr = set_output( writer );
1160 ok( hr == S_OK, "got %08x\n", hr );
1162 hr = WsWriteXmlBuffer( writer, buffer, NULL );
1163 ok( hr == S_OK, "got %08x\n", hr );
1165 memset( &bytes, 0, sizeof(bytes) );
1166 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
1167 ok( hr == S_OK, "%u: got %08x\n", line, hr );
1168 ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len );
1169 if (bytes.length != len) return;
1170 ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
1172 WsFreeWriter( writer );
1175 static void prepare_xmlns_test( WS_XML_WRITER *writer, WS_HEAP **heap, WS_XML_BUFFER **buffer )
1177 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1178 HRESULT hr;
1180 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, heap, NULL );
1181 ok( hr == S_OK, "got %08x\n", hr );
1183 hr = WsCreateXmlBuffer( *heap, NULL, 0, buffer, NULL );
1184 ok( hr == S_OK, "got %08x\n", hr );
1186 hr = WsSetOutputToBuffer( writer, *buffer, NULL, 0, NULL );
1187 ok( hr == S_OK, "got %08x\n", hr );
1189 hr = WsWriteStartElement( writer, &prefix, &localname, &ns, NULL );
1190 ok( hr == S_OK, "got %08x\n", hr );
1193 static void test_WsWriteXmlnsAttribute(void)
1195 WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1196 WS_XML_STRING prefix = {6, (BYTE *)"prefix"}, prefix2 = {7, (BYTE *)"prefix2"};
1197 WS_XML_STRING xmlns = {6, (BYTE *)"xmlns"}, attr = {4, (BYTE *)"attr"};
1198 WS_XML_STRING localname = {1, (BYTE *)"u"};
1199 WS_HEAP *heap;
1200 WS_XML_BUFFER *buffer;
1201 WS_XML_WRITER *writer;
1202 HRESULT hr;
1204 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1205 ok( hr == S_OK, "got %08x\n", hr );
1207 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1208 ok( hr == S_OK, "got %08x\n", hr );
1210 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1211 ok( hr == S_OK, "got %08x\n", hr );
1213 hr = WsWriteXmlnsAttribute( NULL, NULL, NULL, FALSE, NULL );
1214 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1215 WsFreeHeap( heap );
1217 prepare_xmlns_test( writer, &heap, &buffer );
1218 hr = WsWriteXmlnsAttribute( writer, NULL, NULL, FALSE, NULL );
1219 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1220 WsFreeHeap( heap );
1222 prepare_xmlns_test( writer, &heap, &buffer );
1223 hr = WsWriteXmlnsAttribute( writer, &prefix2, NULL, FALSE, NULL );
1224 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1226 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1227 ok( hr == S_OK, "got %08x\n", hr );
1228 hr = WsWriteXmlnsAttribute( writer, NULL, &ns, FALSE, NULL );
1229 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1230 WsFreeHeap( heap );
1232 /* no prefix */
1233 prepare_xmlns_test( writer, &heap, &buffer );
1234 hr = WsWriteXmlnsAttribute( writer, NULL, &ns2, FALSE, NULL );
1235 ok( hr == S_OK, "got %08x\n", hr );
1236 hr = WsWriteEndElement( writer, NULL );
1237 ok( hr == S_OK, "got %08x\n", hr );
1238 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__ );
1239 WsFreeHeap( heap );
1241 /* prefix */
1242 prepare_xmlns_test( writer, &heap, &buffer );
1243 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1244 ok( hr == S_OK, "got %08x\n", hr );
1245 hr = WsWriteEndElement( writer, NULL );
1246 ok( hr == S_OK, "got %08x\n", hr );
1247 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__ );
1248 WsFreeHeap( heap );
1250 /* implicitly set element prefix namespace */
1251 prepare_xmlns_test( writer, &heap, &buffer );
1252 hr = WsWriteEndElement( writer, NULL );
1253 ok( hr == S_OK, "got %08x\n", hr );
1254 check_output_buffer( buffer, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__ );
1255 WsFreeHeap( heap );
1257 /* explicitly set element prefix namespace */
1258 prepare_xmlns_test( writer, &heap, &buffer );
1259 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1260 ok( hr == S_OK, "got %08x\n", hr );
1261 hr = WsWriteEndElement( writer, NULL );
1262 ok( hr == S_OK, "got %08x\n", hr );
1263 check_output_buffer( buffer, "<prefix:t xmlns:prefix='ns'/>", __LINE__ );
1264 WsFreeHeap( heap );
1266 /* repeated calls, same namespace */
1267 prepare_xmlns_test( writer, &heap, &buffer );
1268 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1269 ok( hr == S_OK, "got %08x\n", hr );
1270 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1271 ok( hr == S_OK, "got %08x\n", hr );
1272 hr = WsWriteEndElement( writer, NULL );
1273 ok( hr == S_OK, "got %08x\n", hr );
1274 check_output_buffer( buffer, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__ );
1275 WsFreeHeap( heap );
1277 /* repeated calls, different namespace */
1278 prepare_xmlns_test( writer, &heap, &buffer );
1279 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, FALSE, NULL );
1280 ok( hr == S_OK, "got %08x\n", hr );
1281 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, FALSE, NULL );
1282 ok( hr == S_OK, "got %08x\n", hr );
1283 hr = WsWriteEndElement( writer, NULL );
1284 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1285 WsFreeHeap( heap );
1287 /* single quotes */
1288 prepare_xmlns_test( writer, &heap, &buffer );
1289 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns, TRUE, NULL );
1290 ok( hr == S_OK, "got %08x\n", hr );
1291 hr = WsWriteEndElement( writer, NULL );
1292 ok( hr == S_OK, "got %08x\n", hr );
1293 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns' xmlns:prefix=\"ns\"/>", __LINE__ );
1294 WsFreeHeap( heap );
1296 /* different namespace, different prefix */
1297 prepare_xmlns_test( writer, &heap, &buffer );
1298 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1299 ok( hr == S_OK, "got %08x\n", hr );
1300 hr = WsWriteEndElement( writer, NULL );
1301 ok( hr == S_OK, "got %08x\n", hr );
1302 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__ );
1303 WsFreeHeap( heap );
1305 /* different namespace, same prefix */
1306 prepare_xmlns_test( writer, &heap, &buffer );
1307 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns2, TRUE, NULL );
1308 ok( hr == S_OK, "got %08x\n", hr );
1309 hr = WsWriteEndElement( writer, NULL );
1310 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1311 WsFreeHeap( heap );
1313 /* regular attribute */
1314 prepare_xmlns_test( writer, &heap, &buffer );
1315 hr = WsWriteStartAttribute( writer, &xmlns, &prefix2, &ns2, TRUE, NULL );
1316 ok( hr == S_OK, "got %08x\n", hr );
1317 hr = WsWriteEndAttribute( writer, NULL );
1318 ok( hr == S_OK, "got %08x\n", hr );
1319 hr = WsWriteEndElement( writer, NULL );
1320 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1321 WsFreeHeap( heap );
1323 /* attribute order */
1324 prepare_xmlns_test( writer, &heap, &buffer );
1325 hr = WsWriteXmlnsAttribute( writer, &prefix, &ns, TRUE, NULL );
1326 ok( hr == S_OK, "got %08x\n", hr );
1327 hr = WsWriteStartAttribute( writer, &prefix, &attr, &ns, TRUE, NULL );
1328 ok( hr == S_OK, "got %08x\n", hr );
1329 hr = WsWriteEndAttribute( writer, NULL );
1330 ok( hr == S_OK, "got %08x\n", hr );
1331 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1332 ok( hr == S_OK, "got %08x\n", hr );
1333 hr = WsWriteEndElement( writer, NULL );
1334 ok( hr == S_OK, "got %08x\n", hr );
1335 check_output_buffer( buffer, "<prefix:t prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__ );
1336 WsFreeHeap( heap );
1338 /* scope */
1339 prepare_xmlns_test( writer, &heap, &buffer );
1340 hr = WsWriteXmlnsAttribute( writer, &prefix2, &ns2, TRUE, NULL );
1341 ok( hr == S_OK, "got %08x\n", hr );
1342 hr = WsWriteStartElement( writer, &prefix2, &localname, &ns2, 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 hr = WsWriteEndElement( writer, NULL );
1347 ok( hr == S_OK, "got %08x\n", hr );
1348 check_output_buffer( buffer, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"><prefix2:u/></prefix:t>",
1349 __LINE__ );
1350 WsFreeHeap( heap );
1352 WsFreeWriter( writer );
1355 static void prepare_prefix_test( WS_XML_WRITER *writer )
1357 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, ns = {2, (BYTE *)"ns"};
1358 HRESULT hr;
1360 hr = set_output( writer );
1361 ok( hr == S_OK, "got %08x\n", hr );
1362 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1363 ok( hr == S_OK, "got %08x\n", hr );
1364 hr = WsWriteEndStartElement( writer, NULL );
1365 ok( hr == S_OK, "got %08x\n", hr );
1368 static void test_WsGetPrefixFromNamespace(void)
1370 const WS_XML_STRING p = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, *prefix;
1371 const WS_XML_STRING ns = {2, (BYTE *)"ns"}, ns2 = {3, (BYTE *)"ns2"};
1372 WS_XML_WRITER *writer;
1373 HRESULT hr;
1375 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1376 ok( hr == S_OK, "got %08x\n", hr );
1378 hr = set_output( writer );
1379 ok( hr == S_OK, "got %08x\n", hr );
1380 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1381 ok( hr == S_OK, "got %08x\n", hr );
1383 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, NULL, NULL );
1384 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1386 hr = WsGetPrefixFromNamespace( NULL, NULL, FALSE, &prefix, NULL );
1387 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1389 hr = WsGetPrefixFromNamespace( writer, NULL, FALSE, &prefix, NULL );
1390 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1392 /* element must be committed */
1393 hr = set_output( writer );
1394 ok( hr == S_OK, "got %08x\n", hr );
1395 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1396 ok( hr == S_OK, "got %08x\n", hr );
1397 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1398 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1400 /* but writer can't be positioned on end element node */
1401 hr = set_output( writer );
1402 ok( hr == S_OK, "got %08x\n", hr );
1403 hr = WsWriteStartElement( writer, &p, &localname, &ns, NULL );
1404 ok( hr == S_OK, "got %08x\n", hr );
1405 hr = WsWriteEndElement( writer, NULL );
1406 ok( hr == S_OK, "got %08x\n", hr );
1407 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1408 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1410 /* required = TRUE */
1411 prefix = NULL;
1412 prepare_prefix_test( writer );
1413 hr = WsGetPrefixFromNamespace( writer, &ns, TRUE, &prefix, NULL );
1414 ok( hr == S_OK, "got %08x\n", hr );
1415 ok( prefix != NULL, "prefix not set\n" );
1416 if (prefix)
1418 ok( prefix->length == 1, "got %u\n", prefix->length );
1419 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1422 prefix = (const WS_XML_STRING *)0xdeadbeef;
1423 hr = WsGetPrefixFromNamespace( writer, &ns2, TRUE, &prefix, NULL );
1424 ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1425 ok( prefix == (const WS_XML_STRING *)0xdeadbeef, "prefix set\n" );
1427 /* required = FALSE */
1428 prefix = NULL;
1429 prepare_prefix_test( writer );
1430 hr = WsGetPrefixFromNamespace( writer, &ns, FALSE, &prefix, NULL );
1431 ok( hr == S_OK, "got %08x\n", hr );
1432 ok( prefix != NULL, "prefix not set\n" );
1433 if (prefix)
1435 ok( prefix->length == 1, "got %u\n", prefix->length );
1436 ok( !memcmp( prefix->bytes, "p", 1 ), "wrong prefix\n" );
1439 prefix = (const WS_XML_STRING *)0xdeadbeef;
1440 hr = WsGetPrefixFromNamespace( writer, &ns2, FALSE, &prefix, NULL );
1441 ok( hr == S_FALSE, "got %08x\n", hr );
1442 ok( prefix == NULL, "prefix not set\n" );
1444 WsFreeWriter( writer );
1447 static void test_complex_struct_type(void)
1449 static const char expected[] =
1450 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1451 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1452 "</o:OfficeConfig>";
1453 static const WCHAR timestampW[] =
1454 {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
1455 WS_XML_STRING str_officeconfig = {12, (BYTE *)"OfficeConfig"};
1456 WS_XML_STRING str_services = {8, (BYTE *)"services"};
1457 WS_XML_STRING str_generationtime = {14, (BYTE *)"GenerationTime"};
1458 WS_XML_STRING ns = {39, (BYTE *)"urn:schemas-microsoft-com:office:office"};
1459 WS_XML_STRING prefix = {1, (BYTE *)"o"};
1460 DWORD size;
1461 HRESULT hr;
1462 WS_HEAP *heap;
1463 WS_XML_BUFFER *buffer;
1464 WS_XML_WRITER *writer;
1465 WS_STRUCT_DESCRIPTION s, s2;
1466 WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
1467 struct services
1469 const WCHAR *generationtime;
1471 struct officeconfig
1473 struct services *services;
1474 } *test;
1476 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1477 ok( hr == S_OK, "got %08x\n", hr );
1479 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1480 ok( hr == S_OK, "got %08x\n", hr );
1482 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1483 ok( hr == S_OK, "got %08x\n", hr );
1485 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1486 ok( hr == S_OK, "got %08x\n", hr );
1488 hr = WsWriteStartElement( writer, &prefix, &str_officeconfig, &ns, NULL );
1489 ok( hr == S_OK, "got %08x\n", hr );
1491 memset( &f2, 0, sizeof(f2) );
1492 f2.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
1493 f2.localName = &str_generationtime;
1494 f2.ns = &ns;
1495 f2.type = WS_WSZ_TYPE;
1496 f2.options = WS_FIELD_OPTIONAL;
1497 fields2[0] = &f2;
1499 memset( &s2, 0, sizeof(s2) );
1500 s2.size = sizeof(*test->services);
1501 s2.alignment = 4;
1502 s2.fields = fields2;
1503 s2.fieldCount = 1;
1504 s2.typeLocalName = &str_services;
1505 s2.typeNs = &ns;
1507 memset( &f, 0, sizeof(f) );
1508 f.mapping = WS_ELEMENT_FIELD_MAPPING;
1509 f.localName = &str_services;
1510 f.ns = &ns;
1511 f.type = WS_STRUCT_TYPE;
1512 f.typeDescription = &s2;
1513 f.options = WS_FIELD_POINTER;
1514 fields[0] = &f;
1516 memset( &s, 0, sizeof(s) );
1517 s.size = sizeof(*test);
1518 s.alignment = 4;
1519 s.fields = fields;
1520 s.fieldCount = 1;
1521 s.typeLocalName = &str_officeconfig;
1522 s.typeNs = &ns;
1524 size = sizeof(struct officeconfig) + sizeof(struct services);
1525 test = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
1526 test->services = (struct services *)(test + 1);
1527 test->services->generationtime = timestampW;
1528 hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
1529 WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
1530 ok( hr == S_OK, "got %08x\n", hr );
1532 hr = WsWriteEndElement( writer, NULL );
1533 ok( hr == S_OK, "got %08x\n", hr );
1534 check_output_buffer( buffer, expected, __LINE__ );
1536 HeapFree( GetProcessHeap(), 0, test );
1537 WsFreeWriter( writer );
1538 WsFreeHeap( heap );
1541 static void test_WsMoveWriter(void)
1543 WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, ns = {0, NULL};
1544 WS_HEAP *heap;
1545 WS_XML_WRITER *writer;
1546 WS_XML_BUFFER *buffer;
1547 HRESULT hr;
1549 hr = WsMoveWriter( NULL, WS_MOVE_TO_EOF, NULL, NULL );
1550 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1552 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1553 ok( hr == S_OK, "got %08x\n", hr );
1555 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1556 ok( hr == S_OK, "got %08x\n", hr );
1558 hr = set_output( writer );
1559 ok( hr == S_OK, "got %08x\n", hr );
1561 /* writer must be set to an XML buffer */
1562 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1563 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1565 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1566 ok( hr == S_OK, "got %08x\n", hr );
1568 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1569 ok( hr == S_OK, "got %08x\n", hr );
1571 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1572 ok( hr == S_OK, "got %08x\n", hr );
1574 /* <a><b/></a> */
1575 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1576 ok( hr == S_OK, "got %08x\n", hr );
1578 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1579 ok( hr == S_OK, "got %08x\n", hr );
1581 hr = WsWriteEndElement( writer, NULL );
1582 ok( hr == S_OK, "got %08x\n", hr );
1584 hr = WsWriteEndElement( writer, NULL );
1585 ok( hr == S_OK, "got %08x\n", hr );
1587 hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
1588 ok( hr == S_OK, "got %08x\n", hr );
1590 hr = WsMoveWriter( writer, WS_MOVE_TO_ROOT_ELEMENT, NULL, NULL );
1591 ok( hr == S_OK, "got %08x\n", hr );
1593 hr = WsMoveWriter( writer, WS_MOVE_TO_CHILD_ELEMENT, NULL, NULL );
1594 ok( hr == S_OK, "got %08x\n", hr );
1596 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1597 ok( hr == S_OK, "got %08x\n", hr );
1599 hr = WsMoveWriter( writer, WS_MOVE_TO_PARENT_ELEMENT, NULL, NULL );
1600 ok( hr == S_OK, "got %08x\n", hr );
1602 hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
1603 ok( hr == S_OK, "got %08x\n", hr );
1605 hr = WsMoveWriter( writer, WS_MOVE_TO_BOF, NULL, NULL );
1606 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1608 WsFreeWriter( writer );
1609 WsFreeHeap( heap );
1612 static void test_WsGetWriterPosition(void)
1614 WS_HEAP *heap;
1615 WS_XML_WRITER *writer;
1616 WS_XML_BUFFER *buffer;
1617 WS_XML_NODE_POSITION pos;
1618 HRESULT hr;
1620 hr = WsGetWriterPosition( NULL, NULL, NULL );
1621 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1623 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1624 ok( hr == S_OK, "got %08x\n", hr );
1626 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1627 ok( hr == S_OK, "got %08x\n", hr );
1629 hr = WsGetWriterPosition( writer, &pos, NULL );
1630 ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1632 hr = set_output( writer );
1633 ok( hr == S_OK, "got %08x\n", hr );
1635 /* writer must be set to an XML buffer */
1636 hr = WsGetWriterPosition( writer, &pos, NULL );
1637 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1639 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1640 ok( hr == S_OK, "got %08x\n", hr );
1642 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1643 ok( hr == S_OK, "got %08x\n", hr );
1645 hr = WsGetWriterPosition( writer, NULL, NULL );
1646 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1648 pos.buffer = pos.node = NULL;
1649 hr = WsGetWriterPosition( writer, &pos, NULL );
1650 ok( hr == S_OK, "got %08x\n", hr );
1651 ok( pos.buffer != NULL, "buffer not set\n" );
1652 ok( pos.node != NULL, "node not set\n" );
1654 WsFreeWriter( writer );
1655 WsFreeHeap( heap );
1658 static void test_WsSetWriterPosition(void)
1660 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1661 WS_HEAP *heap;
1662 WS_XML_WRITER *writer;
1663 WS_XML_BUFFER *buf1, *buf2;
1664 WS_XML_NODE_POSITION pos;
1665 HRESULT hr;
1667 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1668 ok( hr == S_OK, "got %08x\n", hr );
1670 hr = WsSetWriterPosition( NULL, NULL, NULL );
1671 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1673 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1674 ok( hr == S_OK, "got %08x\n", hr );
1676 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf1, NULL );
1677 ok( hr == S_OK, "got %08x\n", hr );
1679 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1680 ok( hr == S_OK, "got %08x\n", hr );
1682 hr = WsSetWriterPosition( writer, NULL, NULL );
1683 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1685 pos.buffer = pos.node = NULL;
1686 hr = WsGetWriterPosition( writer, &pos, NULL );
1687 ok( hr == S_OK, "got %08x\n", hr );
1688 ok( pos.buffer == buf1, "wrong buffer\n" );
1689 ok( pos.node != NULL, "node not set\n" );
1691 hr = WsSetWriterPosition( writer, &pos, NULL );
1692 ok( hr == S_OK, "got %08x\n", hr );
1694 /* different buffer */
1695 hr = WsCreateXmlBuffer( heap, NULL, 0, &buf2, NULL );
1696 ok( hr == S_OK, "got %08x\n", hr );
1698 pos.buffer = buf2;
1699 hr = WsSetWriterPosition( writer, &pos, NULL );
1700 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1702 hr = WsSetOutputToBuffer( writer, buf1, NULL, 0, NULL );
1703 ok( hr == S_OK, "got %08x\n", hr );
1705 /* try to write at non-final position */
1706 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1707 ok( hr == S_OK, "got %08x\n", hr );
1709 pos.buffer = pos.node = NULL;
1710 hr = WsGetWriterPosition( writer, &pos, NULL );
1711 ok( hr == S_OK, "got %08x\n", hr );
1712 ok( pos.buffer == buf1, "wrong buffer\n" );
1713 ok( pos.node != NULL, "node not set\n" );
1715 hr = WsWriteEndElement( writer, NULL );
1716 ok( hr == S_OK, "got %08x\n", hr );
1717 check_output_buffer( buf1, "<t/>", __LINE__ );
1719 hr = WsSetWriterPosition( writer, &pos, NULL );
1720 ok( hr == S_OK, "got %08x\n", hr );
1722 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1723 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1725 WsFreeWriter( writer );
1726 WsFreeHeap( heap );
1729 static void test_WsWriteXmlBuffer(void)
1731 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1732 WS_XML_WRITER *writer1, *writer2;
1733 WS_XML_BUFFER *buffer1, *buffer2;
1734 WS_HEAP *heap;
1735 HRESULT hr;
1737 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1738 ok( hr == S_OK, "got %08x\n", hr );
1740 hr = WsCreateXmlBuffer( NULL, NULL, 0, NULL, NULL );
1741 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1743 hr = WsCreateWriter( NULL, 0, &writer1, NULL );
1744 ok( hr == S_OK, "got %08x\n", hr );
1746 hr = WsCreateXmlBuffer( heap, NULL, 0, NULL, NULL );
1747 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1749 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer1, NULL );
1750 ok( hr == S_OK, "got %08x\n", hr );
1752 hr = WsSetOutputToBuffer( writer1, buffer1, NULL, 0, NULL );
1753 ok( hr == S_OK, "got %08x\n", hr );
1755 hr = WsWriteStartElement( writer1, NULL, &localname, &ns, NULL );
1756 ok( hr == S_OK, "got %08x\n", hr );
1758 hr = WsWriteEndElement( writer1, NULL );
1759 ok( hr == S_OK, "got %08x\n", hr );
1760 check_output_buffer( buffer1, "<t/>", __LINE__ );
1762 hr = WsCreateWriter( NULL, 0, &writer2, NULL );
1763 ok( hr == S_OK, "got %08x\n", hr );
1765 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer2, NULL );
1766 ok( hr == S_OK, "got %08x\n", hr );
1768 hr = WsSetOutputToBuffer( writer2, buffer2, NULL, 0, NULL );
1769 ok( hr == S_OK, "got %08x\n", hr );
1771 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1772 ok( hr == S_OK, "got %08x\n", hr );
1773 check_output_buffer( buffer2, "<t/>", __LINE__ );
1775 hr = WsMoveWriter( writer2, WS_MOVE_TO_PREVIOUS_ELEMENT, NULL, NULL );
1776 todo_wine ok( hr == S_OK, "got %08x\n", hr );
1778 hr = WsWriteXmlBuffer( writer2, buffer1, NULL );
1779 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
1781 WsFreeWriter( writer1 );
1782 WsFreeWriter( writer2 );
1783 WsFreeHeap( heap );
1786 static void test_WsWriteNode(void)
1788 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {4, (BYTE *)"attr"}, ns = {0, NULL};
1789 WS_XML_WRITER *writer;
1790 WS_XML_BUFFER *buffer;
1791 WS_XML_UTF8_TEXT utf8;
1792 WS_XML_ATTRIBUTE attr, *attrs[1];
1793 WS_XML_ELEMENT_NODE elem;
1794 WS_XML_COMMENT_NODE comment;
1795 WS_XML_NODE node;
1796 WS_XML_TEXT_NODE text;
1797 WS_HEAP *heap;
1798 HRESULT hr;
1800 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1801 ok( hr == S_OK, "got %08x\n", hr );
1803 hr = WsWriteNode( NULL, NULL, NULL );
1804 ok( hr == E_INVALIDARG, "got %08x\n", hr );
1806 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1807 ok( hr == S_OK, "got %08x\n", hr );
1809 hr = WsWriteNode( writer, NULL, NULL );
1810 todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
1812 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1813 ok( hr == S_OK, "got %08x\n", hr );
1815 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1816 ok( hr == S_OK, "got %08x\n", hr );
1818 utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
1819 utf8.value.bytes = (BYTE *)"value";
1820 utf8.value.length = sizeof("value") - 1;
1822 attr.singleQuote = TRUE;
1823 attr.isXmlNs = FALSE;
1824 attr.prefix = NULL;
1825 attr.localName = &localname2;
1826 attr.ns = &ns;
1827 attr.value = &utf8.text;
1828 attrs[0] = &attr;
1830 elem.node.nodeType = WS_XML_NODE_TYPE_ELEMENT;
1831 elem.prefix = NULL;
1832 elem.localName = &localname;
1833 elem.ns = &ns;
1834 elem.attributeCount = 1;
1835 elem.attributes = attrs;
1836 elem.isEmpty = FALSE;
1837 hr = WsWriteNode( writer, (const WS_XML_NODE *)&elem, NULL );
1838 ok( hr == S_OK, "got %08x\n", hr );
1840 comment.node.nodeType = WS_XML_NODE_TYPE_COMMENT;
1841 comment.value.bytes = (BYTE *)"comment";
1842 comment.value.length = sizeof("comment") - 1;
1843 hr = WsWriteNode( writer, (const WS_XML_NODE *)&comment, NULL );
1844 ok( hr == S_OK, "got %08x\n", hr );
1846 node.nodeType = WS_XML_NODE_TYPE_EOF;
1847 hr = WsWriteNode( writer, &node, NULL );
1848 ok( hr == S_OK, "got %08x\n", hr );
1850 node.nodeType = WS_XML_NODE_TYPE_BOF;
1851 hr = WsWriteNode( writer, &node, NULL );
1852 ok( hr == S_OK, "got %08x\n", hr );
1854 node.nodeType = WS_XML_NODE_TYPE_CDATA;
1855 hr = WsWriteNode( writer, &node, NULL );
1856 ok( hr == S_OK, "got %08x\n", hr );
1858 utf8.value.bytes = (BYTE *)"cdata";
1859 utf8.value.length = sizeof("cdata") - 1;
1860 text.node.nodeType = WS_XML_NODE_TYPE_TEXT;
1861 text.text = &utf8.text;
1862 hr = WsWriteNode( writer, (const WS_XML_NODE *)&text, NULL );
1863 ok( hr == S_OK, "got %08x\n", hr );
1865 node.nodeType = WS_XML_NODE_TYPE_END_CDATA;
1866 hr = WsWriteNode( writer, &node, NULL );
1867 ok( hr == S_OK, "got %08x\n", hr );
1869 utf8.value.bytes = (BYTE *)"text";
1870 utf8.value.length = sizeof("text") - 1;
1871 hr = WsWriteNode( writer, (const WS_XML_NODE *)&text, NULL );
1872 ok( hr == S_OK, "got %08x\n", hr );
1874 node.nodeType = WS_XML_NODE_TYPE_END_ELEMENT;
1875 hr = WsWriteNode( writer, &node, NULL );
1876 ok( hr == S_OK, "got %08x\n", hr );
1877 check_output_buffer( buffer, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__ );
1879 WsFreeWriter( writer );
1880 WsFreeHeap( heap );
1883 static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
1885 WS_XML_READER_TEXT_ENCODING enc;
1886 WS_XML_READER_BUFFER_INPUT input;
1888 enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
1889 enc.charSet = WS_CHARSET_AUTO;
1891 input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
1892 input.encodedData = (void *)data;
1893 input.encodedDataSize = size;
1895 return WsSetInput( reader, &enc.encoding, &input.input, NULL, 0, NULL );
1898 static void test_WsCopyNode(void)
1900 WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
1901 WS_XML_NODE_POSITION pos, pos2;
1902 WS_XML_WRITER *writer;
1903 WS_XML_READER *reader;
1904 WS_XML_BUFFER *buffer;
1905 WS_HEAP *heap;
1906 HRESULT hr;
1908 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
1909 ok( hr == S_OK, "got %08x\n", hr );
1911 hr = WsCreateWriter( NULL, 0, &writer, NULL );
1912 ok( hr == S_OK, "got %08x\n", hr );
1914 hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
1915 ok( hr == S_OK, "got %08x\n", hr );
1917 hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
1918 ok( hr == S_OK, "got %08x\n", hr );
1920 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
1921 ok( hr == S_OK, "got %08x\n", hr );
1923 hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
1924 ok( hr == S_OK, "got %08x\n", hr );
1926 hr = WsWriteEndElement( writer, NULL );
1927 ok( hr == S_OK, "got %08x\n", hr );
1929 hr = WsGetWriterPosition( writer, &pos, NULL );
1930 ok( hr == S_OK, "got %08x\n", hr );
1932 hr = WsWriteEndElement( writer, NULL );
1933 ok( hr == S_OK, "got %08x\n", hr );
1934 check_output_buffer( buffer, "<t><u/></t>", __LINE__ );
1936 hr = WsCreateReader( NULL, 0, &reader, NULL );
1937 ok( hr == S_OK, "got %08x\n", hr );
1939 hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
1940 ok( hr == S_OK, "got %08x\n", hr );
1942 hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
1943 ok( hr == S_OK, "got %08x\n", hr );
1945 hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
1946 ok( hr == S_OK, "got %08x\n", hr );
1948 hr = WsSetWriterPosition( writer, &pos, NULL );
1949 ok( hr == S_OK, "got %08x\n", hr );
1951 hr = WsCopyNode( writer, reader, NULL );
1952 ok( hr == S_OK, "got %08x\n", hr );
1953 check_output_buffer( buffer, "<t><u/><v/></t>", __LINE__ );
1955 hr = WsGetWriterPosition( writer, &pos2, NULL );
1956 ok( hr == S_OK, "got %08x\n", hr );
1957 ok( pos2.buffer == pos.buffer, "wrong buffer\n" );
1958 ok( pos2.node == pos.node, "wrong node\n" );
1960 WsFreeReader( reader );
1961 WsFreeWriter( writer );
1962 WsFreeHeap( heap );
1965 static void test_text_types(void)
1967 static const WCHAR utf16W[] = {'u','t','f','1','6'};
1968 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
1969 WS_XML_WRITER *writer;
1970 static const WS_XML_UTF8_TEXT val_utf8 = { {WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"utf8"} };
1971 static WS_XML_UTF16_TEXT val_utf16 = { {WS_XML_TEXT_TYPE_UTF16} };
1972 static const WS_XML_GUID_TEXT val_guid = { {WS_XML_TEXT_TYPE_GUID} };
1973 static const WS_XML_UNIQUE_ID_TEXT val_urn = { {WS_XML_TEXT_TYPE_UNIQUE_ID} };
1974 static const WS_XML_BOOL_TEXT val_bool = { {WS_XML_TEXT_TYPE_BOOL}, TRUE };
1975 static const WS_XML_INT32_TEXT val_int32 = { {WS_XML_TEXT_TYPE_INT32}, -2147483647 - 1 };
1976 static const WS_XML_INT64_TEXT val_int64 = { {WS_XML_TEXT_TYPE_INT64}, -9223372036854775807 - 1 };
1977 static const WS_XML_UINT64_TEXT val_uint64 = { {WS_XML_TEXT_TYPE_UINT64}, ~0 };
1978 static const struct
1980 const WS_XML_TEXT *text;
1981 const char *result;
1983 tests[] =
1985 { &val_utf8.text, "<t>utf8</t>" },
1986 { &val_utf16.text, "<t>utf16</t>" },
1987 { &val_guid.text, "<t>00000000-0000-0000-0000-000000000000</t>" },
1988 { &val_urn.text, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
1989 { &val_bool.text, "<t>true</t>" },
1990 { &val_int32.text, "<t>-2147483648</t>" },
1991 { &val_int64.text, "<t>-9223372036854775808</t>" },
1992 { &val_uint64.text, "<t>18446744073709551615</t>" },
1994 HRESULT hr;
1995 ULONG i;
1997 val_utf16.bytes = (BYTE *)utf16W;
1998 val_utf16.byteCount = sizeof(utf16W);
2000 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2001 ok( hr == S_OK, "got %08x\n", hr );
2003 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2005 hr = set_output( writer );
2006 ok( hr == S_OK, "got %08x\n", hr );
2007 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2008 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2010 hr = WsWriteText( writer, tests[i].text, NULL );
2011 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2013 hr = WsWriteEndElement( writer, NULL );
2014 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2015 check_output( writer, tests[i].result, __LINE__ );
2018 WsFreeWriter( writer );
2021 static void test_double(void)
2023 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
2024 static const struct
2026 double val;
2027 const char *result;
2029 tests[] =
2031 {0.0, "<t>0</t>"},
2032 {1.0, "<t>1</t>"},
2033 {-1.0, "<t>-1</t>"},
2034 {1.0000000000000001, "<t>1</t>"},
2035 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2036 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2037 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2038 {100000000000000, "<t>100000000000000</t>"},
2039 {1000000000000000, "<t>1E+15</t>"},
2040 {0.1, "<t>0.1</t>"},
2041 {0.01, "<t>1E-2</t>"},
2042 {-0.1, "<t>-0.1</t>"},
2043 {-0.01, "<t>-1E-2</t>"},
2044 {1.7976931348623158e308, "<t>1.7976931348623157E+308</t>"},
2045 {-1.7976931348623158e308, "<t>-1.7976931348623157E+308</t>"},
2047 HRESULT hr;
2048 WS_XML_WRITER *writer;
2049 WS_XML_DOUBLE_TEXT text;
2050 ULONG i;
2052 hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
2053 ok( hr == S_OK, "got %08x\n", hr );
2055 text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
2056 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
2058 hr = set_output( writer );
2059 ok( hr == S_OK, "got %08x\n", hr );
2060 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2061 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2063 text.value = tests[i].val;
2064 hr = WsWriteText( writer, &text.text, NULL );
2065 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2067 hr = WsWriteEndElement( writer, NULL );
2068 ok( hr == S_OK, "%u: got %08x\n", i, hr );
2069 check_output( writer, tests[i].result, __LINE__ );
2072 hr = set_output( writer );
2073 ok( hr == S_OK, "got %08x\n", hr );
2074 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2075 ok( hr == S_OK, "got %08x\n", hr );
2077 text.value = NAN;
2078 hr = WsWriteText( writer, &text.text, NULL );
2079 ok( hr == S_OK, "got %08x\n", hr );
2081 hr = WsWriteEndElement( writer, NULL );
2082 ok( hr == S_OK, "got %08x\n", hr );
2083 check_output( writer, "<t>NaN</t>", __LINE__ );
2085 hr = set_output( writer );
2086 ok( hr == S_OK, "got %08x\n", hr );
2087 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2088 ok( hr == S_OK, "got %08x\n", hr );
2090 text.value = INFINITY;
2091 hr = WsWriteText( writer, &text.text, NULL );
2092 ok( hr == S_OK, "got %08x\n", hr );
2094 hr = WsWriteEndElement( writer, NULL );
2095 ok( hr == S_OK, "got %08x\n", hr );
2096 check_output( writer, "<t>INF</t>", __LINE__ );
2098 hr = set_output( writer );
2099 ok( hr == S_OK, "got %08x\n", hr );
2100 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2101 ok( hr == S_OK, "got %08x\n", hr );
2103 text.value = -INFINITY;
2104 hr = WsWriteText( writer, &text.text, NULL );
2105 ok( hr == S_OK, "got %08x\n", hr );
2107 hr = WsWriteEndElement( writer, NULL );
2108 ok( hr == S_OK, "got %08x\n", hr );
2109 check_output( writer, "<t>-INF</t>", __LINE__ );
2111 WsFreeWriter( writer );
2114 static void test_field_flags(void)
2116 static const char expected[] =
2117 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2118 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2119 HRESULT hr;
2120 WS_XML_WRITER *writer;
2121 WS_STRUCT_DESCRIPTION s;
2122 WS_FIELD_DESCRIPTION f, f2, f3, f4, *fields[4];
2123 WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, str_guid = {4, (BYTE *)"guid"};
2124 WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_bool = {4, (BYTE *)"bool"};
2125 WS_XML_STRING str_xmlstr = {6, (BYTE *)"xmlstr"};
2126 INT32 val = -1;
2127 struct test
2129 GUID guid;
2130 BOOL *bool_ptr;
2131 INT32 *int32_ptr;
2132 WS_XML_STRING xmlstr;
2133 } test;
2135 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2136 ok( hr == S_OK, "got %08x\n", hr );
2138 hr = set_output( writer );
2139 ok( hr == S_OK, "got %08x\n", hr );
2141 hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
2142 ok( hr == S_OK, "got %08x\n", hr );
2144 memset( &f, 0, sizeof(f) );
2145 f.mapping = WS_ELEMENT_FIELD_MAPPING;
2146 f.localName = &str_guid;
2147 f.ns = &ns;
2148 f.type = WS_GUID_TYPE;
2149 f.options = WS_FIELD_OPTIONAL;
2150 fields[0] = &f;
2152 memset( &f2, 0, sizeof(f2) );
2153 f2.mapping = WS_ELEMENT_FIELD_MAPPING;
2154 f2.localName = &str_bool;
2155 f2.offset = FIELD_OFFSET(struct test, bool_ptr);
2156 f2.ns = &ns;
2157 f2.type = WS_BOOL_TYPE;
2158 f2.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2159 fields[1] = &f2;
2161 memset( &f3, 0, sizeof(f3) );
2162 f3.mapping = WS_ELEMENT_FIELD_MAPPING;
2163 f3.localName = &str_int32;
2164 f3.offset = FIELD_OFFSET(struct test, int32_ptr);
2165 f3.ns = &ns;
2166 f3.type = WS_INT32_TYPE;
2167 f3.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
2168 fields[2] = &f3;
2170 memset( &f4, 0, sizeof(f4) );
2171 f4.mapping = WS_ELEMENT_FIELD_MAPPING;
2172 f4.localName = &str_xmlstr;
2173 f4.offset = FIELD_OFFSET(struct test, xmlstr);
2174 f4.ns = &ns;
2175 f4.type = WS_XML_STRING_TYPE;
2176 f4.options = WS_FIELD_NILLABLE;
2177 fields[3] = &f4;
2179 memset( &s, 0, sizeof(s) );
2180 s.size = sizeof(struct test);
2181 s.alignment = TYPE_ALIGNMENT(struct test);
2182 s.fields = fields;
2183 s.fieldCount = 4;
2185 memset( &test, 0, sizeof(test) );
2186 test.int32_ptr = &val;
2187 hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE,
2188 &test, sizeof(test), NULL );
2189 ok( hr == S_OK, "got %08x\n", hr );
2191 hr = WsWriteEndElement( writer, NULL );
2192 ok( hr == S_OK, "got %08x\n", hr );
2193 check_output( writer, expected, __LINE__ );
2195 WsFreeWriter( writer );
2198 static void test_WsWriteText(void)
2200 HRESULT hr;
2201 WS_XML_WRITER *writer;
2202 WS_XML_UTF8_TEXT utf8;
2204 hr = WsCreateWriter( NULL, 0, &writer, NULL );
2205 ok( hr == S_OK, "got %08x\n", hr );
2207 hr = set_output( writer );
2208 ok( hr == S_OK, "got %08x\n", hr );
2210 utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
2211 utf8.value.bytes = (BYTE *)"test";
2212 utf8.value.length = 4;
2213 hr = WsWriteText( writer, &utf8.text, NULL );
2214 todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
2216 WsFreeWriter( writer );
2219 START_TEST(writer)
2221 test_WsCreateWriter();
2222 test_WsCreateXmlBuffer();
2223 test_WsSetOutput();
2224 test_WsSetOutputToBuffer();
2225 test_WsWriteStartElement();
2226 test_WsWriteStartAttribute();
2227 test_WsWriteType();
2228 test_basic_type();
2229 test_simple_struct_type();
2230 test_WsWriteElement();
2231 test_WsWriteValue();
2232 test_WsWriteAttribute();
2233 test_WsWriteStartCData();
2234 test_WsWriteXmlnsAttribute();
2235 test_WsGetPrefixFromNamespace();
2236 test_complex_struct_type();
2237 test_WsMoveWriter();
2238 test_WsGetWriterPosition();
2239 test_WsSetWriterPosition();
2240 test_WsWriteXmlBuffer();
2241 test_WsWriteNode();
2242 test_WsCopyNode();
2243 test_text_types();
2244 test_double();
2245 test_field_flags();
2246 test_WsWriteText();