Filter out CTEXT nodes when building element child lists.
[wine] / dlls / msxml3 / tests / domdoc.c
1 /*
2  * XML test
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21
22 #define COBJMACROS
23
24 #include "windows.h"
25 #include "ole2.h"
26 #include "msxml.h"
27 #include "xmldom.h"
28 #include <stdio.h>
29
30 #include "wine/test.h"
31
32 static const WCHAR szEmpty[] = { 0 };
33 static const WCHAR szIncomplete[] = {
34     '<','?','x','m','l',' ',
35     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
36 };
37 static const WCHAR szComplete1[] = {
38     '<','?','x','m','l',' ',
39     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
40     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
41 };
42 static const WCHAR szComplete2[] = {
43     '<','?','x','m','l',' ',
44     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
45     '<','o','>','<','/','o','>','\n',0
46 };
47 static const WCHAR szComplete3[] = {
48     '<','?','x','m','l',' ',
49     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
50     '<','a','>','<','/','a','>','\n',0
51 };
52 static const WCHAR szComplete4[] = {
53     '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
54     '<','l','c',' ','d','l','=','\'','s','t','r','1','\'','>','\n',
55         '<','b','s',' ','v','r','=','\'','s','t','r','2','\'',' ','s','z','=','\'','1','2','3','4','\'','>',
56             'f','n','1','.','t','x','t','\n',
57         '<','/','b','s','>','\n',
58         '<','p','r',' ','i','d','=','\'','s','t','r','3','\'',' ','v','r','=','\'','1','.','2','.','3','\'',' ',
59                     'p','n','=','\'','w','i','n','e',' ','2','0','0','5','0','8','0','4','\'','>','\n',
60             'f','n','2','.','t','x','t','\n',
61         '<','/','p','r','>','\n',
62     '<','/','l','c','>','\n',0
63 };
64 static const WCHAR szNonExistentFile[] = {
65     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
66 };
67 static const WCHAR szDocument[] = {
68     '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
69 };
70
71 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
72 static const WCHAR szdl[] = { 'd','l',0 };
73 static const WCHAR szlc[] = { 'l','c',0 };
74 static const WCHAR szbs[] = { 'b','s',0 };
75
76 const GUID CLSID_DOMDocument = 
77     { 0x2933BF90, 0x7B36, 0x11d2, {0xB2,0x0E,0x00,0xC0,0x4F,0x98,0x3E,0x60}};
78 const GUID IID_IXMLDOMDocument = 
79     { 0x2933BF81, 0x7B36, 0x11d2, {0xB2,0x0E,0x00,0xC0,0x4F,0x98,0x3E,0x60}};
80
81 void test_domdoc( void )
82 {
83     HRESULT r;
84     IXMLDOMDocument *doc = NULL;
85     IXMLDOMElement *element = NULL;
86     VARIANT_BOOL b;
87     VARIANT var;
88     BSTR str;
89
90     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
91         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
92     if( r != S_OK )
93         return;
94
95     /* try some stupid things */
96     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
97     ok( r == S_FALSE, "loadXML failed\n");
98
99     b = VARIANT_TRUE;
100     r = IXMLDOMDocument_loadXML( doc, NULL, &b );
101     ok( r == S_FALSE, "loadXML failed\n");
102     ok( b == VARIANT_FALSE, "failed to load XML string\n");
103
104     /* try to load an document from an non-existent file */
105     b = VARIANT_TRUE;
106     str = SysAllocString( szNonExistentFile );
107     VariantInit(&var);
108     V_VT(&var) = VT_BSTR;
109     V_BSTR(&var) = str;
110
111     r = IXMLDOMDocument_load( doc, var, &b);
112     ok( r == S_FALSE, "load (from file) failed\n");
113     ok( b == VARIANT_FALSE, "failed to load XML file\n");
114     SysFreeString( str );
115
116     /* try load an empty document */
117     b = VARIANT_TRUE;
118     str = SysAllocString( szEmpty );
119     r = IXMLDOMDocument_loadXML( doc, str, &b );
120     ok( r == S_FALSE, "loadXML failed\n");
121     ok( b == VARIANT_FALSE, "failed to load XML string\n");
122     SysFreeString( str );
123
124     /* check that there's no document element */
125     element = NULL;
126     r = IXMLDOMDocument_get_documentElement( doc, &element );
127     ok( r == S_FALSE, "should be no document element\n");
128
129     b = VARIANT_TRUE;
130     str = SysAllocString( szIncomplete );
131     r = IXMLDOMDocument_loadXML( doc, str, &b );
132     ok( r == S_FALSE, "loadXML failed\n");
133     ok( b == VARIANT_FALSE, "failed to load XML string\n");
134     SysFreeString( str );
135
136     /* check that there's no document element */
137     element = (IXMLDOMElement*)1;
138     r = IXMLDOMDocument_get_documentElement( doc, &element );
139     ok( r == S_FALSE, "should be no document element\n");
140     ok( element == NULL, "Element should be NULL\n");
141
142     /* try to load something valid */
143     b = VARIANT_FALSE;
144     str = SysAllocString( szComplete1 );
145     r = IXMLDOMDocument_loadXML( doc, str, &b );
146     ok( r == S_OK, "loadXML failed\n");
147     ok( b == VARIANT_TRUE, "failed to load XML string\n");
148     SysFreeString( str );
149
150     /* try with a null out pointer - crashes */
151     if (0)
152     {
153         r = IXMLDOMDocument_get_documentElement( doc, NULL );
154         ok( r == S_OK, "should be no document element\n");
155     }
156
157     /* check if nodename is correct */
158     r = IXMLDOMDocument_get_nodeName( doc, NULL );
159     ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code");
160
161     /* content doesn't matter here */
162     str = SysAllocString( szNonExistentFile );
163     r = IXMLDOMDocument_get_nodeName( doc, &str );
164     ok ( r == S_OK, "get_nodeName wrong code\n");
165     ok ( str != NULL, "str is null\n");
166     ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
167     SysFreeString( str );
168
169
170     /* check that there's no document element */
171     element = NULL;
172     r = IXMLDOMDocument_get_documentElement( doc, &element );
173     ok( r == S_OK, "should be a document element\n");
174     if( element )
175     {
176         BSTR tag = NULL;
177
178         /* check if the tag is correct */
179         r = IXMLDOMElement_get_tagName( element, &tag );
180         ok( r == S_OK, "couldn't get tag name\n");
181         ok( tag != NULL, "tag was null\n");
182         ok( !lstrcmpW( tag, szOpen ), "incorrect tag name\n");
183         SysFreeString( tag );
184
185         /* figure out what happens if we try to reload the document */
186         str = SysAllocString( szComplete2 );
187         r = IXMLDOMDocument_loadXML( doc, str, &b );
188         ok( r == S_OK, "loadXML failed\n");
189         ok( b == VARIANT_TRUE, "failed to load XML string\n");
190         SysFreeString( str );
191
192         /* check if the tag is still correct */
193         tag = NULL;
194         r = IXMLDOMElement_get_tagName( element, &tag );
195         ok( r == S_OK, "couldn't get tag name\n");
196         ok( tag != NULL, "tag was null\n");
197         ok( !lstrcmpW( tag, szOpen ), "incorrect tag name\n");
198         SysFreeString( tag );
199
200         IXMLDOMElement_Release( element );
201         element = NULL;
202     }
203
204     /* as soon as we call loadXML again, the document element will disappear */
205     b = 2;
206     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
207     ok( r == S_FALSE, "loadXML failed\n");
208     ok( b == 2, "variant modified\n");
209     r = IXMLDOMDocument_get_documentElement( doc, &element );
210     ok( r == S_FALSE, "should be no document element\n");
211
212     /* try to load something else simple and valid */
213     b = VARIANT_FALSE;
214     str = SysAllocString( szComplete3 );
215     r = IXMLDOMDocument_loadXML( doc, str, &b );
216     ok( r == S_OK, "loadXML failed\n");
217     ok( b == VARIANT_TRUE, "failed to load XML string\n");
218     SysFreeString( str );
219
220     /* try something a little more complicated */
221     b = FALSE;
222     str = SysAllocString( szComplete4 );
223     r = IXMLDOMDocument_loadXML( doc, str, &b );
224     ok( r == S_OK, "loadXML failed\n");
225     ok( b == VARIANT_TRUE, "failed to load XML string\n");
226     SysFreeString( str );
227
228     r = IXMLDocument_Release( doc );
229     ok( r == 0, "document ref count incorrect\n");
230
231 }
232
233 void test_domnode( void )
234 {
235     HRESULT r;
236     IXMLDOMDocument *doc = NULL, *owner = NULL;
237     IXMLDOMElement *element = NULL;
238     IXMLDOMNamedNodeMap *map = NULL;
239     IXMLDOMNode *node = NULL, *next = NULL;
240     IXMLDOMNodeList *list = NULL;
241     DOMNodeType type = NODE_INVALID;
242     VARIANT_BOOL b;
243     BSTR str;
244     VARIANT var;
245     long count;
246
247     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
248         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
249     if( r != S_OK )
250         return;
251
252     b = FALSE;
253     str = SysAllocString( szComplete4 );
254     r = IXMLDOMDocument_loadXML( doc, str, &b );
255     ok( r == S_OK, "loadXML failed\n");
256     ok( b == VARIANT_TRUE, "failed to load XML string\n");
257     SysFreeString( str );
258
259     if (doc)
260     {
261         b = 1;
262         r = IXMLDOMNode_hasChildNodes( doc, &b );
263         ok( r == S_OK, "hasChildNoes bad return\n");
264         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
265
266         r = IXMLDOMDocument_get_documentElement( doc, &element );
267         ok( r == S_OK, "should be a document element\n");
268         ok( element != NULL, "should be an element\n");
269     }
270     else
271         ok( FALSE, "no document\n");
272
273     VariantInit(&var);
274     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
275     r = IXMLDOMNode_get_nodeValue( doc, &var );
276     ok( r == S_FALSE, "nextNode returned wrong code\n");
277     ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
278     ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
279
280     if (element)
281     {
282         owner = NULL;
283         r = IXMLDOMNode_get_ownerDocument( element, &owner );
284         todo_wine {
285         ok( r == S_OK, "get_ownerDocument return code\n");
286         }
287         ok( owner != doc, "get_ownerDocument return\n");
288
289         type = NODE_INVALID;
290         r = IXMLDOMNode_get_nodeType( element, &type);
291         ok( r == S_OK, "getNamedItem returned wrong code\n");
292         ok( type == NODE_ELEMENT, "node not an element\n");
293
294         str = NULL;
295         r = IXMLDOMNode_get_baseName( element, &str );
296         ok( r == S_OK, "get_baseName returned wrong code\n");
297         ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
298
299         /* check if nodename is correct */
300         r = IXMLDOMElement_get_nodeName( element, NULL );
301         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code");
302     
303         /* content doesn't matter here */
304         str = SysAllocString( szNonExistentFile );
305         r = IXMLDOMElement_get_nodeName( element, &str );
306         ok ( r == S_OK, "get_nodeName wrong code\n");
307         ok ( str != NULL, "str is null\n");
308         ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
309         SysFreeString( str );
310
311         r = IXMLDOMElement_get_attributes( element, &map );
312         ok( r == S_OK, "get_attributes returned wrong code\n");
313         ok( map != NULL, "should be attributes\n");
314
315         b = 1;
316         r = IXMLDOMNode_hasChildNodes( element, &b );
317         ok( r == S_OK, "hasChildNoes bad return\n");
318         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
319     }
320     else
321         ok( FALSE, "no element\n");
322
323     if (map)
324     {
325         str = SysAllocString( szdl );
326         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
327         ok( r == S_OK, "getNamedItem returned wrong code\n");
328         ok( node != NULL, "should be attributes\n");
329         SysFreeString( str );
330
331         /* test indexed access of attributes */
332         r = IXMLDOMNamedNodeMap_get_length( map, &count );
333         ok ( r == S_OK, "get_length wrong code\n");
334         ok ( count == 1, "get_length != 1\n");
335
336         node = NULL;
337         r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
338         ok ( r == S_FALSE, "get_item (-1) wrong code\n");
339         ok ( node == NULL, "there is no node\n");
340
341         node = NULL;
342         r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
343         ok ( r == S_FALSE, "get_item (1) wrong code\n");
344         ok ( node == NULL, "there is no attribute\n");
345
346         node = NULL;
347         r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
348         ok ( r == S_OK, "get_item (0) wrong code\n");
349         ok ( node != NULL, "should be attribute\n");
350
351         r = IXMLDOMNode_get_nodeName( node, NULL );
352         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code");
353
354         /* content doesn't matter here */
355         str = SysAllocString( szNonExistentFile );
356         r = IXMLDOMNode_get_nodeName( node, &str );
357         ok ( r == S_OK, "get_nodeName wrong code\n");
358         ok ( str != NULL, "str is null\n");
359         ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
360         SysFreeString( str );
361     }
362     else
363         ok( FALSE, "no map\n");
364
365     if (node)
366     {
367         type = NODE_INVALID;
368         r = IXMLDOMNode_get_nodeType( node, &type);
369         ok( r == S_OK, "getNamedItem returned wrong code\n");
370         ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
371
372         str = NULL;
373         r = IXMLDOMNode_get_baseName( node, NULL );
374         ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
375
376         str = NULL;
377         r = IXMLDOMNode_get_baseName( node, &str );
378         ok( r == S_OK, "get_baseName returned wrong code\n");
379         ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
380
381         r = IXMLDOMNode_get_childNodes( node, NULL );
382         ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
383
384         r = IXMLDOMNode_get_childNodes( node, &list );
385         ok( r == S_OK, "get_childNodes returned wrong code\n");
386
387         if (list)
388         {
389             r = IXMLDOMNodeList_nextNode( list, &next );
390             ok( r == S_OK, "nextNode returned wrong code\n");
391         }
392         else
393             ok( FALSE, "no childlist\n");
394
395         if (next)
396         {
397             b = 1;
398             r = IXMLDOMNode_hasChildNodes( next, &b );
399             ok( r == S_FALSE, "hasChildNoes bad return\n");
400             ok( b == VARIANT_FALSE, "hasChildNoes wrong result\n");
401
402             type = NODE_INVALID;
403             r = IXMLDOMNode_get_nodeType( next, &type);
404             ok( r == S_OK, "getNamedItem returned wrong code\n");
405             ok( type == NODE_TEXT, "node not text\n");
406
407             str = (BSTR) 1;
408             r = IXMLDOMNode_get_baseName( next, &str );
409             ok( r == S_FALSE, "get_baseName returned wrong code\n");
410             ok( str == NULL, "basename was wrong\n");
411         }
412         else
413             ok( FALSE, "no next\n");
414
415         if (next)
416             IXMLDOMNode_Release( next );
417         next = NULL;
418         if (list)
419             IXMLDOMNodeList_Release( list );
420         list = NULL;
421         if (node)
422             IXMLDOMNode_Release( node );
423     }
424     else
425         ok( FALSE, "no node\n");
426     node = NULL;
427
428     if (map)
429         IXMLDOMNamedNodeMap_Release( map );
430
431     /* now traverse the tree from the root node */
432     if (element)
433     {
434         r = IXMLDOMNode_get_childNodes( element, &list );
435         ok( r == S_OK, "get_childNodes returned wrong code\n");
436     }
437     else
438         ok( FALSE, "no element\n");
439
440     if (list)
441     {
442         r = IXMLDOMNodeList_get_length( list, &count );
443         ok( r == S_OK, "get_length returns %08lx\n", r );
444         ok( count == 2, "get_length got %ld\n", count );
445
446         r = IXMLDOMNodeList_nextNode( list, &node );
447         ok( r == S_OK, "nextNode returned wrong code\n");
448     }
449     else
450         ok( FALSE, "no list\n");
451
452     if (node)
453     {
454         type = NODE_INVALID;
455         r = IXMLDOMNode_get_nodeType( node, &type);
456         ok( r == S_OK, "getNamedItem returned wrong code\n");
457         ok( type == NODE_ELEMENT, "node not text\n");
458
459         VariantInit(&var);
460         ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
461         r = IXMLDOMNode_get_nodeValue( node, &var );
462         ok( r == S_FALSE, "nextNode returned wrong code\n");
463         ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
464         ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
465
466         r = IXMLDOMNode_hasChildNodes( node, NULL );
467         ok( r == E_INVALIDARG, "hasChildNoes bad return\n");
468
469         b = 1;
470         r = IXMLDOMNode_hasChildNodes( node, &b );
471         ok( r == S_OK, "hasChildNoes bad return\n");
472         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
473
474         str = NULL;
475         r = IXMLDOMNode_get_baseName( node, &str );
476         ok( r == S_OK, "get_baseName returned wrong code\n");
477         ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
478     }
479     else
480         ok( FALSE, "no node\n");
481
482     if (node)
483         IXMLDOMNode_Release( node );
484     if (list)
485         IXMLDOMNodeList_Release( list );
486     if (element)
487         IXMLDOMElement_Release( element );
488     if (doc)
489         IXMLDocument_Release( doc );
490 }
491
492 START_TEST(domdoc)
493 {
494     HRESULT r;
495
496     r = CoInitialize( NULL );
497     ok( r == S_OK, "failed to init com\n");
498
499     test_domdoc();
500     test_domnode();
501
502     CoUninitialize();
503 }