msxml3: Move domdoc properties into their own struct.
[wine] / dlls / msxml3 / tests / xmlelem.c
1 /*
2  * IXMLElement tests
3  *
4  * Copyright 2007 James Hawkins
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include <stdio.h>
24
25 #include "windows.h"
26 #include "ole2.h"
27 #include "xmldom.h"
28 #include "msxml2.h"
29 #include "ocidl.h"
30
31 #include "wine/test.h"
32
33 #define ERROR_URL_NOT_FOUND 0x800c0006
34
35 static void test_xmlelem(void)
36 {
37     HRESULT hr;
38     IXMLDocument *doc = NULL;
39     IXMLElement *element = NULL, *parent;
40     IXMLElement *child, *child2;
41     IXMLElementCollection *children;
42     VARIANT vType, vName;
43     VARIANT vIndex, vValue;
44     BSTR str, val;
45     LONG type, num_child;
46
47     static const WCHAR propName[] = {'p','r','o','p',0};
48     static const WCHAR propVal[] = {'v','a','l',0};
49     static const WCHAR nextVal[] = {'n','e','x','t',0};
50     static const WCHAR noexist[] = {'n','o','e','x','i','s','t',0};
51     static const WCHAR crazyCase1[] = {'C','R','a','z','Y','c','A','S','E',0};
52     static const WCHAR crazyCase2[] = {'C','R','A','Z','Y','C','A','S','E',0};
53
54     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
55                           &IID_IXMLDocument, (LPVOID*)&doc);
56     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
57
58     V_VT(&vType) = VT_I4;
59     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
60     V_VT(&vName) = VT_NULL;
61     hr = IXMLDocument_createElement(doc, vType, vName, &element);
62     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
63     ok(element != NULL, "Expected non-NULL element\n");
64
65     hr = IXMLElement_get_tagName(element, &str);
66     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
67     ok(lstrlenW(str) == 0, "Expected empty tag name\n");
68     SysFreeString(str);
69
70     parent = (IXMLElement *)0xdeadbeef;
71     hr = IXMLElement_get_parent(element, &parent);
72     ok(hr == 1, "Expected 1, got %08x\n", hr);
73     ok(parent == NULL, "Expected NULL parent\n");
74
75     str = SysAllocString(noexist);
76     hr = IXMLElement_getAttribute(element, str, &vValue);
77     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
78     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
79     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
80     VariantClear(&vValue);
81     SysFreeString(str);
82
83     str = SysAllocString(crazyCase1);
84     val = SysAllocString(propVal);
85     V_VT(&vValue) = VT_BSTR;
86     V_BSTR(&vValue) = val;
87     hr = IXMLElement_setAttribute(element, str, vValue);
88     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
89     SysFreeString(str);
90     SysFreeString(val);
91
92     str = SysAllocString(crazyCase2);
93     hr = IXMLElement_getAttribute(element, str, &vValue);
94     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
95     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
96     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
97     VariantClear(&vValue);
98     SysFreeString(str);
99
100     str = SysAllocString(propName);
101     val = SysAllocString(propVal);
102     V_VT(&vValue) = VT_BSTR;
103     V_BSTR(&vValue) = val;
104     hr = IXMLElement_setAttribute(element, str, vValue);
105     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
106     SysFreeString(val);
107
108     hr = IXMLElement_getAttribute(element, str, &vValue);
109     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
110     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
111     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
112     VariantClear(&vValue);
113
114     hr = IXMLElement_removeAttribute(element, str);
115     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
116
117     /* remove now nonexistent attribute */
118     hr = IXMLElement_removeAttribute(element, str);
119     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
120
121     hr = IXMLElement_getAttribute(element, str, &vValue);
122     ok(hr == 1, "Expected 1, got %08x\n", hr);
123     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
124     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
125     SysFreeString(str);
126     VariantClear(&vValue);
127
128     children = (IXMLElementCollection *)0xdeadbeef;
129     hr = IXMLElement_get_children(element, &children);
130     ok(hr == 1, "Expected 1, got %08x\n", hr);
131     ok(children == NULL, "Expected NULL collection\n");
132
133     hr = IXMLElement_get_type(element, &type);
134     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
135     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
136
137     hr = IXMLElement_get_text(element, &str);
138     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
139     ok(lstrlenW(str) == 0, "Expected empty text\n");
140     SysFreeString(str);
141
142     /* put_text with an ELEMENT */
143     str = SysAllocString(propVal);
144     hr = IXMLElement_put_text(element, str);
145     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
146     SysFreeString(str);
147
148     V_VT(&vType) = VT_I4;
149     V_I4(&vType) = XMLELEMTYPE_TEXT;
150     V_VT(&vName) = VT_NULL;
151     hr = IXMLDocument_createElement(doc, vType, vName, &child);
152     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
153     ok(child != NULL, "Expected non-NULL child\n");
154
155     hr = IXMLElement_addChild(element, child, 0, -1);
156     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
157
158     str = SysAllocString(propVal);
159     hr = IXMLElement_put_text(child, str);
160     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
161     SysFreeString(str);
162
163     parent = (IXMLElement *)0xdeadbeef;
164     hr = IXMLElement_get_parent(child, &parent);
165     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
166     ok(parent != element, "Expected parent != element\n");
167
168     hr = IXMLElement_get_type(parent, &type);
169     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
170     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
171
172     children = (IXMLElementCollection *)0xdeadbeef;
173     hr = IXMLElement_get_children(element, &children);
174     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
175     ok(children != NULL, "Expected non-NULL collection\n");
176
177     hr = IXMLElementCollection_get_length(children, &num_child);
178     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
179     ok(num_child == 1, "Expected 1, got %d\n", num_child);
180
181     V_VT(&vIndex) = VT_I4;
182     V_I4(&vIndex) = 0;
183     V_VT(&vName) = VT_ERROR;
184     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
185     hr = IXMLElementCollection_item(children, vIndex, vName, (IDispatch **)&child2);
186     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
187     ok(child2 != NULL, "Expected non-NULL child\n");
188
189     hr = IXMLElement_get_type(child2, &type);
190     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
191     ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %d\n", type);
192
193     hr = IXMLElement_get_text(element, &str);
194     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
195     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
196     SysFreeString(str);
197
198     hr = IXMLElement_get_text(child2, &str);
199     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
200     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
201     SysFreeString(str);
202
203     /* try put_text on ELEMENT again, now that it has a text child */
204     str = SysAllocString(nextVal);
205     hr = IXMLElement_put_text(element, str);
206     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
207     SysFreeString(str);
208
209     str = SysAllocString(nextVal);
210     hr = IXMLElement_put_text(child2, str);
211     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
212     SysFreeString(str);
213
214     hr = IXMLElement_get_text(element, &str);
215     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
216     ok(!lstrcmpW(str, nextVal), "Expected 'val'\n");
217     SysFreeString(str);
218
219     IXMLElement_Release(child2);
220     IXMLElementCollection_Release(children);
221     IXMLElement_Release(parent);
222     IXMLElement_Release(child);
223     IXMLElement_Release(element);
224     IXMLDocument_Release(doc);
225 }
226
227 static void create_xml_file(LPCSTR filename)
228 {
229     DWORD dwNumberOfBytesWritten;
230     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
231                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
232
233     static const char data[] =
234         "<?xml version=\"1.0\" ?>\n"
235         "<BankAccount>\n"
236         "  <Number>1234</Number>\n"
237         "  <Name>Captain Ahab</Name>\n"
238         "</BankAccount>\n";
239
240     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
241     CloseHandle(hf);
242 }
243
244 static void test_xmlelem_collection(void)
245 {
246     HRESULT hr;
247     IUnknown *unk = NULL;
248     IXMLDocument *doc = NULL;
249     IXMLElement *element = NULL, *child;
250     IXMLElementCollection *collection = NULL;
251     IEnumVARIANT *enumVar = NULL;
252     CHAR pathA[MAX_PATH];
253     WCHAR path[MAX_PATH];
254     LONG length, type;
255     ULONG num_vars;
256     VARIANT var, vIndex, vName;
257     BSTR url, str;
258     static const CHAR szBankXML[] = "bank.xml";
259     static const WCHAR szNumber[] = {'N','U','M','B','E','R',0};
260     static const WCHAR szName[] = {'N','A','M','E',0};
261
262     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
263                           &IID_IXMLDocument, (LPVOID*)&doc);
264     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
265
266     create_xml_file(szBankXML);
267     GetFullPathNameA(szBankXML, MAX_PATH, pathA, NULL);
268     MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
269
270     url = SysAllocString(path);
271     hr = IXMLDocument_put_URL(doc, url);
272     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
273     SysFreeString(url);
274
275     if(hr != S_OK)
276         goto cleanup;
277
278     hr = IXMLDocument_get_root(doc, &element);
279     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
280     ok(element != NULL, "Expected non-NULL element\n");
281
282     hr = IXMLElement_get_children(element, &collection);
283     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
284     ok(collection != NULL, "Expected non-NULL collection\n");
285
286     hr = IXMLElementCollection_get_length(collection, NULL);
287     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
288
289     hr = IXMLElementCollection_get_length(collection, &length);
290     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
291     ok(length == 2, "Expected 2, got %d\n", length);
292
293     /* IXMLElementCollection:put_length does nothing */
294     hr = IXMLElementCollection_put_length(collection, -1);
295     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
296
297     hr = IXMLElementCollection_put_length(collection, 0);
298     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
299
300     hr = IXMLElementCollection_put_length(collection, 1);
301     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
302
303     hr = IXMLElementCollection_put_length(collection, 2);
304     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
305
306     hr = IXMLElementCollection_put_length(collection, 3);
307     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
308
309     hr = IXMLElementCollection_put_length(collection, 50);
310     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
311
312     /* make sure the length hasn't changed */
313     hr = IXMLElementCollection_get_length(collection, &length);
314     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
315     ok(length == 2, "Expected 2, got %d\n", length);
316
317     /* IXMLElementCollection implements IEnumVARIANT */
318     hr = IXMLElementCollection_QueryInterface(collection, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
319     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
320     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
321     IEnumVARIANT_Release(enumVar);
322
323     hr = IXMLElementCollection_get__newEnum(collection, &unk);
324     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
325     ok(unk != NULL, "Expected non-NULL unk\n");
326
327     hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
328     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
329     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
330     IUnknown_Release(unk);
331
332     /* <Number>1234</Number> */
333     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
334     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
335     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
336     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
337
338     hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
339     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
340     ok(child != NULL, "Expected non-NULL child\n");
341
342     VariantClear(&var);
343
344     hr = IXMLElement_get_type(child, &type);
345     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
346     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
347
348     hr = IXMLElement_get_tagName(child, &str);
349     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
350     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
351     SysFreeString(str);
352     IXMLElement_Release(child);
353
354     /* <Name>Captain Ahab</Name> */
355     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
356     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
357     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
358     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
359
360     /* try advance further, no children left */
361     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
362     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
363     ok(V_VT(&var) == 0, "Expected 0, got %d\n", V_VT(&var));
364     ok(num_vars == 0, "Expected 0, got %d\n", num_vars);
365
366     hr = IEnumVARIANT_Next(enumVar, 1, &var, NULL);
367     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
368     ok(V_VT(&var) == 0, "Expected 0, got %d\n", V_VT(&var));
369
370     hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
371     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
372     ok(child != NULL, "Expected non-NULL child\n");
373
374     VariantClear(&var);
375
376     hr = IXMLElement_get_type(child, &type);
377     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
378     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
379
380     hr = IXMLElement_get_tagName(child, &str);
381     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
382     ok(!lstrcmpW(str, szName), "Expected NAME\n");
383     SysFreeString(str);
384     IXMLElement_Release(child);
385
386     /* <Number>1234</Number> */
387     V_VT(&vIndex) = VT_I4;
388     V_I4(&vIndex) = 0;
389     V_VT(&vName) = VT_ERROR;
390     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
391     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
392     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
393     ok(child != NULL, "Expected non-NULL child\n");
394
395     hr = IXMLElement_get_type(child, &type);
396     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
397     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
398
399     hr = IXMLElement_get_tagName(child, &str);
400     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
401     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
402     SysFreeString(str);
403     IXMLElement_Release(child);
404
405     /* <Name>Captain Ahab</Name> */
406     V_VT(&vIndex) = VT_I4;
407     V_I4(&vIndex) = 1;
408     V_VT(&vName) = VT_ERROR;
409     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
410     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
411     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
412     ok(child != NULL, "Expected non-NULL child\n");
413
414     hr = IXMLElement_get_type(child, &type);
415     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
416     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
417
418     hr = IXMLElement_get_tagName(child, &str);
419     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
420     ok(!lstrcmpW(str, szName), "Expected NAME\n");
421     SysFreeString(str);
422     IXMLElement_Release(child);
423
424     V_I4(&vIndex) = 100;
425     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
426     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
427     ok(child == NULL, "Expected NULL child\n");
428
429     V_I4(&vIndex) = -1;
430     child = (IXMLElement *)0xdeadbeef;
431     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
432     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
433     ok(child == NULL, "Expected NULL child\n");
434
435     IEnumVARIANT_Release(enumVar);
436     IXMLElement_Release(element);
437     IXMLElementCollection_Release(collection);
438 cleanup:
439     IXMLDocument_Release(doc);
440     DeleteFileA("bank.xml");
441 }
442
443 static void test_xmlelem_children(void)
444 {
445     IXMLDocument *doc = NULL;
446     IXMLElement *element = NULL, *child = NULL, *child2 = NULL;
447     IXMLElementCollection *collection = NULL;
448     VARIANT vType, vName, vIndex;
449     LONG length;
450     HRESULT hr;
451
452     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
453                           &IID_IXMLDocument, (LPVOID*)&doc);
454     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
455
456     V_VT(&vType) = VT_I4;
457     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
458     V_VT(&vName) = VT_NULL;
459     hr = IXMLDocument_createElement(doc, vType, vName, &element);
460     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
461     ok(element != NULL, "Expected non-NULL element\n");
462
463     V_VT(&vType) = VT_I4;
464     V_I4(&vType) = XMLELEMTYPE_TEXT;
465     V_VT(&vName) = VT_NULL;
466     hr = IXMLDocument_createElement(doc, vType, vName, &child);
467     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
468     ok(child != NULL, "Expected non-NULL child\n");
469
470     V_VT(&vType) = VT_I4;
471     V_I4(&vType) = XMLELEMTYPE_TEXT;
472     V_VT(&vName) = VT_NULL;
473     hr = IXMLDocument_createElement(doc, vType, vName, &child2);
474     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
475     ok(child2 != NULL, "Expected non-NULL child\n");
476
477     hr = IXMLElement_addChild(element, child, 0, -1);
478     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
479
480     hr = IXMLElement_get_children(element, &collection);
481     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
482     ok(collection != NULL, "Expected non-NULL collection\n");
483
484     length = 0;
485     hr = IXMLElementCollection_get_length(collection, &length);
486     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
487     ok(length == 1, "Expected 1, got %08x\n", length);
488
489     /* remove/add child and check what happens with collection */
490     hr = IXMLElement_removeChild(element, child);
491     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
492
493     length = -1;
494     hr = IXMLElementCollection_get_length(collection, &length);
495     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
496     ok(length == 0, "Expected 0, got %08x\n", length);
497     IXMLElementCollection_Release(collection);
498
499     hr = IXMLElement_AddRef(child);
500     ok(hr == 2, "Expected 2, got %08x\n", hr);
501     IXMLElement_Release(child);
502     hr = IXMLElement_addChild(element, child, 0, -1);
503     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
504     hr = IXMLElement_AddRef(child);
505     ok(hr == 2, "Expected 2, got %08x\n", hr);
506     IXMLElement_Release(child);
507     hr = IXMLElement_addChild(element, child2, 0, -1);
508     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
509
510     hr = IXMLElement_get_children(element, &collection);
511     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
512     ok(collection != NULL, "Expected non-NULL collection\n");
513
514     hr = IXMLElement_AddRef(child);
515     ok(hr == 2, "Expected 2, got %08x\n", hr);
516     IXMLElement_Release(child);
517
518     length = 0;
519     hr = IXMLElementCollection_get_length(collection, &length);
520     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
521     ok(length == 2, "Expected 2, got %08x\n", length);
522
523     IXMLElement_Release(child2);
524
525     length = 0;
526     hr = IXMLElementCollection_get_length(collection, &length);
527     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
528     ok(length == 2, "Expected 2, got %08x\n", length);
529
530     V_VT(&vIndex) = VT_I4;
531     V_I4(&vIndex) = 1;
532     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child2);
533     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
534     ok(child2 != NULL, "Expected not NULL child\n");
535     IXMLElementCollection_Release(collection);
536     IXMLElement_Release(child2);
537
538     /* add element->child->child2 structure, then remove child2 from node */
539     V_VT(&vType) = VT_I4;
540     V_I4(&vType) = XMLELEMTYPE_TEXT;
541     V_VT(&vName) = VT_NULL;
542     hr = IXMLDocument_createElement(doc, vType, vName, &child2);
543     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
544     ok(child2 != NULL, "Expected non-NULL child\n");
545
546     hr = IXMLElement_addChild(child, child2, 0, -1);
547     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
548
549     hr = IXMLElement_removeChild(element, child2);
550     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
551
552     hr = IXMLElement_removeChild(child, child2);
553     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
554
555     hr = IXMLElement_removeChild(child, NULL);
556     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
557
558     IXMLElement_Release(element);
559     IXMLElement_Release(child);
560     IXMLElement_Release(child2);
561     IXMLDocument_Release(doc);
562 }
563
564 static BOOL test_try_xmldoc(void)
565 {
566     IXMLDocument *doc = NULL;
567     HRESULT hr;
568
569     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
570                           &IID_IXMLDocument, (LPVOID*)&doc);
571     if (FAILED(hr))
572     {
573         skip("Failed to create XMLDocument instance\n");
574         return FALSE;
575     }
576
577     IXMLDocument_Release(doc);
578     return TRUE;
579 }
580
581 START_TEST(xmlelem)
582 {
583     HRESULT hr;
584
585     hr = CoInitialize(NULL);
586     ok(hr == S_OK, "failed to init com\n");
587
588     if (!test_try_xmldoc())
589     {
590         CoUninitialize();
591         return;
592     }
593
594     test_xmlelem();
595     test_xmlelem_collection();
596     test_xmlelem_children();
597
598     CoUninitialize();
599 }