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
24 #include "webservices.h"
25 #include "wine/test.h"
27 static HRESULT
set_output( WS_XML_WRITER
*writer
)
29 WS_XML_WRITER_TEXT_ENCODING text
= { {WS_XML_WRITER_ENCODING_TYPE_TEXT
}, WS_CHARSET_UTF8
};
30 WS_XML_WRITER_BUFFER_OUTPUT buf
= { {WS_XML_WRITER_OUTPUT_TYPE_BUFFER
} };
31 return WsSetOutput( writer
, &text
.encoding
, &buf
.output
, NULL
, 0, NULL
);
34 static void test_WsCreateWriter(void)
37 WS_XML_WRITER
*writer
;
38 WS_XML_WRITER_PROPERTY prop
;
39 ULONG size
, max_depth
, max_attrs
, indent
, trim_size
, max_size
, max_ns
;
40 BOOL allow_fragment
, write_decl
, in_attr
;
45 hr
= WsCreateWriter( NULL
, 0, NULL
, NULL
);
46 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
49 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
50 ok( hr
== S_OK
, "got %08x\n", hr
);
51 ok( writer
!= NULL
, "writer not set\n" );
53 /* can't retrieve properties before output is set */
54 max_depth
= 0xdeadbeef;
55 size
= sizeof(max_depth
);
56 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, size
, NULL
);
57 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
58 ok( max_depth
== 0xdeadbeef, "max_depth set\n" );
60 hr
= set_output( writer
);
61 ok( hr
== S_OK
, "got %08x\n", hr
);
63 /* check some defaults */
64 max_depth
= 0xdeadbeef;
65 size
= sizeof(max_depth
);
66 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, size
, NULL
);
67 ok( hr
== S_OK
, "got %08x\n", hr
);
68 ok( max_depth
== 32, "got %u\n", max_depth
);
70 allow_fragment
= TRUE
;
71 size
= sizeof(allow_fragment
);
72 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT
, &allow_fragment
, size
, NULL
);
73 ok( hr
== S_OK
, "got %08x\n", hr
);
74 ok( !allow_fragment
, "got %d\n", allow_fragment
);
76 max_attrs
= 0xdeadbeef;
77 size
= sizeof(max_attrs
);
78 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, size
, NULL
);
79 ok( hr
== S_OK
, "got %08x\n", hr
);
80 ok( max_attrs
== 128, "got %u\n", max_attrs
);
83 size
= sizeof(write_decl
);
84 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_WRITE_DECLARATION
, &write_decl
, size
, NULL
);
85 ok( hr
== S_OK
, "got %08x\n", hr
);
86 ok( !write_decl
, "got %d\n", write_decl
);
89 size
= sizeof(indent
);
90 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_INDENT
, &indent
, size
, NULL
);
91 ok( hr
== S_OK
, "got %08x\n", hr
);
92 ok( !indent
, "got %u\n", indent
);
94 trim_size
= 0xdeadbeef;
95 size
= sizeof(trim_size
);
96 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, size
, NULL
);
97 ok( hr
== S_OK
, "got %08x\n", hr
);
98 ok( trim_size
== 4096, "got %u\n", trim_size
);
100 charset
= 0xdeadbeef;
101 size
= sizeof(charset
);
102 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, size
, NULL
);
103 ok( hr
== S_OK
, "got %08x\n", hr
);
104 ok( charset
== WS_CHARSET_UTF8
, "got %u\n", charset
);
106 buffers
.bufferCount
= 0xdeadbeef;
107 buffers
.buffers
= (WS_BYTES
*)0xdeadbeef;
108 size
= sizeof(buffers
);
109 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BUFFERS
, &buffers
, size
, NULL
);
110 ok( hr
== S_OK
, "got %08x\n", hr
);
111 ok( !buffers
.bufferCount
, "got %u\n", buffers
.bufferCount
);
112 ok( !buffers
.buffers
, "got %p\n", buffers
.buffers
);
114 max_size
= 0xdeadbeef;
115 size
= sizeof(max_size
);
116 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, size
, NULL
);
117 ok( hr
== S_OK
, "got %08x\n", hr
);
118 ok( max_size
== 65536, "got %u\n", max_size
);
120 bytes
.length
= 0xdeadbeef;
121 bytes
.bytes
= (BYTE
*)0xdeadbeef;
122 size
= sizeof(bytes
);
123 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
124 ok( hr
== S_OK
, "got %08x\n", hr
);
125 ok( !bytes
.length
, "got %u\n", bytes
.length
);
126 ok( bytes
.bytes
!= NULL
, "got %p\n", bytes
.bytes
);
128 max_size
= 0xdeadbeef;
129 size
= sizeof(max_size
);
130 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, size
, NULL
);
131 ok( hr
== S_OK
, "got %08x\n", hr
);
132 ok( max_size
== 65536, "got %u\n", max_size
);
134 bytes
.length
= 0xdeadbeef;
135 bytes
.bytes
= (BYTE
*)0xdeadbeef;
136 size
= sizeof(bytes
);
137 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_INITIAL_BUFFER
, &bytes
, size
, NULL
);
138 ok( hr
== S_OK
, "got %08x\n", hr
);
139 ok( !bytes
.length
, "got %u\n", bytes
.length
);
140 ok( !bytes
.bytes
, "got %p\n", bytes
.bytes
);
143 size
= sizeof(max_ns
);
144 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, size
, NULL
);
145 ok( hr
== S_OK
, "got %08x\n", hr
);
146 ok( max_ns
== 32, "got %u\n", max_ns
);
147 WsFreeWriter( writer
);
149 /* change a property */
151 prop
.id
= WS_XML_WRITER_PROPERTY_MAX_DEPTH
;
152 prop
.value
= &max_depth
;
153 prop
.valueSize
= sizeof(max_depth
);
154 hr
= WsCreateWriter( &prop
, 1, &writer
, NULL
);
155 ok( hr
== S_OK
, "got %08x\n", hr
);
157 hr
= set_output( writer
);
158 ok( hr
== S_OK
, "got %08x\n", hr
);
160 max_depth
= 0xdeadbeef;
161 size
= sizeof(max_depth
);
162 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, size
, NULL
);
163 ok( hr
== S_OK
, "got %08x\n", hr
);
164 ok( max_depth
== 16, "got %u\n", max_depth
);
165 WsFreeWriter( writer
);
167 /* show that some properties are read-only */
169 prop
.id
= WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE
;
170 prop
.value
= &in_attr
;
171 prop
.valueSize
= sizeof(in_attr
);
172 hr
= WsCreateWriter( &prop
, 1, &writer
, NULL
);
173 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
176 prop
.id
= WS_XML_WRITER_PROPERTY_BYTES_WRITTEN
;
178 prop
.valueSize
= sizeof(size
);
179 hr
= WsCreateWriter( &prop
, 1, &writer
, NULL
);
180 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
183 prop
.id
= WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE
;
185 prop
.valueSize
= sizeof(size
);
186 hr
= WsCreateWriter( &prop
, 1, &writer
, NULL
);
187 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
190 static void test_WsCreateXmlBuffer(void)
194 WS_XML_WRITER
*writer
;
195 WS_XML_BUFFER
*buffer
;
199 hr
= WsCreateXmlBuffer( NULL
, NULL
, 0, NULL
, NULL
);
200 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
202 hr
= WsCreateXmlBuffer( NULL
, NULL
, 0, &buffer
, NULL
);
203 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
205 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
206 ok( hr
== S_OK
, "got %08x\n", hr
);
208 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, NULL
, NULL
);
209 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
212 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
213 ok( hr
== S_OK
, "got %08x\n", hr
);
214 ok( buffer
!= NULL
, "buffer not set\n" );
216 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
217 ok( hr
== S_OK
, "got %08x\n", hr
);
219 size
= sizeof(bytes
);
220 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
221 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
223 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
224 ok( hr
== S_OK
, "got %08x\n", hr
);
226 size
= sizeof(bytes
);
227 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
228 todo_wine
ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
230 WsFreeWriter( writer
);
234 static void test_WsSetOutput(void)
237 WS_XML_WRITER
*writer
;
238 WS_XML_WRITER_PROPERTY prop
;
239 WS_XML_WRITER_TEXT_ENCODING encoding
;
240 WS_XML_WRITER_BUFFER_OUTPUT output
;
241 ULONG size
, max_depth
;
243 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
244 ok( hr
== S_OK
, "got %08x\n", hr
);
246 hr
= WsSetOutput( NULL
, NULL
, NULL
, NULL
, 0, NULL
);
247 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
249 encoding
.encoding
.encodingType
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
250 encoding
.charSet
= WS_CHARSET_UTF8
;
252 output
.output
.outputType
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
254 hr
= WsSetOutput( writer
, &encoding
.encoding
, &output
.output
, NULL
, 0, NULL
);
255 ok( hr
== S_OK
, "got %08x\n", hr
);
257 /* multiple calls are allowed */
258 hr
= WsSetOutput( writer
, &encoding
.encoding
, &output
.output
, NULL
, 0, NULL
);
259 ok( hr
== S_OK
, "got %08x\n", hr
);
261 /* writer properties can be set with WsSetOutput */
263 prop
.id
= WS_XML_WRITER_PROPERTY_MAX_DEPTH
;
264 prop
.value
= &max_depth
;
265 prop
.valueSize
= sizeof(max_depth
);
266 hr
= WsSetOutput( writer
, &encoding
.encoding
, &output
.output
, &prop
, 1, NULL
);
267 ok( hr
== S_OK
, "got %08x\n", hr
);
269 max_depth
= 0xdeadbeef;
270 size
= sizeof(max_depth
);
271 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, size
, NULL
);
272 ok( hr
== S_OK
, "got %08x\n", hr
);
273 ok( max_depth
== 16, "got %u\n", max_depth
);
274 WsFreeWriter( writer
);
277 static void test_WsSetOutputToBuffer(void)
281 WS_XML_BUFFER
*buffer
;
282 WS_XML_WRITER
*writer
;
283 WS_XML_WRITER_PROPERTY prop
;
284 ULONG size
, max_depth
;
286 hr
= WsSetOutputToBuffer( NULL
, NULL
, NULL
, 0, NULL
);
287 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
289 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
290 ok( hr
== S_OK
, "got %08x\n", hr
);
292 hr
= WsSetOutputToBuffer( writer
, NULL
, NULL
, 0, NULL
);
293 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
295 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
296 ok( hr
== S_OK
, "got %08x\n", hr
);
298 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
299 ok( hr
== S_OK
, "got %08x\n", hr
);
301 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
302 ok( hr
== S_OK
, "got %08x\n", hr
);
304 /* multiple calls are allowed */
305 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
306 ok( hr
== S_OK
, "got %08x\n", hr
);
308 /* writer properties can be set with WsSetOutputToBuffer */
310 prop
.id
= WS_XML_WRITER_PROPERTY_MAX_DEPTH
;
311 prop
.value
= &max_depth
;
312 prop
.valueSize
= sizeof(max_depth
);
313 hr
= WsSetOutputToBuffer( writer
, buffer
, &prop
, 1, NULL
);
314 ok( hr
== S_OK
, "got %08x\n", hr
);
316 max_depth
= 0xdeadbeef;
317 size
= sizeof(max_depth
);
318 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, size
, NULL
);
319 ok( hr
== S_OK
, "got %08x\n", hr
);
320 ok( max_depth
== 16, "got %u\n", max_depth
);
322 WsFreeWriter( writer
);
326 static char strbuf
[512];
327 static const char *debugstr_bytes( const BYTE
*bytes
, ULONG len
)
329 const BYTE
*src
= bytes
;
335 if (dst
- strbuf
> sizeof(strbuf
) - 7) break;
338 case '\n': *dst
++ = '\\'; *dst
++ = 'n'; break;
339 case '\r': *dst
++ = '\\'; *dst
++ = 'r'; break;
340 case '\t': *dst
++ = '\\'; *dst
++ = 't'; break;
342 if (c
>= ' ' && c
< 127) *dst
++ = c
;
345 sprintf( dst
, "\\%02x", c
);
361 static void check_output( WS_XML_WRITER
*writer
, const char *expected
, unsigned int line
)
364 ULONG size
= sizeof(bytes
);
365 int len
= strlen( expected
);
368 memset( &bytes
, 0, sizeof(bytes
) );
369 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
370 ok( hr
== S_OK
, "%u: got %08x\n", line
, hr
);
371 ok( bytes
.length
== len
, "%u: got %u expected %u\n", line
, bytes
.length
, len
);
372 if (bytes
.length
!= len
) return;
373 ok( !memcmp( bytes
.bytes
, expected
, len
),
374 "%u: got %s expected %s\n", line
, debugstr_bytes(bytes
.bytes
, bytes
.length
), expected
);
377 static void test_WsWriteStartElement(void)
380 WS_XML_WRITER
*writer
;
381 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, ns
= {2, (BYTE
*)"ns"}, ns2
= {3, (BYTE
*)"ns2"};
382 WS_XML_STRING localname
= {1, (BYTE
*)"a"}, localname2
= {1, (BYTE
*)"b"}, empty
= {0, NULL
};
384 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
385 ok( hr
== S_OK
, "got %08x\n", hr
);
387 hr
= set_output( writer
);
388 ok( hr
== S_OK
, "got %08x\n", hr
);
390 hr
= WsWriteStartElement( NULL
, &prefix
, &localname
, &ns
, NULL
);
391 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
393 /* first call to WsWriteStartElement doesn't output anything */
394 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
395 ok( hr
== S_OK
, "got %08x\n", hr
);
396 check_output( writer
, "", __LINE__
);
398 /* two ways to close an element */
399 hr
= WsWriteEndStartElement( writer
, NULL
);
400 ok( hr
== S_OK
, "got %08x\n", hr
);
401 check_output( writer
, "<p:a xmlns:p=\"ns\">", __LINE__
);
403 hr
= WsWriteEndElement( writer
, NULL
);
404 ok( hr
== S_OK
, "got %08x\n", hr
);
405 check_output( writer
, "<p:a xmlns:p=\"ns\"></p:a>", __LINE__
);
407 hr
= set_output( writer
);
408 ok( hr
== S_OK
, "got %08x\n", hr
);
410 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
411 ok( hr
== S_OK
, "got %08x\n", hr
);
413 hr
= WsWriteEndElement( writer
, NULL
);
414 ok( hr
== S_OK
, "got %08x\n", hr
);
415 check_output( writer
, "<p:a xmlns:p=\"ns\"/>", __LINE__
);
417 /* nested elements */
418 hr
= set_output( writer
);
419 ok( hr
== S_OK
, "got %08x\n", hr
);
421 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
422 ok( hr
== S_OK
, "got %08x\n", hr
);
423 check_output( writer
, "", __LINE__
);
425 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
426 ok( hr
== S_OK
, "got %08x\n", hr
);
427 check_output( writer
, "<p:a xmlns:p=\"ns\">", __LINE__
);
429 hr
= WsWriteEndElement( writer
, NULL
);
430 ok( hr
== S_OK
, "got %08x\n", hr
);
431 check_output( writer
, "<p:a xmlns:p=\"ns\"><p:b/>", __LINE__
);
433 hr
= WsWriteEndElement( writer
, NULL
);
434 ok( hr
== S_OK
, "got %08x\n", hr
);
435 check_output( writer
, "<p:a xmlns:p=\"ns\"><p:b/></p:a>", __LINE__
);
437 hr
= set_output( writer
);
438 ok( hr
== S_OK
, "got %08x\n", hr
);
440 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
441 ok( hr
== S_OK
, "got %08x\n", hr
);
442 check_output( writer
, "", __LINE__
);
444 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns2
, NULL
);
445 ok( hr
== S_OK
, "got %08x\n", hr
);
446 check_output( writer
, "<p:a xmlns:p=\"ns\">", __LINE__
);
448 hr
= WsWriteEndElement( writer
, NULL
);
449 ok( hr
== S_OK
, "got %08x\n", hr
);
450 check_output( writer
, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/>", __LINE__
);
452 hr
= WsWriteEndElement( writer
, NULL
);
453 ok( hr
== S_OK
, "got %08x\n", hr
);
454 check_output( writer
, "<p:a xmlns:p=\"ns\"><b xmlns=\"ns2\"/></p:a>", __LINE__
);
456 hr
= set_output( writer
);
457 ok( hr
== S_OK
, "got %08x\n", hr
);
459 hr
= WsWriteStartElement( writer
, &empty
, &localname
, &empty
, NULL
);
460 ok( hr
== S_OK
, "got %08x\n", hr
);
461 hr
= WsWriteEndStartElement( writer
, NULL
);
462 ok( hr
== S_OK
, "got %08x\n", hr
);
463 hr
= WsWriteEndElement( writer
, NULL
);
464 ok( hr
== S_OK
, "got %08x\n", hr
);
465 check_output( writer
, "<a></a>", __LINE__
);
467 WsFreeWriter( writer
);
470 static void test_WsWriteStartAttribute(void)
473 WS_XML_WRITER
*writer
;
474 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, localname
= {3, (BYTE
*)"str"};
475 WS_XML_STRING localname2
= {3, (BYTE
*)"len"}, ns
= {2, (BYTE
*)"ns"}, empty
= {0, NULL
};
476 WS_XML_UTF8_TEXT text
= {{WS_XML_TEXT_TYPE_UTF8
}};
478 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
479 ok( hr
== S_OK
, "got %08x\n", hr
);
481 hr
= set_output( writer
);
482 ok( hr
== S_OK
, "got %08x\n", hr
);
484 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
485 ok( hr
== S_OK
, "got %08x\n", hr
);
487 hr
= WsWriteStartAttribute( NULL
, &prefix
, &localname
, &ns
, FALSE
, NULL
);
488 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
490 /* WsWriteStartAttribute doesn't output anything */
491 hr
= WsWriteStartAttribute( writer
, &prefix
, &localname2
, &ns
, FALSE
, NULL
);
492 ok( hr
== S_OK
, "got %08x\n", hr
);
493 check_output( writer
, "", __LINE__
);
495 text
.value
.length
= 1;
496 text
.value
.bytes
= (BYTE
*)"0";
497 hr
= WsWriteText( writer
, &text
.text
, NULL
);
498 ok( hr
== S_OK
, "got %08x\n", hr
);
499 check_output( writer
, "", __LINE__
);
501 /* WsWriteEndAttribute doesn't output anything */
502 hr
= WsWriteEndAttribute( writer
, NULL
);
503 ok( hr
== S_OK
, "got %08x\n", hr
);
504 check_output( writer
, "", __LINE__
);
506 hr
= WsWriteEndElement( writer
, NULL
);
507 ok( hr
== S_OK
, "got %08x\n", hr
);
508 check_output( writer
, "<p:str p:len=\"0\" xmlns:p=\"ns\"/>", __LINE__
);
510 hr
= set_output( writer
);
511 ok( hr
== S_OK
, "got %08x\n", hr
);
513 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
514 ok( hr
== S_OK
, "got %08x\n", hr
);
516 hr
= WsWriteStartAttribute( writer
, &empty
, &localname2
, &empty
, FALSE
, NULL
);
517 ok( hr
== S_OK
, "got %08x\n", hr
);
518 hr
= WsWriteEndAttribute( writer
, NULL
);
519 ok( hr
== S_OK
, "got %08x\n", hr
);
521 hr
= WsWriteEndElement( writer
, NULL
);
522 ok( hr
== S_OK
, "got %08x\n", hr
);
523 check_output( writer
, "<p:str len=\"\" xmlns:p=\"ns\"/>", __LINE__
);
525 hr
= set_output( writer
);
526 ok( hr
== S_OK
, "got %08x\n", hr
);
528 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
529 ok( hr
== S_OK
, "got %08x\n", hr
);
531 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &empty
, FALSE
, NULL
);
532 ok( hr
== S_OK
, "got %08x\n", hr
);
534 hr
= WsWriteEndAttribute( writer
, NULL
);
535 ok( hr
== S_OK
, "got %08x\n", hr
);
537 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
538 ok( hr
== S_OK
, "got %08x\n", hr
);
540 hr
= WsWriteEndAttribute( writer
, NULL
);
541 ok( hr
== S_OK
, "got %08x\n", hr
);
543 hr
= WsWriteEndElement( writer
, NULL
);
544 ok( hr
== S_OK
, "got %08x\n", hr
);
545 check_output( writer
, "<p:str len=\"\" p:str=\"\" xmlns:p=\"ns\"/>", __LINE__
);
547 WsFreeWriter( writer
);
550 static void test_WsWriteType(void)
553 WS_XML_WRITER
*writer
;
554 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, localname
= {3, (BYTE
*)"str"}, ns
= {2, (BYTE
*)"ns"};
555 const WCHAR
*val_str
;
556 enum {ONE
= 1, TWO
= 2};
557 WS_XML_STRING one
= {3, (BYTE
*)"ONE" }, two
= {3, (BYTE
*)"TWO"};
558 WS_ENUM_VALUE enum_values
[] = {{ONE
, &one
}, {TWO
, &two
}};
559 WS_ENUM_DESCRIPTION enum_desc
;
562 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
563 ok( hr
== S_OK
, "got %08x\n", hr
);
565 hr
= set_output( writer
);
566 ok( hr
== S_OK
, "got %08x\n", hr
);
569 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
570 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(val_str
), NULL
);
571 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
573 hr
= set_output( writer
);
574 ok( hr
== S_OK
, "got %08x\n", hr
);
576 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
577 ok( hr
== S_OK
, "got %08x\n", hr
);
580 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
581 WS_WRITE_REQUIRED_VALUE
, NULL
, sizeof(L
"test"), NULL
);
582 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
584 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
585 WS_WRITE_REQUIRED_VALUE
, L
"test", sizeof(L
"test"), NULL
);
586 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
588 /* required pointer */
589 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
590 WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(val_str
), NULL
);
591 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
593 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
594 WS_WRITE_REQUIRED_VALUE
, L
"test", sizeof(L
"test"), NULL
);
595 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
597 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
598 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(WCHAR
**), NULL
);
599 ok( hr
== S_OK
, "got %08x\n", hr
);
600 check_output( writer
, "<p:str xmlns:p=\"ns\">test", __LINE__
);
602 hr
= WsWriteEndElement( writer
, NULL
);
603 ok( hr
== S_OK
, "got %08x\n", hr
);
604 check_output( writer
, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__
);
606 hr
= set_output( writer
);
607 ok( hr
== S_OK
, "got %08x\n", hr
);
609 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
610 ok( hr
== S_OK
, "got %08x\n", hr
);
612 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
613 ok( hr
== S_OK
, "got %08x\n", hr
);
616 hr
= WsWriteType( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
617 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(val_str
), NULL
);
618 ok( hr
== S_OK
, "got %08x\n", hr
);
619 check_output( writer
, "", __LINE__
);
621 hr
= WsWriteEndAttribute( writer
, NULL
);
622 ok( hr
== S_OK
, "got %08x\n", hr
);
623 check_output( writer
, "", __LINE__
);
625 hr
= WsWriteEndElement( writer
, NULL
);
626 ok( hr
== S_OK
, "got %08x\n", hr
);
627 check_output( writer
, "<p:str p:str=\"test\" xmlns:p=\"ns\"/>", __LINE__
);
629 hr
= set_output( writer
);
630 ok( hr
== S_OK
, "got %08x\n", hr
);
632 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
633 ok( hr
== S_OK
, "got %08x\n", hr
);
636 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
,
637 WS_WRITE_REQUIRED_POINTER
, &val_str
, sizeof(val_str
), NULL
);
638 ok( hr
== S_OK
, "got %08x\n", hr
);
639 check_output( writer
, "<p:str xmlns:p=\"ns\">test", __LINE__
);
641 hr
= WsWriteEndElement( writer
, NULL
);
642 ok( hr
== S_OK
, "got %08x\n", hr
);
643 check_output( writer
, "<p:str xmlns:p=\"ns\">test</p:str>", __LINE__
);
645 hr
= set_output( writer
);
646 ok( hr
== S_OK
, "got %08x\n", hr
);
648 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
649 ok( hr
== S_OK
, "got %08x\n", hr
);
651 enum_desc
.values
= enum_values
;
652 enum_desc
.valueCount
= ARRAY_SIZE(enum_values
);
653 enum_desc
.maxByteCount
= 3;
654 enum_desc
.nameIndices
= NULL
;
657 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_ENUM_TYPE
, &enum_desc
,
658 WS_WRITE_REQUIRED_VALUE
, &val_enum
, sizeof(val_enum
), NULL
);
659 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
662 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_ENUM_TYPE
, &enum_desc
,
663 WS_WRITE_REQUIRED_VALUE
, &val_enum
, sizeof(val_enum
), NULL
);
664 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
667 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_ENUM_TYPE
, &enum_desc
,
668 WS_WRITE_REQUIRED_VALUE
, &val_enum
, sizeof(val_enum
), NULL
);
669 ok( hr
== S_OK
, "got %08x\n", hr
);
671 hr
= WsWriteEndElement( writer
, NULL
);
672 ok( hr
== S_OK
, "got %08x\n", hr
);
673 check_output( writer
, "<p:str xmlns:p=\"ns\">ONE</p:str>", __LINE__
);
675 WsFreeWriter( writer
);
678 static void prepare_basic_type_test( WS_XML_WRITER
*writer
)
680 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
683 hr
= set_output( writer
);
684 ok( hr
== S_OK
, "got %08x\n", hr
);
685 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
686 ok( hr
== S_OK
, "got %08x\n", hr
);
689 static void test_basic_type(void)
692 WS_XML_WRITER
*writer
;
693 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
}, xmlstr
;
710 { WS_BOOL_TYPE
, TRUE
, sizeof(BOOL
), "<t>true</t>", "<t t=\"true\"/>" },
711 { WS_BOOL_TYPE
, FALSE
, sizeof(BOOL
), "<t>false</t>", "<t t=\"false\"/>" },
712 { WS_INT8_TYPE
, -128, sizeof(INT8
), "<t>-128</t>", "<t t=\"-128\"/>" },
713 { WS_INT16_TYPE
, -32768, sizeof(INT16
), "<t>-32768</t>", "<t t=\"-32768\"/>" },
714 { WS_INT32_TYPE
, -2147483647 - 1, sizeof(INT32
), "<t>-2147483648</t>",
715 "<t t=\"-2147483648\"/>" },
716 { WS_INT64_TYPE
, -9223372036854775807 - 1, sizeof(INT64
), "<t>-9223372036854775808</t>",
717 "<t t=\"-9223372036854775808\"/>" },
718 { WS_UINT8_TYPE
, 255, sizeof(UINT8
), "<t>255</t>", "<t t=\"255\"/>" },
719 { WS_UINT16_TYPE
, 65535, sizeof(UINT16
), "<t>65535</t>", "<t t=\"65535\"/>" },
720 { WS_UINT32_TYPE
, ~0u, sizeof(UINT32
), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
721 { WS_UINT64_TYPE
, ~0, sizeof(UINT64
), "<t>18446744073709551615</t>",
722 "<t t=\"18446744073709551615\"/>" },
725 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
726 ok( hr
== S_OK
, "got %08x\n", hr
);
728 /* element content type mapping */
729 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
731 prepare_basic_type_test( writer
);
732 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, tests
[i
].type
, NULL
,
733 WS_WRITE_REQUIRED_VALUE
, &tests
[i
].val
, tests
[i
].size
, NULL
);
734 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
736 hr
= WsWriteEndElement( writer
, NULL
);
737 ok( hr
== S_OK
, "got %08x\n", hr
);
738 check_output( writer
, tests
[i
].result
, __LINE__
);
741 /* element type mapping is the same as element content type mapping for basic types */
742 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
744 const INT64
*ptr
= &tests
[i
].val
;
746 prepare_basic_type_test( writer
);
747 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, tests
[i
].type
, NULL
,
748 WS_WRITE_REQUIRED_POINTER
, &ptr
, sizeof(ptr
), NULL
);
749 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
751 hr
= WsWriteEndElement( writer
, NULL
);
752 ok( hr
== S_OK
, "got %08x\n", hr
);
753 check_output( writer
, tests
[i
].result
, __LINE__
);
756 /* attribute type mapping */
757 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
759 prepare_basic_type_test( writer
);
760 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
761 ok( hr
== S_OK
, "got %08x\n", hr
);
763 hr
= WsWriteType( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, tests
[i
].type
, NULL
,
764 WS_WRITE_REQUIRED_VALUE
, &tests
[i
].val
, tests
[i
].size
, NULL
);
765 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
767 hr
= WsWriteEndAttribute( writer
, NULL
);
768 ok( hr
== S_OK
, "got %08x\n", hr
);
770 hr
= WsWriteEndElement( writer
, NULL
);
771 ok( hr
== S_OK
, "got %08x\n", hr
);
772 check_output( writer
, tests
[i
].result2
, __LINE__
);
775 prepare_basic_type_test( writer
);
776 memset( &guid
, 0, sizeof(guid
) );
777 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_GUID_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
778 &guid
, sizeof(guid
), 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>00000000-0000-0000-0000-000000000000</t>", __LINE__
);
784 prepare_basic_type_test( writer
);
785 string
.chars
= (WCHAR
*)L
"test";
787 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRING_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
788 &string
, sizeof(string
), NULL
);
789 ok( hr
== S_OK
, "got %08x\n", hr
);
790 hr
= WsWriteEndElement( writer
, NULL
);
791 ok( hr
== S_OK
, "got %08x\n", hr
);
792 check_output( writer
, "<t>test</t>", __LINE__
);
794 prepare_basic_type_test( writer
);
796 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_WSZ_TYPE
, NULL
, WS_WRITE_REQUIRED_POINTER
,
797 &str
, sizeof(str
), NULL
);
798 ok( hr
== S_OK
, "got %08x\n", hr
);
799 hr
= WsWriteEndElement( writer
, NULL
);
800 ok( hr
== S_OK
, "got %08x\n", hr
);
801 check_output( writer
, "<t>test</t>", __LINE__
);
803 prepare_basic_type_test( writer
);
804 xmlstr
.bytes
= (BYTE
*)"test";
806 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_XML_STRING_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
807 &xmlstr
, sizeof(xmlstr
), NULL
);
808 ok( hr
== S_OK
, "got %08x\n", hr
);
809 hr
= WsWriteEndElement( writer
, NULL
);
810 ok( hr
== S_OK
, "got %08x\n", hr
);
811 check_output( writer
, "<t>test</t>", __LINE__
);
813 prepare_basic_type_test( writer
);
814 bytes
.bytes
= (BYTE
*)"test";
816 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
817 &bytes
, sizeof(bytes
), NULL
);
818 ok( hr
== S_OK
, "got %08x\n", hr
);
819 hr
= WsWriteEndElement( writer
, NULL
);
820 ok( hr
== S_OK
, "got %08x\n", hr
);
821 check_output( writer
, "<t>dGVzdA==</t>", __LINE__
);
823 prepare_basic_type_test( writer
);
825 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
826 &bytes
, sizeof(bytes
), NULL
);
827 ok( hr
== S_OK
, "got %08x\n", hr
);
828 hr
= WsWriteEndElement( writer
, NULL
);
829 ok( hr
== S_OK
, "got %08x\n", hr
);
830 check_output( writer
, "<t/>", __LINE__
);
832 prepare_basic_type_test( writer
);
834 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
835 &bytes
, sizeof(bytes
), NULL
);
836 ok( hr
== S_OK
, "got %08x\n", hr
);
837 hr
= WsWriteEndElement( writer
, NULL
);
838 ok( hr
== S_OK
, "got %08x\n", hr
);
839 check_output( writer
, "<t/>", __LINE__
);
841 prepare_basic_type_test( writer
);
842 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_BYTES_TYPE
, NULL
, WS_WRITE_NILLABLE_VALUE
,
843 &bytes
, sizeof(bytes
), NULL
);
844 ok( hr
== S_OK
, "got %08x\n", hr
);
845 hr
= WsWriteEndElement( writer
, NULL
);
846 ok( hr
== S_OK
, "got %08x\n", hr
);
847 check_output( writer
, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
850 prepare_basic_type_test( writer
);
851 memset( &id
, 0, sizeof(id
) );
852 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_UNIQUE_ID_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
853 &id
, sizeof(id
), NULL
);
854 ok( hr
== S_OK
, "got %08x\n", hr
);
855 hr
= WsWriteEndElement( writer
, NULL
);
856 ok( hr
== S_OK
, "got %08x\n", hr
);
857 check_output( writer
, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>", __LINE__
);
859 prepare_basic_type_test( writer
);
861 id
.uri
.chars
= (WCHAR
*)L
"test";
862 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_UNIQUE_ID_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
863 &id
, sizeof(id
), NULL
);
864 ok( hr
== S_OK
, "got %08x\n", hr
);
865 hr
= WsWriteEndElement( writer
, NULL
);
866 ok( hr
== S_OK
, "got %08x\n", hr
);
867 check_output( writer
, "<t>test</t>", __LINE__
);
869 WsFreeWriter( writer
);
872 static void test_simple_struct_type(void)
875 WS_XML_WRITER
*writer
;
876 WS_STRUCT_DESCRIPTION s
;
877 WS_FIELD_DESCRIPTION f
, *fields
[1];
878 WS_XML_STRING localname
= {6, (BYTE
*)"struct"}, ns
= {0, NULL
};
884 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
885 ok( hr
== S_OK
, "got %08x\n", hr
);
887 hr
= set_output( writer
);
888 ok( hr
== S_OK
, "got %08x\n", hr
);
890 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
891 ok( hr
== S_OK
, "got %08x\n", hr
);
893 memset( &f
, 0, sizeof(f
) );
894 f
.mapping
= WS_TEXT_FIELD_MAPPING
;
895 f
.type
= WS_WSZ_TYPE
;
898 memset( &s
, 0, sizeof(s
) );
899 s
.size
= sizeof(struct test
);
900 s
.alignment
= TYPE_ALIGNMENT(struct test
);
904 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) );
905 test
->field
= L
"value";
906 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, NULL
,
907 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
908 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
910 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, NULL
,
911 WS_WRITE_REQUIRED_VALUE
, test
, sizeof(*test
), NULL
);
912 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
914 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
915 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
916 ok( hr
== S_OK
, "got %08x\n", hr
);
918 hr
= WsWriteEndElement( writer
, NULL
);
919 ok( hr
== S_OK
, "got %08x\n", hr
);
920 check_output( writer
, "<struct>value</struct>", __LINE__
);
923 hr
= set_output( writer
);
924 ok( hr
== S_OK
, "got %08x\n", hr
);
926 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
927 ok( hr
== S_OK
, "got %08x\n", hr
);
929 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
930 WS_WRITE_REQUIRED_VALUE
, test
, sizeof(*test
), NULL
);
931 ok( hr
== S_OK
, "got %08x\n", hr
);
933 hr
= WsWriteEndElement( writer
, NULL
);
934 ok( hr
== S_OK
, "got %08x\n", hr
);
935 check_output( writer
, "<struct>value</struct>", __LINE__
);
937 hr
= set_output( writer
);
938 ok( hr
== S_OK
, "got %08x\n", hr
);
940 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
941 ok( hr
== S_OK
, "got %08x\n", hr
);
943 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
944 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
945 ok( hr
== S_OK
, "got %08x\n", hr
);
947 hr
= WsWriteEndElement( writer
, NULL
);
948 ok( hr
== S_OK
, "got %08x\n", hr
);
949 check_output( writer
, "<struct>value</struct>", __LINE__
);
951 hr
= set_output( writer
);
952 ok( hr
== S_OK
, "got %08x\n", hr
);
954 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
955 ok( hr
== S_OK
, "got %08x\n", hr
);
957 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
958 ok( hr
== S_OK
, "got %08x\n", hr
);
960 hr
= WsWriteType( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
961 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
962 ok( hr
== S_OK
, "got %08x\n", hr
);
964 hr
= WsWriteEndAttribute( writer
, NULL
);
965 ok( hr
== S_OK
, "got %08x\n", hr
);
967 hr
= WsWriteEndElement( writer
, NULL
);
968 ok( hr
== S_OK
, "got %08x\n", hr
);
969 check_output( writer
, "<struct struct=\"value\"/>", __LINE__
);
971 HeapFree( GetProcessHeap(), 0, test
);
972 WsFreeWriter( writer
);
975 static void test_WsWriteElement(void)
978 WS_XML_WRITER
*writer
;
979 WS_STRUCT_DESCRIPTION s
;
980 WS_FIELD_DESCRIPTION f
, *fields
[1];
981 WS_ELEMENT_DESCRIPTION desc
;
982 WS_XML_STRING localname
= {3, (BYTE
*)"str"}, ns
= {0, NULL
};
983 struct test
{ const WCHAR
*str
; } *test
;
985 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
986 ok( hr
== S_OK
, "got %08x\n", hr
);
988 hr
= set_output( writer
);
989 ok( hr
== S_OK
, "got %08x\n", hr
);
991 /* text field mapping */
992 memset( &f
, 0, sizeof(f
) );
993 f
.mapping
= WS_TEXT_FIELD_MAPPING
;
994 f
.type
= WS_WSZ_TYPE
;
997 memset( &s
, 0, sizeof(s
) );
998 s
.size
= sizeof(struct test
);
999 s
.alignment
= TYPE_ALIGNMENT(struct test
);
1003 desc
.elementLocalName
= &localname
;
1004 desc
.elementNs
= &ns
;
1005 desc
.type
= WS_STRUCT_TYPE
;
1006 desc
.typeDescription
= &s
;
1008 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) );
1009 test
->str
= L
"test";
1010 hr
= WsWriteElement( NULL
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1011 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1013 hr
= WsWriteElement( writer
, NULL
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1014 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1016 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, NULL
);
1017 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1019 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1020 ok( hr
== S_OK
, "got %08x\n", hr
);
1021 check_output( writer
, "<str>test</str>", __LINE__
);
1023 hr
= set_output( writer
);
1024 ok( hr
== S_OK
, "got %08x\n", hr
);
1026 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1027 ok( hr
== S_OK
, "got %08x\n", hr
);
1029 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1030 ok( hr
== S_OK
, "got %08x\n", hr
);
1031 check_output( writer
, "<str><str>test</str>", __LINE__
);
1033 hr
= set_output( writer
);
1034 ok( hr
== S_OK
, "got %08x\n", hr
);
1036 /* attribute field mapping */
1037 f
.mapping
= WS_ATTRIBUTE_FIELD_MAPPING
;
1039 /* requires localName and ns to be set */
1040 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1041 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1043 hr
= set_output( writer
);
1044 ok( hr
== S_OK
, "got %08x\n", hr
);
1046 f
.localName
= &localname
;
1048 hr
= WsWriteElement( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1049 ok( hr
== S_OK
, "got %08x\n", hr
);
1050 check_output( writer
, "<str str=\"test\"/>", __LINE__
);
1052 HeapFree( GetProcessHeap(), 0, test
);
1053 WsFreeWriter( writer
);
1056 static void test_WsWriteValue(void)
1059 WS_XML_WRITER
*writer
;
1060 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1068 const char *result2
;
1072 { WS_BOOL_VALUE_TYPE
, ~0, sizeof(BOOL
), "<t>true</t>", "<t t=\"true\"/>" },
1073 { WS_BOOL_VALUE_TYPE
, FALSE
, sizeof(BOOL
), "<t>false</t>", "<t t=\"false\"/>" },
1074 { WS_INT8_VALUE_TYPE
, -128, sizeof(INT8
), "<t>-128</t>", "<t t=\"-128\"/>" },
1075 { WS_INT16_VALUE_TYPE
, -32768, sizeof(INT16
), "<t>-32768</t>", "<t t=\"-32768\"/>" },
1076 { WS_INT32_VALUE_TYPE
, -2147483647 - 1, sizeof(INT32
), "<t>-2147483648</t>",
1077 "<t t=\"-2147483648\"/>" },
1078 { WS_INT64_VALUE_TYPE
, -9223372036854775807 - 1, sizeof(INT64
), "<t>-9223372036854775808</t>",
1079 "<t t=\"-9223372036854775808\"/>" },
1080 { WS_UINT8_VALUE_TYPE
, 255, sizeof(UINT8
), "<t>255</t>", "<t t=\"255\"/>" },
1081 { WS_UINT16_VALUE_TYPE
, 65535, sizeof(UINT16
), "<t>65535</t>", "<t t=\"65535\"/>" },
1082 { WS_UINT32_VALUE_TYPE
, ~0u, sizeof(UINT32
), "<t>4294967295</t>", "<t t=\"4294967295\"/>" },
1083 { WS_UINT64_VALUE_TYPE
, ~0, sizeof(UINT64
), "<t>18446744073709551615</t>",
1084 "<t t=\"18446744073709551615\"/>" },
1087 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1088 ok( hr
== S_OK
, "got %08x\n", hr
);
1090 hr
= set_output( writer
);
1091 ok( hr
== S_OK
, "got %08x\n", hr
);
1093 hr
= WsWriteValue( NULL
, tests
[0].type
, &tests
[0].val
, tests
[0].size
, NULL
);
1094 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1096 hr
= WsWriteValue( writer
, tests
[0].type
, &tests
[0].val
, tests
[0].size
, NULL
);
1097 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1099 hr
= set_output( writer
);
1100 ok( hr
== S_OK
, "got %08x\n", hr
);
1102 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1103 ok( hr
== S_OK
, "got %08x\n", hr
);
1106 hr
= WsWriteValue( writer
, tests
[0].type
, &tests
[0].val
, 0, NULL
);
1107 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1109 hr
= set_output( writer
);
1110 ok( hr
== S_OK
, "got %08x\n", hr
);
1112 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1113 ok( hr
== S_OK
, "got %08x\n", hr
);
1116 hr
= WsWriteValue( writer
, tests
[0].type
, NULL
, 0, NULL
);
1117 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1119 /* element type mapping */
1120 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
1122 hr
= set_output( writer
);
1123 ok( hr
== S_OK
, "got %08x\n", hr
);
1125 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1126 ok( hr
== S_OK
, "got %08x\n", hr
);
1128 hr
= WsWriteValue( writer
, tests
[i
].type
, &tests
[i
].val
, tests
[i
].size
, NULL
);
1129 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
1131 hr
= WsWriteEndElement( writer
, NULL
);
1132 ok( hr
== S_OK
, "got %08x\n", hr
);
1133 check_output( writer
, tests
[i
].result
, __LINE__
);
1136 /* attribute type mapping */
1137 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
1139 hr
= set_output( writer
);
1140 ok( hr
== S_OK
, "got %08x\n", hr
);
1142 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1143 ok( hr
== S_OK
, "got %08x\n", hr
);
1145 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, FALSE
, NULL
);
1146 ok( hr
== S_OK
, "got %08x\n", hr
);
1148 hr
= WsWriteValue( writer
, tests
[i
].type
, &tests
[i
].val
, tests
[i
].size
, NULL
);
1149 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
1151 hr
= WsWriteEndAttribute( writer
, NULL
);
1152 ok( hr
== S_OK
, "got %08x\n", hr
);
1154 hr
= WsWriteEndElement( writer
, NULL
);
1155 ok( hr
== S_OK
, "got %08x\n", hr
);
1156 check_output( writer
, tests
[i
].result2
, __LINE__
);
1159 WsFreeWriter( writer
);
1162 static void test_WsWriteAttribute(void)
1165 WS_XML_WRITER
*writer
;
1166 WS_STRUCT_DESCRIPTION s
;
1167 WS_FIELD_DESCRIPTION f
, *fields
[1];
1168 WS_ATTRIBUTE_DESCRIPTION desc
;
1169 WS_XML_STRING localname
= {3, (BYTE
*)"str"}, ns
= {0, NULL
};
1170 struct test
{ const WCHAR
*str
; } *test
;
1172 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1173 ok( hr
== S_OK
, "got %08x\n", hr
);
1175 hr
= set_output( writer
);
1176 ok( hr
== S_OK
, "got %08x\n", hr
);
1178 /* text field mapping */
1179 memset( &f
, 0, sizeof(f
) );
1180 f
.mapping
= WS_TEXT_FIELD_MAPPING
;
1181 f
.type
= WS_WSZ_TYPE
;
1184 memset( &s
, 0, sizeof(s
) );
1185 s
.size
= sizeof(struct test
);
1186 s
.alignment
= TYPE_ALIGNMENT(struct test
);
1190 desc
.attributeLocalName
= &localname
;
1191 desc
.attributeNs
= &ns
;
1192 desc
.type
= WS_STRUCT_TYPE
;
1193 desc
.typeDescription
= &s
;
1195 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) );
1196 test
->str
= L
"test";
1197 hr
= WsWriteAttribute( NULL
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1198 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1200 hr
= WsWriteAttribute( writer
, NULL
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1201 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1203 hr
= WsWriteAttribute( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, NULL
);
1204 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1206 hr
= WsWriteAttribute( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1207 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1209 hr
= set_output( writer
);
1210 ok( hr
== S_OK
, "got %08x\n", hr
);
1212 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1213 ok( hr
== S_OK
, "got %08x\n", hr
);
1215 hr
= WsWriteAttribute( writer
, &desc
, WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1216 ok( hr
== S_OK
, "got %08x\n", hr
);
1218 hr
= WsWriteEndElement( writer
, NULL
);
1219 ok( hr
== S_OK
, "got %08x\n", hr
);
1220 check_output( writer
, "<str str=\"test\"/>", __LINE__
);
1222 HeapFree( GetProcessHeap(), 0, test
);
1223 WsFreeWriter( writer
);
1226 static void test_WsWriteStartCData(void)
1229 WS_XML_WRITER
*writer
;
1230 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1231 WS_XML_UTF8_TEXT text
= {{WS_XML_TEXT_TYPE_UTF8
}};
1233 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1234 ok( hr
== S_OK
, "got %08x\n", hr
);
1236 hr
= set_output( writer
);
1237 ok( hr
== S_OK
, "got %08x\n", hr
);
1239 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1240 ok( hr
== S_OK
, "got %08x\n", hr
);
1242 hr
= WsWriteEndCData( writer
, NULL
);
1243 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1245 hr
= set_output( writer
);
1246 ok( hr
== S_OK
, "got %08x\n", hr
);
1248 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1249 ok( hr
== S_OK
, "got %08x\n", hr
);
1250 check_output( writer
, "", __LINE__
);
1252 hr
= WsWriteStartCData( writer
, NULL
);
1253 ok( hr
== S_OK
, "got %08x\n", hr
);
1254 check_output( writer
, "<t><![CDATA[", __LINE__
);
1256 text
.value
.bytes
= (BYTE
*)"<data>";
1257 text
.value
.length
= 6;
1258 hr
= WsWriteText( writer
, &text
.text
, NULL
);
1259 ok( hr
== S_OK
, "got %08x\n", hr
);
1260 check_output( writer
, "<t><![CDATA[<data>", __LINE__
);
1262 hr
= WsWriteEndCData( writer
, NULL
);
1263 ok( hr
== S_OK
, "got %08x\n", hr
);
1264 check_output( writer
, "<t><![CDATA[<data>]]>", __LINE__
);
1266 hr
= WsWriteEndElement( writer
, NULL
);
1267 ok( hr
== S_OK
, "got %08x\n", hr
);
1268 check_output( writer
, "<t><![CDATA[<data>]]></t>", __LINE__
);
1270 WsFreeWriter( writer
);
1273 static void check_output_buffer( WS_XML_BUFFER
*buffer
, const char *expected
, unsigned int line
)
1275 WS_XML_WRITER
*writer
;
1277 ULONG size
= sizeof(bytes
);
1278 int len
= strlen(expected
);
1281 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1282 ok( hr
== S_OK
, "got %08x\n", hr
);
1284 hr
= set_output( writer
);
1285 ok( hr
== S_OK
, "got %08x\n", hr
);
1287 hr
= WsWriteXmlBuffer( writer
, buffer
, NULL
);
1288 ok( hr
== S_OK
, "got %08x\n", hr
);
1290 memset( &bytes
, 0, sizeof(bytes
) );
1291 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
1292 ok( hr
== S_OK
, "%u: got %08x\n", line
, hr
);
1293 ok( bytes
.length
== len
, "%u: got %u expected %u\n", line
, bytes
.length
, len
);
1294 if (bytes
.length
!= len
) return;
1295 ok( !memcmp( bytes
.bytes
, expected
, len
), "%u: got %s expected %s\n", line
, bytes
.bytes
, expected
);
1297 WsFreeWriter( writer
);
1300 static void prepare_xmlns_test( WS_XML_WRITER
*writer
, WS_HEAP
**heap
, WS_XML_BUFFER
**buffer
)
1302 WS_XML_STRING prefix
= {6, (BYTE
*)"prefix"}, localname
= {1, (BYTE
*)"t"}, ns
= {2, (BYTE
*)"ns"};
1305 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, heap
, NULL
);
1306 ok( hr
== S_OK
, "got %08x\n", hr
);
1308 hr
= WsCreateXmlBuffer( *heap
, NULL
, 0, buffer
, NULL
);
1309 ok( hr
== S_OK
, "got %08x\n", hr
);
1311 hr
= WsSetOutputToBuffer( writer
, *buffer
, NULL
, 0, NULL
);
1312 ok( hr
== S_OK
, "got %08x\n", hr
);
1314 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
1315 ok( hr
== S_OK
, "got %08x\n", hr
);
1318 static void test_WsWriteXmlnsAttribute(void)
1320 WS_XML_STRING ns
= {2, (BYTE
*)"ns"}, ns2
= {3, (BYTE
*)"ns2"};
1321 WS_XML_STRING prefix
= {6, (BYTE
*)"prefix"}, prefix2
= {7, (BYTE
*)"prefix2"};
1322 WS_XML_STRING xmlns
= {6, (BYTE
*)"xmlns"}, attr
= {4, (BYTE
*)"attr"};
1323 WS_XML_STRING localname
= {1, (BYTE
*)"u"};
1325 WS_XML_BUFFER
*buffer
;
1326 WS_XML_WRITER
*writer
;
1329 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1330 ok( hr
== S_OK
, "got %08x\n", hr
);
1332 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1333 ok( hr
== S_OK
, "got %08x\n", hr
);
1335 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1336 ok( hr
== S_OK
, "got %08x\n", hr
);
1338 hr
= WsWriteXmlnsAttribute( NULL
, NULL
, NULL
, FALSE
, NULL
);
1339 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1342 prepare_xmlns_test( writer
, &heap
, &buffer
);
1343 hr
= WsWriteXmlnsAttribute( writer
, NULL
, NULL
, FALSE
, NULL
);
1344 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1347 prepare_xmlns_test( writer
, &heap
, &buffer
);
1348 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, NULL
, FALSE
, NULL
);
1349 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1351 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1352 ok( hr
== S_OK
, "got %08x\n", hr
);
1353 hr
= WsWriteXmlnsAttribute( writer
, NULL
, &ns
, FALSE
, NULL
);
1354 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1358 prepare_xmlns_test( writer
, &heap
, &buffer
);
1359 hr
= WsWriteXmlnsAttribute( writer
, NULL
, &ns2
, FALSE
, NULL
);
1360 ok( hr
== S_OK
, "got %08x\n", hr
);
1361 hr
= WsWriteEndElement( writer
, NULL
);
1362 ok( hr
== S_OK
, "got %08x\n", hr
);
1363 check_output_buffer( buffer
, "<prefix:t xmlns:prefix=\"ns\" xmlns=\"ns2\"/>", __LINE__
);
1367 prepare_xmlns_test( writer
, &heap
, &buffer
);
1368 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, FALSE
, NULL
);
1369 ok( hr
== S_OK
, "got %08x\n", hr
);
1370 hr
= WsWriteEndElement( writer
, NULL
);
1371 ok( hr
== S_OK
, "got %08x\n", hr
);
1372 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2=\"ns2\" xmlns:prefix=\"ns\"/>", __LINE__
);
1375 /* implicitly set element prefix namespace */
1376 prepare_xmlns_test( writer
, &heap
, &buffer
);
1377 hr
= WsWriteEndElement( writer
, NULL
);
1378 ok( hr
== S_OK
, "got %08x\n", hr
);
1379 check_output_buffer( buffer
, "<prefix:t xmlns:prefix=\"ns\"/>", __LINE__
);
1382 /* explicitly set element prefix namespace */
1383 prepare_xmlns_test( writer
, &heap
, &buffer
);
1384 hr
= WsWriteXmlnsAttribute( writer
, &prefix
, &ns
, TRUE
, NULL
);
1385 ok( hr
== S_OK
, "got %08x\n", hr
);
1386 hr
= WsWriteEndElement( writer
, NULL
);
1387 ok( hr
== S_OK
, "got %08x\n", hr
);
1388 check_output_buffer( buffer
, "<prefix:t xmlns:prefix='ns'/>", __LINE__
);
1391 /* repeated calls, same namespace */
1392 prepare_xmlns_test( writer
, &heap
, &buffer
);
1393 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, FALSE
, NULL
);
1394 ok( hr
== S_OK
, "got %08x\n", hr
);
1395 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, FALSE
, NULL
);
1396 ok( hr
== S_OK
, "got %08x\n", hr
);
1397 hr
= WsWriteEndElement( writer
, NULL
);
1398 ok( hr
== S_OK
, "got %08x\n", hr
);
1399 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2=\"ns\" xmlns:prefix=\"ns\"/>", __LINE__
);
1402 /* repeated calls, different namespace */
1403 prepare_xmlns_test( writer
, &heap
, &buffer
);
1404 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, FALSE
, NULL
);
1405 ok( hr
== S_OK
, "got %08x\n", hr
);
1406 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, FALSE
, NULL
);
1407 ok( hr
== S_OK
, "got %08x\n", hr
);
1408 hr
= WsWriteEndElement( writer
, NULL
);
1409 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1413 prepare_xmlns_test( writer
, &heap
, &buffer
);
1414 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns
, TRUE
, NULL
);
1415 ok( hr
== S_OK
, "got %08x\n", hr
);
1416 hr
= WsWriteEndElement( writer
, NULL
);
1417 ok( hr
== S_OK
, "got %08x\n", hr
);
1418 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2='ns' xmlns:prefix=\"ns\"/>", __LINE__
);
1421 /* different namespace, different prefix */
1422 prepare_xmlns_test( writer
, &heap
, &buffer
);
1423 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, TRUE
, NULL
);
1424 ok( hr
== S_OK
, "got %08x\n", hr
);
1425 hr
= WsWriteEndElement( writer
, NULL
);
1426 ok( hr
== S_OK
, "got %08x\n", hr
);
1427 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"/>", __LINE__
);
1430 /* different namespace, same prefix */
1431 prepare_xmlns_test( writer
, &heap
, &buffer
);
1432 hr
= WsWriteXmlnsAttribute( writer
, &prefix
, &ns2
, TRUE
, NULL
);
1433 ok( hr
== S_OK
, "got %08x\n", hr
);
1434 hr
= WsWriteEndElement( writer
, NULL
);
1435 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1438 /* regular attribute */
1439 prepare_xmlns_test( writer
, &heap
, &buffer
);
1440 hr
= WsWriteStartAttribute( writer
, &xmlns
, &prefix2
, &ns2
, TRUE
, NULL
);
1441 ok( hr
== S_OK
, "got %08x\n", hr
);
1442 hr
= WsWriteEndAttribute( writer
, NULL
);
1443 ok( hr
== S_OK
, "got %08x\n", hr
);
1444 hr
= WsWriteEndElement( writer
, NULL
);
1445 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1448 /* attribute order */
1449 prepare_xmlns_test( writer
, &heap
, &buffer
);
1450 hr
= WsWriteXmlnsAttribute( writer
, &prefix
, &ns
, TRUE
, NULL
);
1451 ok( hr
== S_OK
, "got %08x\n", hr
);
1452 hr
= WsWriteStartAttribute( writer
, &prefix
, &attr
, &ns
, TRUE
, NULL
);
1453 ok( hr
== S_OK
, "got %08x\n", hr
);
1454 hr
= WsWriteEndAttribute( writer
, NULL
);
1455 ok( hr
== S_OK
, "got %08x\n", hr
);
1456 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, TRUE
, NULL
);
1457 ok( hr
== S_OK
, "got %08x\n", hr
);
1458 hr
= WsWriteEndElement( writer
, NULL
);
1459 ok( hr
== S_OK
, "got %08x\n", hr
);
1460 check_output_buffer( buffer
, "<prefix:t prefix:attr='' xmlns:prefix='ns' xmlns:prefix2='ns2'/>", __LINE__
);
1464 prepare_xmlns_test( writer
, &heap
, &buffer
);
1465 hr
= WsWriteXmlnsAttribute( writer
, &prefix2
, &ns2
, TRUE
, NULL
);
1466 ok( hr
== S_OK
, "got %08x\n", hr
);
1467 hr
= WsWriteStartElement( writer
, &prefix2
, &localname
, &ns2
, NULL
);
1468 ok( hr
== S_OK
, "got %08x\n", hr
);
1469 hr
= WsWriteEndElement( writer
, NULL
);
1470 ok( hr
== S_OK
, "got %08x\n", hr
);
1471 hr
= WsWriteEndElement( writer
, NULL
);
1472 ok( hr
== S_OK
, "got %08x\n", hr
);
1473 check_output_buffer( buffer
, "<prefix:t xmlns:prefix2='ns2' xmlns:prefix=\"ns\"><prefix2:u/></prefix:t>",
1477 WsFreeWriter( writer
);
1480 static void prepare_prefix_test( WS_XML_WRITER
*writer
)
1482 const WS_XML_STRING p
= {1, (BYTE
*)"p"}, localname
= {1, (BYTE
*)"t"}, ns
= {2, (BYTE
*)"ns"};
1485 hr
= set_output( writer
);
1486 ok( hr
== S_OK
, "got %08x\n", hr
);
1487 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1488 ok( hr
== S_OK
, "got %08x\n", hr
);
1489 hr
= WsWriteEndStartElement( writer
, NULL
);
1490 ok( hr
== S_OK
, "got %08x\n", hr
);
1493 static void test_WsGetPrefixFromNamespace(void)
1495 const WS_XML_STRING p
= {1, (BYTE
*)"p"}, localname
= {1, (BYTE
*)"t"}, *prefix
;
1496 const WS_XML_STRING ns
= {2, (BYTE
*)"ns"}, ns2
= {3, (BYTE
*)"ns2"};
1497 WS_XML_WRITER
*writer
;
1500 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1501 ok( hr
== S_OK
, "got %08x\n", hr
);
1503 hr
= set_output( writer
);
1504 ok( hr
== S_OK
, "got %08x\n", hr
);
1505 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1506 ok( hr
== S_OK
, "got %08x\n", hr
);
1508 hr
= WsGetPrefixFromNamespace( NULL
, NULL
, FALSE
, NULL
, NULL
);
1509 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1511 hr
= WsGetPrefixFromNamespace( NULL
, NULL
, FALSE
, &prefix
, NULL
);
1512 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1514 hr
= WsGetPrefixFromNamespace( writer
, NULL
, FALSE
, &prefix
, NULL
);
1515 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1517 /* element must be committed */
1518 hr
= set_output( writer
);
1519 ok( hr
== S_OK
, "got %08x\n", hr
);
1520 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1521 ok( hr
== S_OK
, "got %08x\n", hr
);
1522 hr
= WsGetPrefixFromNamespace( writer
, &ns
, TRUE
, &prefix
, NULL
);
1523 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1525 /* but writer can't be positioned on end element node */
1526 hr
= set_output( writer
);
1527 ok( hr
== S_OK
, "got %08x\n", hr
);
1528 hr
= WsWriteStartElement( writer
, &p
, &localname
, &ns
, NULL
);
1529 ok( hr
== S_OK
, "got %08x\n", hr
);
1530 hr
= WsWriteEndElement( writer
, NULL
);
1531 ok( hr
== S_OK
, "got %08x\n", hr
);
1532 hr
= WsGetPrefixFromNamespace( writer
, &ns
, TRUE
, &prefix
, NULL
);
1533 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1535 /* required = TRUE */
1537 prepare_prefix_test( writer
);
1538 hr
= WsGetPrefixFromNamespace( writer
, &ns
, TRUE
, &prefix
, NULL
);
1539 ok( hr
== S_OK
, "got %08x\n", hr
);
1540 ok( prefix
!= NULL
, "prefix not set\n" );
1543 ok( prefix
->length
== 1, "got %u\n", prefix
->length
);
1544 ok( !memcmp( prefix
->bytes
, "p", 1 ), "wrong prefix\n" );
1547 prefix
= (const WS_XML_STRING
*)0xdeadbeef;
1548 hr
= WsGetPrefixFromNamespace( writer
, &ns2
, TRUE
, &prefix
, NULL
);
1549 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1550 ok( prefix
== (const WS_XML_STRING
*)0xdeadbeef, "prefix set\n" );
1552 /* required = FALSE */
1554 prepare_prefix_test( writer
);
1555 hr
= WsGetPrefixFromNamespace( writer
, &ns
, FALSE
, &prefix
, NULL
);
1556 ok( hr
== S_OK
, "got %08x\n", hr
);
1557 ok( prefix
!= NULL
, "prefix not set\n" );
1560 ok( prefix
->length
== 1, "got %u\n", prefix
->length
);
1561 ok( !memcmp( prefix
->bytes
, "p", 1 ), "wrong prefix\n" );
1564 prefix
= (const WS_XML_STRING
*)0xdeadbeef;
1565 hr
= WsGetPrefixFromNamespace( writer
, &ns2
, FALSE
, &prefix
, NULL
);
1566 ok( hr
== S_FALSE
, "got %08x\n", hr
);
1567 ok( prefix
== NULL
, "prefix not set\n" );
1569 WsFreeWriter( writer
);
1572 static void test_complex_struct_type(void)
1574 static const char expected
[] =
1575 "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
1576 "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
1577 "</o:OfficeConfig>";
1578 WS_XML_STRING str_officeconfig
= {12, (BYTE
*)"OfficeConfig"};
1579 WS_XML_STRING str_services
= {8, (BYTE
*)"services"};
1580 WS_XML_STRING str_generationtime
= {14, (BYTE
*)"GenerationTime"};
1581 WS_XML_STRING ns
= {39, (BYTE
*)"urn:schemas-microsoft-com:office:office"};
1582 WS_XML_STRING prefix
= {1, (BYTE
*)"o"};
1586 WS_XML_BUFFER
*buffer
;
1587 WS_XML_WRITER
*writer
;
1588 WS_STRUCT_DESCRIPTION s
, s2
;
1589 WS_FIELD_DESCRIPTION f
, f2
, f3
, *fields
[1], *fields2
[2];
1592 const WCHAR
*generationtime
;
1597 struct services
*services
;
1600 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1601 ok( hr
== S_OK
, "got %08x\n", hr
);
1603 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1604 ok( hr
== S_OK
, "got %08x\n", hr
);
1606 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1607 ok( hr
== S_OK
, "got %08x\n", hr
);
1609 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1610 ok( hr
== S_OK
, "got %08x\n", hr
);
1612 hr
= WsWriteStartElement( writer
, &prefix
, &str_officeconfig
, &ns
, NULL
);
1613 ok( hr
== S_OK
, "got %08x\n", hr
);
1615 memset( &f2
, 0, sizeof(f2
) );
1616 f2
.mapping
= WS_ATTRIBUTE_FIELD_MAPPING
;
1617 f2
.localName
= &str_generationtime
;
1619 f2
.type
= WS_WSZ_TYPE
;
1620 f2
.options
= WS_FIELD_OPTIONAL
;
1623 memset( &f3
, 0, sizeof(f3
) );
1624 f3
.mapping
= WS_ANY_ATTRIBUTES_FIELD_MAPPING
;
1625 f3
.type
= WS_ANY_ATTRIBUTES_TYPE
;
1626 f3
.offset
= FIELD_OFFSET(struct services
, dummy
);
1629 memset( &s2
, 0, sizeof(s2
) );
1630 s2
.size
= sizeof(*test
->services
);
1632 s2
.fields
= fields2
;
1634 s2
.typeLocalName
= &str_services
;
1637 memset( &f
, 0, sizeof(f
) );
1638 f
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
1639 f
.localName
= &str_services
;
1641 f
.type
= WS_STRUCT_TYPE
;
1642 f
.typeDescription
= &s2
;
1643 f
.options
= WS_FIELD_POINTER
;
1646 memset( &s
, 0, sizeof(s
) );
1647 s
.size
= sizeof(*test
);
1651 s
.typeLocalName
= &str_officeconfig
;
1654 size
= sizeof(struct officeconfig
) + sizeof(struct services
);
1655 test
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1656 test
->services
= (struct services
*)(test
+ 1);
1657 test
->services
->generationtime
= L
"2015-09-03T18:47:54";
1658 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
1659 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
1660 ok( hr
== S_OK
, "got %08x\n", hr
);
1662 hr
= WsWriteEndElement( writer
, NULL
);
1663 ok( hr
== S_OK
, "got %08x\n", hr
);
1664 check_output_buffer( buffer
, expected
, __LINE__
);
1666 HeapFree( GetProcessHeap(), 0, test
);
1667 WsFreeWriter( writer
);
1671 static void test_WsMoveWriter(void)
1673 WS_XML_STRING localname
= {1, (BYTE
*)"a"}, localname2
= {1, (BYTE
*)"b"}, ns
= {0, NULL
};
1675 WS_XML_WRITER
*writer
;
1676 WS_XML_BUFFER
*buffer
;
1679 hr
= WsMoveWriter( NULL
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1680 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1682 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1683 ok( hr
== S_OK
, "got %08x\n", hr
);
1685 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1686 ok( hr
== S_OK
, "got %08x\n", hr
);
1688 hr
= set_output( writer
);
1689 ok( hr
== S_OK
, "got %08x\n", hr
);
1691 /* writer must be set to an XML buffer */
1692 hr
= WsMoveWriter( writer
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1693 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1695 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1696 ok( hr
== S_OK
, "got %08x\n", hr
);
1698 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1699 ok( hr
== S_OK
, "got %08x\n", hr
);
1701 hr
= WsMoveWriter( writer
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1702 ok( hr
== S_OK
, "got %08x\n", hr
);
1705 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1706 ok( hr
== S_OK
, "got %08x\n", hr
);
1708 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
1709 ok( hr
== S_OK
, "got %08x\n", hr
);
1711 hr
= WsWriteEndElement( writer
, NULL
);
1712 ok( hr
== S_OK
, "got %08x\n", hr
);
1714 hr
= WsWriteEndElement( writer
, NULL
);
1715 ok( hr
== S_OK
, "got %08x\n", hr
);
1717 hr
= WsMoveWriter( writer
, WS_MOVE_TO_EOF
, NULL
, NULL
);
1718 ok( hr
== S_OK
, "got %08x\n", hr
);
1720 hr
= WsMoveWriter( writer
, WS_MOVE_TO_ROOT_ELEMENT
, NULL
, NULL
);
1721 ok( hr
== S_OK
, "got %08x\n", hr
);
1723 hr
= WsMoveWriter( writer
, WS_MOVE_TO_CHILD_ELEMENT
, NULL
, NULL
);
1724 ok( hr
== S_OK
, "got %08x\n", hr
);
1726 hr
= WsMoveWriter( writer
, WS_MOVE_TO_END_ELEMENT
, NULL
, NULL
);
1727 ok( hr
== S_OK
, "got %08x\n", hr
);
1729 hr
= WsMoveWriter( writer
, WS_MOVE_TO_PARENT_ELEMENT
, NULL
, NULL
);
1730 ok( hr
== S_OK
, "got %08x\n", hr
);
1732 hr
= WsMoveWriter( writer
, WS_MOVE_TO_END_ELEMENT
, NULL
, NULL
);
1733 ok( hr
== S_OK
, "got %08x\n", hr
);
1735 hr
= WsMoveWriter( writer
, WS_MOVE_TO_BOF
, NULL
, NULL
);
1736 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1738 WsFreeWriter( writer
);
1742 static void test_WsGetWriterPosition(void)
1745 WS_XML_WRITER
*writer
;
1746 WS_XML_BUFFER
*buffer
;
1747 WS_XML_NODE_POSITION pos
;
1750 hr
= WsGetWriterPosition( NULL
, NULL
, NULL
);
1751 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1753 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1754 ok( hr
== S_OK
, "got %08x\n", hr
);
1756 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1757 ok( hr
== S_OK
, "got %08x\n", hr
);
1759 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1760 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1762 hr
= set_output( writer
);
1763 ok( hr
== S_OK
, "got %08x\n", hr
);
1765 /* writer must be set to an XML buffer */
1766 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1767 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1769 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1770 ok( hr
== S_OK
, "got %08x\n", hr
);
1772 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1773 ok( hr
== S_OK
, "got %08x\n", hr
);
1775 hr
= WsGetWriterPosition( writer
, NULL
, NULL
);
1776 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1778 pos
.buffer
= pos
.node
= NULL
;
1779 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1780 ok( hr
== S_OK
, "got %08x\n", hr
);
1781 ok( pos
.buffer
!= NULL
, "buffer not set\n" );
1782 ok( pos
.node
!= NULL
, "node not set\n" );
1784 WsFreeWriter( writer
);
1788 static void test_WsSetWriterPosition(void)
1790 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1792 WS_XML_WRITER
*writer
;
1793 WS_XML_BUFFER
*buf1
, *buf2
;
1794 WS_XML_NODE_POSITION pos
;
1797 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1798 ok( hr
== S_OK
, "got %08x\n", hr
);
1800 hr
= WsSetWriterPosition( NULL
, NULL
, NULL
);
1801 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1803 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1804 ok( hr
== S_OK
, "got %08x\n", hr
);
1806 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buf1
, NULL
);
1807 ok( hr
== S_OK
, "got %08x\n", hr
);
1809 hr
= WsSetOutputToBuffer( writer
, buf1
, NULL
, 0, NULL
);
1810 ok( hr
== S_OK
, "got %08x\n", hr
);
1812 hr
= WsSetWriterPosition( writer
, NULL
, NULL
);
1813 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1815 pos
.buffer
= pos
.node
= NULL
;
1816 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1817 ok( hr
== S_OK
, "got %08x\n", hr
);
1818 ok( pos
.buffer
== buf1
, "wrong buffer\n" );
1819 ok( pos
.node
!= NULL
, "node not set\n" );
1821 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1822 ok( hr
== S_OK
, "got %08x\n", hr
);
1824 /* different buffer */
1825 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buf2
, NULL
);
1826 ok( hr
== S_OK
, "got %08x\n", hr
);
1829 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1830 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1832 hr
= WsSetOutputToBuffer( writer
, buf1
, NULL
, 0, NULL
);
1833 ok( hr
== S_OK
, "got %08x\n", hr
);
1835 /* try to write at non-final position */
1836 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1837 ok( hr
== S_OK
, "got %08x\n", hr
);
1839 pos
.buffer
= pos
.node
= NULL
;
1840 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
1841 ok( hr
== S_OK
, "got %08x\n", hr
);
1842 ok( pos
.buffer
== buf1
, "wrong buffer\n" );
1843 ok( pos
.node
!= NULL
, "node not set\n" );
1845 hr
= WsWriteEndElement( writer
, NULL
);
1846 ok( hr
== S_OK
, "got %08x\n", hr
);
1847 check_output_buffer( buf1
, "<t/>", __LINE__
);
1849 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
1850 ok( hr
== S_OK
, "got %08x\n", hr
);
1852 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
1853 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1855 WsFreeWriter( writer
);
1859 static void test_WsWriteXmlBuffer(void)
1861 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
1862 WS_XML_WRITER
*writer1
, *writer2
;
1863 WS_XML_BUFFER
*buffer1
, *buffer2
;
1867 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1868 ok( hr
== S_OK
, "got %08x\n", hr
);
1870 hr
= WsCreateXmlBuffer( NULL
, NULL
, 0, NULL
, NULL
);
1871 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1873 hr
= WsCreateWriter( NULL
, 0, &writer1
, NULL
);
1874 ok( hr
== S_OK
, "got %08x\n", hr
);
1876 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, NULL
, NULL
);
1877 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1879 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer1
, NULL
);
1880 ok( hr
== S_OK
, "got %08x\n", hr
);
1882 hr
= WsSetOutputToBuffer( writer1
, buffer1
, NULL
, 0, NULL
);
1883 ok( hr
== S_OK
, "got %08x\n", hr
);
1885 hr
= WsWriteStartElement( writer1
, NULL
, &localname
, &ns
, NULL
);
1886 ok( hr
== S_OK
, "got %08x\n", hr
);
1888 hr
= WsWriteEndElement( writer1
, NULL
);
1889 ok( hr
== S_OK
, "got %08x\n", hr
);
1890 check_output_buffer( buffer1
, "<t/>", __LINE__
);
1892 hr
= WsCreateWriter( NULL
, 0, &writer2
, NULL
);
1893 ok( hr
== S_OK
, "got %08x\n", hr
);
1895 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer2
, NULL
);
1896 ok( hr
== S_OK
, "got %08x\n", hr
);
1898 hr
= WsSetOutputToBuffer( writer2
, buffer2
, NULL
, 0, NULL
);
1899 ok( hr
== S_OK
, "got %08x\n", hr
);
1901 hr
= WsWriteXmlBuffer( writer2
, buffer1
, NULL
);
1902 ok( hr
== S_OK
, "got %08x\n", hr
);
1903 check_output_buffer( buffer2
, "<t/>", __LINE__
);
1905 hr
= WsMoveWriter( writer2
, WS_MOVE_TO_PREVIOUS_ELEMENT
, NULL
, NULL
);
1906 todo_wine
ok( hr
== S_OK
, "got %08x\n", hr
);
1908 hr
= WsWriteXmlBuffer( writer2
, buffer1
, NULL
);
1909 todo_wine
ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
1911 WsFreeWriter( writer1
);
1912 WsFreeWriter( writer2
);
1916 static void test_WsWriteNode(void)
1918 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {4, (BYTE
*)"attr"}, ns
= {0, NULL
};
1919 WS_XML_WRITER
*writer
;
1920 WS_XML_BUFFER
*buffer
;
1921 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
1922 WS_XML_ATTRIBUTE attr
, *attrs
[1];
1923 WS_XML_ELEMENT_NODE elem
;
1924 WS_XML_COMMENT_NODE comment
= {{WS_XML_NODE_TYPE_COMMENT
}};
1926 WS_XML_TEXT_NODE text
= {{WS_XML_NODE_TYPE_TEXT
}};
1930 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
1931 ok( hr
== S_OK
, "got %08x\n", hr
);
1933 hr
= WsWriteNode( NULL
, NULL
, NULL
);
1934 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
1936 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
1937 ok( hr
== S_OK
, "got %08x\n", hr
);
1939 hr
= WsWriteNode( writer
, NULL
, NULL
);
1940 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
1942 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
1943 ok( hr
== S_OK
, "got %08x\n", hr
);
1945 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
1946 ok( hr
== S_OK
, "got %08x\n", hr
);
1948 utf8
.value
.bytes
= (BYTE
*)"value";
1949 utf8
.value
.length
= sizeof("value") - 1;
1951 attr
.singleQuote
= TRUE
;
1952 attr
.isXmlNs
= FALSE
;
1954 attr
.localName
= &localname2
;
1956 attr
.value
= &utf8
.text
;
1959 elem
.node
.nodeType
= WS_XML_NODE_TYPE_ELEMENT
;
1961 elem
.localName
= &localname
;
1963 elem
.attributeCount
= 1;
1964 elem
.attributes
= attrs
;
1965 elem
.isEmpty
= FALSE
;
1966 hr
= WsWriteNode( writer
, &elem
.node
, NULL
);
1967 ok( hr
== S_OK
, "got %08x\n", hr
);
1969 comment
.value
.bytes
= (BYTE
*)"comment";
1970 comment
.value
.length
= sizeof("comment") - 1;
1971 hr
= WsWriteNode( writer
, &comment
.node
, NULL
);
1972 ok( hr
== S_OK
, "got %08x\n", hr
);
1974 node
.nodeType
= WS_XML_NODE_TYPE_EOF
;
1975 hr
= WsWriteNode( writer
, &node
, NULL
);
1976 ok( hr
== S_OK
, "got %08x\n", hr
);
1978 node
.nodeType
= WS_XML_NODE_TYPE_BOF
;
1979 hr
= WsWriteNode( writer
, &node
, NULL
);
1980 ok( hr
== S_OK
, "got %08x\n", hr
);
1982 node
.nodeType
= WS_XML_NODE_TYPE_CDATA
;
1983 hr
= WsWriteNode( writer
, &node
, NULL
);
1984 ok( hr
== S_OK
, "got %08x\n", hr
);
1986 utf8
.value
.bytes
= (BYTE
*)"cdata";
1987 utf8
.value
.length
= sizeof("cdata") - 1;
1988 text
.text
= &utf8
.text
;
1989 hr
= WsWriteNode( writer
, &text
.node
, NULL
);
1990 ok( hr
== S_OK
, "got %08x\n", hr
);
1992 node
.nodeType
= WS_XML_NODE_TYPE_END_CDATA
;
1993 hr
= WsWriteNode( writer
, &node
, NULL
);
1994 ok( hr
== S_OK
, "got %08x\n", hr
);
1996 utf8
.value
.bytes
= (BYTE
*)"text";
1997 utf8
.value
.length
= sizeof("text") - 1;
1998 hr
= WsWriteNode( writer
, &text
.node
, NULL
);
1999 ok( hr
== S_OK
, "got %08x\n", hr
);
2001 node
.nodeType
= WS_XML_NODE_TYPE_END_ELEMENT
;
2002 hr
= WsWriteNode( writer
, &node
, NULL
);
2003 ok( hr
== S_OK
, "got %08x\n", hr
);
2004 check_output_buffer( buffer
, "<t attr='value'><!--comment--><![CDATA[cdata]]>text</t>", __LINE__
);
2006 WsFreeWriter( writer
);
2010 static HRESULT
set_input( WS_XML_READER
*reader
, const char *data
, ULONG size
)
2012 WS_XML_READER_TEXT_ENCODING text
= {{WS_XML_READER_ENCODING_TYPE_TEXT
}, WS_CHARSET_AUTO
};
2013 WS_XML_READER_BUFFER_INPUT buf
= {{WS_XML_READER_INPUT_TYPE_BUFFER
}, (void *)data
, size
};
2014 return WsSetInput( reader
, &text
.encoding
, &buf
.input
, NULL
, 0, NULL
);
2017 static void test_WsCopyNode(void)
2019 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"u"}, ns
= {0, NULL
};
2020 WS_XML_NODE_POSITION pos
, pos2
;
2021 const WS_XML_NODE
*node
;
2022 WS_XML_WRITER
*writer
;
2023 WS_XML_READER
*reader
;
2024 WS_XML_BUFFER
*buffer
;
2029 hr
= WsCreateHeap( 1 << 16, 0, NULL
, 0, &heap
, NULL
);
2030 ok( hr
== S_OK
, "got %08x\n", hr
);
2032 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2033 ok( hr
== S_OK
, "got %08x\n", hr
);
2035 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
2036 ok( hr
== S_OK
, "got %08x\n", hr
);
2038 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
2039 ok( hr
== S_OK
, "got %08x\n", hr
);
2041 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2042 ok( hr
== S_OK
, "got %08x\n", hr
);
2044 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
2045 ok( hr
== S_OK
, "got %08x\n", hr
);
2047 hr
= WsWriteEndElement( writer
, NULL
);
2048 ok( hr
== S_OK
, "got %08x\n", hr
);
2050 hr
= WsGetWriterPosition( writer
, &pos
, NULL
);
2051 ok( hr
== S_OK
, "got %08x\n", hr
);
2053 hr
= WsWriteEndElement( writer
, NULL
);
2054 ok( hr
== S_OK
, "got %08x\n", hr
);
2055 check_output_buffer( buffer
, "<t><u/></t>", __LINE__
);
2057 hr
= WsCreateReader( NULL
, 0, &reader
, NULL
);
2058 ok( hr
== S_OK
, "got %08x\n", hr
);
2060 hr
= set_input( reader
, "<v/>", sizeof("<v/>") - 1 );
2061 ok( hr
== S_OK
, "got %08x\n", hr
);
2063 hr
= WsFillReader( reader
, sizeof("<v/>") - 1, NULL
, NULL
);
2064 ok( hr
== S_OK
, "got %08x\n", hr
);
2066 hr
= WsReadToStartElement( reader
, NULL
, NULL
, NULL
, NULL
);
2067 ok( hr
== S_OK
, "got %08x\n", hr
);
2069 hr
= WsSetWriterPosition( writer
, &pos
, NULL
);
2070 ok( hr
== S_OK
, "got %08x\n", hr
);
2072 hr
= WsCopyNode( writer
, reader
, NULL
);
2073 ok( hr
== S_OK
, "got %08x\n", hr
);
2074 check_output_buffer( buffer
, "<t><u/><v/></t>", __LINE__
);
2076 hr
= WsGetWriterPosition( writer
, &pos2
, NULL
);
2077 ok( hr
== S_OK
, "got %08x\n", hr
);
2078 ok( pos2
.buffer
== pos
.buffer
, "wrong buffer\n" );
2079 ok( pos2
.node
== pos
.node
, "wrong node\n" );
2081 hr
= WsGetReaderNode( reader
, &node
, NULL
);
2082 ok( hr
== S_OK
, "got %08x\n", hr
);
2083 ok( node
->nodeType
== WS_XML_NODE_TYPE_EOF
, "got %u\n", node
->nodeType
);
2085 /* reader positioned at EOF */
2086 hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
);
2087 ok( hr
== S_OK
, "got %08x\n", hr
);
2089 hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
);
2090 ok( hr
== S_OK
, "got %08x\n", hr
);
2092 hr
= WsCopyNode( writer
, reader
, NULL
);
2093 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2095 /* reader positioned at BOF */
2096 hr
= set_input( reader
, "<v/>", sizeof("<v/>") - 1 );
2097 ok( hr
== S_OK
, "got %08x\n", hr
);
2099 hr
= WsFillReader( reader
, sizeof("<v/>") - 1, NULL
, NULL
);
2100 ok( hr
== S_OK
, "got %08x\n", hr
);
2102 hr
= WsGetReaderNode( reader
, &node
, NULL
);
2103 ok( hr
== S_OK
, "got %08x\n", hr
);
2104 ok( node
->nodeType
== WS_XML_NODE_TYPE_BOF
, "got %u\n", node
->nodeType
);
2106 hr
= set_output( writer
);
2107 ok( hr
== S_OK
, "got %08x\n", hr
);
2109 hr
= WsCopyNode( writer
, reader
, NULL
);
2110 ok( hr
== S_OK
, "got %08x\n", hr
);
2111 check_output( writer
, "<v/>", __LINE__
);
2113 hr
= WsGetReaderNode( reader
, &node
, NULL
);
2114 ok( hr
== S_OK
, "got %08x\n", hr
);
2115 ok( node
->nodeType
== WS_XML_NODE_TYPE_EOF
, "got %u\n", node
->nodeType
);
2117 memset( &bufs
, 0, sizeof(bufs
) );
2118 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BUFFERS
, &bufs
, sizeof(bufs
), NULL
);
2119 ok( hr
== S_OK
, "got %08x\n", hr
);
2120 ok( bufs
.bufferCount
== 1, "got %u\n", bufs
.bufferCount
);
2121 ok( bufs
.buffers
!= NULL
, "buffers not set\n" );
2123 /* reader positioned at BOF, single text node */
2124 hr
= set_input( reader
, "text", sizeof("text") - 1 );
2125 ok( hr
== S_OK
, "got %08x\n", hr
);
2127 hr
= WsGetReaderNode( reader
, &node
, NULL
);
2128 ok( hr
== S_OK
, "got %08x\n", hr
);
2129 ok( node
->nodeType
== WS_XML_NODE_TYPE_BOF
, "got %u\n", node
->nodeType
);
2131 hr
= set_output( writer
);
2132 ok( hr
== S_OK
, "got %08x\n", hr
);
2134 hr
= WsCopyNode( writer
, reader
, NULL
);
2135 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
2137 WsFreeReader( reader
);
2138 WsFreeWriter( writer
);
2142 static void test_text_types(void)
2144 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"u"};
2145 WS_XML_STRING ns
= {0, NULL
}, ns2
= {2, (BYTE
*)"ns"};
2146 WS_XML_WRITER
*writer
;
2147 static const WS_XML_UTF8_TEXT val_utf8
= { {WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"utf8"} };
2148 static WS_XML_UTF16_TEXT val_utf16
= { {WS_XML_TEXT_TYPE_UTF16
} };
2149 static WS_XML_QNAME_TEXT val_qname
= { {WS_XML_TEXT_TYPE_QNAME
} };
2150 static const WS_XML_GUID_TEXT val_guid
= { {WS_XML_TEXT_TYPE_GUID
} };
2151 static const WS_XML_UNIQUE_ID_TEXT val_urn
= { {WS_XML_TEXT_TYPE_UNIQUE_ID
} };
2152 static const WS_XML_BOOL_TEXT val_bool
= { {WS_XML_TEXT_TYPE_BOOL
}, TRUE
};
2153 static const WS_XML_INT32_TEXT val_int32
= { {WS_XML_TEXT_TYPE_INT32
}, -2147483647 - 1 };
2154 static const WS_XML_INT64_TEXT val_int64
= { {WS_XML_TEXT_TYPE_INT64
}, -9223372036854775807 - 1 };
2155 static const WS_XML_UINT64_TEXT val_uint64
= { {WS_XML_TEXT_TYPE_UINT64
}, ~0 };
2156 static const WS_XML_DATETIME_TEXT val_datetime
= { {WS_XML_TEXT_TYPE_DATETIME
}, {0, WS_DATETIME_FORMAT_UTC
} };
2157 static const WS_XML_DOUBLE_TEXT val_double
= { {WS_XML_TEXT_TYPE_DOUBLE
}, 1.1 };
2158 static const WS_XML_BASE64_TEXT val_base64
= { {WS_XML_TEXT_TYPE_BASE64
}, (BYTE
*)"test", 4 };
2161 const WS_XML_TEXT
*text
;
2166 { &val_utf8
.text
, "<t>utf8</t>" },
2167 { &val_utf16
.text
, "<t>utf16</t>" },
2168 { &val_guid
.text
, "<t>00000000-0000-0000-0000-000000000000</t>" },
2169 { &val_urn
.text
, "<t>urn:uuid:00000000-0000-0000-0000-000000000000</t>" },
2170 { &val_bool
.text
, "<t>true</t>" },
2171 { &val_int32
.text
, "<t>-2147483648</t>" },
2172 { &val_int64
.text
, "<t>-9223372036854775808</t>" },
2173 { &val_uint64
.text
, "<t>18446744073709551615</t>" },
2174 { &val_datetime
.text
, "<t>0001-01-01T00:00:00Z</t>" },
2175 { &val_double
.text
, "<t>1.1</t>" },
2176 { &val_base64
.text
, "<t>dGVzdA==</t>" },
2177 { &val_qname
.text
, "<t>u</t>" },
2182 val_utf16
.bytes
= (BYTE
*)L
"utf16";
2183 val_utf16
.byteCount
= 10;
2184 val_qname
.localName
= &localname2
;
2187 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2188 ok( hr
== S_OK
, "got %08x\n", hr
);
2190 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
2192 hr
= set_output( writer
);
2193 ok( hr
== S_OK
, "got %08x\n", hr
);
2194 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2195 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2197 hr
= WsWriteText( writer
, tests
[i
].text
, NULL
);
2198 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2200 hr
= WsWriteEndElement( writer
, NULL
);
2201 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2202 check_output( writer
, tests
[i
].result
, __LINE__
);
2205 hr
= set_output( writer
);
2206 ok( hr
== S_OK
, "got %08x\n", hr
);
2207 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns2
, NULL
);
2208 ok( hr
== S_OK
, "got %08x\n", hr
);
2210 val_qname
.prefix
= &prefix
;
2211 val_qname
.localName
= &localname2
;
2212 val_qname
.ns
= &ns2
;
2213 hr
= WsWriteText( writer
, &val_qname
.text
, NULL
);
2214 ok( hr
== S_OK
, "got %08x\n", hr
);
2216 hr
= WsWriteEndElement( writer
, NULL
);
2217 ok( hr
== S_OK
, "got %08x\n", hr
);
2218 check_output( writer
, "<p:t xmlns:p=\"ns\">p:u</p:t>", __LINE__
);
2220 WsFreeWriter( writer
);
2223 static void test_double(void)
2225 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2226 unsigned int fpword
, fpword_orig
;
2236 {-1.0, "<t>-1</t>"},
2237 {1.0000000000000001, "<t>1</t>"},
2238 {1.0000000000000002, "<t>1.0000000000000002</t>"},
2239 {1.0000000000000003, "<t>1.0000000000000002</t>"},
2240 {1.0000000000000004, "<t>1.0000000000000004</t>"},
2241 {100000000000000, "<t>100000000000000</t>"},
2242 {1000000000000000, "<t>1E+15</t>"},
2243 {0.1, "<t>0.1</t>"},
2244 {0.01, "<t>1E-2</t>"},
2245 {-0.1, "<t>-0.1</t>"},
2246 {-0.01, "<t>-1E-2</t>"},
2247 {1.7976931348623158e308
, "<t>1.7976931348623157E+308</t>"},
2248 {-1.7976931348623158e308
, "<t>-1.7976931348623157E+308</t>"},
2251 WS_XML_WRITER
*writer
;
2252 WS_XML_DOUBLE_TEXT text
;
2255 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
) ;
2256 ok( hr
== S_OK
, "got %08x\n", hr
);
2258 text
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
2259 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
2261 hr
= set_output( writer
);
2262 ok( hr
== S_OK
, "got %08x\n", hr
);
2263 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2264 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2266 text
.value
= tests
[i
].val
;
2267 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2268 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2270 hr
= WsWriteEndElement( writer
, NULL
);
2271 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2272 check_output( writer
, tests
[i
].result
, __LINE__
);
2275 hr
= set_output( writer
);
2276 ok( hr
== S_OK
, "got %08x\n", hr
);
2277 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2278 ok( hr
== S_OK
, "got %08x\n", hr
);
2281 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2282 ok( hr
== S_OK
, "got %08x\n", hr
);
2284 hr
= WsWriteEndElement( writer
, NULL
);
2285 ok( hr
== S_OK
, "got %08x\n", hr
);
2286 check_output( writer
, "<t>NaN</t>", __LINE__
);
2288 hr
= set_output( writer
);
2289 ok( hr
== S_OK
, "got %08x\n", hr
);
2290 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2291 ok( hr
== S_OK
, "got %08x\n", hr
);
2293 text
.value
= INFINITY
;
2294 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2295 ok( hr
== S_OK
, "got %08x\n", hr
);
2297 hr
= WsWriteEndElement( writer
, NULL
);
2298 ok( hr
== S_OK
, "got %08x\n", hr
);
2299 check_output( writer
, "<t>INF</t>", __LINE__
);
2301 hr
= set_output( writer
);
2302 ok( hr
== S_OK
, "got %08x\n", hr
);
2303 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2304 ok( hr
== S_OK
, "got %08x\n", hr
);
2306 text
.value
= -INFINITY
;
2307 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2308 ok( hr
== S_OK
, "got %08x\n", hr
);
2310 hr
= WsWriteEndElement( writer
, NULL
);
2311 ok( hr
== S_OK
, "got %08x\n", hr
);
2312 check_output( writer
, "<t>-INF</t>", __LINE__
);
2314 fpword_orig
= _control87( 0, 0 );
2315 fpword
= _control87( _MCW_EM
| _RC_CHOP
| _PC_64
, _MCW_EM
| _MCW_RC
| _MCW_PC
);
2316 ok( fpword
== (_MCW_EM
| _RC_CHOP
| _PC_64
), "got %08x\n", fpword
);
2318 hr
= set_output( writer
);
2319 ok( hr
== S_OK
, "got %08x\n", hr
);
2320 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2321 ok( hr
== S_OK
, "got %08x\n", hr
);
2323 text
.value
= 100000000000000;
2324 hr
= WsWriteText( writer
, &text
.text
, NULL
);
2325 ok( hr
== S_OK
, "got %08x\n", hr
);
2327 hr
= WsWriteEndElement( writer
, NULL
);
2328 ok( hr
== S_OK
, "got %08x\n", hr
);
2329 check_output( writer
, "<t>100000000000000</t>", __LINE__
);
2331 fpword
= _control87( 0, 0 );
2332 ok( fpword
== (_MCW_EM
| _RC_CHOP
| _PC_64
), "got %08x\n", fpword
);
2333 _control87( fpword_orig
, _MCW_EM
| _MCW_RC
| _MCW_PC
);
2335 WsFreeWriter( writer
);
2338 static void test_field_options(void)
2340 static const char expected
[] =
2341 "<t><bool a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/><int32>-1</int32>"
2342 "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></t>";
2344 WS_XML_WRITER
*writer
;
2345 WS_STRUCT_DESCRIPTION s
;
2346 WS_FIELD_DESCRIPTION f
, f2
, f3
, f4
, f5
, *fields
[5];
2347 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
}, str_guid
= {4, (BYTE
*)"guid"};
2348 WS_XML_STRING str_int32
= {5, (BYTE
*)"int32"}, str_bool
= {4, (BYTE
*)"bool"};
2349 WS_XML_STRING str_xmlstr
= {6, (BYTE
*)"xmlstr"}, str_str
= {3, (BYTE
*)"str"};
2356 WS_XML_STRING xmlstr
;
2360 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2361 ok( hr
== S_OK
, "got %08x\n", hr
);
2363 hr
= set_output( writer
);
2364 ok( hr
== S_OK
, "got %08x\n", hr
);
2366 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2367 ok( hr
== S_OK
, "got %08x\n", hr
);
2369 memset( &f
, 0, sizeof(f
) );
2370 f
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2371 f
.localName
= &str_guid
;
2373 f
.type
= WS_GUID_TYPE
;
2374 f
.options
= WS_FIELD_OPTIONAL
;
2377 memset( &f2
, 0, sizeof(f2
) );
2378 f2
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2379 f2
.localName
= &str_bool
;
2380 f2
.offset
= FIELD_OFFSET(struct test
, bool_ptr
);
2382 f2
.type
= WS_BOOL_TYPE
;
2383 f2
.options
= WS_FIELD_POINTER
|WS_FIELD_NILLABLE
;
2386 memset( &f3
, 0, sizeof(f3
) );
2387 f3
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2388 f3
.localName
= &str_int32
;
2389 f3
.offset
= FIELD_OFFSET(struct test
, int32_ptr
);
2391 f3
.type
= WS_INT32_TYPE
;
2392 f3
.options
= WS_FIELD_POINTER
|WS_FIELD_NILLABLE
;
2395 memset( &f4
, 0, sizeof(f4
) );
2396 f4
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2397 f4
.localName
= &str_xmlstr
;
2398 f4
.offset
= FIELD_OFFSET(struct test
, xmlstr
);
2400 f4
.type
= WS_XML_STRING_TYPE
;
2401 f4
.options
= WS_FIELD_NILLABLE
;
2404 memset( &f5
, 0, sizeof(f5
) );
2405 f5
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
2406 f5
.localName
= &str_str
;
2407 f5
.offset
= FIELD_OFFSET(struct test
, str
);
2409 f5
.type
= WS_WSZ_TYPE
;
2410 f5
.options
= WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
;
2413 memset( &s
, 0, sizeof(s
) );
2414 s
.size
= sizeof(struct test
);
2415 s
.alignment
= TYPE_ALIGNMENT(struct test
);
2419 memset( &test
, 0, sizeof(test
) );
2420 test
.int32_ptr
= &val
;
2421 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
2422 &test
, sizeof(test
), NULL
);
2423 ok( hr
== S_OK
, "got %08x\n", hr
);
2425 hr
= WsWriteEndElement( writer
, NULL
);
2426 ok( hr
== S_OK
, "got %08x\n", hr
);
2427 check_output( writer
, expected
, __LINE__
);
2429 WsFreeWriter( writer
);
2432 static void test_WsWriteText(void)
2434 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"a"}, ns
= {0, NULL
};
2436 WS_XML_WRITER
*writer
;
2437 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
2438 WS_XML_UTF16_TEXT utf16
= {{WS_XML_TEXT_TYPE_UTF16
}};
2439 WS_XML_GUID_TEXT guid
= {{WS_XML_TEXT_TYPE_GUID
}};
2441 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2442 ok( hr
== S_OK
, "got %08x\n", hr
);
2444 hr
= set_output( writer
);
2445 ok( hr
== S_OK
, "got %08x\n", hr
);
2447 utf8
.value
.bytes
= (BYTE
*)"test";
2448 utf8
.value
.length
= 4;
2449 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2450 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
2452 hr
= set_output( writer
);
2453 ok( hr
== S_OK
, "got %08x\n", hr
);
2456 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2457 ok( hr
== S_OK
, "got %08x\n", hr
);
2459 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2460 ok( hr
== S_OK
, "got %08x\n", hr
);
2461 check_output( writer
, "<t>test", __LINE__
);
2463 utf8
.value
.bytes
= (BYTE
*)"tset";
2464 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2465 ok( hr
== S_OK
, "got %08x\n", hr
);
2466 check_output( writer
, "<t>testtset", __LINE__
);
2468 hr
= WsWriteEndElement( writer
, NULL
);
2469 ok( hr
== S_OK
, "got %08x\n", hr
);
2470 check_output( writer
, "<t>testtset</t>", __LINE__
);
2472 hr
= set_output( writer
);
2473 ok( hr
== S_OK
, "got %08x\n", hr
);
2475 /* attribute, utf8 */
2476 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2477 ok( hr
== S_OK
, "got %08x\n", hr
);
2479 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, 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
);
2484 check_output( writer
, "", __LINE__
);
2486 utf8
.value
.bytes
= (BYTE
*)"test";
2487 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2488 ok( hr
== S_OK
, "got %08x\n", hr
);
2489 check_output( writer
, "", __LINE__
);
2491 hr
= WsWriteEndAttribute( writer
, NULL
);
2492 ok( hr
== S_OK
, "got %08x\n", hr
);
2494 hr
= WsWriteEndElement( writer
, NULL
);
2495 ok( hr
== S_OK
, "got %08x\n", hr
);
2496 check_output( writer
, "<t a=\"tsettest\"/>", __LINE__
);
2498 hr
= set_output( writer
);
2499 ok( hr
== S_OK
, "got %08x\n", hr
);
2501 /* element, utf16 */
2502 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2503 ok( hr
== S_OK
, "got %08x\n", hr
);
2505 utf16
.bytes
= (BYTE
*)L
"test";
2506 utf16
.byteCount
= 8;
2507 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2508 ok( hr
== S_OK
, "got %08x\n", hr
);
2509 check_output( writer
, "<t>test", __LINE__
);
2511 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2512 ok( hr
== S_OK
, "got %08x\n", hr
);
2513 check_output( writer
, "<t>testtest", __LINE__
);
2515 hr
= WsWriteEndElement( writer
, NULL
);
2516 ok( hr
== S_OK
, "got %08x\n", hr
);
2517 check_output( writer
, "<t>testtest</t>", __LINE__
);
2519 hr
= set_output( writer
);
2520 ok( hr
== S_OK
, "got %08x\n", hr
);
2522 /* attribute, utf16 */
2523 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2524 ok( hr
== S_OK
, "got %08x\n", hr
);
2526 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2527 ok( hr
== S_OK
, "got %08x\n", hr
);
2529 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2530 ok( hr
== S_OK
, "got %08x\n", hr
);
2531 check_output( writer
, "", __LINE__
);
2533 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2534 ok( hr
== S_OK
, "got %08x\n", hr
);
2535 check_output( writer
, "", __LINE__
);
2537 hr
= WsWriteEndAttribute( writer
, NULL
);
2538 ok( hr
== S_OK
, "got %08x\n", hr
);
2540 hr
= WsWriteEndElement( writer
, NULL
);
2541 ok( hr
== S_OK
, "got %08x\n", hr
);
2542 check_output( writer
, "<t a=\"testtest\"/>", __LINE__
);
2544 hr
= set_output( writer
);
2545 ok( hr
== S_OK
, "got %08x\n", hr
);
2548 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2549 ok( hr
== S_OK
, "got %08x\n", hr
);
2551 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2552 ok( hr
== S_OK
, "got %08x\n", hr
);
2553 check_output( writer
, "<t>00000000-0000-0000-0000-000000000000", __LINE__
);
2555 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2556 ok( hr
== S_OK
, "got %08x\n", hr
);
2557 check_output( writer
, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000",
2560 /* continue with different text type */
2561 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2562 ok( hr
== S_OK
, "got %08x\n", hr
);
2563 check_output( writer
, "<t>00000000-0000-0000-0000-00000000000000000000-0000-0000-0000-000000000000test",
2566 hr
= WsWriteEndElement( writer
, NULL
);
2567 ok( hr
== S_OK
, "got %08x\n", hr
);
2569 hr
= set_output( writer
);
2570 ok( hr
== S_OK
, "got %08x\n", hr
);
2572 /* attribute, guid */
2573 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2574 ok( hr
== S_OK
, "got %08x\n", hr
);
2576 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2577 ok( hr
== S_OK
, "got %08x\n", hr
);
2579 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2580 ok( hr
== S_OK
, "got %08x\n", hr
);
2581 check_output( writer
, "", __LINE__
);
2583 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2584 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2586 hr
= set_output( writer
);
2587 ok( hr
== S_OK
, "got %08x\n", hr
);
2589 /* attribute, mix allowed text types */
2590 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2591 ok( hr
== S_OK
, "got %08x\n", hr
);
2593 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
2594 ok( hr
== S_OK
, "got %08x\n", hr
);
2596 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2597 ok( hr
== S_OK
, "got %08x\n", hr
);
2599 hr
= WsWriteText( writer
, &utf16
.text
, NULL
);
2600 todo_wine
ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2602 hr
= set_output( writer
);
2603 ok( hr
== S_OK
, "got %08x\n", hr
);
2606 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2607 ok( hr
== S_OK
, "got %08x\n", hr
);
2608 hr
= WsWriteStartCData( writer
, NULL
);
2609 ok( hr
== S_OK
, "got %08x\n", hr
);
2611 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2612 ok( hr
== S_OK
, "got %08x\n", hr
);
2614 hr
= WsWriteText( writer
, &guid
.text
, NULL
);
2615 ok( hr
== S_OK
, "got %08x\n", hr
);
2617 hr
= WsWriteEndCData( writer
, NULL
);
2618 ok( hr
== S_OK
, "got %08x\n", hr
);
2619 hr
= WsWriteEndElement( writer
, NULL
);
2620 ok( hr
== S_OK
, "got %08x\n", hr
);
2621 check_output( writer
, "<t><![CDATA[test00000000-0000-0000-0000-000000000000]]></t>", __LINE__
);
2623 WsFreeWriter( writer
);
2626 static void test_WsWriteArray(void)
2628 static const WS_XML_STRING localname
= {4, (BYTE
*)"item"}, localname2
= {5, (BYTE
*)"array"};
2629 static const WS_XML_STRING ns
= {0, NULL
};
2630 WS_XML_WRITER
*writer
;
2634 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2635 ok( hr
== S_OK
, "got %08x\n", hr
);
2637 hr
= WsWriteArray( writer
, NULL
, NULL
, 0, NULL
, 0, 0, 0, NULL
);
2638 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
2640 hr
= set_output( writer
);
2641 ok( hr
== S_OK
, "got %08x\n", hr
);
2642 hr
= WsWriteArray( writer
, NULL
, NULL
, 0, NULL
, 0, 0, 0, NULL
);
2643 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2645 hr
= set_output( writer
);
2646 ok( hr
== S_OK
, "got %08x\n", hr
);
2647 hr
= WsWriteArray( writer
, &localname
, NULL
, 0, NULL
, 0, 0, 0, NULL
);
2648 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2650 hr
= set_output( writer
);
2651 ok( hr
== S_OK
, "got %08x\n", hr
);
2652 hr
= WsWriteArray( writer
, &localname
, &ns
, 0, NULL
, 0, 0, 0, NULL
);
2653 ok( hr
== S_OK
, "got %08x\n", hr
);
2654 check_output( writer
, "", __LINE__
);
2656 hr
= WsWriteArray( writer
, &localname
, &ns
, ~0u, NULL
, 0, 0, 0, NULL
);
2657 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2659 hr
= set_output( writer
);
2660 ok( hr
== S_OK
, "got %08x\n", hr
);
2661 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, NULL
, 0, 0, 0, NULL
);
2662 ok( hr
== S_OK
, "got %08x\n", hr
);
2663 check_output( writer
, "", __LINE__
);
2665 array_bool
[0] = FALSE
;
2666 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, 0, 0, 0, NULL
);
2667 ok( hr
== S_OK
, "got %08x\n", hr
);
2668 check_output( writer
, "", __LINE__
);
2670 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 0, NULL
);
2671 ok( hr
== S_OK
, "got %08x\n", hr
);
2672 check_output( writer
, "", __LINE__
);
2674 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, NULL
, sizeof(array_bool
), 0, 0, NULL
);
2675 ok( hr
== S_OK
, "got %08x\n", hr
);
2676 check_output( writer
, "", __LINE__
);
2678 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, NULL
, sizeof(array_bool
), 0, 1, NULL
);
2679 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2681 hr
= set_output( writer
);
2682 ok( hr
== S_OK
, "got %08x\n", hr
);
2683 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 1, NULL
);
2684 ok( hr
== S_OK
, "got %08x\n", hr
);
2685 check_output( writer
, "<item>false</item>", __LINE__
);
2687 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
) - 1, 0, 2, NULL
);
2688 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2690 hr
= set_output( writer
);
2691 ok( hr
== S_OK
, "got %08x\n", hr
);
2692 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 3, NULL
);
2693 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
2695 hr
= set_output( writer
);
2696 ok( hr
== S_OK
, "got %08x\n", hr
);
2698 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &ns
, NULL
);
2699 ok( hr
== S_OK
, "got %08x\n", hr
);
2701 array_bool
[1] = TRUE
;
2702 hr
= WsWriteArray( writer
, &localname
, &ns
, WS_BOOL_VALUE_TYPE
, array_bool
, sizeof(array_bool
), 0, 2, NULL
);
2703 ok( hr
== S_OK
, "got %08x\n", hr
);
2705 hr
= WsWriteEndElement( writer
, NULL
);
2706 ok( hr
== S_OK
, "got %08x\n", hr
);
2707 check_output( writer
, "<array><item>false</item><item>true</item></array>", __LINE__
);
2709 WsFreeWriter( writer
);
2712 static void test_escapes(void)
2714 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2715 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
2716 WS_XML_WRITER
*writer
;
2723 static const struct test tests_elem
[] =
2725 { "<", "<t><</t>" },
2726 { ">", "<t>></t>" },
2727 { "\"", "<t>\"</t>" },
2728 { "&", "<t>&</t>" },
2729 { "&&", "<t>&&</t>" },
2730 { "'", "<t>'</t>" },
2732 static const struct test tests_attr
[] =
2734 { "<", "<t t=\"<\"/>" },
2735 { ">", "<t t=\">\"/>" },
2736 { "\"", "<t t=\""\"/>" },
2737 { "&", "<t t=\"&\"/>" },
2738 { "'", "<t t=\"'\"/>" },
2739 { "\"", "<t t='\"'/>", TRUE
},
2740 { "'", "<t t='''/>", TRUE
},
2742 static const struct test tests_cdata
[] =
2744 { "<", "<t><![CDATA[<]]></t>" },
2745 { ">", "<t><![CDATA[>]]></t>" },
2746 { "\"", "<t><![CDATA[\"]]></t>" },
2747 { "&", "<t><![CDATA[&]]></t>" },
2748 { "[", "<t><![CDATA[[]]></t>" },
2749 { "]", "<t><![CDATA[]]]></t>" },
2750 { "'", "<t><![CDATA[']]></t>" },
2752 static const struct test tests_comment
[] =
2754 { "<", "<t><!--<--></t>" },
2755 { ">", "<t><!-->--></t>" },
2756 { "\"", "<t><!--\"--></t>" },
2757 { "&", "<t><!--&--></t>" },
2758 { "'", "<t><!--'--></t>" },
2763 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2764 ok( hr
== S_OK
, "got %08x\n", hr
);
2766 for (i
= 0; i
< ARRAY_SIZE( tests_elem
); i
++)
2768 hr
= set_output( writer
);
2769 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2770 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2771 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2773 utf8
.value
.bytes
= (BYTE
*)tests_elem
[i
].text
;
2774 utf8
.value
.length
= strlen( tests_elem
[i
].text
);
2775 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2776 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2778 hr
= WsWriteEndElement( writer
, NULL
);
2779 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2780 check_output( writer
, tests_elem
[i
].result
, __LINE__
);
2783 for (i
= 0; i
< ARRAY_SIZE( tests_attr
); i
++)
2785 hr
= set_output( writer
);
2786 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2787 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2788 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2790 hr
= WsWriteStartAttribute( writer
, NULL
, &localname
, &ns
, tests_attr
[i
].single
, NULL
);
2791 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2793 utf8
.value
.bytes
= (BYTE
*)tests_attr
[i
].text
;
2794 utf8
.value
.length
= strlen( tests_attr
[i
].text
);
2795 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2796 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2798 hr
= WsWriteEndAttribute( writer
, NULL
);
2799 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2801 hr
= WsWriteEndElement( writer
, NULL
);
2802 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2803 check_output( writer
, tests_attr
[i
].result
, __LINE__
);
2806 for (i
= 0; i
< ARRAY_SIZE( tests_cdata
); i
++)
2808 hr
= set_output( writer
);
2809 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2810 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2811 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2813 hr
= WsWriteStartCData( writer
, NULL
);
2814 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2816 utf8
.value
.bytes
= (BYTE
*)tests_cdata
[i
].text
;
2817 utf8
.value
.length
= strlen( tests_cdata
[i
].text
);
2818 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
2819 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2821 hr
= WsWriteEndCData( writer
, NULL
);
2822 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2824 hr
= WsWriteEndElement( writer
, NULL
);
2825 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2826 check_output( writer
, tests_cdata
[i
].result
, __LINE__
);
2829 for (i
= 0; i
< ARRAY_SIZE( tests_comment
); i
++)
2831 WS_XML_COMMENT_NODE comment
= {{WS_XML_NODE_TYPE_COMMENT
}};
2833 hr
= set_output( writer
);
2834 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2835 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2836 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2838 comment
.value
.bytes
= (BYTE
*)tests_comment
[i
].text
;
2839 comment
.value
.length
= strlen( tests_comment
[i
].text
);
2840 hr
= WsWriteNode( writer
, &comment
.node
, NULL
);
2841 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2843 hr
= WsWriteEndElement( writer
, NULL
);
2844 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2845 check_output( writer
, tests_comment
[i
].result
, __LINE__
);
2848 WsFreeWriter( writer
);
2851 static void test_write_option(void)
2853 static const WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2854 WS_XML_WRITER
*writer
;
2855 int val_int
= -1, val_int_zero
= 0, *ptr_int
= &val_int
, *ptr_int_null
= NULL
;
2856 const WCHAR
*ptr_wsz
= L
"s", *ptr_wsz_null
= NULL
;
2857 static const WS_XML_STRING val_xmlstr
= {1, (BYTE
*)"x"}, val_xmlstr_zero
= {0, NULL
};
2858 const WS_XML_STRING
*ptr_xmlstr
= &val_xmlstr
, *ptr_xmlstr_null
= NULL
;
2862 WS_WRITE_OPTION option
;
2870 { WS_INT32_TYPE
, 0, NULL
, 0, E_INVALIDARG
},
2871 { WS_INT32_TYPE
, 0, "str", 0, E_INVALIDARG
},
2872 { WS_INT32_TYPE
, 0, NULL
, sizeof(val_int
), E_INVALIDARG
},
2873 { WS_INT32_TYPE
, 0, &val_int
, sizeof(val_int
), E_INVALIDARG
},
2874 { WS_INT32_TYPE
, 0, &val_int_zero
, sizeof(val_int_zero
), E_INVALIDARG
},
2875 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, 0, E_INVALIDARG
},
2876 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_int
, 0, E_INVALIDARG
},
2877 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, sizeof(val_int
), E_INVALIDARG
},
2878 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_int
, sizeof(val_int
), S_OK
, "<t>-1</t>" },
2879 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_int_zero
, sizeof(val_int_zero
), S_OK
, "<t>0</t>" },
2880 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, NULL
, 0, E_INVALIDARG
},
2881 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_int
, 0, E_INVALIDARG
},
2882 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, NULL
, sizeof(val_int
), E_INVALIDARG
},
2883 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_int
, sizeof(val_int
), E_INVALIDARG
},
2884 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_int_zero
, sizeof(val_int_zero
), E_INVALIDARG
},
2885 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, E_INVALIDARG
},
2886 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_int
, 0, E_INVALIDARG
},
2887 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(ptr_int
), E_INVALIDARG
},
2888 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_int
, sizeof(ptr_int
), S_OK
, "<t>-1</t>" },
2889 { WS_INT32_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_int_null
, sizeof(ptr_int_null
), E_INVALIDARG
},
2890 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, 0, E_INVALIDARG
},
2891 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_int
, 0, E_INVALIDARG
},
2892 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, sizeof(ptr_int
), E_INVALIDARG
},
2893 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_int
, sizeof(ptr_int
), S_OK
, "<t>-1</t>" },
2894 { WS_INT32_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_int_null
, sizeof(ptr_int_null
), S_OK
,
2895 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2896 { WS_XML_STRING_TYPE
, 0, NULL
, 0, E_INVALIDARG
},
2897 { WS_XML_STRING_TYPE
, 0, &val_xmlstr
, 0, E_INVALIDARG
},
2898 { WS_XML_STRING_TYPE
, 0, NULL
, sizeof(val_xmlstr
), E_INVALIDARG
},
2899 { WS_XML_STRING_TYPE
, 0, &val_xmlstr
, sizeof(val_xmlstr
), E_INVALIDARG
},
2900 { WS_XML_STRING_TYPE
, 0, &val_xmlstr_zero
, sizeof(val_xmlstr_zero
), E_INVALIDARG
},
2901 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, 0, E_INVALIDARG
},
2902 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_xmlstr
, 0, E_INVALIDARG
},
2903 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, NULL
, sizeof(&val_xmlstr
), E_INVALIDARG
},
2904 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_xmlstr
, sizeof(val_xmlstr
), S_OK
, "<t>x</t>" },
2905 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_VALUE
, &val_xmlstr_zero
, sizeof(val_xmlstr_zero
), S_OK
, "<t/>" },
2906 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_xmlstr
, 0, E_INVALIDARG
},
2907 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, NULL
, sizeof(&val_xmlstr
), E_INVALIDARG
},
2908 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_xmlstr
, sizeof(&val_xmlstr
), E_INVALIDARG
},
2909 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_VALUE
, &val_xmlstr_zero
, sizeof(val_xmlstr_zero
), S_OK
,
2910 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2911 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, E_INVALIDARG
},
2912 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_xmlstr
, 0, E_INVALIDARG
},
2913 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(ptr_xmlstr
), E_INVALIDARG
},
2914 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_xmlstr
, sizeof(ptr_xmlstr
), S_OK
, "<t>x</t>" },
2915 { WS_XML_STRING_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_xmlstr_null
, sizeof(ptr_xmlstr_null
), E_INVALIDARG
},
2916 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, 0, E_INVALIDARG
},
2917 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_xmlstr
, 0, E_INVALIDARG
},
2918 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, sizeof(ptr_xmlstr
), E_INVALIDARG
},
2919 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_xmlstr
, sizeof(ptr_xmlstr
), S_OK
, "<t>x</t>" },
2920 { WS_XML_STRING_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_xmlstr_null
, sizeof(ptr_xmlstr_null
), S_OK
,
2921 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2922 { WS_WSZ_TYPE
, 0, NULL
, 0, E_INVALIDARG
},
2923 { WS_WSZ_TYPE
, 0, &ptr_wsz
, 0, E_INVALIDARG
},
2924 { WS_WSZ_TYPE
, 0, NULL
, sizeof(ptr_wsz
), E_INVALIDARG
},
2925 { WS_WSZ_TYPE
, 0, &ptr_wsz
, sizeof(ptr_wsz
), E_INVALIDARG
},
2926 { WS_WSZ_TYPE
, 0, &ptr_wsz_null
, sizeof(ptr_wsz_null
), E_INVALIDARG
},
2927 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_VALUE
, &ptr_wsz
, sizeof(ptr_wsz
), E_INVALIDARG
},
2928 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_VALUE
, &ptr_wsz
, sizeof(ptr_wsz
), E_INVALIDARG
},
2929 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, 0, E_INVALIDARG
},
2930 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_wsz
, 0, E_INVALIDARG
},
2931 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, NULL
, sizeof(ptr_wsz
), E_INVALIDARG
},
2932 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_wsz
, sizeof(ptr_wsz
), S_OK
, "<t>s</t>" },
2933 { WS_WSZ_TYPE
, WS_WRITE_REQUIRED_POINTER
, &ptr_wsz_null
, sizeof(ptr_wsz_null
), E_INVALIDARG
},
2934 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, 0, E_INVALIDARG
},
2935 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_wsz
, 0, E_INVALIDARG
},
2936 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, NULL
, sizeof(ptr_wsz
), E_INVALIDARG
},
2937 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_wsz
, sizeof(ptr_wsz
), S_OK
, "<t>s</t>" },
2938 { WS_WSZ_TYPE
, WS_WRITE_NILLABLE_POINTER
, &ptr_wsz_null
, sizeof(ptr_wsz_null
), S_OK
,
2939 "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
2944 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
2945 ok( hr
== S_OK
, "got %08x\n", hr
);
2947 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
2949 hr
= set_output( writer
);
2950 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
2951 WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
2952 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, tests
[i
].type
, NULL
, tests
[i
].option
, tests
[i
].value
,
2953 tests
[i
].size
, NULL
);
2954 ok( hr
== tests
[i
].hr
, "%u: got %08x\n", i
, hr
);
2955 WsWriteEndElement( writer
, NULL
);
2956 if (hr
== S_OK
) check_output( writer
, tests
[i
].result
, __LINE__
);
2959 WsFreeWriter( writer
);
2962 static BOOL
check_result( WS_XML_WRITER
*writer
, const char *expected
)
2965 ULONG size
= sizeof(bytes
);
2966 int len
= strlen( expected
);
2968 memset( &bytes
, 0, sizeof(bytes
) );
2969 WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
2970 if (bytes
.length
!= len
) return FALSE
;
2971 return !memcmp( bytes
.bytes
, expected
, len
);
2974 static void test_datetime(void)
2976 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, ns
= {0, NULL
};
2979 unsigned __int64 ticks
;
2980 WS_DATETIME_FORMAT format
;
2983 const char *result2
;
2988 { 0, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0001-01-01T00:00:00Z</t>" },
2989 { 0, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T00:00:00+00:00</t>" },
2990 { 0, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00</t>" },
2991 { 1, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0001-01-01T00:00:00.0000001Z</t>" },
2992 { 1, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T00:00:00.0000001+00:00</t>" },
2993 { 1, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00.0000001</t>" },
2994 { 10, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00.000001</t>" },
2995 { 1000000, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:00.1</t>" },
2996 { 0x23c34600, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T00:01:00+00:00</t>" },
2997 { 0x861c46800, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T01:00:00+00:00</t>" },
2998 { 0x430e234000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T08:00:00+00:00</t>" },
2999 { 0x4b6fe7a800, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>0001-01-01T09:00:00+00:00</t>" },
3000 { 0x989680, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:00:01</t>" },
3001 { 0x23c34600, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T00:01:00</t>" },
3002 { 0x861c46800, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-01T01:00:00</t>" },
3003 { 0xc92a69c000, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0001-01-02T00:00:00</t>" },
3004 { 0x11ed178c6c000, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>0002-01-01T00:00:00</t>" },
3005 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>9999-12-31T23:59:59.9999999Z</t>" },
3006 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>9999-12-31T15:59:59.9999999-08:00</t>",
3007 "<t>9999-12-31T17:59:59.9999999-06:00</t>" /* win7 */, WS_E_INVALID_FORMAT
},
3008 { 0x2bca2875f4373fff, WS_DATETIME_FORMAT_NONE
, S_OK
, "<t>9999-12-31T23:59:59.9999999</t>" },
3009 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_UTC
, WS_E_INVALID_FORMAT
},
3010 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_LOCAL
, WS_E_INVALID_FORMAT
},
3011 { 0x2bca2875f4374000, WS_DATETIME_FORMAT_NONE
, WS_E_INVALID_FORMAT
},
3012 { 0x8d3123e7df74000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>2015-12-31T16:00:00-08:00</t>",
3013 "<t>2015-12-31T18:00:00-06:00</t>" /* win7 */ },
3014 { 0x701ce1722770000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T00:00:00+00:00</t>" },
3015 { 0x701ce5a309a4000, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T00:00:00-08:00</t>",
3016 "<t>1601-01-01T02:00:00-06:00</t>" /* win7 */ },
3017 { 0x701ce5e617c7400, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T00:30:00-08:00</t>",
3018 "<t>1601-01-01T02:30:00-06:00</t>" /* win7 */ },
3019 { 0x701ce51ced5d800, WS_DATETIME_FORMAT_LOCAL
, S_OK
, "<t>1601-01-01T07:00:00+00:00</t>",
3020 "<t>1601-01-01T01:00:00-06:00</t>" /* win7 */ },
3021 { 0, WS_DATETIME_FORMAT_NONE
+ 1, WS_E_INVALID_FORMAT
},
3022 { 0x38a080649c000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0004-02-28T00:00:00Z</t>" },
3023 { 0x38ad130b38000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>0004-02-29T00:00:00Z</t>" },
3024 { 0x8c1505f0e438000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>2000-02-29T00:00:00Z</t>" },
3025 { 0x8d46035e7870000, WS_DATETIME_FORMAT_UTC
, S_OK
, "<t>2017-03-01T00:00:00Z</t>" },
3028 WS_XML_WRITER
*writer
;
3032 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3033 ok( hr
== S_OK
, "got %08x\n", hr
);
3034 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
3036 hr
= set_output( writer
);
3037 ok( hr
== S_OK
, "got %08x\n", hr
);
3039 date
.ticks
= tests
[i
].ticks
;
3040 date
.format
= tests
[i
].format
;
3041 WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3042 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_DATETIME_TYPE
, NULL
, WS_WRITE_REQUIRED_VALUE
,
3043 &date
, sizeof(date
), NULL
);
3044 WsWriteEndElement( writer
, NULL
);
3045 ok( hr
== tests
[i
].hr
|| broken(hr
== tests
[i
].hr_broken
), "%u: got %08x\n", i
, hr
);
3046 if (hr
!= tests
[i
].hr
&& hr
== tests
[i
].hr_broken
) break;
3049 ok( check_result( writer
, tests
[i
].result
) ||
3050 (tests
[i
].result2
&& broken(check_result( writer
, tests
[i
].result2
))),
3051 "%u: wrong result\n", i
);
3055 WsFreeWriter( writer
);
3058 static void test_repeating_element(void)
3060 WS_XML_STRING localname
= {4, (BYTE
*)"test"}, ns
= {0, NULL
}, data
= {4, (BYTE
*)"data"};
3061 WS_XML_STRING val
= {3, (BYTE
*)"val"}, wrapper
= {7, (BYTE
*)"wrapper"}, structval
= {9, (BYTE
*)"structval"};
3063 WS_XML_WRITER
*writer
;
3064 WS_STRUCT_DESCRIPTION s
, s2
;
3065 WS_FIELD_DESCRIPTION f
, f2
, *fields
[1], *fields2
[1];
3066 WS_ITEM_RANGE range
;
3083 const struct value
**val
;
3087 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3088 ok( hr
== S_OK
, "got %08x\n", hr
);
3090 /* array of strings, wrapper */
3091 hr
= set_output( writer
);
3092 ok( hr
== S_OK
, "got %08x\n", hr
);
3093 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3094 ok( hr
== S_OK
, "got %08x\n", hr
);
3096 memset( &f
, 0, sizeof(f
) );
3097 f
.mapping
= WS_REPEATING_ELEMENT_FIELD_MAPPING
;
3098 f
.localName
= &wrapper
;
3100 f
.type
= WS_WSZ_TYPE
;
3101 f
.countOffset
= FIELD_OFFSET(struct test
, count
);
3102 f
.itemLocalName
= &val
;
3106 memset( &s
, 0, sizeof(s
) );
3107 s
.size
= sizeof(struct test
);
3108 s
.alignment
= TYPE_ALIGNMENT(struct test
);
3109 s
.typeLocalName
= &localname
;
3114 hr
= set_output( writer
);
3115 ok( hr
== S_OK
, "got %08x\n", hr
);
3116 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3117 ok( hr
== S_OK
, "got %08x\n", hr
);
3119 test
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test
) + 2 * sizeof(const WCHAR
*) );
3120 test
->val
= (const WCHAR
**)(test
+ 1);
3121 test
->val
[0] = L
"1";
3122 test
->val
[1] = L
"2";
3124 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
3125 WS_WRITE_REQUIRED_POINTER
, &test
, sizeof(test
), NULL
);
3126 ok( hr
== S_OK
, "got %08x\n", hr
);
3127 hr
= WsWriteEndElement( writer
, NULL
);
3128 ok( hr
== S_OK
, "got %08x\n", hr
);
3129 check_output( writer
, "<test><wrapper><val>1</val><val>2</val></wrapper></test>", __LINE__
);
3130 HeapFree( GetProcessHeap(), 0, test
);
3132 /* array of integers, no wrapper */
3133 hr
= set_output( writer
);
3134 ok( hr
== S_OK
, "got %08x\n", hr
);
3135 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3136 ok( hr
== S_OK
, "got %08x\n", hr
);
3138 f
.type
= WS_INT32_TYPE
;
3142 test2
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test2
) + 2 * sizeof(INT32
) );
3143 test2
->val
= (INT32
*)(test2
+ 1);
3147 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
3148 WS_WRITE_REQUIRED_POINTER
, &test2
, sizeof(test2
), NULL
);
3149 ok( hr
== S_OK
, "got %08x\n", hr
);
3150 hr
= WsWriteEndElement( writer
, NULL
);
3151 ok( hr
== S_OK
, "got %08x\n", hr
);
3152 check_output( writer
, "<test><val>1</val><val>2</val></test>", __LINE__
);
3154 /* item range has no effect */
3155 hr
= set_output( writer
);
3156 ok( hr
== S_OK
, "got %08x\n", hr
);
3157 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3158 ok( hr
== S_OK
, "got %08x\n", hr
);
3160 range
.minItemCount
= 0;
3161 range
.maxItemCount
= 0;
3162 f
.itemRange
= &range
;
3164 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
3165 WS_WRITE_REQUIRED_POINTER
, &test2
, sizeof(test2
), NULL
);
3166 ok( hr
== S_OK
, "got %08x\n", hr
);
3167 hr
= WsWriteEndElement( writer
, NULL
);
3168 ok( hr
== S_OK
, "got %08x\n", hr
);
3169 check_output( writer
, "<test><val>1</val><val>2</val></test>", __LINE__
);
3170 HeapFree( GetProcessHeap(), 0, test2
);
3173 hr
= set_output( writer
);
3174 ok( hr
== S_OK
, "got %08x\n", hr
);
3175 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3176 ok( hr
== S_OK
, "got %08x\n", hr
);
3178 memset( &f2
, 0, sizeof(f2
) );
3179 f2
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
3180 f2
.localName
= &data
;
3182 f2
.type
= WS_INT32_TYPE
;
3185 memset( &s2
, 0, sizeof(s2
) );
3186 s2
.size
= sizeof(struct test3
);
3187 s2
.alignment
= TYPE_ALIGNMENT(struct test3
);
3188 s2
.typeLocalName
= &structval
;
3190 s2
.fields
= fields2
;
3193 f
.type
= WS_STRUCT_TYPE
;
3194 f
.typeDescription
= &s2
;
3195 f
.localName
= &wrapper
;
3198 f
.options
= WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
;
3201 test3
= HeapAlloc( GetProcessHeap(), 0, sizeof(*test3
) + 2 * sizeof(const struct value
*) );
3202 test3
->val
= (const struct value
**)(test3
+ 1);
3203 test3
->val
[0] = &value
;
3204 test3
->val
[1] = NULL
;
3207 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
3208 WS_WRITE_REQUIRED_POINTER
, &test3
, sizeof(test3
), NULL
);
3209 ok( hr
== S_OK
, "got %08x\n", hr
);
3210 hr
= WsWriteEndElement( writer
, NULL
);
3211 ok( hr
== S_OK
, "got %08x\n", hr
);
3212 check_output( writer
, "<test><wrapper><val><data>-1</data></val><val a:nil=\"true\" "
3213 "xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></wrapper></test>", __LINE__
);
3214 HeapFree( GetProcessHeap(), 0, test3
);
3216 WsFreeWriter( writer
);
3219 static const WS_XML_STRING
*init_xmlstring( const char *src
, WS_XML_STRING
*str
)
3221 if (!src
) return NULL
;
3222 str
->length
= strlen( src
);
3223 str
->bytes
= (BYTE
*)src
;
3224 str
->dictionary
= NULL
;
3229 static void test_WsWriteQualifiedName(void)
3231 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, localname
= {1, (BYTE
*)"t"}, ns
= {2, (BYTE
*)"ns"};
3232 WS_XML_WRITER
*writer
;
3238 const char *localname
;
3244 { NULL
, NULL
, NULL
, E_INVALIDARG
, NULL
},
3245 { NULL
, "t2", NULL
, E_INVALIDARG
, NULL
},
3246 { "p2", "t2", NULL
, S_OK
, "<p:t xmlns:p=\"ns\">p2:t2" },
3247 { NULL
, "t2", "ns2", WS_E_INVALID_FORMAT
, NULL
},
3248 { NULL
, "t2", "ns", S_OK
, "<p:t xmlns:p=\"ns\">p:t2" },
3249 { "p2", "t2", "ns2", S_OK
, "<p:t xmlns:p=\"ns\">p2:t2" },
3250 { "p2", "t2", "ns", S_OK
, "<p:t xmlns:p=\"ns\">p2:t2" },
3251 { "p", "t", NULL
, S_OK
, "<p:t xmlns:p=\"ns\">p:t" },
3252 { NULL
, "t", "ns", S_OK
, "<p:t xmlns:p=\"ns\">p:t" },
3253 { "p2", "", "", S_OK
, "<p:t xmlns:p=\"ns\">p2:" },
3254 { "p2", "", "ns2", S_OK
, "<p:t xmlns:p=\"ns\">p2:" },
3255 { "p2", "t2", "", S_OK
, "<p:t xmlns:p=\"ns\">p2:t2" },
3256 { "", "t2", "", S_OK
, "<p:t xmlns:p=\"ns\">t2" },
3257 { "", "", "ns2", S_OK
, "<p:t xmlns:p=\"ns\">" },
3258 { "", "", "", S_OK
, "<p:t xmlns:p=\"ns\">" },
3261 hr
= WsWriteQualifiedName( NULL
, NULL
, NULL
, NULL
, NULL
);
3262 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
3264 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3265 ok( hr
== S_OK
, "got %08x\n", hr
);
3267 hr
= WsWriteQualifiedName( writer
, NULL
, NULL
, NULL
, NULL
);
3268 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3270 hr
= set_output( writer
);
3271 ok( hr
== S_OK
, "got %08x\n", hr
);
3273 hr
= WsWriteQualifiedName( writer
, NULL
, NULL
, NULL
, NULL
);
3274 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
3276 for (i
= 0; i
< ARRAY_SIZE( tests
); i
++)
3278 WS_XML_STRING prefix2
, localname2
, ns2
;
3279 const WS_XML_STRING
*prefix_ptr
, *localname_ptr
, *ns_ptr
;
3281 hr
= set_output( writer
);
3282 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3284 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
3285 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3287 prefix_ptr
= init_xmlstring( tests
[i
].prefix
, &prefix2
);
3288 localname_ptr
= init_xmlstring( tests
[i
].localname
, &localname2
);
3289 ns_ptr
= init_xmlstring( tests
[i
].ns
, &ns2
);
3291 hr
= WsWriteQualifiedName( writer
, prefix_ptr
, localname_ptr
, ns_ptr
, NULL
);
3292 ok( hr
== tests
[i
].hr
, "%u: got %08x\n", i
, hr
);
3293 if (tests
[i
].hr
== S_OK
&& hr
== S_OK
) check_output( writer
, tests
[i
].result
, __LINE__
);
3296 WsFreeWriter( writer
);
3299 static void test_WsWriteBytes(void)
3301 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"a"}, ns
= {0, NULL
};
3302 WS_XML_WRITER
*writer
;
3305 hr
= WsWriteBytes( NULL
, NULL
, 0, NULL
);
3306 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
3308 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3309 ok( hr
== S_OK
, "got %08x\n", hr
);
3311 hr
= WsWriteBytes( writer
, NULL
, 0, NULL
);
3312 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3314 hr
= WsWriteBytes( writer
, "test", 0, NULL
);
3315 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3317 hr
= WsWriteBytes( writer
, NULL
, 1, NULL
);
3318 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3320 hr
= WsWriteBytes( writer
, "test", sizeof("test"), NULL
);
3321 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3323 hr
= set_output( writer
);
3324 ok( hr
== S_OK
, "got %08x\n", hr
);
3326 hr
= WsWriteBytes( writer
, "test", sizeof("test"), NULL
);
3327 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
3329 hr
= set_output( writer
);
3330 ok( hr
== S_OK
, "got %08x\n", hr
);
3333 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3334 ok( hr
== S_OK
, "got %08x\n", hr
);
3336 hr
= WsWriteBytes( writer
, "test", sizeof("test"), NULL
);
3337 ok( hr
== S_OK
, "got %08x\n", hr
);
3339 hr
= WsWriteEndElement( writer
, NULL
);
3340 ok( hr
== S_OK
, "got %08x\n", hr
);
3341 check_output( writer
, "<t>dGVzdAA=</t>", __LINE__
);
3343 hr
= set_output( writer
);
3344 ok( hr
== S_OK
, "got %08x\n", hr
);
3347 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3348 ok( hr
== S_OK
, "got %08x\n", hr
);
3350 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
3351 ok( hr
== S_OK
, "got %08x\n", hr
);
3353 hr
= WsWriteBytes( writer
, "test", sizeof("test"), NULL
);
3354 ok( hr
== S_OK
, "got %08x\n", hr
);
3356 hr
= WsWriteEndAttribute( writer
, NULL
);
3357 ok( hr
== S_OK
, "got %08x\n", hr
);
3359 hr
= WsWriteEndElement( writer
, NULL
);
3360 ok( hr
== S_OK
, "got %08x\n", hr
);
3361 check_output( writer
, "<t a=\"dGVzdAA=\"/>", __LINE__
);
3363 WsFreeWriter( writer
);
3366 static void test_WsWriteChars(void)
3368 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"a"}, ns
= {0, NULL
};
3369 WS_XML_WRITER
*writer
;
3372 hr
= WsWriteChars( NULL
, NULL
, 0, NULL
);
3373 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
3375 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3376 ok( hr
== S_OK
, "got %08x\n", hr
);
3378 hr
= WsWriteChars( writer
, NULL
, 0, NULL
);
3379 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3381 hr
= WsWriteChars( writer
, L
"test", 0, NULL
);
3382 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3384 hr
= WsWriteChars( writer
, NULL
, 1, NULL
);
3385 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3387 hr
= WsWriteChars( writer
, L
"test", 4, NULL
);
3388 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3390 hr
= set_output( writer
);
3391 ok( hr
== S_OK
, "got %08x\n", hr
);
3393 hr
= WsWriteChars( writer
, L
"test", 4, NULL
);
3394 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
3396 hr
= set_output( writer
);
3397 ok( hr
== S_OK
, "got %08x\n", hr
);
3400 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3401 ok( hr
== S_OK
, "got %08x\n", hr
);
3403 hr
= WsWriteChars( writer
, L
"test", 4, NULL
);
3404 ok( hr
== S_OK
, "got %08x\n", hr
);
3406 hr
= WsWriteChars( writer
, L
"test", 4, NULL
);
3407 ok( hr
== S_OK
, "got %08x\n", hr
);
3409 hr
= WsWriteEndElement( writer
, NULL
);
3410 ok( hr
== S_OK
, "got %08x\n", hr
);
3411 check_output( writer
, "<t>testtest</t>", __LINE__
);
3413 hr
= set_output( writer
);
3414 ok( hr
== S_OK
, "got %08x\n", hr
);
3417 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3418 ok( hr
== S_OK
, "got %08x\n", hr
);
3420 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
3421 ok( hr
== S_OK
, "got %08x\n", hr
);
3423 hr
= WsWriteChars( writer
, L
"test", 4, NULL
);
3424 ok( hr
== S_OK
, "got %08x\n", hr
);
3426 hr
= WsWriteChars( writer
, L
"test", 4, NULL
);
3427 ok( hr
== S_OK
, "got %08x\n", hr
);
3429 hr
= WsWriteEndAttribute( writer
, NULL
);
3430 ok( hr
== S_OK
, "got %08x\n", hr
);
3432 hr
= WsWriteEndElement( writer
, NULL
);
3433 ok( hr
== S_OK
, "got %08x\n", hr
);
3434 check_output( writer
, "<t a=\"testtest\"/>", __LINE__
);
3436 WsFreeWriter( writer
);
3439 static void test_WsWriteCharsUtf8(void)
3441 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"a"}, ns
= {0, NULL
};
3442 static const BYTE test
[] = {'t','e','s','t'};
3443 WS_XML_WRITER
*writer
;
3446 hr
= WsWriteCharsUtf8( NULL
, NULL
, 0, NULL
);
3447 ok( hr
== E_INVALIDARG
, "got %08x\n", hr
);
3449 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3450 ok( hr
== S_OK
, "got %08x\n", hr
);
3452 hr
= WsWriteCharsUtf8( writer
, NULL
, 0, NULL
);
3453 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3455 hr
= WsWriteCharsUtf8( writer
, test
, 0, NULL
);
3456 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3458 hr
= WsWriteCharsUtf8( writer
, NULL
, 1, NULL
);
3459 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3461 hr
= WsWriteCharsUtf8( writer
, test
, sizeof(test
), NULL
);
3462 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
3464 hr
= set_output( writer
);
3465 ok( hr
== S_OK
, "got %08x\n", hr
);
3467 hr
= WsWriteCharsUtf8( writer
, test
, sizeof(test
), NULL
);
3468 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
3470 hr
= set_output( writer
);
3471 ok( hr
== S_OK
, "got %08x\n", hr
);
3474 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3475 ok( hr
== S_OK
, "got %08x\n", hr
);
3477 hr
= WsWriteCharsUtf8( writer
, test
, sizeof(test
), NULL
);
3478 ok( hr
== S_OK
, "got %08x\n", hr
);
3480 hr
= WsWriteCharsUtf8( writer
, test
, sizeof(test
), NULL
);
3481 ok( hr
== S_OK
, "got %08x\n", hr
);
3483 hr
= WsWriteEndElement( writer
, NULL
);
3484 ok( hr
== S_OK
, "got %08x\n", hr
);
3485 check_output( writer
, "<t>testtest</t>", __LINE__
);
3487 hr
= set_output( writer
);
3488 ok( hr
== S_OK
, "got %08x\n", hr
);
3491 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3492 ok( hr
== S_OK
, "got %08x\n", hr
);
3494 hr
= WsWriteStartAttribute( writer
, NULL
, &localname2
, &ns
, FALSE
, NULL
);
3495 ok( hr
== S_OK
, "got %08x\n", hr
);
3497 hr
= WsWriteCharsUtf8( writer
, test
, sizeof(test
), NULL
);
3498 ok( hr
== S_OK
, "got %08x\n", hr
);
3500 hr
= WsWriteCharsUtf8( writer
, test
, sizeof(test
), NULL
);
3501 ok( hr
== S_OK
, "got %08x\n", hr
);
3503 hr
= WsWriteEndAttribute( writer
, NULL
);
3504 ok( hr
== S_OK
, "got %08x\n", hr
);
3506 hr
= WsWriteEndElement( writer
, NULL
);
3507 ok( hr
== S_OK
, "got %08x\n", hr
);
3508 check_output( writer
, "<t a=\"testtest\"/>", __LINE__
);
3510 WsFreeWriter( writer
);
3513 static void check_output_bin( WS_XML_WRITER
*writer
, const char *expected
, int len
, unsigned int line
)
3516 ULONG size
= sizeof(bytes
);
3519 memset( &bytes
, 0, sizeof(bytes
) );
3520 hr
= WsGetWriterProperty( writer
, WS_XML_WRITER_PROPERTY_BYTES
, &bytes
, size
, NULL
);
3521 ok( hr
== S_OK
, "%u: got %08x\n", line
, hr
);
3522 ok( bytes
.length
== len
, "%u: got %u expected %u\n", line
, bytes
.length
, len
);
3523 if (bytes
.length
!= len
) return;
3524 ok( !memcmp( bytes
.bytes
, expected
, bytes
.length
), "%u: got %s expected %s\n", line
,
3525 debugstr_bytes(bytes
.bytes
, bytes
.length
), debugstr_bytes((const BYTE
*)expected
, len
) );
3528 static void test_binary_encoding(void)
3530 static const char res
[] =
3531 {0x40,0x01,'t',0x01};
3532 static const char res2
[] =
3533 {0x6d,0x01,'t',0x09,0x01,'p',0x02,'n','s',0x01};
3534 static const char res3
[] =
3535 {0x41,0x02,'p','2',0x01,'t',0x09,0x02,'p','2',0x02,'n','s',0x01};
3536 static const char res4
[] =
3537 {0x41,0x02,'p','2',0x01,'t',0x09,0x02,'p','2',0x02,'n','s',0x99,0x04,'t','e','s','t'};
3538 static const char res100
[] =
3539 {0x40,0x01,'t',0x04,0x01,'t',0x98,0x00,0x01};
3540 static const char res101
[] =
3541 {0x40,0x01,'t',0x35,0x01,'t',0x98,0x00,0x09,0x01,'p',0x02,'n','s',0x01};
3542 static const char res102
[] =
3543 {0x40,0x01,'t',0x05,0x02,'p','2',0x01,'t',0x98,0x00,0x09,0x02,'p','2',0x02,'n','s',0x01};
3544 static const char res103
[] =
3545 {0x40,0x01,'t',0x05,0x02,'p','2',0x01,'t',0x98,0x04,'t','e','s','t',0x09,0x02,'p','2',0x02,'n','s',0x01};
3546 static const char res200
[] =
3547 {0x02,0x07,'c','o','m','m','e','n','t'};
3548 WS_XML_WRITER_BINARY_ENCODING bin
= {{WS_XML_WRITER_ENCODING_TYPE_BINARY
}};
3549 WS_XML_WRITER_BUFFER_OUTPUT buf
= {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER
}};
3550 static const char prefix
[] = "p", prefix2
[] = "p2";
3551 static const char localname
[] = "t", ns
[] = "ns";
3552 const WS_XML_STRING
*prefix_ptr
, *localname_ptr
, *ns_ptr
;
3553 WS_XML_STRING str
, str2
, str3
, localname2
= {1, (BYTE
*)"t"}, empty
= {0, NULL
};
3554 WS_XML_UTF8_TEXT utf8
= {{WS_XML_TEXT_TYPE_UTF8
}};
3555 WS_XML_COMMENT_NODE comment
= {{WS_XML_NODE_TYPE_COMMENT
}};
3556 WS_XML_WRITER
*writer
;
3562 const char *localname
;
3570 { NULL
, localname
, "", NULL
, res
, sizeof(res
) }, /* short element */
3571 { prefix
, localname
, ns
, NULL
, res2
, sizeof(res2
) }, /* one character prefix element */
3572 { prefix2
, localname
, ns
, NULL
, res3
, sizeof(res3
) }, /* element */
3573 { prefix2
, localname
, ns
, "test", res4
, sizeof(res4
) }, /* element with text */
3578 const char *localname
;
3586 { NULL
, localname
, "", NULL
, res100
, sizeof(res100
) }, /* short attribute */
3587 { prefix
, localname
, ns
, NULL
, res101
, sizeof(res101
) }, /* one character prefix attribute */
3588 { prefix2
, localname
, ns
, NULL
, res102
, sizeof(res102
) }, /* attribute */
3589 { prefix2
, localname
, ns
, "test", res103
, sizeof(res103
) }, /* attribute with value */
3592 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3593 ok( hr
== S_OK
, "got %08x\n", hr
);
3595 for (i
= 0; i
< ARRAY_SIZE( elem_tests
); i
++)
3597 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3598 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3600 prefix_ptr
= init_xmlstring( elem_tests
[i
].prefix
, &str
);
3601 localname_ptr
= init_xmlstring( elem_tests
[i
].localname
, &str2
);
3602 ns_ptr
= init_xmlstring( elem_tests
[i
].ns
, &str3
);
3604 hr
= WsWriteStartElement( writer
, prefix_ptr
, localname_ptr
, ns_ptr
, NULL
);
3605 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3606 if (elem_tests
[i
].text
)
3608 utf8
.value
.length
= strlen( elem_tests
[i
].text
);
3609 utf8
.value
.bytes
= (BYTE
*)elem_tests
[i
].text
;
3610 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
3611 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3613 hr
= WsWriteEndElement( writer
, NULL
);
3614 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3615 if (hr
== S_OK
) check_output_bin( writer
, elem_tests
[i
].result
, elem_tests
[i
].len_result
, __LINE__
);
3618 for (i
= 0; i
< ARRAY_SIZE( attr_tests
); i
++)
3620 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3621 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3623 prefix_ptr
= init_xmlstring( attr_tests
[i
].prefix
, &str
);
3624 localname_ptr
= init_xmlstring( attr_tests
[i
].localname
, &str2
);
3625 ns_ptr
= init_xmlstring( elem_tests
[i
].ns
, &str3
);
3627 hr
= WsWriteStartElement( writer
, NULL
, &localname2
, &empty
, NULL
);
3628 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3629 hr
= WsWriteStartAttribute( writer
, prefix_ptr
, localname_ptr
, ns_ptr
, FALSE
, NULL
);
3630 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3631 if (attr_tests
[i
].value
)
3633 utf8
.value
.length
= strlen( attr_tests
[i
].value
);
3634 utf8
.value
.bytes
= (BYTE
*)attr_tests
[i
].value
;
3635 hr
= WsWriteText( writer
, &utf8
.text
, NULL
);
3636 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3638 hr
= WsWriteEndAttribute( writer
, NULL
);
3639 ok( hr
== S_OK
, "got %08x\n", hr
);
3640 hr
= WsWriteEndElement( writer
, NULL
);
3641 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3642 if (hr
== S_OK
) check_output_bin( writer
, attr_tests
[i
].result
, attr_tests
[i
].len_result
, __LINE__
);
3645 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3646 ok( hr
== S_OK
, "got %08x\n", hr
);
3648 comment
.value
.bytes
= (BYTE
*)"comment";
3649 comment
.value
.length
= sizeof("comment") - 1;
3650 hr
= WsWriteNode( writer
, &comment
.node
, NULL
);
3651 ok( hr
== S_OK
, "got %08x\n", hr
);
3652 if (hr
== S_OK
) check_output_bin( writer
, res200
, sizeof(res200
), __LINE__
);
3654 WsFreeWriter( writer
);
3657 static void test_namespaces(void)
3659 WS_XML_STRING prefix
= {1, (BYTE
*)"p"}, prefix2
= {1, (BYTE
*)"q"};
3660 WS_XML_STRING localname
= {1, (BYTE
*)"t"}, localname2
= {1, (BYTE
*)"a"};
3661 WS_XML_STRING ns
= {1, (BYTE
*)"n"}, ns2
= {1, (BYTE
*)"o"};
3662 WS_XML_WRITER
*writer
;
3665 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3666 ok( hr
== S_OK
, "got %08x\n", hr
);
3668 hr
= set_output( writer
);
3669 ok( hr
== S_OK
, "got %08x\n", hr
);
3670 hr
= WsWriteStartElement( writer
, &prefix
, &localname
, &ns
, NULL
);
3671 ok( hr
== S_OK
, "got %08x\n", hr
);
3672 hr
= WsWriteStartAttribute( writer
, &prefix2
, &localname2
, &ns2
, FALSE
, NULL
);
3673 ok( hr
== S_OK
, "got %08x\n", hr
);
3674 hr
= WsWriteEndAttribute( writer
, NULL
);
3675 ok( hr
== S_OK
, "got %08x\n", hr
);
3676 hr
= WsWriteEndElement( writer
, NULL
);
3677 ok( hr
== S_OK
, "got %08x\n", hr
);
3678 check_output( writer
, "<p:t q:a=\"\" xmlns:p=\"n\" xmlns:q=\"o\"/>", __LINE__
);
3680 WsFreeWriter( writer
);
3683 static const WS_XML_STRING
*init_xmlstring_dict( WS_XML_DICTIONARY
*dict
, ULONG id
, WS_XML_STRING
*str
)
3685 if (id
>= dict
->stringCount
) return NULL
;
3686 str
->length
= dict
->strings
[id
].length
;
3687 str
->bytes
= dict
->strings
[id
].bytes
;
3688 str
->dictionary
= dict
;
3693 static HRESULT CALLBACK
dict_cb( void *state
, const WS_XML_STRING
*str
, BOOL
*found
, ULONG
*id
, WS_ERROR
*error
)
3695 ULONG
*call_count
= state
;
3698 switch (str
->bytes
[0])
3726 static void test_dictionary(void)
3728 static const char res
[] =
3730 static const char res2
[] =
3732 static const char res3
[] =
3733 {0x53,0x06,0x0b,0x01,'p',0x0a,0x01};
3734 static const char res4
[] =
3735 {0x43,0x02,'p','2',0x06,0x0b,0x02,'p','2',0x0a,0x01};
3736 static const char res5
[] =
3737 {0x42,0x03,0x0a,0x05,0x01};
3738 static const char res6
[] =
3739 {0x40,0x01,0x75,0x0a,0x05,0x01};
3740 static const char res7
[] =
3741 {0x40,0x01,0x76,0x0a,0x05,0x01};
3742 static const char res8
[] =
3743 {0x42,0x03,0x0a,0x05,0x01};
3744 static const char res9
[] =
3745 {0x42,0x07,0x0a,0x05,0x01};
3746 static const char res10
[] =
3747 {0x42,0xd6,0x03,0x0a,0x05,0x01};
3748 static const char res100
[] =
3749 {0x42,0x06,0x06,0x06,0x98,0x00,0x01};
3750 static const char res101
[] =
3751 {0x42,0x06,0x1b,0x06,0x98,0x00,0x0b,0x01,'p',0x0a,0x01};
3752 static const char res102
[] =
3753 {0x42,0x06,0x07,0x02,'p','2',0x06,0x98,0x00,0x0b,0x02,'p','2',0x0a,0x01};
3754 WS_XML_WRITER_BINARY_ENCODING bin
= {{WS_XML_WRITER_ENCODING_TYPE_BINARY
}};
3755 WS_XML_WRITER_BUFFER_OUTPUT buf
= {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER
}};
3756 WS_XML_STRING prefix
, localname
, ns
, strings
[6];
3757 const WS_XML_STRING
*prefix_ptr
, *localname_ptr
, *ns_ptr
;
3758 WS_XML_DICTIONARY dict
, *dict_builtin
;
3759 WS_XML_WRITER
*writer
;
3761 ULONG i
, call_count
;
3772 { ~0u, 2, 0, res
, sizeof(res
) }, /* short dictionary element, invalid dict id */
3773 { ~0u, 3, 0, res2
, sizeof(res2
) }, /* short dictionary element */
3774 { 1, 3, 5, res3
, sizeof(res3
) }, /* single character prefix dictionary element */
3775 { 4, 3, 5, res4
, sizeof(res4
) }, /* dictionary element */
3787 { ~0u, 3, 0, res100
, sizeof(res100
) }, /* short dictionary attribute */
3788 { 1, 3, 5, res101
, sizeof(res101
) }, /* single character prefix dictionary attribute */
3789 { 4, 3, 5, res102
, sizeof(res102
) }, /* dictionary attribute */
3792 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3793 ok( hr
== S_OK
, "got %08x\n", hr
);
3795 strings
[0].length
= 0;
3796 strings
[0].bytes
= NULL
;
3797 strings
[0].dictionary
= &dict
;
3799 strings
[1].length
= 1;
3800 strings
[1].bytes
= (BYTE
*)"p";
3801 strings
[1].dictionary
= &dict
;
3803 strings
[2].length
= 1;
3804 strings
[2].bytes
= (BYTE
*)"t";
3805 strings
[2].dictionary
= &dict
;
3806 strings
[2].id
= ~0u;
3807 strings
[3].length
= 1;
3808 strings
[3].bytes
= (BYTE
*)"u";
3809 strings
[3].dictionary
= &dict
;
3811 strings
[4].length
= 2;
3812 strings
[4].bytes
= (BYTE
*)"p2";
3813 strings
[4].dictionary
= &dict
;
3815 strings
[5].length
= 2;
3816 strings
[5].bytes
= (BYTE
*)"ns";
3817 strings
[5].dictionary
= &dict
;
3820 UuidCreate( &dict
.guid
);
3821 dict
.strings
= strings
;
3822 dict
.stringCount
= ARRAY_SIZE( strings
);
3823 dict
.isConst
= TRUE
;
3825 bin
.staticDictionary
= &dict
;
3827 for (i
= 0; i
< ARRAY_SIZE( elem_tests
); i
++)
3829 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3830 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3832 prefix_ptr
= init_xmlstring_dict( &dict
, elem_tests
[i
].prefix
, &prefix
);
3833 localname_ptr
= init_xmlstring_dict( &dict
, elem_tests
[i
].localname
, &localname
);
3834 ns_ptr
= init_xmlstring_dict( &dict
, elem_tests
[i
].ns
, &ns
);
3836 hr
= WsWriteStartElement( writer
, prefix_ptr
, localname_ptr
, ns_ptr
, NULL
);
3837 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3838 hr
= WsWriteEndElement( writer
, NULL
);
3839 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3840 if (hr
== S_OK
) check_output_bin( writer
, elem_tests
[i
].result
, elem_tests
[i
].len_result
, __LINE__
);
3843 for (i
= 0; i
< ARRAY_SIZE( attr_tests
); i
++)
3845 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3846 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3848 prefix_ptr
= init_xmlstring_dict( &dict
, attr_tests
[i
].prefix
, &prefix
);
3849 localname_ptr
= init_xmlstring_dict( &dict
, attr_tests
[i
].localname
, &localname
);
3850 ns_ptr
= init_xmlstring_dict( &dict
, attr_tests
[i
].ns
, &ns
);
3852 hr
= WsWriteStartElement( writer
, NULL
, &strings
[3], &strings
[0], NULL
);
3853 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3854 hr
= WsWriteStartAttribute( writer
, prefix_ptr
, localname_ptr
, ns_ptr
, FALSE
, NULL
);
3855 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3856 hr
= WsWriteEndAttribute( writer
, NULL
);
3857 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3858 hr
= WsWriteEndElement( writer
, NULL
);
3859 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
3860 if (hr
== S_OK
) check_output_bin( writer
, attr_tests
[i
].result
, attr_tests
[i
].len_result
, __LINE__
);
3864 bin
.staticDictionary
= NULL
;
3865 bin
.dynamicStringCallback
= dict_cb
;
3866 bin
.dynamicStringCallbackState
= &call_count
;
3868 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3869 ok( hr
== S_OK
, "got %08x\n", hr
);
3870 init_xmlstring( "t", &localname
);
3871 init_xmlstring( "ns", &ns
);
3873 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3874 ok( hr
== S_OK
, "got %08x\n", hr
);
3875 hr
= WsWriteEndElement( writer
, NULL
);
3876 ok( hr
== S_OK
, "got %08x\n", hr
);
3877 ok( call_count
== 2, "got %u\n", call_count
);
3878 check_output_bin( writer
, res5
, sizeof(res5
), __LINE__
);
3880 /* unknown string */
3881 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3882 ok( hr
== S_OK
, "got %08x\n", hr
);
3883 init_xmlstring( "u", &localname
);
3884 init_xmlstring( "ns", &ns
);
3886 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3887 ok( hr
== S_OK
, "got %08x\n", hr
);
3888 hr
= WsWriteEndElement( writer
, NULL
);
3889 ok( hr
== S_OK
, "got %08x\n", hr
);
3890 ok( call_count
== 2, "got %u\n", call_count
);
3891 check_output_bin( writer
, res6
, sizeof(res6
), __LINE__
);
3893 /* unknown string, error return from callback */
3894 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3895 ok( hr
== S_OK
, "got %08x\n", hr
);
3896 init_xmlstring( "v", &localname
);
3897 init_xmlstring( "ns", &ns
);
3899 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3900 ok( hr
== S_OK
, "got %08x\n", hr
);
3901 hr
= WsWriteEndElement( writer
, NULL
);
3902 ok( hr
== S_OK
, "got %08x\n", hr
);
3903 ok( call_count
== 2, "got %u\n", call_count
);
3904 check_output_bin( writer
, res7
, sizeof(res7
), __LINE__
);
3906 /* dictionary and callback */
3907 hr
= WsGetDictionary( WS_ENCODING_XML_BINARY_1
, &dict_builtin
, NULL
);
3908 ok( hr
== S_OK
, "got %08x\n", hr
);
3909 bin
.staticDictionary
= dict_builtin
;
3911 /* string in dictionary, no string dictionary set */
3912 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3913 ok( hr
== S_OK
, "got %08x\n", hr
);
3914 init_xmlstring( "t", &localname
);
3915 init_xmlstring( "ns", &ns
);
3917 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3918 ok( hr
== S_OK
, "got %08x\n", hr
);
3919 hr
= WsWriteEndElement( writer
, NULL
);
3920 ok( hr
== S_OK
, "got %08x\n", hr
);
3921 ok( call_count
== 2, "got %u\n", call_count
);
3922 check_output_bin( writer
, res8
, sizeof(res8
), __LINE__
);
3924 /* string not in dictionary, no string dictionary set */
3925 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3926 ok( hr
== S_OK
, "got %08x\n", hr
);
3927 init_xmlstring( "z", &localname
);
3928 init_xmlstring( "ns", &ns
);
3930 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3931 ok( hr
== S_OK
, "got %08x\n", hr
);
3932 hr
= WsWriteEndElement( writer
, NULL
);
3933 ok( hr
== S_OK
, "got %08x\n", hr
);
3934 ok( call_count
== 2, "got %u\n", call_count
);
3935 check_output_bin( writer
, res9
, sizeof(res9
), __LINE__
);
3937 /* string in dictionary, string dictionary set */
3938 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
3939 ok( hr
== S_OK
, "got %08x\n", hr
);
3940 init_xmlstring_dict( dict_builtin
, 235, &localname
);
3941 init_xmlstring( "ns", &ns
);
3943 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
3944 ok( hr
== S_OK
, "got %08x\n", hr
);
3945 hr
= WsWriteEndElement( writer
, NULL
);
3946 ok( hr
== S_OK
, "got %08x\n", hr
);
3947 ok( call_count
== 1, "got %u\n", call_count
);
3948 check_output_bin( writer
, res10
, sizeof(res10
), __LINE__
);
3950 WsFreeWriter( writer
);
3953 static void test_union_type(void)
3955 static WS_XML_STRING str_ns
= {0, NULL
}, str_a
= {1, (BYTE
*)"a"}, str_b
= {1, (BYTE
*)"b"};
3956 static WS_XML_STRING str_none
= {4, (BYTE
*)"none"}, str_s
= {1, (BYTE
*)"s"}, str_t
= {1, (BYTE
*)"t"};
3958 WS_XML_WRITER
*writer
;
3959 WS_UNION_DESCRIPTION u
;
3960 WS_UNION_FIELD_DESCRIPTION f
, f2
, f3
, *fields
[3];
3961 WS_FIELD_DESCRIPTION f_struct
, *fields_struct
[1];
3962 WS_STRUCT_DESCRIPTION s
;
3963 enum choice
{CHOICE_A
= 30, CHOICE_B
= 20, CHOICE_C
= 10, CHOICE_NONE
= 0};
3964 ULONG index
[2] = {1, 0};
3976 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
3977 ok( hr
== S_OK
, "got %08x\n", hr
);
3979 memset( &f
, 0, sizeof(f
) );
3981 f
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
3982 f
.field
.localName
= &str_a
;
3983 f
.field
.ns
= &str_ns
;
3984 f
.field
.type
= WS_WSZ_TYPE
;
3985 f
.field
.offset
= FIELD_OFFSET(struct test
, value
.a
);
3988 memset( &f2
, 0, sizeof(f2
) );
3989 f2
.value
= CHOICE_B
;
3990 f2
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
3991 f2
.field
.localName
= &str_b
;
3992 f2
.field
.ns
= &str_ns
;
3993 f2
.field
.type
= WS_UINT32_TYPE
;
3994 f2
.field
.offset
= FIELD_OFFSET(struct test
, value
.b
);
3997 memset( &u
, 0, sizeof(u
) );
3998 u
.size
= sizeof(struct test
);
3999 u
.alignment
= TYPE_ALIGNMENT(struct test
);
4002 u
.enumOffset
= FIELD_OFFSET(struct test
, choice
);
4003 u
.noneEnumValue
= CHOICE_NONE
;
4005 memset( &f_struct
, 0, sizeof(f_struct
) );
4006 f_struct
.mapping
= WS_ELEMENT_CHOICE_FIELD_MAPPING
;
4007 f_struct
.type
= WS_UNION_TYPE
;
4008 f_struct
.typeDescription
= &u
;
4009 fields_struct
[0] = &f_struct
;
4011 memset( &s
, 0, sizeof(s
) );
4012 s
.size
= sizeof(struct test
);
4013 s
.alignment
= TYPE_ALIGNMENT(struct test
);
4014 s
.fields
= fields_struct
;
4016 s
.typeLocalName
= &str_s
;
4019 hr
= set_output( writer
);
4020 ok( hr
== S_OK
, "got %08x\n", hr
);
4021 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4022 ok( hr
== S_OK
, "got %08x\n", hr
);
4023 test
.choice
= CHOICE_A
;
4024 test
.value
.a
= L
"test";
4025 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4026 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4027 ok( hr
== S_OK
, "got %08x\n", hr
);
4028 hr
= WsWriteEndElement( writer
, NULL
);
4029 ok( hr
== S_OK
, "got %08x\n", hr
);
4030 check_output( writer
, "<t><a>test</a></t>", __LINE__
);
4032 u
.valueIndices
= index
;
4033 hr
= set_output( writer
);
4034 ok( hr
== S_OK
, "got %08x\n", hr
);
4035 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4036 ok( hr
== S_OK
, "got %08x\n", hr
);
4037 test
.choice
= CHOICE_B
;
4039 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4040 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4041 ok( hr
== S_OK
, "got %08x\n", hr
);
4042 hr
= WsWriteEndElement( writer
, NULL
);
4043 ok( hr
== S_OK
, "got %08x\n", hr
);
4044 check_output( writer
, "<t><b>123</b></t>", __LINE__
);
4046 hr
= set_output( writer
);
4047 ok( hr
== S_OK
, "got %08x\n", hr
);
4048 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4049 ok( hr
== S_OK
, "got %08x\n", hr
);
4050 test
.choice
= CHOICE_C
;
4051 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4052 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4053 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
4055 hr
= set_output( writer
);
4056 ok( hr
== S_OK
, "got %08x\n", hr
);
4057 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4058 ok( hr
== S_OK
, "got %08x\n", hr
);
4059 test
.choice
= CHOICE_NONE
;
4060 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4061 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4062 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
4064 /* field value equals noneEnumValue */
4065 memset( &f3
, 0, sizeof(f3
) );
4066 f3
.value
= CHOICE_NONE
;
4067 f3
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4068 f3
.field
.localName
= &str_none
;
4069 f3
.field
.ns
= &str_ns
;
4070 f3
.field
.type
= WS_BOOL_TYPE
;
4071 f3
.field
.offset
= FIELD_OFFSET(struct test
, value
.none
);
4075 u
.valueIndices
= NULL
;
4076 hr
= set_output( writer
);
4077 ok( hr
== S_OK
, "got %08x\n", hr
);
4078 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4079 ok( hr
== S_OK
, "got %08x\n", hr
);
4080 test
.choice
= CHOICE_NONE
;
4081 test
.value
.none
= TRUE
;
4082 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4083 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4084 ok( hr
== S_OK
, "got %08x\n", hr
);
4085 hr
= WsWriteEndElement( writer
, NULL
);
4086 ok( hr
== S_OK
, "got %08x\n", hr
);
4087 check_output( writer
, "<t><none>true</none></t>", __LINE__
);
4089 hr
= set_output( writer
);
4090 ok( hr
== S_OK
, "got %08x\n", hr
);
4091 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4092 ok( hr
== S_OK
, "got %08x\n", hr
);
4093 f_struct
.options
= WS_FIELD_OPTIONAL
;
4094 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4095 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4096 ok( hr
== S_OK
, "got %08x\n", hr
);
4097 hr
= WsWriteEndElement( writer
, NULL
);
4098 ok( hr
== S_OK
, "got %08x\n", hr
);
4099 check_output( writer
, "<t/>", __LINE__
);
4101 WsFreeWriter( writer
);
4104 static void prepare_binary_type_test( WS_XML_WRITER
*writer
, const WS_XML_STRING
*prefix
,
4105 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4107 WS_XML_WRITER_BINARY_ENCODING bin
= {{WS_XML_WRITER_ENCODING_TYPE_BINARY
}};
4108 WS_XML_WRITER_BUFFER_OUTPUT buf
= {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER
}};
4111 hr
= WsSetOutput( writer
, &bin
.encoding
, &buf
.output
, NULL
, 0, NULL
);
4112 ok( hr
== S_OK
, "got %08x\n", hr
);
4113 hr
= WsWriteStartElement( writer
, prefix
, localname
, ns
, NULL
);
4114 ok( hr
== S_OK
, "got %08x\n", hr
);
4117 static void test_text_types_binary(void)
4119 static WS_XML_STRING str_s
= {1, (BYTE
*)"s"}, str_t
= {1, (BYTE
*)"t"}, str_u
= {1, (BYTE
*)"u"};
4120 static WS_XML_STRING str_ns
= {0, NULL
};
4121 static const char res
[] =
4122 {0x40,0x01,'t',0x40,0x01,'u',0x99,0x04,'t','e','s','t',0x01};
4123 static const char res2
[] =
4124 {0x40,0x01,'t',0x40,0x01,'u',0x9e,0x03,'t','e','s',0x9f,0x01,'t',0x01};
4125 static const char res2a
[] =
4126 {0x40,0x01,'t',0x40,0x01,'u',0x9f,0x03,'t','e','s',0x01};
4127 static const char res2b
[] =
4128 {0x40,0x01,'t',0x40,0x01,'u',0x9f,0x01,'t',0x01};
4129 static const char res2c
[] =
4130 {0x40,0x01,'t',0x40,0x01,'u',0x01,0x01};
4131 static const char res2d
[] =
4132 {0x40,0x01,'t',0x40,0x01,'u',0x9f,0xff,'a','a','a','a','a','a','a','a','a','a',
4133 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4134 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4135 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4136 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4137 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4138 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4139 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4140 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4141 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4142 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4143 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4144 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4145 'a','a','a','a','a',0x01};
4146 static const char res2e
[] =
4147 {0x40,0x01,'t',0x40,0x01,'u',0x9e,0xff,'a','a','a','a','a','a','a','a','a','a',
4148 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4149 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4150 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4151 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4152 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4153 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4154 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4155 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4156 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4157 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4158 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4159 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4160 'a','a','a','a','a',0x9f,0x01,'a',0x01};
4161 static const char res2f
[] =
4162 {0x40,0x01,'t',0x40,0x01,'u',0x9f,0x06,'t','e','s','t','t','e',0x01};
4163 static const char res3
[] =
4164 {0x40,0x01,'t',0x40,0x01,'u',0x87,0x01};
4165 static const char res4
[] =
4166 {0x40,0x01,'t',0x40,0x01,'u',0x89,0xff,0x01};
4167 static const char res5
[] =
4168 {0x40,0x01,'t',0x40,0x01,'u',0x83,0x01};
4169 static const char res5b
[] =
4170 {0x40,0x01,'t',0x40,0x01,'u',0x89,0x02,0x01};
4171 static const char res6
[] =
4172 {0x40,0x01,'t',0x40,0x01,'u',0x81,0x01};
4173 static const char res7
[] =
4174 {0x40,0x01,'t',0x40,0x01,'u',0x89,0x02,0x01};
4175 static const char res8
[] =
4176 {0x40,0x01,'t',0x40,0x01,'u',0x93,0xcd,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x40,0x01};
4177 static const char res8a
[] =
4178 {0x40,0x01,'t',0x40,0x01,'u',0x93,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x7f,0x01};
4179 static const char res8b
[] =
4180 {0x40,0x01,'t',0x40,0x01,'u',0x93,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x01};
4181 static const char res8c
[] =
4182 {0x40,0x01,'t',0x40,0x01,'u',0x93,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x7f,0x01};
4183 static const char res9
[] =
4184 {0x40,0x01,'t',0x40,0x01,'u',0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
4185 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
4186 static const char res10
[] =
4187 {0x40,0x01,'t',0x40,0x01,'u',0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
4188 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
4189 static const char res11
[] =
4190 {0x40,0x01,'t',0x40,0x01,'u',0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01};
4191 static const char res11b
[] =
4192 {0x40,0x01,'t',0x40,0x01,'u',0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01};
4193 static const char res11c
[] =
4194 {0x40,0x01,'t',0x40,0x01,'u',0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
4195 static const char res11d
[] =
4196 {0x40,0x01,'t',0x40,0x01,'u',0x97,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01};
4198 WS_XML_WRITER
*writer
;
4199 WS_UNION_DESCRIPTION u
;
4200 WS_UNION_FIELD_DESCRIPTION f
, f2
, f3
, f4
, f5
, f6
, f7
, f8
, f9
, f10
, f11
, *fields
[11];
4201 WS_FIELD_DESCRIPTION f_struct
, *fields_struct
[1];
4202 WS_STRUCT_DESCRIPTION s
;
4205 WS_XML_TEXT_TYPE type
;
4208 WS_XML_STRING val_utf8
;
4209 WS_STRING val_utf16
;
4217 WS_UNIQUE_ID val_unique_id
;
4218 WS_DATETIME val_datetime
;
4223 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
4224 ok( hr
== S_OK
, "got %08x\n", hr
);
4226 memset( &f
, 0, sizeof(f
) );
4227 f
.value
= WS_XML_TEXT_TYPE_UTF8
;
4228 f
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4229 f
.field
.localName
= &str_u
;
4230 f
.field
.ns
= &str_ns
;
4231 f
.field
.type
= WS_XML_STRING_TYPE
;
4232 f
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_utf8
);
4235 memset( &f2
, 0, sizeof(f2
) );
4236 f2
.value
= WS_XML_TEXT_TYPE_UTF16
;
4237 f2
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4238 f2
.field
.localName
= &str_u
;
4239 f2
.field
.ns
= &str_ns
;
4240 f2
.field
.type
= WS_STRING_TYPE
;
4241 f2
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_utf16
);
4244 memset( &f3
, 0, sizeof(f3
) );
4245 f3
.value
= WS_XML_TEXT_TYPE_BASE64
;
4246 f3
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4247 f3
.field
.localName
= &str_u
;
4248 f3
.field
.ns
= &str_ns
;
4249 f3
.field
.type
= WS_BYTES_TYPE
;
4250 f3
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_bytes
);
4253 memset( &f4
, 0, sizeof(f4
) );
4254 f4
.value
= WS_XML_TEXT_TYPE_BOOL
;
4255 f4
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4256 f4
.field
.localName
= &str_u
;
4257 f4
.field
.ns
= &str_ns
;
4258 f4
.field
.type
= WS_BOOL_TYPE
;
4259 f4
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_bool
);
4262 memset( &f5
, 0, sizeof(f5
) );
4263 f5
.value
= WS_XML_TEXT_TYPE_INT32
;
4264 f5
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4265 f5
.field
.localName
= &str_u
;
4266 f5
.field
.ns
= &str_ns
;
4267 f5
.field
.type
= WS_INT32_TYPE
;
4268 f5
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_int32
);
4271 memset( &f6
, 0, sizeof(f6
) );
4272 f6
.value
= WS_XML_TEXT_TYPE_INT64
;
4273 f6
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4274 f6
.field
.localName
= &str_u
;
4275 f6
.field
.ns
= &str_ns
;
4276 f6
.field
.type
= WS_INT64_TYPE
;
4277 f6
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_int64
);
4280 memset( &f7
, 0, sizeof(f7
) );
4281 f7
.value
= WS_XML_TEXT_TYPE_UINT64
;
4282 f7
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4283 f7
.field
.localName
= &str_u
;
4284 f7
.field
.ns
= &str_ns
;
4285 f7
.field
.type
= WS_UINT64_TYPE
;
4286 f7
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_uint64
);
4289 memset( &f8
, 0, sizeof(f8
) );
4290 f8
.value
= WS_XML_TEXT_TYPE_DOUBLE
;
4291 f8
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4292 f8
.field
.localName
= &str_u
;
4293 f8
.field
.ns
= &str_ns
;
4294 f8
.field
.type
= WS_DOUBLE_TYPE
;
4295 f8
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_double
);
4298 memset( &f9
, 0, sizeof(f9
) );
4299 f9
.value
= WS_XML_TEXT_TYPE_GUID
;
4300 f9
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4301 f9
.field
.localName
= &str_u
;
4302 f9
.field
.ns
= &str_ns
;
4303 f9
.field
.type
= WS_GUID_TYPE
;
4304 f9
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_guid
);
4307 memset( &f10
, 0, sizeof(f10
) );
4308 f10
.value
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
4309 f10
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4310 f10
.field
.localName
= &str_u
;
4311 f10
.field
.ns
= &str_ns
;
4312 f10
.field
.type
= WS_UNIQUE_ID_TYPE
;
4313 f10
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_unique_id
);
4316 memset( &f11
, 0, sizeof(f11
) );
4317 f11
.value
= WS_XML_TEXT_TYPE_DATETIME
;
4318 f11
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4319 f11
.field
.localName
= &str_u
;
4320 f11
.field
.ns
= &str_ns
;
4321 f11
.field
.type
= WS_DATETIME_TYPE
;
4322 f11
.field
.offset
= FIELD_OFFSET(struct test
, u
.val_datetime
);
4325 memset( &u
, 0, sizeof(u
) );
4326 u
.size
= sizeof(struct test
);
4327 u
.alignment
= TYPE_ALIGNMENT(struct test
);
4330 u
.enumOffset
= FIELD_OFFSET(struct test
, type
);
4332 memset( &f_struct
, 0, sizeof(f_struct
) );
4333 f_struct
.mapping
= WS_ELEMENT_CHOICE_FIELD_MAPPING
;
4334 f_struct
.type
= WS_UNION_TYPE
;
4335 f_struct
.typeDescription
= &u
;
4336 fields_struct
[0] = &f_struct
;
4338 memset( &s
, 0, sizeof(s
) );
4339 s
.size
= sizeof(struct test
);
4340 s
.alignment
= TYPE_ALIGNMENT(struct test
);
4341 s
.fields
= fields_struct
;
4343 s
.typeLocalName
= &str_s
;
4346 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4347 test
.type
= WS_XML_TEXT_TYPE_UTF8
;
4348 test
.u
.val_utf8
.bytes
= (BYTE
*)"test";
4349 test
.u
.val_utf8
.length
= 4;
4350 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4351 &test
, sizeof(test
), NULL
);
4352 ok( hr
== S_OK
, "got %08x\n", hr
);
4353 hr
= WsWriteEndElement( writer
, NULL
);
4354 ok( hr
== S_OK
, "got %08x\n", hr
);
4355 check_output_bin( writer
, res
, sizeof(res
), __LINE__
);
4357 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4358 test
.type
= WS_XML_TEXT_TYPE_UTF16
;
4359 test
.u
.val_utf16
.chars
= (WCHAR
*)L
"test";
4360 test
.u
.val_utf16
.length
= 4;
4361 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4362 &test
, sizeof(test
), NULL
);
4363 ok( hr
== S_OK
, "got %08x\n", hr
);
4364 hr
= WsWriteEndElement( writer
, NULL
);
4365 ok( hr
== S_OK
, "got %08x\n", hr
);
4366 check_output_bin( writer
, res
, sizeof(res
), __LINE__
);
4368 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4369 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4370 test
.u
.val_bytes
.bytes
= (BYTE
*)"test";
4371 test
.u
.val_bytes
.length
= 4;
4372 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4373 &test
, sizeof(test
), NULL
);
4374 ok( hr
== S_OK
, "got %08x\n", hr
);
4375 hr
= WsWriteEndElement( writer
, NULL
);
4376 ok( hr
== S_OK
, "got %08x\n", hr
);
4377 check_output_bin( writer
, res2
, sizeof(res2
), __LINE__
);
4379 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4380 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4381 test
.u
.val_bytes
.bytes
= (BYTE
*)"tes";
4382 test
.u
.val_bytes
.length
= 3;
4383 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4384 &test
, sizeof(test
), NULL
);
4385 ok( hr
== S_OK
, "got %08x\n", hr
);
4386 hr
= WsWriteEndElement( writer
, NULL
);
4387 ok( hr
== S_OK
, "got %08x\n", hr
);
4388 check_output_bin( writer
, res2a
, sizeof(res2a
), __LINE__
);
4390 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4391 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4392 test
.u
.val_bytes
.bytes
= (BYTE
*)"t";
4393 test
.u
.val_bytes
.length
= 1;
4394 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4395 &test
, sizeof(test
), NULL
);
4396 ok( hr
== S_OK
, "got %08x\n", hr
);
4397 hr
= WsWriteEndElement( writer
, NULL
);
4398 ok( hr
== S_OK
, "got %08x\n", hr
);
4399 check_output_bin( writer
, res2b
, sizeof(res2b
), __LINE__
);
4401 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4402 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4403 test
.u
.val_bytes
.bytes
= (BYTE
*)"";
4404 test
.u
.val_bytes
.length
= 0;
4405 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4406 &test
, sizeof(test
), NULL
);
4407 ok( hr
== S_OK
, "got %08x\n", hr
);
4408 hr
= WsWriteEndElement( writer
, NULL
);
4409 ok( hr
== S_OK
, "got %08x\n", hr
);
4410 check_output_bin( writer
, res2c
, sizeof(res2c
), __LINE__
);
4412 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4413 memset( buf
, 'a', sizeof(buf
) );
4414 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4415 test
.u
.val_bytes
.bytes
= buf
;
4416 test
.u
.val_bytes
.length
= 255;
4417 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4418 &test
, sizeof(test
), NULL
);
4419 ok( hr
== S_OK
, "got %08x\n", hr
);
4420 hr
= WsWriteEndElement( writer
, NULL
);
4421 ok( hr
== S_OK
, "got %08x\n", hr
);
4422 check_output_bin( writer
, res2d
, sizeof(res2d
), __LINE__
);
4424 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4425 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4426 test
.u
.val_bytes
.bytes
= buf
;
4427 test
.u
.val_bytes
.length
= 256;
4428 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4429 &test
, sizeof(test
), NULL
);
4430 ok( hr
== S_OK
, "got %08x\n", hr
);
4431 hr
= WsWriteEndElement( writer
, NULL
);
4432 ok( hr
== S_OK
, "got %08x\n", hr
);
4433 check_output_bin( writer
, res2e
, sizeof(res2e
), __LINE__
);
4435 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4436 test
.type
= WS_XML_TEXT_TYPE_BASE64
;
4437 test
.u
.val_bytes
.bytes
= (BYTE
*)"testte";
4438 test
.u
.val_bytes
.length
= 6;
4439 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4440 &test
, sizeof(test
), NULL
);
4441 ok( hr
== S_OK
, "got %08x\n", hr
);
4442 hr
= WsWriteEndElement( writer
, NULL
);
4443 ok( hr
== S_OK
, "got %08x\n", hr
);
4444 check_output_bin( writer
, res2f
, sizeof(res2f
), __LINE__
);
4446 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4447 test
.type
= WS_XML_TEXT_TYPE_BOOL
;
4448 test
.u
.val_bool
= TRUE
;
4449 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4450 &test
, sizeof(test
), NULL
);
4451 ok( hr
== S_OK
, "got %08x\n", hr
);
4452 hr
= WsWriteEndElement( writer
, NULL
);
4453 ok( hr
== S_OK
, "got %08x\n", hr
);
4454 check_output_bin( writer
, res3
, sizeof(res3
), __LINE__
);
4456 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4457 test
.type
= WS_XML_TEXT_TYPE_INT32
;
4458 test
.u
.val_int32
= -1;
4459 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4460 &test
, sizeof(test
), NULL
);
4461 ok( hr
== S_OK
, "got %08x\n", hr
);
4462 hr
= WsWriteEndElement( writer
, NULL
);
4463 ok( hr
== S_OK
, "got %08x\n", hr
);
4464 check_output_bin( writer
, res4
, sizeof(res4
), __LINE__
);
4466 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4467 test
.type
= WS_XML_TEXT_TYPE_INT64
;
4468 test
.u
.val_int64
= -1;
4469 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4470 &test
, sizeof(test
), NULL
);
4471 ok( hr
== S_OK
, "got %08x\n", hr
);
4472 hr
= WsWriteEndElement( writer
, NULL
);
4473 ok( hr
== S_OK
, "got %08x\n", hr
);
4474 check_output_bin( writer
, res4
, sizeof(res4
), __LINE__
);
4476 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4477 test
.type
= WS_XML_TEXT_TYPE_UINT64
;
4478 test
.u
.val_uint64
= 1;
4479 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4480 &test
, sizeof(test
), NULL
);
4481 ok( hr
== S_OK
, "got %08x\n", hr
);
4482 hr
= WsWriteEndElement( writer
, NULL
);
4483 ok( hr
== S_OK
, "got %08x\n", hr
);
4484 check_output_bin( writer
, res5
, sizeof(res5
), __LINE__
);
4486 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4487 test
.type
= WS_XML_TEXT_TYPE_UINT64
;
4488 test
.u
.val_uint64
= 2;
4489 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4490 &test
, sizeof(test
), NULL
);
4491 ok( hr
== S_OK
, "got %08x\n", hr
);
4492 hr
= WsWriteEndElement( writer
, NULL
);
4493 ok( hr
== S_OK
, "got %08x\n", hr
);
4494 check_output_bin( writer
, res5b
, sizeof(res5b
), __LINE__
);
4496 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4497 test
.type
= WS_XML_TEXT_TYPE_DOUBLE
;
4498 test
.u
.val_double
= 0.0;
4499 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4500 &test
, sizeof(test
), NULL
);
4501 ok( hr
== S_OK
, "got %08x\n", hr
);
4502 hr
= WsWriteEndElement( writer
, NULL
);
4503 ok( hr
== S_OK
, "got %08x\n", hr
);
4504 check_output_bin( writer
, res6
, sizeof(res6
), __LINE__
);
4506 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4507 test
.type
= WS_XML_TEXT_TYPE_DOUBLE
;
4508 test
.u
.val_double
= 2.0;
4509 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4510 &test
, sizeof(test
), NULL
);
4511 ok( hr
== S_OK
, "got %08x\n", hr
);
4512 hr
= WsWriteEndElement( writer
, NULL
);
4513 ok( hr
== S_OK
, "got %08x\n", hr
);
4514 check_output_bin( writer
, res7
, sizeof(res7
), __LINE__
);
4516 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4517 test
.type
= WS_XML_TEXT_TYPE_DOUBLE
;
4518 test
.u
.val_double
= 2.1;
4519 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4520 &test
, sizeof(test
), NULL
);
4521 ok( hr
== S_OK
, "got %08x\n", hr
);
4522 hr
= WsWriteEndElement( writer
, NULL
);
4523 ok( hr
== S_OK
, "got %08x\n", hr
);
4524 check_output_bin( writer
, res8
, sizeof(res8
), __LINE__
);
4526 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4527 test
.type
= WS_XML_TEXT_TYPE_DOUBLE
;
4528 test
.u
.val_double
= INFINITY
;
4529 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4530 &test
, sizeof(test
), NULL
);
4531 ok( hr
== S_OK
, "got %08x\n", hr
);
4532 hr
= WsWriteEndElement( writer
, NULL
);
4533 ok( hr
== S_OK
, "got %08x\n", hr
);
4534 check_output_bin( writer
, res8a
, sizeof(res8a
), __LINE__
);
4536 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4537 test
.type
= WS_XML_TEXT_TYPE_DOUBLE
;
4538 test
.u
.val_double
= -INFINITY
;
4539 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4540 &test
, sizeof(test
), NULL
);
4541 ok( hr
== S_OK
, "got %08x\n", hr
);
4542 hr
= WsWriteEndElement( writer
, NULL
);
4543 ok( hr
== S_OK
, "got %08x\n", hr
);
4544 check_output_bin( writer
, res8b
, sizeof(res8b
), __LINE__
);
4546 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4547 test
.type
= WS_XML_TEXT_TYPE_DOUBLE
;
4548 test
.u
.val_double
= NAN
;
4549 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4550 &test
, sizeof(test
), NULL
);
4551 ok( hr
== S_OK
, "got %08x\n", hr
);
4552 hr
= WsWriteEndElement( writer
, NULL
);
4553 ok( hr
== S_OK
, "got %08x\n", hr
);
4554 check_output_bin( writer
, res8c
, sizeof(res8c
), __LINE__
);
4556 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4557 test
.type
= WS_XML_TEXT_TYPE_GUID
;
4558 memset( &test
.u
.val_guid
, 0, sizeof(test
.u
.val_guid
) );
4559 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4560 &test
, sizeof(test
), NULL
);
4561 ok( hr
== S_OK
, "got %08x\n", hr
);
4562 hr
= WsWriteEndElement( writer
, NULL
);
4563 ok( hr
== S_OK
, "got %08x\n", hr
);
4564 check_output_bin( writer
, res9
, sizeof(res9
), __LINE__
);
4566 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4567 test
.type
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
4568 memset( &test
.u
.val_unique_id
, 0, sizeof(test
.u
.val_unique_id
) );
4569 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4570 &test
, sizeof(test
), NULL
);
4571 ok( hr
== S_OK
, "got %08x\n", hr
);
4572 hr
= WsWriteEndElement( writer
, NULL
);
4573 ok( hr
== S_OK
, "got %08x\n", hr
);
4574 check_output_bin( writer
, res10
, sizeof(res10
), __LINE__
);
4576 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4577 test
.type
= WS_XML_TEXT_TYPE_DATETIME
;
4578 memset( &test
.u
.val_datetime
, 0, sizeof(test
.u
.val_datetime
) );
4579 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4580 &test
, sizeof(test
), NULL
);
4581 ok( hr
== S_OK
, "got %08x\n", hr
);
4582 hr
= WsWriteEndElement( writer
, NULL
);
4583 ok( hr
== S_OK
, "got %08x\n", hr
);
4584 check_output_bin( writer
, res11
, sizeof(res11
), __LINE__
);
4586 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4587 test
.type
= WS_XML_TEXT_TYPE_DATETIME
;
4588 memset( &test
.u
.val_datetime
, 0, sizeof(test
.u
.val_datetime
) );
4589 test
.u
.val_datetime
.format
= WS_DATETIME_FORMAT_LOCAL
;
4590 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4591 &test
, sizeof(test
), NULL
);
4592 ok( hr
== S_OK
, "got %08x\n", hr
);
4593 hr
= WsWriteEndElement( writer
, NULL
);
4594 ok( hr
== S_OK
, "got %08x\n", hr
);
4595 check_output_bin( writer
, res11b
, sizeof(res11b
), __LINE__
);
4597 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4598 test
.type
= WS_XML_TEXT_TYPE_DATETIME
;
4599 memset( &test
.u
.val_datetime
, 0, sizeof(test
.u
.val_datetime
) );
4600 test
.u
.val_datetime
.format
= WS_DATETIME_FORMAT_NONE
;
4601 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4602 &test
, sizeof(test
), NULL
);
4603 ok( hr
== S_OK
, "got %08x\n", hr
);
4604 hr
= WsWriteEndElement( writer
, NULL
);
4605 ok( hr
== S_OK
, "got %08x\n", hr
);
4606 check_output_bin( writer
, res11c
, sizeof(res11c
), __LINE__
);
4608 prepare_binary_type_test( writer
, NULL
, &str_t
, &str_ns
);
4609 test
.type
= WS_XML_TEXT_TYPE_DATETIME
;
4610 memset( &test
.u
.val_datetime
, 0, sizeof(test
.u
.val_datetime
) );
4611 test
.u
.val_datetime
.ticks
= 1;
4612 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
, WS_WRITE_REQUIRED_VALUE
,
4613 &test
, sizeof(test
), NULL
);
4614 ok( hr
== S_OK
, "got %08x\n", hr
);
4615 hr
= WsWriteEndElement( writer
, NULL
);
4616 ok( hr
== S_OK
, "got %08x\n", hr
);
4617 check_output_bin( writer
, res11d
, sizeof(res11d
), __LINE__
);
4619 WsFreeWriter( writer
);
4622 static void test_repeating_element_choice(void)
4624 static WS_XML_STRING str_ns
= {0, NULL
}, str_a
= {1, (BYTE
*)"a"}, str_b
= {1, (BYTE
*)"b"};
4625 static WS_XML_STRING str_s
= {1, (BYTE
*)"s"}, str_t
= {1, (BYTE
*)"t"};
4627 WS_XML_WRITER
*writer
;
4628 WS_UNION_DESCRIPTION u
;
4629 WS_UNION_FIELD_DESCRIPTION f
, f2
, *fields
[2];
4630 WS_FIELD_DESCRIPTION f_items
, *fields_items
[1];
4631 WS_STRUCT_DESCRIPTION s
;
4632 enum choice
{CHOICE_A
, CHOICE_B
, CHOICE_NONE
};
4648 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
4649 ok( hr
== S_OK
, "got %08x\n", hr
);
4651 memset( &f
, 0, sizeof(f
) );
4653 f
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4654 f
.field
.localName
= &str_a
;
4655 f
.field
.ns
= &str_ns
;
4656 f
.field
.type
= WS_WSZ_TYPE
;
4657 f
.field
.offset
= FIELD_OFFSET(struct item
, value
.a
);
4660 memset( &f2
, 0, sizeof(f2
) );
4661 f2
.value
= CHOICE_B
;
4662 f2
.field
.mapping
= WS_ELEMENT_FIELD_MAPPING
;
4663 f2
.field
.localName
= &str_b
;
4664 f2
.field
.ns
= &str_ns
;
4665 f2
.field
.type
= WS_UINT32_TYPE
;
4666 f2
.field
.offset
= FIELD_OFFSET(struct item
, value
.b
);
4669 memset( &u
, 0, sizeof(u
) );
4670 u
.size
= sizeof(struct item
);
4671 u
.alignment
= TYPE_ALIGNMENT(struct item
);
4674 u
.enumOffset
= FIELD_OFFSET(struct item
, choice
);
4675 u
.noneEnumValue
= CHOICE_NONE
;
4677 memset( &f_items
, 0, sizeof(f_items
) );
4678 f_items
.mapping
= WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING
;
4679 f_items
.localName
= &str_t
;
4680 f_items
.ns
= &str_ns
;
4681 f_items
.type
= WS_UNION_TYPE
;
4682 f_items
.typeDescription
= &u
;
4683 f_items
.countOffset
= FIELD_OFFSET(struct test
, count
);
4684 fields_items
[0] = &f_items
;
4686 memset( &s
, 0, sizeof(s
) );
4687 s
.size
= sizeof(struct test
);
4688 s
.alignment
= TYPE_ALIGNMENT(struct test
);
4689 s
.fields
= fields_items
;
4691 s
.typeLocalName
= &str_s
;
4694 items
[0].choice
= CHOICE_A
;
4695 items
[0].value
.a
= L
"test";
4696 items
[1].choice
= CHOICE_B
;
4697 items
[1].value
.b
= 1;
4701 hr
= set_output( writer
);
4702 ok( hr
== S_OK
, "got %08x\n", hr
);
4703 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4704 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4705 ok( hr
== S_OK
, "got %08x\n", hr
);
4706 check_output( writer
, "<t><a>test</a><b>1</b></t>", __LINE__
);
4708 items
[0].choice
= CHOICE_NONE
;
4709 hr
= set_output( writer
);
4710 ok( hr
== S_OK
, "got %08x\n", hr
);
4711 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4712 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4713 ok( hr
== WS_E_INVALID_FORMAT
, "got %08x\n", hr
);
4716 hr
= set_output( writer
);
4717 ok( hr
== S_OK
, "got %08x\n", hr
);
4718 hr
= WsWriteType( writer
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4719 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4720 ok( hr
== S_OK
, "got %08x\n", hr
);
4721 check_output( writer
, "<t/>", __LINE__
);
4723 WsFreeWriter( writer
);
4726 static const struct stream_test
4739 static CALLBACK HRESULT
write_callback( void *state
, const WS_BYTES
*buf
, ULONG count
,
4740 const WS_ASYNC_CONTEXT
*ctx
, WS_ERROR
*error
)
4742 ULONG i
= *(ULONG
*)state
;
4743 ok( buf
->length
== stream_tests
[i
].ret_size
, "%u: got %u\n", i
, buf
->length
);
4744 ok( !memcmp( buf
->bytes
, "<t/>", stream_tests
[i
].ret_size
), "%u: wrong data\n", i
);
4745 ok( count
== 1, "%u: got %u\n", i
, count
);
4749 static void test_stream_output(void)
4751 static WS_XML_STRING str_ns
= {0, NULL
}, str_t
= {1, (BYTE
*)"t"};
4752 WS_XML_WRITER_TEXT_ENCODING text
= {{WS_XML_WRITER_ENCODING_TYPE_TEXT
}, WS_CHARSET_UTF8
};
4753 WS_XML_WRITER_STREAM_OUTPUT stream
;
4754 WS_XML_WRITER
*writer
;
4758 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
4759 ok( hr
== S_OK
, "got %08x\n", hr
);
4761 hr
= WsFlushWriter( writer
, 0, NULL
, NULL
);
4762 ok( hr
== WS_E_INVALID_OPERATION
, "got %08x\n", hr
);
4764 stream
.output
.outputType
= WS_XML_WRITER_OUTPUT_TYPE_STREAM
;
4765 stream
.writeCallback
= write_callback
;
4766 stream
.writeCallbackState
= &i
;
4767 hr
= WsSetOutput( writer
, &text
.encoding
, &stream
.output
, NULL
, 0, NULL
);
4768 ok( hr
== S_OK
, "got %08x\n", hr
);
4770 hr
= WsSetOutput( writer
, &text
.encoding
, &stream
.output
, NULL
, 0, NULL
);
4771 ok( hr
== S_OK
, "got %08x\n", hr
);
4773 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4774 ok( hr
== S_OK
, "got %08x\n", hr
);
4775 hr
= WsWriteEndElement( writer
, NULL
);
4776 ok( hr
== S_OK
, "got %08x\n", hr
);
4777 hr
= WsFlushWriter( writer
, 0, NULL
, NULL
);
4778 ok( hr
== S_OK
, "got %08x\n", hr
);
4780 for (i
= 0; i
< ARRAY_SIZE(stream_tests
); i
++)
4782 stream
.writeCallbackState
= &i
;
4783 hr
= WsSetOutput( writer
, &text
.encoding
, &stream
.output
, NULL
, 0, NULL
);
4784 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
4785 hr
= WsWriteStartElement( writer
, NULL
, &str_t
, &str_ns
, NULL
);
4786 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
4787 hr
= WsWriteEndElement( writer
, NULL
);
4788 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
4789 hr
= WsFlushWriter( writer
, stream_tests
[i
].min_size
, NULL
, NULL
);
4790 ok( hr
== S_OK
, "%u: got %08x\n", i
, hr
);
4793 WsFreeWriter( writer
);
4796 static void test_description_type(void)
4798 static WS_XML_STRING ns
= {0, NULL
}, localname
= {1, (BYTE
*)"t"}, val
= {3, (BYTE
*)"val"};
4800 WS_XML_WRITER
*writer
;
4801 WS_FIELD_DESCRIPTION f
, f2
, *fields
[2];
4802 WS_STRUCT_DESCRIPTION s
;
4805 const WS_STRUCT_DESCRIPTION
*desc
;
4809 hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
);
4810 ok( hr
== S_OK
, "got %08x\n", hr
);
4812 memset( &f
, 0, sizeof(f
) );
4813 f
.mapping
= WS_TYPE_ATTRIBUTE_FIELD_MAPPING
;
4814 f
.type
= WS_DESCRIPTION_TYPE
;
4817 memset( &f2
, 0, sizeof(f2
) );
4818 f2
.mapping
= WS_ATTRIBUTE_FIELD_MAPPING
;
4819 f2
.localName
= &val
;
4821 f2
.offset
= FIELD_OFFSET(struct test
, val
);
4822 f2
.type
= WS_INT32_TYPE
;
4825 memset( &s
, 0, sizeof(s
) );
4826 s
.size
= sizeof(struct test
);
4827 s
.alignment
= TYPE_ALIGNMENT(struct test
);
4830 s
.typeLocalName
= &localname
;
4836 hr
= set_output( writer
);
4837 hr
= WsWriteStartElement( writer
, NULL
, &localname
, &ns
, NULL
);
4838 ok( hr
== S_OK
, "got %08x\n", hr
);
4840 hr
= WsWriteType( writer
, WS_ELEMENT_TYPE_MAPPING
, WS_STRUCT_TYPE
, &s
,
4841 WS_WRITE_REQUIRED_VALUE
, &test
, sizeof(test
), NULL
);
4842 ok( hr
== S_OK
, "got %08x\n", hr
);
4844 hr
= WsWriteEndElement( writer
, NULL
);
4845 ok( hr
== S_OK
, "got %08x\n", hr
);
4846 check_output( writer
, "<t val=\"-1\"/>", __LINE__
);
4848 WsFreeWriter( writer
);
4853 test_WsCreateWriter();
4854 test_WsCreateXmlBuffer();
4856 test_WsSetOutputToBuffer();
4857 test_WsWriteStartElement();
4858 test_WsWriteStartAttribute();
4861 test_simple_struct_type();
4862 test_WsWriteElement();
4863 test_WsWriteValue();
4864 test_WsWriteAttribute();
4865 test_WsWriteStartCData();
4866 test_WsWriteXmlnsAttribute();
4867 test_WsGetPrefixFromNamespace();
4868 test_complex_struct_type();
4869 test_WsMoveWriter();
4870 test_WsGetWriterPosition();
4871 test_WsSetWriterPosition();
4872 test_WsWriteXmlBuffer();
4877 test_field_options();
4879 test_WsWriteArray();
4881 test_write_option();
4883 test_repeating_element();
4884 test_WsWriteQualifiedName();
4885 test_WsWriteBytes();
4886 test_WsWriteChars();
4887 test_WsWriteCharsUtf8();
4888 test_binary_encoding();
4892 test_text_types_binary();
4893 test_repeating_element_choice();
4894 test_stream_output();
4895 test_description_type();