4 * Copyright 2007 James Hawkins
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.
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.
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
31 #include "wine/test.h"
33 #define ERROR_URL_NOT_FOUND 0x800c0006
35 static void test_xmlelem(void)
38 IXMLDocument
*doc
= NULL
;
39 IXMLElement
*element
= NULL
, *parent
;
40 IXMLElement
*child
, *child2
;
41 IXMLElementCollection
*children
;
43 VARIANT vIndex
, vValue
;
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};
54 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
,
55 &IID_IXMLDocument
, (LPVOID
*)&doc
);
58 skip("Failed to create XMLDocument instance\n");
63 V_I4(&vType
) = XMLELEMTYPE_ELEMENT
;
64 V_VT(&vName
) = VT_NULL
;
65 hr
= IXMLDocument_createElement(doc
, vType
, vName
, &element
);
66 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
67 ok(element
!= NULL
, "Expected non-NULL element\n");
69 hr
= IXMLElement_get_tagName(element
, &str
);
70 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
71 ok(lstrlenW(str
) == 0, "Expected empty tag name\n");
74 parent
= (IXMLElement
*)0xdeadbeef;
75 hr
= IXMLElement_get_parent(element
, &parent
);
76 ok(hr
== 1, "Expected 1, got %08x\n", hr
);
77 ok(parent
== NULL
, "Expected NULL parent\n");
79 str
= SysAllocString(noexist
);
80 hr
= IXMLElement_getAttribute(element
, str
, &vValue
);
81 ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
82 ok(V_VT(&vValue
) == VT_EMPTY
, "Expected VT_EMPTY, got %d\n", V_VT(&vValue
));
83 ok(V_BSTR(&vValue
) == NULL
, "Expected null value\n");
84 VariantClear(&vValue
);
87 str
= SysAllocString(crazyCase1
);
88 val
= SysAllocString(propVal
);
89 V_VT(&vValue
) = VT_BSTR
;
90 V_BSTR(&vValue
) = val
;
91 hr
= IXMLElement_setAttribute(element
, str
, vValue
);
92 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
96 str
= SysAllocString(crazyCase2
);
97 hr
= IXMLElement_getAttribute(element
, str
, &vValue
);
98 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
99 ok(V_VT(&vValue
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&vValue
));
100 ok(!lstrcmpW(V_BSTR(&vValue
), propVal
), "Expected 'val'\n");
101 VariantClear(&vValue
);
104 str
= SysAllocString(propName
);
105 val
= SysAllocString(propVal
);
106 V_VT(&vValue
) = VT_BSTR
;
107 V_BSTR(&vValue
) = val
;
108 hr
= IXMLElement_setAttribute(element
, str
, vValue
);
109 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
112 hr
= IXMLElement_getAttribute(element
, str
, &vValue
);
113 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
114 ok(V_VT(&vValue
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&vValue
));
115 ok(!lstrcmpW(V_BSTR(&vValue
), propVal
), "Expected 'val'\n");
116 VariantClear(&vValue
);
118 hr
= IXMLElement_removeAttribute(element
, str
);
119 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
121 /* remove now nonexistent attribute */
122 hr
= IXMLElement_removeAttribute(element
, str
);
123 ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
125 hr
= IXMLElement_getAttribute(element
, str
, &vValue
);
126 ok(hr
== 1, "Expected 1, got %08x\n", hr
);
127 ok(V_VT(&vValue
) == VT_EMPTY
, "Expected VT_EMPTY, got %d\n", V_VT(&vValue
));
128 ok(V_BSTR(&vValue
) == NULL
, "Expected null value\n");
130 VariantClear(&vValue
);
132 children
= (IXMLElementCollection
*)0xdeadbeef;
133 hr
= IXMLElement_get_children(element
, &children
);
134 ok(hr
== 1, "Expected 1, got %08x\n", hr
);
135 ok(children
== NULL
, "Expected NULL collection\n");
137 hr
= IXMLElement_get_type(element
, &type
);
138 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
139 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type
);
141 hr
= IXMLElement_get_text(element
, &str
);
142 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
143 ok(lstrlenW(str
) == 0, "Expected empty text\n");
146 /* put_text with an ELEMENT */
147 str
= SysAllocString(propVal
);
148 hr
= IXMLElement_put_text(element
, str
);
149 ok(hr
== E_NOTIMPL
, "Expected E_NOTIMPL, got %08x\n", hr
);
152 V_VT(&vType
) = VT_I4
;
153 V_I4(&vType
) = XMLELEMTYPE_TEXT
;
154 V_VT(&vName
) = VT_NULL
;
155 hr
= IXMLDocument_createElement(doc
, vType
, vName
, &child
);
156 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
157 ok(child
!= NULL
, "Expected non-NULL child\n");
159 hr
= IXMLElement_addChild(element
, child
, 0, -1);
160 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
162 str
= SysAllocString(propVal
);
163 hr
= IXMLElement_put_text(child
, str
);
164 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
167 parent
= (IXMLElement
*)0xdeadbeef;
168 hr
= IXMLElement_get_parent(child
, &parent
);
169 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
170 ok(parent
!= element
, "Expected parent != element\n");
172 hr
= IXMLElement_get_type(parent
, &type
);
173 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
174 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type
);
176 children
= (IXMLElementCollection
*)0xdeadbeef;
177 hr
= IXMLElement_get_children(element
, &children
);
178 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
179 ok(children
!= NULL
, "Expected non-NULL collection\n");
181 hr
= IXMLElementCollection_get_length(children
, &num_child
);
182 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
183 ok(num_child
== 1, "Expected 1, got %ld\n", num_child
);
185 V_VT(&vIndex
) = VT_I4
;
187 V_VT(&vName
) = VT_ERROR
;
188 V_ERROR(&vName
) = DISP_E_PARAMNOTFOUND
;
189 hr
= IXMLElementCollection_item(children
, vIndex
, vName
, (IDispatch
**)&child2
);
190 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
191 ok(child2
!= NULL
, "Expected non-NULL child\n");
193 hr
= IXMLElement_get_type(child2
, &type
);
194 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
195 ok(type
== XMLELEMTYPE_TEXT
, "Expected XMLELEMTYPE_TEXT, got %ld\n", type
);
197 hr
= IXMLElement_get_text(element
, &str
);
198 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
199 ok(!lstrcmpW(str
, propVal
), "Expected 'val'\n");
202 hr
= IXMLElement_get_text(child2
, &str
);
203 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
204 ok(!lstrcmpW(str
, propVal
), "Expected 'val'\n");
207 /* try put_text on ELEMENT again, now that it has a text child */
208 str
= SysAllocString(nextVal
);
209 hr
= IXMLElement_put_text(element
, str
);
210 ok(hr
== E_NOTIMPL
, "Expected E_NOTIMPL, got %08x\n", hr
);
213 str
= SysAllocString(nextVal
);
214 hr
= IXMLElement_put_text(child2
, str
);
215 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
218 hr
= IXMLElement_get_text(element
, &str
);
219 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
220 ok(!lstrcmpW(str
, nextVal
), "Expected 'val'\n");
223 IXMLElement_Release(child2
);
224 IXMLElementCollection_Release(children
);
225 IXMLElement_Release(parent
);
226 IXMLElement_Release(child
);
227 IXMLElement_Release(element
);
228 IXMLDocument_Release(doc
);
231 static void append_str(char **str
, const char *data
)
234 *str
+= strlen(*str
);
237 static void create_xml_file(LPCSTR filename
)
241 DWORD dwNumberOfBytesWritten
;
242 HANDLE hf
= CreateFile(filename
, GENERIC_WRITE
, 0, NULL
,
243 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
245 append_str(&ptr
, "<?xml version=\"1.0\" ?>\n");
246 append_str(&ptr
, "<BankAccount>\n");
247 append_str(&ptr
, " <Number>1234</Number>\n");
248 append_str(&ptr
, " <Name>Captain Ahab</Name>\n");
249 append_str(&ptr
, "</BankAccount>\n");
251 WriteFile(hf
, data
, ptr
- data
, &dwNumberOfBytesWritten
, NULL
);
255 static void test_xmlelem_collection(void)
258 IUnknown
*unk
= NULL
;
259 IXMLDocument
*doc
= NULL
;
260 IXMLElement
*element
= NULL
, *child
;
261 IXMLElementCollection
*collection
= NULL
;
262 IEnumVARIANT
*enumVar
= NULL
;
263 WCHAR path
[MAX_PATH
];
266 VARIANT var
, vIndex
, vName
;
269 static const WCHAR szBankXML
[] = {'b','a','n','k','.','x','m','l',0};
270 static const WCHAR szNumber
[] = {'N','U','M','B','E','R',0};
271 static const WCHAR szName
[] = {'N','A','M','E',0};
273 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
,
274 &IID_IXMLDocument
, (LPVOID
*)&doc
);
277 skip("Failed to create XMLDocument instance\n");
281 create_xml_file("bank.xml");
282 GetFullPathNameW(szBankXML
, MAX_PATH
, path
, NULL
);
284 url
= SysAllocString(path
);
285 hr
= IXMLDocument_put_URL(doc
, url
);
286 /* Win98 returns ERROR_URL_NOT_FOUND */
287 ok(hr
== S_OK
|| hr
== ERROR_URL_NOT_FOUND
, "Expected S_OK, got 0x%08x\n", hr
);
293 hr
= IXMLDocument_get_root(doc
, &element
);
294 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
295 ok(element
!= NULL
, "Expected non-NULL element\n");
297 hr
= IXMLElement_get_children(element
, &collection
);
298 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
299 ok(collection
!= NULL
, "Expected non-NULL collection\n");
301 hr
= IXMLElementCollection_get_length(collection
, NULL
);
302 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
304 hr
= IXMLElementCollection_get_length(collection
, &length
);
305 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
306 ok(length
== 2, "Expected 2, got %ld\n", length
);
308 /* IXMLElementCollection:put_length does nothing */
309 hr
= IXMLElementCollection_put_length(collection
, -1);
310 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
312 hr
= IXMLElementCollection_put_length(collection
, 0);
313 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
315 hr
= IXMLElementCollection_put_length(collection
, 1);
316 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
318 hr
= IXMLElementCollection_put_length(collection
, 2);
319 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
321 hr
= IXMLElementCollection_put_length(collection
, 3);
322 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
324 hr
= IXMLElementCollection_put_length(collection
, 50);
325 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
327 /* make sure the length hasn't changed */
328 hr
= IXMLElementCollection_get_length(collection
, &length
);
329 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
330 ok(length
== 2, "Expected 2, got %ld\n", length
);
332 /* IXMLElementCollection implements IEnumVARIANT */
333 hr
= IXMLElementCollection_QueryInterface(collection
, &IID_IEnumVARIANT
, (LPVOID
*)&enumVar
);
334 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
335 ok(enumVar
!= NULL
, "Expected non-NULL enumVar\n");
336 IEnumVARIANT_Release(enumVar
);
338 hr
= IXMLElementCollection_get__newEnum(collection
, &unk
);
339 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
340 ok(unk
!= NULL
, "Expected non-NULL unk\n");
342 hr
= IUnknown_QueryInterface(unk
, &IID_IEnumVARIANT
, (LPVOID
*)&enumVar
);
343 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
344 ok(enumVar
!= NULL
, "Expected non-NULL enumVar\n");
345 IUnknown_Release(unk
);
347 /* <Number>1234</Number> */
348 hr
= IEnumVARIANT_Next(enumVar
, 1, &var
, &num_vars
);
349 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
350 ok(V_VT(&var
) == VT_DISPATCH
, "Expected VT_DISPATCH, got %d\n", V_VT(&var
));
351 ok(num_vars
== 1, "Expected 1, got %d\n", num_vars
);
353 hr
= IUnknown_QueryInterface(V_DISPATCH(&var
), &IID_IXMLElement
, (LPVOID
*)&child
);
354 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
355 ok(child
!= NULL
, "Expected non-NULL child\n");
359 hr
= IXMLElement_get_type(child
, &type
);
360 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
361 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type
);
363 hr
= IXMLElement_get_tagName(child
, &str
);
364 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
365 ok(!lstrcmpW(str
, szNumber
), "Expected NUMBER\n");
367 IXMLElement_Release(child
);
369 /* <Name>Captain Ahab</Name> */
370 hr
= IEnumVARIANT_Next(enumVar
, 1, &var
, &num_vars
);
371 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
372 ok(V_VT(&var
) == VT_DISPATCH
, "Expected VT_DISPATCH, got %d\n", V_VT(&var
));
373 ok(num_vars
== 1, "Expected 1, got %d\n", num_vars
);
375 hr
= IUnknown_QueryInterface(V_DISPATCH(&var
), &IID_IXMLElement
, (LPVOID
*)&child
);
376 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
377 ok(child
!= NULL
, "Expected non-NULL child\n");
381 hr
= IXMLElement_get_type(child
, &type
);
382 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
383 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type
);
385 hr
= IXMLElement_get_tagName(child
, &str
);
386 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
387 ok(!lstrcmpW(str
, szName
), "Expected NAME\n");
389 IXMLElement_Release(child
);
391 /* <Number>1234</Number> */
392 V_VT(&vIndex
) = VT_I4
;
394 V_VT(&vName
) = VT_ERROR
;
395 V_ERROR(&vName
) = DISP_E_PARAMNOTFOUND
;
396 hr
= IXMLElementCollection_item(collection
, vIndex
, vName
, (IDispatch
**)&child
);
397 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
398 ok(child
!= NULL
, "Expected non-NULL child\n");
400 hr
= IXMLElement_get_type(child
, &type
);
401 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
402 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type
);
404 hr
= IXMLElement_get_tagName(child
, &str
);
405 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
406 ok(!lstrcmpW(str
, szNumber
), "Expected NUMBER\n");
408 IXMLElement_Release(child
);
410 /* <Name>Captain Ahab</Name> */
411 V_VT(&vIndex
) = VT_I4
;
413 V_VT(&vName
) = VT_ERROR
;
414 V_ERROR(&vName
) = DISP_E_PARAMNOTFOUND
;
415 hr
= IXMLElementCollection_item(collection
, vIndex
, vName
, (IDispatch
**)&child
);
416 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
417 ok(child
!= NULL
, "Expected non-NULL child\n");
419 hr
= IXMLElement_get_type(child
, &type
);
420 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
421 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type
);
423 hr
= IXMLElement_get_tagName(child
, &str
);
424 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
425 ok(!lstrcmpW(str
, szName
), "Expected NAME\n");
427 IXMLElement_Release(child
);
430 hr
= IXMLElementCollection_item(collection
, vIndex
, vName
, (IDispatch
**)&child
);
431 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
432 ok(child
== NULL
, "Expected NULL child\n");
435 child
= (IXMLElement
*)0xdeadbeef;
436 hr
= IXMLElementCollection_item(collection
, vIndex
, vName
, (IDispatch
**)&child
);
437 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
438 ok(child
== NULL
, "Expected NULL child\n");
440 IEnumVARIANT_Release(enumVar
);
441 IXMLElement_Release(element
);
442 IXMLElementCollection_Release(collection
);
444 IXMLDocument_Release(doc
);
445 DeleteFileA("bank.xml");
452 hr
= CoInitialize(NULL
);
453 ok(hr
== S_OK
, "failed to init com\n");
456 test_xmlelem_collection();