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
21 #include "webservices.h"
22 #include "wine/test.h"
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()
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()
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)
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
;
61 hr
= WsCreateWriter( NULL
, 0, NULL
, NULL
);
62 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
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
);
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
);
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
);
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 */
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 */
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
);
192 prop
.id
= WS_XML_WRITER_PROPERTY_BYTES_WRITTEN
;
194 prop
.valueSize
= sizeof(size
);
195 hr
= WsCreateWriter( &prop
, 1, &writer
, NULL
);
196 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
199 prop
.id
= WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE
;
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)
210 WS_XML_WRITER
*writer
;
211 WS_XML_BUFFER
*buffer
;
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
);
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
);
250 static void test_WsSetOutput(void)
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 */
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)
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 */
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
);
342 static char strbuf
[512];
343 static const char *debugstr_bytes( const BYTE
*bytes
, ULONG len
)
345 const BYTE
*src
= bytes
;
351 if (dst
- strbuf
> sizeof(strbuf
) - 7) break;
354 case '\n': *dst
++ = '\\'; *dst
++ = 'n'; break;
355 case '\r': *dst
++ = '\\'; *dst
++ = 'r'; break;
356 case '\t': *dst
++ = '\\'; *dst
++ = 't'; break;
358 if (c
>= ' ' && c
< 127) *dst
++ = c
;
361 sprintf( dst
, "\\%02x", c
);
377 static void check_output( WS_XML_WRITER
*writer
, const char *expected
, unsigned int line
)
380 ULONG size
= sizeof(bytes
);
381 int len
= strlen( expected
);
384 memset( &bytes
, 0, sizeof(bytes
) );
385 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
386 ok( hr
== S_OK
, "%u: got %08x\n", line
, hr
);
387 ok( bytes
.length
== len
, "%u: got %u expected %u\n", line
, bytes
.length
, len
);
388 if (bytes
.length
!= len
) return;
389 ok( !memcmp( bytes
.bytes
, expected
, len
),
390 "%u: got %s expected %s\n", line
, debugstr_bytes(bytes
.bytes
, bytes
.length
), expected
);
393 static void test_WsWriteStartElement(void)
396 WS_XML_WRITER
*writer
;
397 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, ns
= {2, (BYTE
*)"ns"}, ns2
= {3, (BYTE
*)"ns2"};
398 WS_XML_STRING localname
= {1, (BYTE
*)"a"}, localname2
= {1, (BYTE
*)"b"};
400 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
401 ok( hr
== S_OK
, "got %08x\n", hr
);
403 hr
= set_output( writer
);
404 ok( hr
== S_OK
, "got %08x\n", hr
);
406 hr
= WsWriteStartElement( NULL
, &prefix
, &localname
, &ns
, NULL
);
407 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
409 /* first call to WsWriteStartElement doesn't output anything */
410 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
411 ok( hr
== S_OK
, "got %08x\n", hr
);
412 check_output( writer
, "", __LINE__
);
414 /* two ways to close an element */
415 hr
= WsWriteEndStartElement( writer
, NULL
);
416 ok( hr
== S_OK
, "got %08x\n", hr
);
417 check_output( writer
, "<p:a xmlns:p=\"ns\">", __LINE__
);
419 hr
= WsWriteEndElement( writer
, NULL
);
420 ok( hr
== S_OK
, "got %08x\n", hr
);
421 check_output( writer
, "<p:a xmlns:p=\"ns\"></p:a>", __LINE__
);
423 hr
= set_output( writer
);
424 ok( hr
== S_OK
, "got %08x\n", hr
);
426 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
427 ok( hr
== S_OK
, "got %08x\n", hr
);
429 hr
= WsWriteEndElement( writer
, NULL
);
430 ok( hr
== S_OK
, "got %08x\n", hr
);
431 check_output( writer
, "<p:a xmlns:p=\"ns\"/>", __LINE__
);
433 /* nested elements */
434 hr
= set_output( writer
);
435 ok( hr
== S_OK
, "got %08x\n", hr
);
437 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
438 ok( hr
== S_OK
, "got %08x\n", hr
);
439 check_output( writer
, "", __LINE__
);
441 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
442 ok( hr
== S_OK
, "got %08x\n", hr
);
443 check_output( writer
, "<p:a xmlns:p=\"ns\">", __LINE__
);
445 hr
= WsWriteEndElement( writer
, NULL
);
446 ok( hr
== S_OK
, "got %08x\n", hr
);
447 check_output( writer
, "<p:a xmlns:p=\"ns\"><p:b/>", __LINE__
);
449 hr
= WsWriteEndElement( writer
, NULL
);
450 ok( hr
== S_OK
, "got %08x\n", hr
);
451 check_output( writer
, "<p:a xmlns:p=\"ns\"><p:b/></p:a>", __LINE__
);
453 hr
= set_output( writer
);
454 ok( hr
== S_OK
, "got %08x\n", hr
);
456 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
457 ok( hr
== S_OK
, "got %08x\n", hr
);
458 check_output( writer
, "", __LINE__
);
460 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns2
, NULL
);
461 ok( hr
== S_OK
, "got %08x\n", hr
);
462 check_output( writer
, "<p:a xmlns:p=\"ns\">", __LINE__
);
464 hr
= WsWriteEndElement( writer
, NULL
);
465 ok( hr
== S_OK
, "got %08x\n", hr
);
466 check_output( writer
, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/>", __LINE__
);
468 hr
= WsWriteEndElement( writer
, NULL
);
469 ok( hr
== S_OK
, "got %08x\n", hr
);
470 check_output( writer
, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/></p:a>", __LINE__
);
472 WsFreeWriter( writer
);
475 static void test_WsWriteStartAttribute(void)
478 WS_XML_WRITER
*writer
;
479 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, localname
= {3, (BYTE
*)"str"}, ns
= {2, (BYTE
*)"ns"};
480 WS_XML_UTF8_TEXT text
= {{WS_XML_TEXT_TYPE_UTF8
}};
482 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
483 ok( hr
== S_OK
, "got %08x\n", hr
);
485 hr
= set_output( writer
);
486 ok( hr
== S_OK
, "got %08x\n", hr
);
488 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
489 ok( hr
== S_OK
, "got %08x\n", hr
);
491 hr
= WsWriteStartAttribute( NULL
, &prefix
, &localname
, &ns
, FALSE
, NULL
);
492 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
494 /* WsWriteStartAttribute doesn't output anything */
495 localname
.length
= 3;
496 localname
.bytes
= (BYTE
*)"len";
497 hr
= WsWriteStartAttribute( writer
, &prefix
, &localname
, &ns
, FALSE
, NULL
);
498 ok( hr
== S_OK
, "got %08x\n", hr
);
499 check_output( writer
, "", __LINE__
);
501 text
.value
.length
= 1;
502 text
.value
.bytes
= (BYTE
*)"0";
503 hr
= WsWriteText( writer
, &text
.text
, NULL
);
504 ok( hr
== S_OK
, "got %08x\n", hr
);
505 check_output( writer
, "", __LINE__
);
507 /* WsWriteEndAttribute doesn't output anything */
508 hr
= WsWriteEndAttribute( writer
, NULL
);
509 ok( hr
== S_OK
, "got %08x\n", hr
);
510 check_output( writer
, "", __LINE__
);
512 hr
= WsWriteEndElement( writer
, NULL
);
513 ok( hr
== S_OK
, "got %08x\n", hr
);
514 check_output( writer
, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__
);
516 WsFreeWriter( writer
);
519 static void test_WsWriteType(void)
521 static const WCHAR testW
[] = {'t','e','s','t',0};
523 WS_XML_WRITER
*writer
;
524 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, localname
= {3, (BYTE
*)"str"}, ns
= {2, (BYTE
*)"ns"};
525 const WCHAR
*val_str
;
527 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
528 ok( hr
== S_OK
, "got %08x\n", hr
);
530 hr
= set_output( writer
);
531 ok( hr
== S_OK
, "got %08x\n", hr
);
534 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
535 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(val_str
), NULL
);
536 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
538 hr
= set_output( writer
);
539 ok( hr
== S_OK
, "got %08x\n", hr
);
541 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
542 ok( hr
== S_OK
, "got %08x\n", hr
);
545 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
546 WS_WRITE_REQUIRED_VALUE
, NULL
, sizeof(testW
), NULL
);
547 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
549 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
550 WS_WRITE_REQUIRED_VALUE
, testW
, sizeof(testW
), NULL
);
551 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
553 /* required pointer */
554 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
555 WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(val_str
), NULL
);
556 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
558 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
559 WS_WRITE_REQUIRED_VALUE
, testW
, sizeof(testW
), NULL
);
560 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
562 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
563 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(WCHAR
**), NULL
);
564 ok( hr
== S_OK
, "got %08x\n", hr
);
565 check_output( writer
, "<p:str xmlns:p=\"ns\">test", __LINE__
);
567 hr
= WsWriteEndElement( writer
, NULL
);
568 ok( hr
== S_OK
, "got %08x\n", hr
);
569 check_output( writer
, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__
);
571 hr
= set_output( writer
);
572 ok( hr
== S_OK
, "got %08x\n", hr
);
574 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
575 ok( hr
== S_OK
, "got %08x\n", hr
);
577 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
578 ok( hr
== S_OK
, "got %08x\n", hr
);
581 hr
= WsWriteType( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
582 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(val_str
), NULL
);
583 ok( hr
== S_OK
, "got %08x\n", hr
);
584 check_output( writer
, "", __LINE__
);
586 hr
= WsWriteEndAttribute( writer
, NULL
);
587 ok( hr
== S_OK
, "got %08x\n", hr
);
588 check_output( writer
, "", __LINE__
);
590 hr
= WsWriteEndElement( writer
, NULL
);
591 ok( hr
== S_OK
, "got %08x\n", hr
);
592 check_output( writer
, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__
);
594 hr
= set_output( writer
);
595 ok( hr
== S_OK
, "got %08x\n", hr
);
597 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
598 ok( hr
== S_OK
, "got %08x\n", hr
);
601 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
602 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(val_str
), NULL
);
603 ok( hr
== S_OK
, "got %08x\n", hr
);
604 check_output( writer
, "<p:str xmlns:p=\"ns\">test", __LINE__
);
606 hr
= WsWriteEndElement( writer
, NULL
);
607 ok( hr
== S_OK
, "got %08x\n", hr
);
608 check_output( writer
, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__
);
610 WsFreeWriter( writer
);
613 static void prepare_basic_type_test( WS_XML_WRITER
*writer
)
615 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
618 hr
= set_output( writer
);
619 ok( hr
== S_OK
, "got %08x\n", hr
);
620 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
621 ok( hr
== S_OK
, "got %08x\n", hr
);
624 static void test_basic_type(void)
626 static WCHAR testW
[] = {'t','e','s','t',0};
628 WS_XML_WRITER
*writer
;
629 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
}, xmlstr
;
645 { WS_BOOL_TYPE
, TRUE
, sizeof(BOOL
), "<t>true</t>", "<t t=\"true\"/>" },
646 { WS_BOOL_TYPE
, FALSE
, sizeof(BOOL
), "<t>false</t>", "<t t=\"false\"/>" },
647 { WS_INT8_TYPE
, -128, sizeof(INT8
), "<t>-128</t>", "<t t=\"-128\"/>" },
648 { WS_INT16_TYPE
, -32768, sizeof(INT16
), "<t>-32768</t>", "<t t=\"-32768\"/>" },
649 { WS_INT32_TYPE
, -2147483647 - 1, sizeof(INT32
), "<t>-2147483648</t>",
650 "<t t=\"-2147483648\"/>" },
651 { WS_INT64_TYPE
, -9223372036854775807 - 1, sizeof(INT64
), "<t>-9223372036854775808</t>",
652 "<t t=\"-9223372036854775808\"/>" },
653 { WS_UINT8_TYPE
, 255, sizeof(UINT8
), "<t>255</t>", "<t t=\"255\"/>" },
654 { WS_UINT16_TYPE
, 65535, sizeof(UINT16
), "<t>65535</t>", "<t t=\"65535\"/>" },
655 { WS_UINT32_TYPE
, ~0u, sizeof(UINT32
), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
656 { WS_UINT64_TYPE
, ~0, sizeof(UINT64
), "<t>18446744073709551615</t>",
657 "<t t=\"18446744073709551615\"/>" },
660 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
661 ok( hr
== S_OK
, "got %08x\n", hr
);
663 /* element content type mapping */
664 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
666 prepare_basic_type_test( writer
);
667 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, tests
[i
].type
, NULL
,
668 WS_WRITE_REQUIRED_VALUE
, &tests
[i
].val
, tests
[i
].size
, NULL
);
669 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
671 hr
= WsWriteEndElement( writer
, NULL
);
672 ok( hr
== S_OK
, "got %08x\n", hr
);
673 check_output( writer
, tests
[i
].result
, __LINE__
);
676 /* element type mapping is the same as element content type mapping for basic types */
677 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
679 const INT64
*ptr
= &tests
[i
].val
;
681 prepare_basic_type_test( writer
);
682 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, tests
[i
].type
, NULL
,
683 WS_WRITE_REQUIRED_POINTER
, &ptr
, sizeof(ptr
), NULL
);
684 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
686 hr
= WsWriteEndElement( writer
, NULL
);
687 ok( hr
== S_OK
, "got %08x\n", hr
);
688 check_output( writer
, tests
[i
].result
, __LINE__
);
691 /* attribute type mapping */
692 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
694 prepare_basic_type_test( writer
);
695 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
696 ok( hr
== S_OK
, "got %08x\n", hr
);
698 hr
= WsWriteType( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, tests
[i
].type
, NULL
,
699 WS_WRITE_REQUIRED_VALUE
, &tests
[i
].val
, tests
[i
].size
, NULL
);
700 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
702 hr
= WsWriteEndAttribute( writer
, NULL
);
703 ok( hr
== S_OK
, "got %08x\n", hr
);
705 hr
= WsWriteEndElement( writer
, NULL
);
706 ok( hr
== S_OK
, "got %08x\n", hr
);
707 check_output( writer
, tests
[i
].result2
, __LINE__
);
710 prepare_basic_type_test( writer
);
711 memset( &guid
, 0, sizeof(guid
) );
712 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_GUID_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
713 &guid
, sizeof(guid
), NULL
);
714 ok( hr
== S_OK
, "got %08x\n", hr
);
715 hr
= WsWriteEndElement( writer
, NULL
);
716 ok( hr
== S_OK
, "got %08x\n", hr
);
717 check_output( writer
, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__
);
719 prepare_basic_type_test( writer
);
720 string
.chars
= testW
;
722 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRING_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
723 &string
, sizeof(string
), NULL
);
724 ok( hr
== S_OK
, "got %08x\n", hr
);
725 hr
= WsWriteEndElement( writer
, NULL
);
726 ok( hr
== S_OK
, "got %08x\n", hr
);
727 check_output( writer
, "<t>test</t>", __LINE__
);
729 prepare_basic_type_test( writer
);
731 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
, WS_WRITE_REQUIRED_POINTER
,
732 &str
, sizeof(str
), NULL
);
733 ok( hr
== S_OK
, "got %08x\n", hr
);
734 hr
= WsWriteEndElement( writer
, NULL
);
735 ok( hr
== S_OK
, "got %08x\n", hr
);
736 check_output( writer
, "<t>test</t>", __LINE__
);
738 prepare_basic_type_test( writer
);
739 xmlstr
.bytes
= (BYTE
*)"test";
741 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_XML_STRING_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
742 &xmlstr
, sizeof(xmlstr
), NULL
);
743 ok( hr
== S_OK
, "got %08x\n", hr
);
744 hr
= WsWriteEndElement( writer
, NULL
);
745 ok( hr
== S_OK
, "got %08x\n", hr
);
746 check_output( writer
, "<t>test</t>", __LINE__
);
748 prepare_basic_type_test( writer
);
749 bytes
.bytes
= (BYTE
*)"test";
751 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
752 &bytes
, sizeof(bytes
), NULL
);
753 ok( hr
== S_OK
, "got %08x\n", hr
);
754 hr
= WsWriteEndElement( writer
, NULL
);
755 ok( hr
== S_OK
, "got %08x\n", hr
);
756 check_output( writer
, "<t>dGVzdA==</t>", __LINE__
);
758 prepare_basic_type_test( writer
);
760 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
761 &bytes
, sizeof(bytes
), NULL
);
762 ok( hr
== S_OK
, "got %08x\n", hr
);
763 hr
= WsWriteEndElement( writer
, NULL
);
764 ok( hr
== S_OK
, "got %08x\n", hr
);
765 check_output( writer
, "<t/>", __LINE__
);
767 prepare_basic_type_test( writer
);
769 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
770 &bytes
, sizeof(bytes
), NULL
);
771 ok( hr
== S_OK
, "got %08x\n", hr
);
772 hr
= WsWriteEndElement( writer
, NULL
);
773 ok( hr
== S_OK
, "got %08x\n", hr
);
774 check_output( writer
, "<t/>", __LINE__
);
776 prepare_basic_type_test( writer
);
777 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_NILLABLE_VALUE
,
778 &bytes
, sizeof(bytes
), NULL
);
779 ok( hr
== S_OK
, "got %08x\n", hr
);
780 hr
= WsWriteEndElement( writer
, NULL
);
781 ok( hr
== S_OK
, "got %08x\n", hr
);
782 check_output( writer
, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
785 WsFreeWriter( writer
);
788 static void test_simple_struct_type(void)
790 static const WCHAR valueW
[] = {'v','a','l','u','e',0};
792 WS_XML_WRITER
*writer
;
793 WS_STRUCT_DESCRIPTION s
;
794 WS_FIELD_DESCRIPTION f
, *fields
[1];
795 WS_XML_STRING localname
= {6, (BYTE
*)"struct"}, ns
= {0, NULL
};
801 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
802 ok( hr
== S_OK
, "got %08x\n", hr
);
804 hr
= set_output( writer
);
805 ok( hr
== S_OK
, "got %08x\n", hr
);
807 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
808 ok( hr
== S_OK
, "got %08x\n", hr
);
810 memset( &f
, 0, sizeof(f
) );
811 f
.mapping
= WS_TEXT_FIELD_MAPPING
;
812 f
.type
= WS_WSZ_TYPE
;
815 memset( &s
, 0, sizeof(s
) );
816 s
.size
= sizeof(struct test
);
817 s
.alignment
= TYPE_ALIGNMENT(struct test
);
821 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) );
822 test
->field
= valueW
;
823 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, NULL
,
824 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
825 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
827 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, NULL
,
828 WS_WRITE_REQUIRED_VALUE
, test
, sizeof(*test
), NULL
);
829 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
831 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
832 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
833 ok( hr
== S_OK
, "got %08x\n", hr
);
835 hr
= WsWriteEndElement( writer
, NULL
);
836 ok( hr
== S_OK
, "got %08x\n", hr
);
837 check_output( writer
, "<struct>value</struct>", __LINE__
);
840 hr
= set_output( writer
);
841 ok( hr
== S_OK
, "got %08x\n", hr
);
843 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
844 ok( hr
== S_OK
, "got %08x\n", hr
);
846 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
847 WS_WRITE_REQUIRED_VALUE
, test
, sizeof(*test
), NULL
);
848 ok( hr
== S_OK
, "got %08x\n", hr
);
850 hr
= WsWriteEndElement( writer
, NULL
);
851 ok( hr
== S_OK
, "got %08x\n", hr
);
852 check_output( writer
, "<struct>value</struct>", __LINE__
);
854 hr
= set_output( writer
);
855 ok( hr
== S_OK
, "got %08x\n", hr
);
857 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
858 ok( hr
== S_OK
, "got %08x\n", hr
);
860 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
861 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
862 ok( hr
== S_OK
, "got %08x\n", hr
);
864 hr
= WsWriteEndElement( writer
, NULL
);
865 ok( hr
== S_OK
, "got %08x\n", hr
);
866 check_output( writer
, "<struct>value</struct>", __LINE__
);
868 hr
= set_output( writer
);
869 ok( hr
== S_OK
, "got %08x\n", hr
);
871 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
872 ok( hr
== S_OK
, "got %08x\n", hr
);
874 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
875 ok( hr
== S_OK
, "got %08x\n", hr
);
877 hr
= WsWriteType( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
878 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
879 ok( hr
== S_OK
, "got %08x\n", hr
);
881 hr
= WsWriteEndAttribute( writer
, NULL
);
882 ok( hr
== S_OK
, "got %08x\n", hr
);
884 hr
= WsWriteEndElement( writer
, NULL
);
885 ok( hr
== S_OK
, "got %08x\n", hr
);
886 check_output( writer
, "<struct struct=\"value\"/>", __LINE__
);
888 HeapFree( GetProcessHeap(), 0, test
);
889 WsFreeWriter( writer
);
892 static void test_WsWriteElement(void)
894 static const WCHAR testW
[] = {'t','e','s','t',0};
896 WS_XML_WRITER
*writer
;
897 WS_STRUCT_DESCRIPTION s
;
898 WS_FIELD_DESCRIPTION f
, *fields
[1];
899 WS_ELEMENT_DESCRIPTION desc
;
900 WS_XML_STRING localname
= {3, (BYTE
*)"str"}, ns
= {0, NULL
};
901 struct test
{ const WCHAR
*str
; } *test
;
903 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
904 ok( hr
== S_OK
, "got %08x\n", hr
);
906 hr
= set_output( writer
);
907 ok( hr
== S_OK
, "got %08x\n", hr
);
909 /* text field mapping */
910 memset( &f
, 0, sizeof(f
) );
911 f
.mapping
= WS_TEXT_FIELD_MAPPING
;
912 f
.type
= WS_WSZ_TYPE
;
915 memset( &s
, 0, sizeof(s
) );
916 s
.size
= sizeof(struct test
);
917 s
.alignment
= TYPE_ALIGNMENT(struct test
);
921 desc
.elementLocalName
= &localname
;
922 desc
.elementNs
= &ns
;
923 desc
.type
= WS_STRUCT_TYPE
;
924 desc
.typeDescription
= &s
;
926 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) );
928 hr
= WsWriteElement( NULL
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
929 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
931 hr
= WsWriteElement( writer
, NULL
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
932 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
934 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, NULL
);
935 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
937 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
938 ok( hr
== S_OK
, "got %08x\n", hr
);
939 check_output( writer
, "<str>test</str>", __LINE__
);
941 hr
= set_output( writer
);
942 ok( hr
== S_OK
, "got %08x\n", hr
);
944 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
945 ok( hr
== S_OK
, "got %08x\n", hr
);
947 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
948 ok( hr
== S_OK
, "got %08x\n", hr
);
949 check_output( writer
, "<str><str>test</str>", __LINE__
);
951 hr
= set_output( writer
);
952 ok( hr
== S_OK
, "got %08x\n", hr
);
954 /* attribute field mapping */
955 f
.mapping
= WS_ATTRIBUTE_FIELD_MAPPING
;
957 /* requires localName and ns to be set */
958 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
959 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
961 hr
= set_output( writer
);
962 ok( hr
== S_OK
, "got %08x\n", hr
);
964 f
.localName
= &localname
;
966 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
967 ok( hr
== S_OK
, "got %08x\n", hr
);
968 check_output( writer
, "<str str=\"test\"/>", __LINE__
);
970 HeapFree( GetProcessHeap(), 0, test
);
971 WsFreeWriter( writer
);
974 static void test_WsWriteValue(void)
977 WS_XML_WRITER
*writer
;
978 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
990 { WS_BOOL_VALUE_TYPE
, ~0, sizeof(BOOL
), "<t>true</t>", "<t t=\"true\"/>" },
991 { WS_BOOL_VALUE_TYPE
, FALSE
, sizeof(BOOL
), "<t>false</t>", "<t t=\"false\"/>" },
992 { WS_INT8_VALUE_TYPE
, -128, sizeof(INT8
), "<t>-128</t>", "<t t=\"-128\"/>" },
993 { WS_INT16_VALUE_TYPE
, -32768, sizeof(INT16
), "<t>-32768</t>", "<t t=\"-32768\"/>" },
994 { WS_INT32_VALUE_TYPE
, -2147483647 - 1, sizeof(INT32
), "<t>-2147483648</t>",
995 "<t t=\"-2147483648\"/>" },
996 { WS_INT64_VALUE_TYPE
, -9223372036854775807 - 1, sizeof(INT64
), "<t>-9223372036854775808</t>",
997 "<t t=\"-9223372036854775808\"/>" },
998 { WS_UINT8_VALUE_TYPE
, 255, sizeof(UINT8
), "<t>255</t>", "<t t=\"255\"/>" },
999 { WS_UINT16_VALUE_TYPE
, 65535, sizeof(UINT16
), "<t>65535</t>", "<t t=\"65535\"/>" },
1000 { WS_UINT32_VALUE_TYPE
, ~0u, sizeof(UINT32
), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
1001 { WS_UINT64_VALUE_TYPE
, ~0, sizeof(UINT64
), "<t>18446744073709551615</t>",
1002 "<t t=\"18446744073709551615\"/>" },
1005 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1006 ok( hr
== S_OK
, "got %08x\n", hr
);
1008 hr
= set_output( writer
);
1009 ok( hr
== S_OK
, "got %08x\n", hr
);
1011 hr
= WsWriteValue( NULL
, tests
[0].type
, &tests
[0].val
, tests
[0].size
, NULL
);
1012 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1014 hr
= WsWriteValue( writer
, tests
[0].type
, &tests
[0].val
, tests
[0].size
, NULL
);
1015 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1017 hr
= set_output( writer
);
1018 ok( hr
== S_OK
, "got %08x\n", hr
);
1020 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1021 ok( hr
== S_OK
, "got %08x\n", hr
);
1024 hr
= WsWriteValue( writer
, tests
[0].type
, &tests
[0].val
, 0, NULL
);
1025 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1027 hr
= set_output( writer
);
1028 ok( hr
== S_OK
, "got %08x\n", hr
);
1030 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1031 ok( hr
== S_OK
, "got %08x\n", hr
);
1034 hr
= WsWriteValue( writer
, tests
[0].type
, NULL
, 0, NULL
);
1035 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1037 /* element type mapping */
1038 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
1040 hr
= set_output( writer
);
1041 ok( hr
== S_OK
, "got %08x\n", hr
);
1043 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1044 ok( hr
== S_OK
, "got %08x\n", hr
);
1046 hr
= WsWriteValue( writer
, tests
[i
].type
, &tests
[i
].val
, tests
[i
].size
, NULL
);
1047 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
1049 hr
= WsWriteEndElement( writer
, NULL
);
1050 ok( hr
== S_OK
, "got %08x\n", hr
);
1051 check_output( writer
, tests
[i
].result
, __LINE__
);
1054 /* attribute type mapping */
1055 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
1057 hr
= set_output( writer
);
1058 ok( hr
== S_OK
, "got %08x\n", hr
);
1060 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1061 ok( hr
== S_OK
, "got %08x\n", hr
);
1063 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
1064 ok( hr
== S_OK
, "got %08x\n", hr
);
1066 hr
= WsWriteValue( writer
, tests
[i
].type
, &tests
[i
].val
, tests
[i
].size
, NULL
);
1067 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
1069 hr
= WsWriteEndAttribute( writer
, NULL
);
1070 ok( hr
== S_OK
, "got %08x\n", hr
);
1072 hr
= WsWriteEndElement( writer
, NULL
);
1073 ok( hr
== S_OK
, "got %08x\n", hr
);
1074 check_output( writer
, tests
[i
].result2
, __LINE__
);
1077 WsFreeWriter( writer
);
1080 static void test_WsWriteAttribute(void)
1082 static const WCHAR testW
[] = {'t','e','s','t',0};
1084 WS_XML_WRITER
*writer
;
1085 WS_STRUCT_DESCRIPTION s
;
1086 WS_FIELD_DESCRIPTION f
, *fields
[1];
1087 WS_ATTRIBUTE_DESCRIPTION desc
;
1088 WS_XML_STRING localname
= {3, (BYTE
*)"str"}, ns
= {0, NULL
};
1089 struct test
{ const WCHAR
*str
; } *test
;
1091 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1092 ok( hr
== S_OK
, "got %08x\n", hr
);
1094 hr
= set_output( writer
);
1095 ok( hr
== S_OK
, "got %08x\n", hr
);
1097 /* text field mapping */
1098 memset( &f
, 0, sizeof(f
) );
1099 f
.mapping
= WS_TEXT_FIELD_MAPPING
;
1100 f
.type
= WS_WSZ_TYPE
;
1103 memset( &s
, 0, sizeof(s
) );
1104 s
.size
= sizeof(struct test
);
1105 s
.alignment
= TYPE_ALIGNMENT(struct test
);
1109 desc
.attributeLocalName
= &localname
;
1110 desc
.attributeNs
= &ns
;
1111 desc
.type
= WS_STRUCT_TYPE
;
1112 desc
.typeDescription
= &s
;
1114 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) );
1116 hr
= WsWriteAttribute( NULL
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1117 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1119 hr
= WsWriteAttribute( writer
, NULL
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1120 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1122 hr
= WsWriteAttribute( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, NULL
);
1123 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1125 hr
= WsWriteAttribute( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1126 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1128 hr
= set_output( writer
);
1129 ok( hr
== S_OK
, "got %08x\n", hr
);
1131 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1132 ok( hr
== S_OK
, "got %08x\n", hr
);
1134 hr
= WsWriteAttribute( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1135 ok( hr
== S_OK
, "got %08x\n", hr
);
1137 hr
= WsWriteEndElement( writer
, NULL
);
1138 ok( hr
== S_OK
, "got %08x\n", hr
);
1139 check_output( writer
, "<str str=\"test\"/>", __LINE__
);
1141 HeapFree( GetProcessHeap(), 0, test
);
1142 WsFreeWriter( writer
);
1145 static void test_WsWriteStartCData(void)
1148 WS_XML_WRITER
*writer
;
1149 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1150 WS_XML_UTF8_TEXT text
= {{WS_XML_TEXT_TYPE_UTF8
}};
1152 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1153 ok( hr
== S_OK
, "got %08x\n", hr
);
1155 hr
= set_output( writer
);
1156 ok( hr
== S_OK
, "got %08x\n", hr
);
1158 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1159 ok( hr
== S_OK
, "got %08x\n", hr
);
1161 hr
= WsWriteEndCData( writer
, NULL
);
1162 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1164 hr
= set_output( writer
);
1165 ok( hr
== S_OK
, "got %08x\n", hr
);
1167 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1168 ok( hr
== S_OK
, "got %08x\n", hr
);
1169 check_output( writer
, "", __LINE__
);
1171 hr
= WsWriteStartCData( writer
, NULL
);
1172 ok( hr
== S_OK
, "got %08x\n", hr
);
1173 check_output( writer
, "<t><![CDATA[", __LINE__
);
1175 text
.value
.bytes
= (BYTE
*)"<data>";
1176 text
.value
.length
= 6;
1177 hr
= WsWriteText( writer
, &text
.text
, NULL
);
1178 ok( hr
== S_OK
, "got %08x\n", hr
);
1179 check_output( writer
, "<t><![CDATA[<data>", __LINE__
);
1181 hr
= WsWriteEndCData( writer
, NULL
);
1182 ok( hr
== S_OK
, "got %08x\n", hr
);
1183 check_output( writer
, "<t><![CDATA[<data>]]>", __LINE__
);
1185 hr
= WsWriteEndElement( writer
, NULL
);
1186 ok( hr
== S_OK
, "got %08x\n", hr
);
1187 check_output( writer
, "<t><![CDATA[<data>]]></t>", __LINE__
);
1189 WsFreeWriter( writer
);
1192 static void check_output_buffer( WS_XML_BUFFER
*buffer
, const char *expected
, unsigned int line
)
1194 WS_XML_WRITER
*writer
;
1196 ULONG size
= sizeof(bytes
);
1197 int len
= strlen(expected
);
1200 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1201 ok( hr
== S_OK
, "got %08x\n", hr
);
1203 hr
= set_output( writer
);
1204 ok( hr
== S_OK
, "got %08x\n", hr
);
1206 hr
= WsWriteXmlBuffer( writer
, buffer
, NULL
);
1207 ok( hr
== S_OK
, "got %08x\n", hr
);
1209 memset( &bytes
, 0, sizeof(bytes
) );
1210 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
1211 ok( hr
== S_OK
, "%u: got %08x\n", line
, hr
);
1212 ok( bytes
.length
== len
, "%u: got %u expected %u\n", line
, bytes
.length
, len
);
1213 if (bytes
.length
!= len
) return;
1214 ok( !memcmp( bytes
.bytes
, expected
, len
), "%u: got %s expected %s\n", line
, bytes
.bytes
, expected
);
1216 WsFreeWriter( writer
);
1219 static void prepare_xmlns_test( WS_XML_WRITER
*writer
, WS_HEAP
**heap
, WS_XML_BUFFER
**buffer
)
1221 WS_XML_STRING prefix
= {6, (BYTE
*)"prefix"}, localname
= {1, (BYTE
*)"t"}, ns
= {2, (BYTE
*)"ns"};
1224 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, heap
, NULL
);
1225 ok( hr
== S_OK
, "got %08x\n", hr
);
1227 hr
= WsCreateXmlBuffer( *heap
, NULL
, 0, buffer
, NULL
);
1228 ok( hr
== S_OK
, "got %08x\n", hr
);
1230 hr
= WsSetOutputToBuffer( writer
, *buffer
, NULL
, 0, NULL
);
1231 ok( hr
== S_OK
, "got %08x\n", hr
);
1233 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
1234 ok( hr
== S_OK
, "got %08x\n", hr
);
1237 static void test_WsWriteXmlnsAttribute(void)
1239 WS_XML_STRING ns
= {2, (BYTE
*)"ns"}, ns2
= {3, (BYTE
*)"ns2"};
1240 WS_XML_STRING prefix
= {6, (BYTE
*)"prefix"}, prefix2
= {7, (BYTE
*)"prefix2"};
1241 WS_XML_STRING xmlns
= {6, (BYTE
*)"xmlns"}, attr
= {4, (BYTE
*)"attr"};
1242 WS_XML_STRING localname
= {1, (BYTE
*)"u"};
1244 WS_XML_BUFFER
*buffer
;
1245 WS_XML_WRITER
*writer
;
1248 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1249 ok( hr
== S_OK
, "got %08x\n", hr
);
1251 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1252 ok( hr
== S_OK
, "got %08x\n", hr
);
1254 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1255 ok( hr
== S_OK
, "got %08x\n", hr
);
1257 hr
= WsWriteXmlnsAttribute( NULL
, NULL
, NULL
, FALSE
, NULL
);
1258 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1261 prepare_xmlns_test( writer
, &heap
, &buffer
);
1262 hr
= WsWriteXmlnsAttribute( writer
, NULL
, NULL
, FALSE
, NULL
);
1263 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1266 prepare_xmlns_test( writer
, &heap
, &buffer
);
1267 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, NULL
, FALSE
, NULL
);
1268 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1270 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1271 ok( hr
== S_OK
, "got %08x\n", hr
);
1272 hr
= WsWriteXmlnsAttribute( writer
, NULL
, &ns
, FALSE
, NULL
);
1273 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1277 prepare_xmlns_test( writer
, &heap
, &buffer
);
1278 hr
= WsWriteXmlnsAttribute( writer
, NULL
, &ns2
, FALSE
, NULL
);
1279 ok( hr
== S_OK
, "got %08x\n", hr
);
1280 hr
= WsWriteEndElement( writer
, NULL
);
1281 ok( hr
== S_OK
, "got %08x\n", hr
);
1282 check_output_buffer( buffer
, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__
);
1286 prepare_xmlns_test( writer
, &heap
, &buffer
);
1287 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, FALSE
, NULL
);
1288 ok( hr
== S_OK
, "got %08x\n", hr
);
1289 hr
= WsWriteEndElement( writer
, NULL
);
1290 ok( hr
== S_OK
, "got %08x\n", hr
);
1291 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__
);
1294 /* implicitly set element prefix namespace */
1295 prepare_xmlns_test( writer
, &heap
, &buffer
);
1296 hr
= WsWriteEndElement( writer
, NULL
);
1297 ok( hr
== S_OK
, "got %08x\n", hr
);
1298 check_output_buffer( buffer
, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__
);
1301 /* explicitly set element prefix namespace */
1302 prepare_xmlns_test( writer
, &heap
, &buffer
);
1303 hr
= WsWriteXmlnsAttribute( writer
, &prefix
, &ns
, TRUE
, NULL
);
1304 ok( hr
== S_OK
, "got %08x\n", hr
);
1305 hr
= WsWriteEndElement( writer
, NULL
);
1306 ok( hr
== S_OK
, "got %08x\n", hr
);
1307 check_output_buffer( buffer
, "<prefix:t xmlns:prefix='ns'/>", __LINE__
);
1310 /* repeated calls, same namespace */
1311 prepare_xmlns_test( writer
, &heap
, &buffer
);
1312 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, FALSE
, NULL
);
1313 ok( hr
== S_OK
, "got %08x\n", hr
);
1314 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, FALSE
, NULL
);
1315 ok( hr
== S_OK
, "got %08x\n", hr
);
1316 hr
= WsWriteEndElement( writer
, NULL
);
1317 ok( hr
== S_OK
, "got %08x\n", hr
);
1318 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__
);
1321 /* repeated calls, different namespace */
1322 prepare_xmlns_test( writer
, &heap
, &buffer
);
1323 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, FALSE
, NULL
);
1324 ok( hr
== S_OK
, "got %08x\n", hr
);
1325 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, FALSE
, NULL
);
1326 ok( hr
== S_OK
, "got %08x\n", hr
);
1327 hr
= WsWriteEndElement( writer
, NULL
);
1328 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1332 prepare_xmlns_test( writer
, &heap
, &buffer
);
1333 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, TRUE
, NULL
);
1334 ok( hr
== S_OK
, "got %08x\n", hr
);
1335 hr
= WsWriteEndElement( writer
, NULL
);
1336 ok( hr
== S_OK
, "got %08x\n", hr
);
1337 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2='ns' xmlns:prefix=\"ns\"/>", __LINE__
);
1340 /* different namespace, different prefix */
1341 prepare_xmlns_test( writer
, &heap
, &buffer
);
1342 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, TRUE
, NULL
);
1343 ok( hr
== S_OK
, "got %08x\n", hr
);
1344 hr
= WsWriteEndElement( writer
, NULL
);
1345 ok( hr
== S_OK
, "got %08x\n", hr
);
1346 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__
);
1349 /* different namespace, same prefix */
1350 prepare_xmlns_test( writer
, &heap
, &buffer
);
1351 hr
= WsWriteXmlnsAttribute( writer
, &prefix
, &ns2
, TRUE
, NULL
);
1352 ok( hr
== S_OK
, "got %08x\n", hr
);
1353 hr
= WsWriteEndElement( writer
, NULL
);
1354 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1357 /* regular attribute */
1358 prepare_xmlns_test( writer
, &heap
, &buffer
);
1359 hr
= WsWriteStartAttribute( writer
, &xmlns
, &prefix2
, &ns2
, TRUE
, NULL
);
1360 ok( hr
== S_OK
, "got %08x\n", hr
);
1361 hr
= WsWriteEndAttribute( writer
, NULL
);
1362 ok( hr
== S_OK
, "got %08x\n", hr
);
1363 hr
= WsWriteEndElement( writer
, NULL
);
1364 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1367 /* attribute order */
1368 prepare_xmlns_test( writer
, &heap
, &buffer
);
1369 hr
= WsWriteXmlnsAttribute( writer
, &prefix
, &ns
, TRUE
, NULL
);
1370 ok( hr
== S_OK
, "got %08x\n", hr
);
1371 hr
= WsWriteStartAttribute( writer
, &prefix
, &attr
, &ns
, TRUE
, NULL
);
1372 ok( hr
== S_OK
, "got %08x\n", hr
);
1373 hr
= WsWriteEndAttribute( writer
, NULL
);
1374 ok( hr
== S_OK
, "got %08x\n", hr
);
1375 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, TRUE
, NULL
);
1376 ok( hr
== S_OK
, "got %08x\n", hr
);
1377 hr
= WsWriteEndElement( writer
, NULL
);
1378 ok( hr
== S_OK
, "got %08x\n", hr
);
1379 check_output_buffer( buffer
, "<prefix:t prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__
);
1383 prepare_xmlns_test( writer
, &heap
, &buffer
);
1384 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, TRUE
, NULL
);
1385 ok( hr
== S_OK
, "got %08x\n", hr
);
1386 hr
= WsWriteStartElement( writer
, &prefix2
, &localname
, &ns2
, NULL
);
1387 ok( hr
== S_OK
, "got %08x\n", hr
);
1388 hr
= WsWriteEndElement( writer
, NULL
);
1389 ok( hr
== S_OK
, "got %08x\n", hr
);
1390 hr
= WsWriteEndElement( writer
, NULL
);
1391 ok( hr
== S_OK
, "got %08x\n", hr
);
1392 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"><prefix2:u/></prefix:t>",
1396 WsFreeWriter( writer
);
1399 static void prepare_prefix_test( WS_XML_WRITER
*writer
)
1401 const WS_XML_STRING p
= {1, (BYTE
*)"p"}, localname
= {1, (BYTE
*)"t"}, ns
= {2, (BYTE
*)"ns"};
1404 hr
= set_output( writer
);
1405 ok( hr
== S_OK
, "got %08x\n", hr
);
1406 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1407 ok( hr
== S_OK
, "got %08x\n", hr
);
1408 hr
= WsWriteEndStartElement( writer
, NULL
);
1409 ok( hr
== S_OK
, "got %08x\n", hr
);
1412 static void test_WsGetPrefixFromNamespace(void)
1414 const WS_XML_STRING p
= {1, (BYTE
*)"p"}, localname
= {1, (BYTE
*)"t"}, *prefix
;
1415 const WS_XML_STRING ns
= {2, (BYTE
*)"ns"}, ns2
= {3, (BYTE
*)"ns2"};
1416 WS_XML_WRITER
*writer
;
1419 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1420 ok( hr
== S_OK
, "got %08x\n", hr
);
1422 hr
= set_output( writer
);
1423 ok( hr
== S_OK
, "got %08x\n", hr
);
1424 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1425 ok( hr
== S_OK
, "got %08x\n", hr
);
1427 hr
= WsGetPrefixFromNamespace( NULL
, NULL
, FALSE
, NULL
, NULL
);
1428 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1430 hr
= WsGetPrefixFromNamespace( NULL
, NULL
, FALSE
, &prefix
, NULL
);
1431 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1433 hr
= WsGetPrefixFromNamespace( writer
, NULL
, FALSE
, &prefix
, NULL
);
1434 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1436 /* element must be committed */
1437 hr
= set_output( writer
);
1438 ok( hr
== S_OK
, "got %08x\n", hr
);
1439 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1440 ok( hr
== S_OK
, "got %08x\n", hr
);
1441 hr
= WsGetPrefixFromNamespace( writer
, &ns
, TRUE
, &prefix
, NULL
);
1442 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1444 /* but writer can't be positioned on end element node */
1445 hr
= set_output( writer
);
1446 ok( hr
== S_OK
, "got %08x\n", hr
);
1447 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1448 ok( hr
== S_OK
, "got %08x\n", hr
);
1449 hr
= WsWriteEndElement( writer
, NULL
);
1450 ok( hr
== S_OK
, "got %08x\n", hr
);
1451 hr
= WsGetPrefixFromNamespace( writer
, &ns
, TRUE
, &prefix
, NULL
);
1452 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1454 /* required = TRUE */
1456 prepare_prefix_test( writer
);
1457 hr
= WsGetPrefixFromNamespace( writer
, &ns
, TRUE
, &prefix
, NULL
);
1458 ok( hr
== S_OK
, "got %08x\n", hr
);
1459 ok( prefix
!= NULL
, "prefix not set\n" );
1462 ok( prefix
->length
== 1, "got %u\n", prefix
->length
);
1463 ok( !memcmp( prefix
->bytes
, "p", 1 ), "wrong prefix\n" );
1466 prefix
= (const WS_XML_STRING
*)0xdeadbeef;
1467 hr
= WsGetPrefixFromNamespace( writer
, &ns2
, TRUE
, &prefix
, NULL
);
1468 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1469 ok( prefix
== (const WS_XML_STRING
*)0xdeadbeef, "prefix set\n" );
1471 /* required = FALSE */
1473 prepare_prefix_test( writer
);
1474 hr
= WsGetPrefixFromNamespace( writer
, &ns
, FALSE
, &prefix
, NULL
);
1475 ok( hr
== S_OK
, "got %08x\n", hr
);
1476 ok( prefix
!= NULL
, "prefix not set\n" );
1479 ok( prefix
->length
== 1, "got %u\n", prefix
->length
);
1480 ok( !memcmp( prefix
->bytes
, "p", 1 ), "wrong prefix\n" );
1483 prefix
= (const WS_XML_STRING
*)0xdeadbeef;
1484 hr
= WsGetPrefixFromNamespace( writer
, &ns2
, FALSE
, &prefix
, NULL
);
1485 ok( hr
== S_FALSE
, "got %08x\n", hr
);
1486 ok( prefix
== NULL
, "prefix not set\n" );
1488 WsFreeWriter( writer
);
1491 static void test_complex_struct_type(void)
1493 static const char expected
[] =
1494 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1495 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1496 "</o:OfficeConfig>";
1497 static const WCHAR timestampW
[] =
1498 {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
1499 WS_XML_STRING str_officeconfig
= {12, (BYTE
*)"OfficeConfig"};
1500 WS_XML_STRING str_services
= {8, (BYTE
*)"services"};
1501 WS_XML_STRING str_generationtime
= {14, (BYTE
*)"GenerationTime"};
1502 WS_XML_STRING ns
= {39, (BYTE
*)"urn:schemas-microsoft-com:office:office"};
1503 WS_XML_STRING prefix
= {1, (BYTE
*)"o"};
1507 WS_XML_BUFFER
*buffer
;
1508 WS_XML_WRITER
*writer
;
1509 WS_STRUCT_DESCRIPTION s
, s2
;
1510 WS_FIELD_DESCRIPTION f
, f2
, *fields
[1], *fields2
[1];
1513 const WCHAR
*generationtime
;
1517 struct services
*services
;
1520 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1521 ok( hr
== S_OK
, "got %08x\n", hr
);
1523 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1524 ok( hr
== S_OK
, "got %08x\n", hr
);
1526 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1527 ok( hr
== S_OK
, "got %08x\n", hr
);
1529 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1530 ok( hr
== S_OK
, "got %08x\n", hr
);
1532 hr
= WsWriteStartElement( writer
, &prefix
, &str_officeconfig
, &ns
, NULL
);
1533 ok( hr
== S_OK
, "got %08x\n", hr
);
1535 memset( &f2
, 0, sizeof(f2
) );
1536 f2
.mapping
= WS_ATTRIBUTE_FIELD_MAPPING
;
1537 f2
.localName
= &str_generationtime
;
1539 f2
.type
= WS_WSZ_TYPE
;
1540 f2
.options
= WS_FIELD_OPTIONAL
;
1543 memset( &s2
, 0, sizeof(s2
) );
1544 s2
.size
= sizeof(*test
->services
);
1546 s2
.fields
= fields2
;
1548 s2
.typeLocalName
= &str_services
;
1551 memset( &f
, 0, sizeof(f
) );
1552 f
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
1553 f
.localName
= &str_services
;
1555 f
.type
= WS_STRUCT_TYPE
;
1556 f
.typeDescription
= &s2
;
1557 f
.options
= WS_FIELD_POINTER
;
1560 memset( &s
, 0, sizeof(s
) );
1561 s
.size
= sizeof(*test
);
1565 s
.typeLocalName
= &str_officeconfig
;
1568 size
= sizeof(struct officeconfig
) + sizeof(struct services
);
1569 test
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1570 test
->services
= (struct services
*)(test
+ 1);
1571 test
->services
->generationtime
= timestampW
;
1572 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
1573 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1574 ok( hr
== S_OK
, "got %08x\n", hr
);
1576 hr
= WsWriteEndElement( writer
, NULL
);
1577 ok( hr
== S_OK
, "got %08x\n", hr
);
1578 check_output_buffer( buffer
, expected
, __LINE__
);
1580 HeapFree( GetProcessHeap(), 0, test
);
1581 WsFreeWriter( writer
);
1585 static void test_WsMoveWriter(void)
1587 WS_XML_STRING localname
= {1, (BYTE
*)"a"}, localname2
= {1, (BYTE
*)"b"}, ns
= {0, NULL
};
1589 WS_XML_WRITER
*writer
;
1590 WS_XML_BUFFER
*buffer
;
1593 hr
= WsMoveWriter( NULL
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1594 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1596 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1597 ok( hr
== S_OK
, "got %08x\n", hr
);
1599 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1600 ok( hr
== S_OK
, "got %08x\n", hr
);
1602 hr
= set_output( writer
);
1603 ok( hr
== S_OK
, "got %08x\n", hr
);
1605 /* writer must be set to an XML buffer */
1606 hr
= WsMoveWriter( writer
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1607 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1609 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1610 ok( hr
== S_OK
, "got %08x\n", hr
);
1612 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1613 ok( hr
== S_OK
, "got %08x\n", hr
);
1615 hr
= WsMoveWriter( writer
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1616 ok( hr
== S_OK
, "got %08x\n", hr
);
1619 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1620 ok( hr
== S_OK
, "got %08x\n", hr
);
1622 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
1623 ok( hr
== S_OK
, "got %08x\n", hr
);
1625 hr
= WsWriteEndElement( writer
, NULL
);
1626 ok( hr
== S_OK
, "got %08x\n", hr
);
1628 hr
= WsWriteEndElement( writer
, NULL
);
1629 ok( hr
== S_OK
, "got %08x\n", hr
);
1631 hr
= WsMoveWriter( writer
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1632 ok( hr
== S_OK
, "got %08x\n", hr
);
1634 hr
= WsMoveWriter( writer
, WS_MOVE_TO_ROOT_ELEMENT
, NULL
, NULL
);
1635 ok( hr
== S_OK
, "got %08x\n", hr
);
1637 hr
= WsMoveWriter( writer
, WS_MOVE_TO_CHILD_ELEMENT
, NULL
, NULL
);
1638 ok( hr
== S_OK
, "got %08x\n", hr
);
1640 hr
= WsMoveWriter( writer
, WS_MOVE_TO_END_ELEMENT
, NULL
, NULL
);
1641 ok( hr
== S_OK
, "got %08x\n", hr
);
1643 hr
= WsMoveWriter( writer
, WS_MOVE_TO_PARENT_ELEMENT
, NULL
, NULL
);
1644 ok( hr
== S_OK
, "got %08x\n", hr
);
1646 hr
= WsMoveWriter( writer
, WS_MOVE_TO_END_ELEMENT
, NULL
, NULL
);
1647 ok( hr
== S_OK
, "got %08x\n", hr
);
1649 hr
= WsMoveWriter( writer
, WS_MOVE_TO_BOF
, NULL
, NULL
);
1650 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1652 WsFreeWriter( writer
);
1656 static void test_WsGetWriterPosition(void)
1659 WS_XML_WRITER
*writer
;
1660 WS_XML_BUFFER
*buffer
;
1661 WS_XML_NODE_POSITION pos
;
1664 hr
= WsGetWriterPosition( NULL
, NULL
, NULL
);
1665 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1667 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1668 ok( hr
== S_OK
, "got %08x\n", hr
);
1670 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1671 ok( hr
== S_OK
, "got %08x\n", hr
);
1673 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1674 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1676 hr
= set_output( writer
);
1677 ok( hr
== S_OK
, "got %08x\n", hr
);
1679 /* writer must be set to an XML buffer */
1680 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1681 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1683 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1684 ok( hr
== S_OK
, "got %08x\n", hr
);
1686 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1687 ok( hr
== S_OK
, "got %08x\n", hr
);
1689 hr
= WsGetWriterPosition( writer
, NULL
, NULL
);
1690 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1692 pos
.buffer
= pos
.node
= NULL
;
1693 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1694 ok( hr
== S_OK
, "got %08x\n", hr
);
1695 ok( pos
.buffer
!= NULL
, "buffer not set\n" );
1696 ok( pos
.node
!= NULL
, "node not set\n" );
1698 WsFreeWriter( writer
);
1702 static void test_WsSetWriterPosition(void)
1704 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1706 WS_XML_WRITER
*writer
;
1707 WS_XML_BUFFER
*buf1
, *buf2
;
1708 WS_XML_NODE_POSITION pos
;
1711 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1712 ok( hr
== S_OK
, "got %08x\n", hr
);
1714 hr
= WsSetWriterPosition( NULL
, NULL
, NULL
);
1715 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1717 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1718 ok( hr
== S_OK
, "got %08x\n", hr
);
1720 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buf1
, NULL
);
1721 ok( hr
== S_OK
, "got %08x\n", hr
);
1723 hr
= WsSetOutputToBuffer( writer
, buf1
, NULL
, 0, NULL
);
1724 ok( hr
== S_OK
, "got %08x\n", hr
);
1726 hr
= WsSetWriterPosition( writer
, NULL
, NULL
);
1727 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1729 pos
.buffer
= pos
.node
= NULL
;
1730 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1731 ok( hr
== S_OK
, "got %08x\n", hr
);
1732 ok( pos
.buffer
== buf1
, "wrong buffer\n" );
1733 ok( pos
.node
!= NULL
, "node not set\n" );
1735 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1736 ok( hr
== S_OK
, "got %08x\n", hr
);
1738 /* different buffer */
1739 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buf2
, NULL
);
1740 ok( hr
== S_OK
, "got %08x\n", hr
);
1743 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1744 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1746 hr
= WsSetOutputToBuffer( writer
, buf1
, NULL
, 0, NULL
);
1747 ok( hr
== S_OK
, "got %08x\n", hr
);
1749 /* try to write at non-final position */
1750 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1751 ok( hr
== S_OK
, "got %08x\n", hr
);
1753 pos
.buffer
= pos
.node
= NULL
;
1754 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1755 ok( hr
== S_OK
, "got %08x\n", hr
);
1756 ok( pos
.buffer
== buf1
, "wrong buffer\n" );
1757 ok( pos
.node
!= NULL
, "node not set\n" );
1759 hr
= WsWriteEndElement( writer
, NULL
);
1760 ok( hr
== S_OK
, "got %08x\n", hr
);
1761 check_output_buffer( buf1
, "<t/>", __LINE__
);
1763 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1764 ok( hr
== S_OK
, "got %08x\n", hr
);
1766 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1767 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1769 WsFreeWriter( writer
);
1773 static void test_WsWriteXmlBuffer(void)
1775 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1776 WS_XML_WRITER
*writer1
, *writer2
;
1777 WS_XML_BUFFER
*buffer1
, *buffer2
;
1781 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1782 ok( hr
== S_OK
, "got %08x\n", hr
);
1784 hr
= WsCreateXmlBuffer( NULL
, NULL
, 0, NULL
, NULL
);
1785 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1787 hr
= WsCreateWriter( NULL
, 0, &writer1
, NULL
);
1788 ok( hr
== S_OK
, "got %08x\n", hr
);
1790 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, NULL
, NULL
);
1791 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1793 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer1
, NULL
);
1794 ok( hr
== S_OK
, "got %08x\n", hr
);
1796 hr
= WsSetOutputToBuffer( writer1
, buffer1
, NULL
, 0, NULL
);
1797 ok( hr
== S_OK
, "got %08x\n", hr
);
1799 hr
= WsWriteStartElement( writer1
, NULL
, &localname
, &ns
, NULL
);
1800 ok( hr
== S_OK
, "got %08x\n", hr
);
1802 hr
= WsWriteEndElement( writer1
, NULL
);
1803 ok( hr
== S_OK
, "got %08x\n", hr
);
1804 check_output_buffer( buffer1
, "<t/>", __LINE__
);
1806 hr
= WsCreateWriter( NULL
, 0, &writer2
, NULL
);
1807 ok( hr
== S_OK
, "got %08x\n", hr
);
1809 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer2
, NULL
);
1810 ok( hr
== S_OK
, "got %08x\n", hr
);
1812 hr
= WsSetOutputToBuffer( writer2
, buffer2
, NULL
, 0, NULL
);
1813 ok( hr
== S_OK
, "got %08x\n", hr
);
1815 hr
= WsWriteXmlBuffer( writer2
, buffer1
, NULL
);
1816 ok( hr
== S_OK
, "got %08x\n", hr
);
1817 check_output_buffer( buffer2
, "<t/>", __LINE__
);
1819 hr
= WsMoveWriter( writer2
, WS_MOVE_TO_PREVIOUS_ELEMENT
, NULL
, NULL
);
1820 todo_wine
ok( hr
== S_OK
, "got %08x\n", hr
);
1822 hr
= WsWriteXmlBuffer( writer2
, buffer1
, NULL
);
1823 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1825 WsFreeWriter( writer1
);
1826 WsFreeWriter( writer2
);
1830 static void test_WsWriteNode(void)
1832 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {4, (BYTE
*)"attr"}, ns
= {0, NULL
};
1833 WS_XML_WRITER
*writer
;
1834 WS_XML_BUFFER
*buffer
;
1835 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
1836 WS_XML_ATTRIBUTE attr
, *attrs
[1];
1837 WS_XML_ELEMENT_NODE elem
;
1838 WS_XML_COMMENT_NODE comment
= {{WS_XML_NODE_TYPE_COMMENT
}};
1840 WS_XML_TEXT_NODE text
= {{WS_XML_NODE_TYPE_TEXT
}};
1844 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1845 ok( hr
== S_OK
, "got %08x\n", hr
);
1847 hr
= WsWriteNode( NULL
, NULL
, NULL
);
1848 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1850 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1851 ok( hr
== S_OK
, "got %08x\n", hr
);
1853 hr
= WsWriteNode( writer
, NULL
, NULL
);
1854 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1856 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1857 ok( hr
== S_OK
, "got %08x\n", hr
);
1859 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1860 ok( hr
== S_OK
, "got %08x\n", hr
);
1862 utf8
.value
.bytes
= (BYTE
*)"value";
1863 utf8
.value
.length
= sizeof("value") - 1;
1865 attr
.singleQuote
= TRUE
;
1866 attr
.isXmlNs
= FALSE
;
1868 attr
.localName
= &localname2
;
1870 attr
.value
= &utf8
.text
;
1873 elem
.node
.nodeType
= WS_XML_NODE_TYPE_ELEMENT
;
1875 elem
.localName
= &localname
;
1877 elem
.attributeCount
= 1;
1878 elem
.attributes
= attrs
;
1879 elem
.isEmpty
= FALSE
;
1880 hr
= WsWriteNode( writer
, &elem
.node
, NULL
);
1881 ok( hr
== S_OK
, "got %08x\n", hr
);
1883 comment
.value
.bytes
= (BYTE
*)"comment";
1884 comment
.value
.length
= sizeof("comment") - 1;
1885 hr
= WsWriteNode( writer
, &comment
.node
, NULL
);
1886 ok( hr
== S_OK
, "got %08x\n", hr
);
1888 node
.nodeType
= WS_XML_NODE_TYPE_EOF
;
1889 hr
= WsWriteNode( writer
, &node
, NULL
);
1890 ok( hr
== S_OK
, "got %08x\n", hr
);
1892 node
.nodeType
= WS_XML_NODE_TYPE_BOF
;
1893 hr
= WsWriteNode( writer
, &node
, NULL
);
1894 ok( hr
== S_OK
, "got %08x\n", hr
);
1896 node
.nodeType
= WS_XML_NODE_TYPE_CDATA
;
1897 hr
= WsWriteNode( writer
, &node
, NULL
);
1898 ok( hr
== S_OK
, "got %08x\n", hr
);
1900 utf8
.value
.bytes
= (BYTE
*)"cdata";
1901 utf8
.value
.length
= sizeof("cdata") - 1;
1902 text
.text
= &utf8
.text
;
1903 hr
= WsWriteNode( writer
, &text
.node
, NULL
);
1904 ok( hr
== S_OK
, "got %08x\n", hr
);
1906 node
.nodeType
= WS_XML_NODE_TYPE_END_CDATA
;
1907 hr
= WsWriteNode( writer
, &node
, NULL
);
1908 ok( hr
== S_OK
, "got %08x\n", hr
);
1910 utf8
.value
.bytes
= (BYTE
*)"text";
1911 utf8
.value
.length
= sizeof("text") - 1;
1912 hr
= WsWriteNode( writer
, &text
.node
, NULL
);
1913 ok( hr
== S_OK
, "got %08x\n", hr
);
1915 node
.nodeType
= WS_XML_NODE_TYPE_END_ELEMENT
;
1916 hr
= WsWriteNode( writer
, &node
, NULL
);
1917 ok( hr
== S_OK
, "got %08x\n", hr
);
1918 check_output_buffer( buffer
, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__
);
1920 WsFreeWriter( writer
);
1924 static HRESULT
set_input( WS_XML_READER
*reader
, const char *data
, ULONG size
)
1926 WS_XML_READER_TEXT_ENCODING enc
;
1927 WS_XML_READER_BUFFER_INPUT input
;
1929 enc
.encoding
.encodingType
= WS_XML_READER_ENCODING_TYPE_TEXT
;
1930 enc
.charSet
= WS_CHARSET_AUTO
;
1932 input
.input
.inputType
= WS_XML_READER_INPUT_TYPE_BUFFER
;
1933 input
.encodedData
= (void *)data
;
1934 input
.encodedDataSize
= size
;
1936 return WsSetInput( reader
, &enc
.encoding
, &input
.input
, NULL
, 0, NULL
);
1939 static void test_WsCopyNode(void)
1941 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"u"}, ns
= {0, NULL
};
1942 WS_XML_NODE_POSITION pos
, pos2
;
1943 WS_XML_WRITER
*writer
;
1944 WS_XML_READER
*reader
;
1945 WS_XML_BUFFER
*buffer
;
1949 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1950 ok( hr
== S_OK
, "got %08x\n", hr
);
1952 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1953 ok( hr
== S_OK
, "got %08x\n", hr
);
1955 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1956 ok( hr
== S_OK
, "got %08x\n", hr
);
1958 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1959 ok( hr
== S_OK
, "got %08x\n", hr
);
1961 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1962 ok( hr
== S_OK
, "got %08x\n", hr
);
1964 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
1965 ok( hr
== S_OK
, "got %08x\n", hr
);
1967 hr
= WsWriteEndElement( writer
, NULL
);
1968 ok( hr
== S_OK
, "got %08x\n", hr
);
1970 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1971 ok( hr
== S_OK
, "got %08x\n", hr
);
1973 hr
= WsWriteEndElement( writer
, NULL
);
1974 ok( hr
== S_OK
, "got %08x\n", hr
);
1975 check_output_buffer( buffer
, "<t><u/></t>", __LINE__
);
1977 hr
= WsCreateReader( NULL
, 0, &reader
, NULL
);
1978 ok( hr
== S_OK
, "got %08x\n", hr
);
1980 hr
= set_input( reader
, "<v/>", sizeof("<v/>") - 1 );
1981 ok( hr
== S_OK
, "got %08x\n", hr
);
1983 hr
= WsFillReader( reader
, sizeof("<v/>") - 1, NULL
, NULL
);
1984 ok( hr
== S_OK
, "got %08x\n", hr
);
1986 hr
= WsReadToStartElement( reader
, NULL
, NULL
, NULL
, NULL
);
1987 ok( hr
== S_OK
, "got %08x\n", hr
);
1989 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1990 ok( hr
== S_OK
, "got %08x\n", hr
);
1992 hr
= WsCopyNode( writer
, reader
, NULL
);
1993 ok( hr
== S_OK
, "got %08x\n", hr
);
1994 check_output_buffer( buffer
, "<t><u/><v/></t>", __LINE__
);
1996 hr
= WsGetWriterPosition( writer
, &pos2
, NULL
);
1997 ok( hr
== S_OK
, "got %08x\n", hr
);
1998 ok( pos2
.buffer
== pos
.buffer
, "wrong buffer\n" );
1999 ok( pos2
.node
== pos
.node
, "wrong node\n" );
2001 WsFreeReader( reader
);
2002 WsFreeWriter( writer
);
2006 static void test_text_types(void)
2008 static const WCHAR utf16W
[] = {'u','t','f','1','6'};
2009 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2010 WS_XML_WRITER
*writer
;
2011 static const WS_XML_UTF8_TEXT val_utf8
= { {WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"utf8"} };
2012 static WS_XML_UTF16_TEXT val_utf16
= { {WS_XML_TEXT_TYPE_UTF16
} };
2013 static const WS_XML_GUID_TEXT val_guid
= { {WS_XML_TEXT_TYPE_GUID
} };
2014 static const WS_XML_UNIQUE_ID_TEXT val_urn
= { {WS_XML_TEXT_TYPE_UNIQUE_ID
} };
2015 static const WS_XML_BOOL_TEXT val_bool
= { {WS_XML_TEXT_TYPE_BOOL
}, TRUE
};
2016 static const WS_XML_INT32_TEXT val_int32
= { {WS_XML_TEXT_TYPE_INT32
}, -2147483647 - 1 };
2017 static const WS_XML_INT64_TEXT val_int64
= { {WS_XML_TEXT_TYPE_INT64
}, -9223372036854775807 - 1 };
2018 static const WS_XML_UINT64_TEXT val_uint64
= { {WS_XML_TEXT_TYPE_UINT64
}, ~0 };
2019 static const WS_XML_DATETIME_TEXT val_datetime
= { {WS_XML_TEXT_TYPE_DATETIME
}, {0, WS_DATETIME_FORMAT_UTC
} };
2020 static const WS_XML_DOUBLE_TEXT val_double
= { {WS_XML_TEXT_TYPE_DOUBLE
}, 1.1 };
2021 static const WS_XML_BASE64_TEXT val_base64
= { {WS_XML_TEXT_TYPE_BASE64
}, (BYTE
*)"test", 4 };
2024 const WS_XML_TEXT
*text
;
2029 { &val_utf8
.text
, "<t>utf8</t>" },
2030 { &val_utf16
.text
, "<t>utf16</t>" },
2031 { &val_guid
.text
, "<t>00000000-0000-0000-0000-000000000000</t>" },
2032 { &val_urn
.text
, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
2033 { &val_bool
.text
, "<t>true</t>" },
2034 { &val_int32
.text
, "<t>-2147483648</t>" },
2035 { &val_int64
.text
, "<t>-9223372036854775808</t>" },
2036 { &val_uint64
.text
, "<t>18446744073709551615</t>" },
2037 { &val_datetime
.text
, "<t>0001-01-01T00:00:00Z</t>" },
2038 { &val_double
.text
, "<t>1.1</t>" },
2039 { &val_base64
.text
, "<t>dGVzdA==</t>" },
2044 val_utf16
.bytes
= (BYTE
*)utf16W
;
2045 val_utf16
.byteCount
= sizeof(utf16W
);
2047 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2048 ok( hr
== S_OK
, "got %08x\n", hr
);
2050 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
2052 hr
= set_output( writer
);
2053 ok( hr
== S_OK
, "got %08x\n", hr
);
2054 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2055 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2057 hr
= WsWriteText( writer
, tests
[i
].text
, NULL
);
2058 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2060 hr
= WsWriteEndElement( writer
, NULL
);
2061 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2062 check_output( writer
, tests
[i
].result
, __LINE__
);
2065 WsFreeWriter( writer
);
2068 static BOOL
get_fpword( unsigned short *ret
)
2070 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2071 unsigned short fpword
;
2072 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
2079 static void set_fpword( unsigned short fpword
)
2081 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2082 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2086 static void test_double(void)
2088 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2089 unsigned short fpword
;
2099 {-1.0, "<t>-1</t>"},
2100 {1.0000000000000001, "<t>1</t>"},
2101 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2102 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2103 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2104 {100000000000000, "<t>100000000000000</t>"},
2105 {1000000000000000, "<t>1E+15</t>"},
2106 {0.1, "<t>0.1</t>"},
2107 {0.01, "<t>1E-2</t>"},
2108 {-0.1, "<t>-0.1</t>"},
2109 {-0.01, "<t>-1E-2</t>"},
2110 {1.7976931348623158e308
, "<t>1.7976931348623157E+308</t>"},
2111 {-1.7976931348623158e308
, "<t>-1.7976931348623157E+308</t>"},
2114 WS_XML_WRITER
*writer
;
2115 WS_XML_DOUBLE_TEXT text
;
2118 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
) ;
2119 ok( hr
== S_OK
, "got %08x\n", hr
);
2121 text
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
2122 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
2124 hr
= set_output( writer
);
2125 ok( hr
== S_OK
, "got %08x\n", hr
);
2126 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2127 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2129 text
.value
= tests
[i
].val
;
2130 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2131 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2133 hr
= WsWriteEndElement( writer
, NULL
);
2134 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2135 check_output( writer
, tests
[i
].result
, __LINE__
);
2138 hr
= set_output( writer
);
2139 ok( hr
== S_OK
, "got %08x\n", hr
);
2140 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2141 ok( hr
== S_OK
, "got %08x\n", hr
);
2144 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2145 ok( hr
== S_OK
, "got %08x\n", hr
);
2147 hr
= WsWriteEndElement( writer
, NULL
);
2148 ok( hr
== S_OK
, "got %08x\n", hr
);
2149 check_output( writer
, "<t>NaN</t>", __LINE__
);
2151 hr
= set_output( writer
);
2152 ok( hr
== S_OK
, "got %08x\n", hr
);
2153 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2154 ok( hr
== S_OK
, "got %08x\n", hr
);
2156 text
.value
= INFINITY
;
2157 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2158 ok( hr
== S_OK
, "got %08x\n", hr
);
2160 hr
= WsWriteEndElement( writer
, NULL
);
2161 ok( hr
== S_OK
, "got %08x\n", hr
);
2162 check_output( writer
, "<t>INF</t>", __LINE__
);
2164 hr
= set_output( writer
);
2165 ok( hr
== S_OK
, "got %08x\n", hr
);
2166 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2167 ok( hr
== S_OK
, "got %08x\n", hr
);
2169 text
.value
= -INFINITY
;
2170 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2171 ok( hr
== S_OK
, "got %08x\n", hr
);
2173 hr
= WsWriteEndElement( writer
, NULL
);
2174 ok( hr
== S_OK
, "got %08x\n", hr
);
2175 check_output( writer
, "<t>-INF</t>", __LINE__
);
2177 if (!get_fpword( &fpword
))
2179 skip( "can't get floating point control word\n" );
2180 WsFreeWriter( writer
);
2183 ok( fpword
== 0x27f, "got %04x\n", fpword
);
2184 set_fpword( 0x1f7f );
2185 get_fpword( &fpword
);
2186 ok( fpword
== 0x1f7f, "got %04x\n", fpword
);
2188 hr
= set_output( writer
);
2189 ok( hr
== S_OK
, "got %08x\n", hr
);
2190 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2191 ok( hr
== S_OK
, "got %08x\n", hr
);
2193 text
.value
= 100000000000000;
2194 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2195 ok( hr
== S_OK
, "got %08x\n", hr
);
2197 hr
= WsWriteEndElement( writer
, NULL
);
2198 ok( hr
== S_OK
, "got %08x\n", hr
);
2199 check_output( writer
, "<t>100000000000000</t>", __LINE__
);
2201 get_fpword( &fpword
);
2202 ok( fpword
== 0x1f7f, "got %04x\n", fpword
);
2203 set_fpword( 0x27f );
2205 WsFreeWriter( writer
);
2208 static void test_field_options(void)
2210 static const char expected
[] =
2211 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2212 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2214 WS_XML_WRITER
*writer
;
2215 WS_STRUCT_DESCRIPTION s
;
2216 WS_FIELD_DESCRIPTION f
, f2
, f3
, f4
, f5
, *fields
[5];
2217 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
}, str_guid
= {4, (BYTE
*)"guid"};
2218 WS_XML_STRING str_int32
= {5, (BYTE
*)"int32"}, str_bool
= {4, (BYTE
*)"bool"};
2219 WS_XML_STRING str_xmlstr
= {6, (BYTE
*)"xmlstr"}, str_str
= {3, (BYTE
*)"str"};
2226 WS_XML_STRING xmlstr
;
2230 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2231 ok( hr
== S_OK
, "got %08x\n", hr
);
2233 hr
= set_output( writer
);
2234 ok( hr
== S_OK
, "got %08x\n", hr
);
2236 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2237 ok( hr
== S_OK
, "got %08x\n", hr
);
2239 memset( &f
, 0, sizeof(f
) );
2240 f
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2241 f
.localName
= &str_guid
;
2243 f
.type
= WS_GUID_TYPE
;
2244 f
.options
= WS_FIELD_OPTIONAL
;
2247 memset( &f2
, 0, sizeof(f2
) );
2248 f2
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2249 f2
.localName
= &str_bool
;
2250 f2
.offset
= FIELD_OFFSET(struct test
, bool_ptr
);
2252 f2
.type
= WS_BOOL_TYPE
;
2253 f2
.options
= WS_FIELD_POINTER
|WS_FIELD_NILLABLE
;
2256 memset( &f3
, 0, sizeof(f3
) );
2257 f3
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2258 f3
.localName
= &str_int32
;
2259 f3
.offset
= FIELD_OFFSET(struct test
, int32_ptr
);
2261 f3
.type
= WS_INT32_TYPE
;
2262 f3
.options
= WS_FIELD_POINTER
|WS_FIELD_NILLABLE
;
2265 memset( &f4
, 0, sizeof(f4
) );
2266 f4
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2267 f4
.localName
= &str_xmlstr
;
2268 f4
.offset
= FIELD_OFFSET(struct test
, xmlstr
);
2270 f4
.type
= WS_XML_STRING_TYPE
;
2271 f4
.options
= WS_FIELD_NILLABLE
;
2274 memset( &f5
, 0, sizeof(f5
) );
2275 f5
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2276 f5
.localName
= &str_str
;
2277 f5
.offset
= FIELD_OFFSET(struct test
, str
);
2279 f5
.type
= WS_WSZ_TYPE
;
2280 f5
.options
= WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
;
2283 memset( &s
, 0, sizeof(s
) );
2284 s
.size
= sizeof(struct test
);
2285 s
.alignment
= TYPE_ALIGNMENT(struct test
);
2289 memset( &test
, 0, sizeof(test
) );
2290 test
.int32_ptr
= &val
;
2291 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
2292 &test
, sizeof(test
), NULL
);
2293 ok( hr
== S_OK
, "got %08x\n", hr
);
2295 hr
= WsWriteEndElement( writer
, NULL
);
2296 ok( hr
== S_OK
, "got %08x\n", hr
);
2297 check_output( writer
, expected
, __LINE__
);
2299 WsFreeWriter( writer
);
2302 static void test_WsWriteText(void)
2304 static const WCHAR testW
[] = {'t','e','s','t'};
2305 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"a"}, ns
= {0, NULL
};
2307 WS_XML_WRITER
*writer
;
2308 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
2309 WS_XML_UTF16_TEXT utf16
= {{WS_XML_TEXT_TYPE_UTF16
}};
2310 WS_XML_GUID_TEXT guid
= {{WS_XML_TEXT_TYPE_GUID
}};
2312 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2313 ok( hr
== S_OK
, "got %08x\n", hr
);
2315 hr
= set_output( writer
);
2316 ok( hr
== S_OK
, "got %08x\n", hr
);
2318 utf8
.value
.bytes
= (BYTE
*)"test";
2319 utf8
.value
.length
= 4;
2320 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2321 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
2323 hr
= set_output( writer
);
2324 ok( hr
== S_OK
, "got %08x\n", hr
);
2327 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2328 ok( hr
== S_OK
, "got %08x\n", hr
);
2330 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2331 ok( hr
== S_OK
, "got %08x\n", hr
);
2332 check_output( writer
, "<t>test", __LINE__
);
2334 utf8
.value
.bytes
= (BYTE
*)"tset";
2335 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2336 ok( hr
== S_OK
, "got %08x\n", hr
);
2337 check_output( writer
, "<t>testtset", __LINE__
);
2339 hr
= WsWriteEndElement( writer
, NULL
);
2340 ok( hr
== S_OK
, "got %08x\n", hr
);
2341 check_output( writer
, "<t>testtset</t>", __LINE__
);
2343 hr
= set_output( writer
);
2344 ok( hr
== S_OK
, "got %08x\n", hr
);
2346 /* attribute, utf8 */
2347 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2348 ok( hr
== S_OK
, "got %08x\n", hr
);
2350 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2351 ok( hr
== S_OK
, "got %08x\n", hr
);
2353 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2354 ok( hr
== S_OK
, "got %08x\n", hr
);
2355 check_output( writer
, "", __LINE__
);
2357 utf8
.value
.bytes
= (BYTE
*)"test";
2358 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2359 ok( hr
== S_OK
, "got %08x\n", hr
);
2360 check_output( writer
, "", __LINE__
);
2362 hr
= WsWriteEndAttribute( writer
, NULL
);
2363 ok( hr
== S_OK
, "got %08x\n", hr
);
2365 hr
= WsWriteEndElement( writer
, NULL
);
2366 ok( hr
== S_OK
, "got %08x\n", hr
);
2367 check_output( writer
, "<t a=\"tsettest\"/>", __LINE__
);
2369 hr
= set_output( writer
);
2370 ok( hr
== S_OK
, "got %08x\n", hr
);
2372 /* element, utf16 */
2373 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2374 ok( hr
== S_OK
, "got %08x\n", hr
);
2376 utf16
.bytes
= (BYTE
*)testW
;
2377 utf16
.byteCount
= sizeof(testW
);
2378 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2379 ok( hr
== S_OK
, "got %08x\n", hr
);
2380 check_output( writer
, "<t>test", __LINE__
);
2382 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2383 ok( hr
== S_OK
, "got %08x\n", hr
);
2384 check_output( writer
, "<t>testtest", __LINE__
);
2386 hr
= WsWriteEndElement( writer
, NULL
);
2387 ok( hr
== S_OK
, "got %08x\n", hr
);
2388 check_output( writer
, "<t>testtest</t>", __LINE__
);
2390 hr
= set_output( writer
);
2391 ok( hr
== S_OK
, "got %08x\n", hr
);
2393 /* attribute, utf16 */
2394 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2395 ok( hr
== S_OK
, "got %08x\n", hr
);
2397 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2398 ok( hr
== S_OK
, "got %08x\n", hr
);
2400 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2401 ok( hr
== S_OK
, "got %08x\n", hr
);
2402 check_output( writer
, "", __LINE__
);
2404 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2405 ok( hr
== S_OK
, "got %08x\n", hr
);
2406 check_output( writer
, "", __LINE__
);
2408 hr
= WsWriteEndAttribute( writer
, NULL
);
2409 ok( hr
== S_OK
, "got %08x\n", hr
);
2411 hr
= WsWriteEndElement( writer
, NULL
);
2412 ok( hr
== S_OK
, "got %08x\n", hr
);
2413 check_output( writer
, "<t a=\"testtest\"/>", __LINE__
);
2415 hr
= set_output( writer
);
2416 ok( hr
== S_OK
, "got %08x\n", hr
);
2419 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2420 ok( hr
== S_OK
, "got %08x\n", hr
);
2422 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2423 ok( hr
== S_OK
, "got %08x\n", hr
);
2424 check_output( writer
, "<t>00000000-0000-0000-0000-000000000000", __LINE__
);
2426 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2427 ok( hr
== S_OK
, "got %08x\n", hr
);
2428 check_output( writer
, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000",
2431 /* continue with different text type */
2432 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2433 ok( hr
== S_OK
, "got %08x\n", hr
);
2434 check_output( writer
, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000test",
2437 hr
= WsWriteEndElement( writer
, NULL
);
2438 ok( hr
== S_OK
, "got %08x\n", hr
);
2440 hr
= set_output( writer
);
2441 ok( hr
== S_OK
, "got %08x\n", hr
);
2443 /* attribute, guid */
2444 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2445 ok( hr
== S_OK
, "got %08x\n", hr
);
2447 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2448 ok( hr
== S_OK
, "got %08x\n", hr
);
2450 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2451 ok( hr
== S_OK
, "got %08x\n", hr
);
2452 check_output( writer
, "", __LINE__
);
2454 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2455 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2457 hr
= set_output( writer
);
2458 ok( hr
== S_OK
, "got %08x\n", hr
);
2460 /* attribute, mix allowed text types */
2461 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2462 ok( hr
== S_OK
, "got %08x\n", hr
);
2464 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2465 ok( hr
== S_OK
, "got %08x\n", hr
);
2467 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2468 ok( hr
== S_OK
, "got %08x\n", hr
);
2470 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2471 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2473 hr
= set_output( writer
);
2474 ok( hr
== S_OK
, "got %08x\n", hr
);
2477 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2478 ok( hr
== S_OK
, "got %08x\n", hr
);
2479 hr
= WsWriteStartCData( writer
, NULL
);
2480 ok( hr
== S_OK
, "got %08x\n", hr
);
2482 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2483 ok( hr
== S_OK
, "got %08x\n", hr
);
2485 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2486 ok( hr
== S_OK
, "got %08x\n", hr
);
2488 hr
= WsWriteEndCData( writer
, NULL
);
2489 ok( hr
== S_OK
, "got %08x\n", hr
);
2490 hr
= WsWriteEndElement( writer
, NULL
);
2491 ok( hr
== S_OK
, "got %08x\n", hr
);
2492 check_output( writer
, "<t><![CDATA[test00000000-0000-0000-0000-000000000000]]></t>", __LINE__
);
2494 WsFreeWriter( writer
);
2497 static void test_WsWriteArray(void)
2499 static const WS_XML_STRING localname
= {4, (BYTE
*)"item"}, localname2
= {5, (BYTE
*)"array"};
2500 static const WS_XML_STRING ns
= {0, NULL
};
2501 WS_XML_WRITER
*writer
;
2505 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2506 ok( hr
== S_OK
, "got %08x\n", hr
);
2508 hr
= WsWriteArray( writer
, NULL
, NULL
, 0, NULL
, 0, 0, 0, NULL
);
2509 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2511 hr
= set_output( writer
);
2512 ok( hr
== S_OK
, "got %08x\n", hr
);
2513 hr
= WsWriteArray( writer
, NULL
, NULL
, 0, NULL
, 0, 0, 0, NULL
);
2514 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2516 hr
= set_output( writer
);
2517 ok( hr
== S_OK
, "got %08x\n", hr
);
2518 hr
= WsWriteArray( writer
, &localname
, NULL
, 0, NULL
, 0, 0, 0, NULL
);
2519 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2521 hr
= set_output( writer
);
2522 ok( hr
== S_OK
, "got %08x\n", hr
);
2523 hr
= WsWriteArray( writer
, &localname
, &ns
, 0, NULL
, 0, 0, 0, NULL
);
2524 ok( hr
== S_OK
, "got %08x\n", hr
);
2525 check_output( writer
, "", __LINE__
);
2527 hr
= WsWriteArray( writer
, &localname
, &ns
, ~0u, NULL
, 0, 0, 0, NULL
);
2528 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2530 hr
= set_output( writer
);
2531 ok( hr
== S_OK
, "got %08x\n", hr
);
2532 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, NULL
, 0, 0, 0, NULL
);
2533 ok( hr
== S_OK
, "got %08x\n", hr
);
2534 check_output( writer
, "", __LINE__
);
2536 array_bool
[0] = FALSE
;
2537 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, 0, 0, 0, NULL
);
2538 ok( hr
== S_OK
, "got %08x\n", hr
);
2539 check_output( writer
, "", __LINE__
);
2541 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 0, NULL
);
2542 ok( hr
== S_OK
, "got %08x\n", hr
);
2543 check_output( writer
, "", __LINE__
);
2545 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, NULL
, sizeof(array_bool
), 0, 0, NULL
);
2546 ok( hr
== S_OK
, "got %08x\n", hr
);
2547 check_output( writer
, "", __LINE__
);
2549 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, NULL
, sizeof(array_bool
), 0, 1, NULL
);
2550 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2552 hr
= set_output( writer
);
2553 ok( hr
== S_OK
, "got %08x\n", hr
);
2554 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 1, NULL
);
2555 ok( hr
== S_OK
, "got %08x\n", hr
);
2556 check_output( writer
, "<item>false</item>", __LINE__
);
2558 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
) - 1, 0, 2, NULL
);
2559 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2561 hr
= set_output( writer
);
2562 ok( hr
== S_OK
, "got %08x\n", hr
);
2563 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 3, NULL
);
2564 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2566 hr
= set_output( writer
);
2567 ok( hr
== S_OK
, "got %08x\n", hr
);
2569 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
2570 ok( hr
== S_OK
, "got %08x\n", hr
);
2572 array_bool
[1] = TRUE
;
2573 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 2, NULL
);
2574 ok( hr
== S_OK
, "got %08x\n", hr
);
2576 hr
= WsWriteEndElement( writer
, NULL
);
2577 ok( hr
== S_OK
, "got %08x\n", hr
);
2578 check_output( writer
, "<array><item>false</item><item>true</item></array>", __LINE__
);
2580 WsFreeWriter( writer
);
2583 static void test_escapes(void)
2585 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2586 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
2587 WS_XML_WRITER
*writer
;
2594 static const struct test tests_elem
[] =
2596 { "<", "<t><</t>" },
2597 { ">", "<t>></t>" },
2598 { "\"", "<t>\"</t>" },
2599 { "&", "<t>&</t>" },
2600 { "&&", "<t>&&</t>" },
2601 { "'", "<t>'</t>" },
2603 static const struct test tests_attr
[] =
2605 { "<", "<t t=\"<\"/>" },
2606 { ">", "<t t=\">\"/>" },
2607 { "\"", "<t t=\""\"/>" },
2608 { "&", "<t t=\"&\"/>" },
2609 { "'", "<t t=\"'\"/>" },
2610 { "\"", "<t t='\"'/>", TRUE
},
2611 { "'", "<t t='''/>", TRUE
},
2613 static const struct test tests_cdata
[] =
2615 { "<", "<t><![CDATA[<]]></t>" },
2616 { ">", "<t><![CDATA[>]]></t>" },
2617 { "\"", "<t><![CDATA[\"]]></t>" },
2618 { "&", "<t><![CDATA[&]]></t>" },
2619 { "[", "<t><![CDATA[[]]></t>" },
2620 { "]", "<t><![CDATA[]]]></t>" },
2621 { "'", "<t><![CDATA[']]></t>" },
2623 static const struct test tests_comment
[] =
2625 { "<", "<t><!--<--></t>" },
2626 { ">", "<t><!-->--></t>" },
2627 { "\"", "<t><!--\"--></t>" },
2628 { "&", "<t><!--&--></t>" },
2629 { "'", "<t><!--'--></t>" },
2634 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2635 ok( hr
== S_OK
, "got %08x\n", hr
);
2637 for (i
= 0; i
< sizeof(tests_elem
)/sizeof(tests_elem
[0]); i
++)
2639 hr
= set_output( writer
);
2640 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2641 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2642 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2644 utf8
.value
.bytes
= (BYTE
*)tests_elem
[i
].text
;
2645 utf8
.value
.length
= strlen( tests_elem
[i
].text
);
2646 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2647 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2649 hr
= WsWriteEndElement( writer
, NULL
);
2650 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2651 check_output( writer
, tests_elem
[i
].result
, __LINE__
);
2654 for (i
= 0; i
< sizeof(tests_attr
)/sizeof(tests_attr
[0]); i
++)
2656 hr
= set_output( writer
);
2657 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2658 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2659 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2661 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, tests_attr
[i
].single
, NULL
);
2662 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2664 utf8
.value
.bytes
= (BYTE
*)tests_attr
[i
].text
;
2665 utf8
.value
.length
= strlen( tests_attr
[i
].text
);
2666 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2667 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2669 hr
= WsWriteEndAttribute( writer
, NULL
);
2670 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2672 hr
= WsWriteEndElement( writer
, NULL
);
2673 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2674 check_output( writer
, tests_attr
[i
].result
, __LINE__
);
2677 for (i
= 0; i
< sizeof(tests_cdata
)/sizeof(tests_cdata
[0]); i
++)
2679 hr
= set_output( writer
);
2680 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2681 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2682 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2684 hr
= WsWriteStartCData( writer
, NULL
);
2685 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2687 utf8
.value
.bytes
= (BYTE
*)tests_cdata
[i
].text
;
2688 utf8
.value
.length
= strlen( tests_cdata
[i
].text
);
2689 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2690 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2692 hr
= WsWriteEndCData( writer
, NULL
);
2693 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2695 hr
= WsWriteEndElement( writer
, NULL
);
2696 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2697 check_output( writer
, tests_cdata
[i
].result
, __LINE__
);
2700 for (i
= 0; i
< sizeof(tests_comment
)/sizeof(tests_comment
[0]); i
++)
2702 WS_XML_COMMENT_NODE comment
= {{WS_XML_NODE_TYPE_COMMENT
}};
2704 hr
= set_output( writer
);
2705 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2706 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2707 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2709 comment
.value
.bytes
= (BYTE
*)tests_comment
[i
].text
;
2710 comment
.value
.length
= strlen( tests_comment
[i
].text
);
2711 hr
= WsWriteNode( writer
, &comment
.node
, NULL
);
2712 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2714 hr
= WsWriteEndElement( writer
, NULL
);
2715 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2716 check_output( writer
, tests_comment
[i
].result
, __LINE__
);
2719 WsFreeWriter( writer
);
2722 static void test_write_option(void)
2724 static const WCHAR sW
[] = {'s',0};
2725 static const WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2726 WS_XML_WRITER
*writer
;
2727 int val_int
= -1, val_int_zero
= 0, *ptr_int
= &val_int
, *ptr_int_null
= NULL
;
2728 const WCHAR
*ptr_wsz
= sW
, *ptr_wsz_null
= NULL
;
2729 static const WS_XML_STRING val_xmlstr
= {1, (BYTE
*)"x"}, val_xmlstr_zero
= {0, NULL
};
2730 const WS_XML_STRING
*ptr_xmlstr
= &val_xmlstr
, *ptr_xmlstr_null
= NULL
;
2734 WS_WRITE_OPTION option
;
2742 { WS_INT32_TYPE
, 0, NULL
, 0, E_INVALIDARG
},
2743 { WS_INT32_TYPE
, 0, "str", 0, E_INVALIDARG
},
2744 { WS_INT32_TYPE
, 0, NULL
, sizeof(val_int
), E_INVALIDARG
},
2745 { WS_INT32_TYPE
, 0, &val_int
, sizeof(val_int
), E_INVALIDARG
},
2746 { WS_INT32_TYPE
, 0, &val_int_zero
, sizeof(val_int_zero
), E_INVALIDARG
},
2747 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, 0, E_INVALIDARG
},
2748 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_int
, 0, E_INVALIDARG
},
2749 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, sizeof(val_int
), E_INVALIDARG
},
2750 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_int
, sizeof(val_int
), S_OK
, "<t>-1</t>" },
2751 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_int_zero
, sizeof(val_int_zero
), S_OK
, "<t>0</t>" },
2752 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, NULL
, 0, E_INVALIDARG
},
2753 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_int
, 0, E_INVALIDARG
},
2754 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, NULL
, sizeof(val_int
), E_INVALIDARG
},
2755 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_int
, sizeof(val_int
), E_INVALIDARG
},
2756 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_int_zero
, sizeof(val_int_zero
), E_INVALIDARG
},
2757 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, E_INVALIDARG
},
2758 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_int
, 0, E_INVALIDARG
},
2759 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(ptr_int
), E_INVALIDARG
},
2760 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_int
, sizeof(ptr_int
), S_OK
, "<t>-1</t>" },
2761 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_int_null
, sizeof(ptr_int_null
), E_INVALIDARG
},
2762 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, 0, E_INVALIDARG
},
2763 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_int
, 0, E_INVALIDARG
},
2764 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, sizeof(ptr_int
), E_INVALIDARG
},
2765 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_int
, sizeof(ptr_int
), S_OK
, "<t>-1</t>" },
2766 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_int_null
, sizeof(ptr_int_null
), S_OK
,
2767 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2768 { WS_XML_STRING_TYPE
, 0, NULL
, 0, E_INVALIDARG
},
2769 { WS_XML_STRING_TYPE
, 0, &val_xmlstr
, 0, E_INVALIDARG
},
2770 { WS_XML_STRING_TYPE
, 0, NULL
, sizeof(val_xmlstr
), E_INVALIDARG
},
2771 { WS_XML_STRING_TYPE
, 0, &val_xmlstr
, sizeof(val_xmlstr
), E_INVALIDARG
},
2772 { WS_XML_STRING_TYPE
, 0, &val_xmlstr_zero
, sizeof(val_xmlstr_zero
), E_INVALIDARG
},
2773 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, 0, E_INVALIDARG
},
2774 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_xmlstr
, 0, E_INVALIDARG
},
2775 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, sizeof(&val_xmlstr
), E_INVALIDARG
},
2776 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_xmlstr
, sizeof(val_xmlstr
), S_OK
, "<t>x</t>" },
2777 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_xmlstr_zero
, sizeof(val_xmlstr_zero
), S_OK
, "<t/>" },
2778 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_xmlstr
, 0, E_INVALIDARG
},
2779 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, NULL
, sizeof(&val_xmlstr
), E_INVALIDARG
},
2780 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_xmlstr
, sizeof(&val_xmlstr
), E_INVALIDARG
},
2781 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_xmlstr_zero
, sizeof(val_xmlstr_zero
), S_OK
,
2782 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2783 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, E_INVALIDARG
},
2784 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_xmlstr
, 0, E_INVALIDARG
},
2785 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(ptr_xmlstr
), E_INVALIDARG
},
2786 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_xmlstr
, sizeof(ptr_xmlstr
), S_OK
, "<t>x</t>" },
2787 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_xmlstr_null
, sizeof(ptr_xmlstr_null
), E_INVALIDARG
},
2788 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, 0, E_INVALIDARG
},
2789 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_xmlstr
, 0, E_INVALIDARG
},
2790 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, sizeof(ptr_xmlstr
), E_INVALIDARG
},
2791 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_xmlstr
, sizeof(ptr_xmlstr
), S_OK
, "<t>x</t>" },
2792 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_xmlstr_null
, sizeof(ptr_xmlstr_null
), S_OK
,
2793 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2794 { WS_WSZ_TYPE
, 0, NULL
, 0, E_INVALIDARG
},
2795 { WS_WSZ_TYPE
, 0, &ptr_wsz
, 0, E_INVALIDARG
},
2796 { WS_WSZ_TYPE
, 0, NULL
, sizeof(ptr_wsz
), E_INVALIDARG
},
2797 { WS_WSZ_TYPE
, 0, &ptr_wsz
, sizeof(ptr_wsz
), E_INVALIDARG
},
2798 { WS_WSZ_TYPE
, 0, &ptr_wsz_null
, sizeof(ptr_wsz_null
), E_INVALIDARG
},
2799 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_VALUE
, &ptr_wsz
, sizeof(ptr_wsz
), E_INVALIDARG
},
2800 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_VALUE
, &ptr_wsz
, sizeof(ptr_wsz
), E_INVALIDARG
},
2801 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, E_INVALIDARG
},
2802 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_wsz
, 0, E_INVALIDARG
},
2803 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(ptr_wsz
), E_INVALIDARG
},
2804 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_wsz
, sizeof(ptr_wsz
), S_OK
, "<t>s</t>" },
2805 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_wsz_null
, sizeof(ptr_wsz_null
), E_INVALIDARG
},
2806 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, 0, E_INVALIDARG
},
2807 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_wsz
, 0, E_INVALIDARG
},
2808 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, sizeof(ptr_wsz
), E_INVALIDARG
},
2809 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_wsz
, sizeof(ptr_wsz
), S_OK
, "<t>s</t>" },
2810 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_wsz_null
, sizeof(ptr_wsz_null
), S_OK
,
2811 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2816 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2817 ok( hr
== S_OK
, "got %08x\n", hr
);
2819 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
2821 hr
= set_output( writer
);
2822 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2823 WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2824 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, tests
[i
].type
, NULL
, tests
[i
].option
, tests
[i
].value
,
2825 tests
[i
].size
, NULL
);
2826 ok( hr
== tests
[i
].hr
, "%u: got %08x\n", i
, hr
);
2827 WsWriteEndElement( writer
, NULL
);
2828 if (hr
== S_OK
) check_output( writer
, tests
[i
].result
, __LINE__
);
2831 WsFreeWriter( writer
);
2834 static BOOL
check_result( WS_XML_WRITER
*writer
, const char *expected
)
2837 ULONG size
= sizeof(bytes
);
2838 int len
= strlen( expected
);
2840 memset( &bytes
, 0, sizeof(bytes
) );
2841 WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
2842 if (bytes
.length
!= len
) return FALSE
;
2843 return !memcmp( bytes
.bytes
, expected
, len
);
2846 static void test_datetime(void)
2848 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2851 unsigned __int64 ticks
;
2852 WS_DATETIME_FORMAT format
;
2855 const char *result2
;
2860 { 0, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0001-01-01T00:00:00Z</t>" },
2861 { 0, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T00:00:00+00:00</t>" },
2862 { 0, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00</t>" },
2863 { 1, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0001-01-01T00:00:00.0000001Z</t>" },
2864 { 1, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T00:00:00.0000001+00:00</t>" },
2865 { 1, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00.0000001</t>" },
2866 { 10, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00.000001</t>" },
2867 { 1000000, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00.1</t>" },
2868 { 0x23c34600, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T00:01:00+00:00</t>" },
2869 { 0x861c46800, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T01:00:00+00:00</t>" },
2870 { 0x430e234000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T08:00:00+00:00</t>" },
2871 { 0x4b6fe7a800, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T09:00:00+00:00</t>" },
2872 { 0x989680, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:01</t>" },
2873 { 0x23c34600, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:01:00</t>" },
2874 { 0x861c46800, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T01:00:00</t>" },
2875 { 0xc92a69c000, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-02T00:00:00</t>" },
2876 { 0x11ed178c6c000, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0002-01-01T00:00:00</t>" },
2877 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>9999-12-31T23:59:59.9999999Z</t>" },
2878 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>9999-12-31T15:59:59.9999999-08:00</t>",
2879 "<t>9999-12-31T17:59:59.9999999-06:00</t>" /* win7 */, WS_E_INVALID_FORMAT
},
2880 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>9999-12-31T23:59:59.9999999</t>" },
2881 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_UTC
, WS_E_INVALID_FORMAT
},
2882 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_LOCAL
, WS_E_INVALID_FORMAT
},
2883 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_NONE
, WS_E_INVALID_FORMAT
},
2884 { 0x8d3123e7df74000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>2015-12-31T16:00:00-08:00</t>",
2885 "<t>2015-12-31T18:00:00-06:00</t>" /* win7 */ },
2886 { 0x701ce1722770000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T00:00:00+00:00</t>" },
2887 { 0x701ce5a309a4000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T00:00:00-08:00</t>",
2888 "<t>1601-01-01T02:00:00-06:00</t>" /* win7 */ },
2889 { 0x701ce5e617c7400, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T00:30:00-08:00</t>",
2890 "<t>1601-01-01T02:30:00-06:00</t>" /* win7 */ },
2891 { 0x701ce51ced5d800, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T07:00:00+00:00</t>",
2892 "<t>1601-01-01T01:00:00-06:00</t>" /* win7 */ },
2893 { 0, WS_DATETIME_FORMAT_NONE
+ 1, WS_E_INVALID_FORMAT
},
2894 { 0x38a080649c000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0004-02-28T00:00:00Z</t>" },
2895 { 0x38ad130b38000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0004-02-29T00:00:00Z</t>" },
2896 { 0x8c1505f0e438000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>2000-02-29T00:00:00Z</t>" },
2897 { 0x8d46035e7870000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>2017-03-01T00:00:00Z</t>" },
2900 WS_XML_WRITER
*writer
;
2904 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2905 ok( hr
== S_OK
, "got %08x\n", hr
);
2906 for (i
= 0; i
< sizeof(tests
)/sizeof(tests
[0]); i
++)
2908 hr
= set_output( writer
);
2909 ok( hr
== S_OK
, "got %08x\n", hr
);
2911 date
.ticks
= tests
[i
].ticks
;
2912 date
.format
= tests
[i
].format
;
2913 WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2914 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_DATETIME_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
2915 &date
, sizeof(date
), NULL
);
2916 WsWriteEndElement( writer
, NULL
);
2917 ok( hr
== tests
[i
].hr
|| broken(hr
== tests
[i
].hr_broken
), "%u: got %08x\n", i
, hr
);
2918 if (hr
!= tests
[i
].hr
&& hr
== tests
[i
].hr_broken
) break;
2921 ok( check_result( writer
, tests
[i
].result
) ||
2922 (tests
[i
].result2
&& broken(check_result( writer
, tests
[i
].result2
))),
2923 "%u: wrong result\n", i
);
2927 WsFreeWriter( writer
);
2930 static void test_repeating_element(void)
2932 static const WCHAR oneW
[] = {'1',0}, twoW
[] = {'2',0};
2933 WS_XML_STRING localname
= {4, (BYTE
*)"test"}, ns
= {0, NULL
};
2934 WS_XML_STRING val
= {3, (BYTE
*)"val"}, wrapper
= {7, (BYTE
*)"wrapper"};
2936 WS_XML_WRITER
*writer
;
2937 WS_STRUCT_DESCRIPTION s
;
2938 WS_FIELD_DESCRIPTION f
, *fields
[1];
2939 WS_ITEM_RANGE range
;
2951 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2952 ok( hr
== S_OK
, "got %08x\n", hr
);
2954 /* array of strings, wrapper */
2955 hr
= set_output( writer
);
2956 ok( hr
== S_OK
, "got %08x\n", hr
);
2957 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2958 ok( hr
== S_OK
, "got %08x\n", hr
);
2960 memset( &f
, 0, sizeof(f
) );
2961 f
.mapping
= WS_REPEATING_ELEMENT_FIELD_MAPPING
;
2962 f
.localName
= &wrapper
;
2964 f
.type
= WS_WSZ_TYPE
;
2965 f
.countOffset
= FIELD_OFFSET(struct test
, count
);
2966 f
.itemLocalName
= &val
;
2970 memset( &s
, 0, sizeof(s
) );
2971 s
.size
= sizeof(struct test
);
2972 s
.alignment
= TYPE_ALIGNMENT(struct test
);
2973 s
.typeLocalName
= &localname
;
2978 hr
= set_output( writer
);
2979 ok( hr
== S_OK
, "got %08x\n", hr
);
2980 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2981 ok( hr
== S_OK
, "got %08x\n", hr
);
2983 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) + 2 * sizeof(const WCHAR
*) );
2984 test
->val
= (const WCHAR
**)(test
+ 1);
2985 test
->val
[0] = oneW
;
2986 test
->val
[1] = twoW
;
2988 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
2989 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
2990 ok( hr
== S_OK
, "got %08x\n", hr
);
2991 hr
= WsWriteEndElement( writer
, NULL
);
2992 ok( hr
== S_OK
, "got %08x\n", hr
);
2993 check_output( writer
, "<test><wrapper><val>1</val><val>2</val></wrapper></test>", __LINE__
);
2994 HeapFree( GetProcessHeap(), 0, test
);
2996 /* array of integers, no wrapper */
2997 hr
= set_output( writer
);
2998 ok( hr
== S_OK
, "got %08x\n", hr
);
2999 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3000 ok( hr
== S_OK
, "got %08x\n", hr
);
3002 f
.type
= WS_INT32_TYPE
;
3006 test2
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test2
) + 2 * sizeof(INT32
) );
3007 test2
->val
= (INT32
*)(test2
+ 1);
3011 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
3012 WS_WRITE_REQUIRED_POINTER
, &test2
, sizeof(test2
), NULL
);
3013 ok( hr
== S_OK
, "got %08x\n", hr
);
3014 hr
= WsWriteEndElement( writer
, NULL
);
3015 ok( hr
== S_OK
, "got %08x\n", hr
);
3016 check_output( writer
, "<test><val>1</val><val>2</val></test>", __LINE__
);
3018 /* item range has no effect */
3019 hr
= set_output( writer
);
3020 ok( hr
== S_OK
, "got %08x\n", hr
);
3021 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3022 ok( hr
== S_OK
, "got %08x\n", hr
);
3024 range
.minItemCount
= 0;
3025 range
.maxItemCount
= 0;
3026 f
.itemRange
= &range
;
3028 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
3029 WS_WRITE_REQUIRED_POINTER
, &test2
, sizeof(test2
), NULL
);
3030 ok( hr
== S_OK
, "got %08x\n", hr
);
3031 hr
= WsWriteEndElement( writer
, NULL
);
3032 ok( hr
== S_OK
, "got %08x\n", hr
);
3033 check_output( writer
, "<test><val>1</val><val>2</val></test>", __LINE__
);
3034 HeapFree( GetProcessHeap(), 0, test2
);
3036 WsFreeWriter( writer
);
3041 test_WsCreateWriter();
3042 test_WsCreateXmlBuffer();
3044 test_WsSetOutputToBuffer();
3045 test_WsWriteStartElement();
3046 test_WsWriteStartAttribute();
3049 test_simple_struct_type();
3050 test_WsWriteElement();
3051 test_WsWriteValue();
3052 test_WsWriteAttribute();
3053 test_WsWriteStartCData();
3054 test_WsWriteXmlnsAttribute();
3055 test_WsGetPrefixFromNamespace();
3056 test_complex_struct_type();
3057 test_WsMoveWriter();
3058 test_WsGetWriterPosition();
3059 test_WsSetWriterPosition();
3060 test_WsWriteXmlBuffer();
3065 test_field_options();
3067 test_WsWriteArray();
3069 test_write_option();
3071 test_repeating_element();