From 9c04d0d8ca8811f5ddfc66c987c83a50075a1da9 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Thu, 24 May 2007 11:13:43 -0700 Subject: [PATCH] msxml3: Add tests for IXMLElement and IXMLElementCollection. --- dlls/msxml3/tests/Makefile.in | 3 +- dlls/msxml3/tests/xmlelem.c | 449 ++++++++++++++++++++++++++++++++++ 2 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 dlls/msxml3/tests/xmlelem.c diff --git a/dlls/msxml3/tests/Makefile.in b/dlls/msxml3/tests/Makefile.in index e1131b81a90..3e917d79783 100644 --- a/dlls/msxml3/tests/Makefile.in +++ b/dlls/msxml3/tests/Makefile.in @@ -8,7 +8,8 @@ EXTRALIBS = -luuid CTESTS = \ domdoc.c \ - schema.c + schema.c \ + xmlelem.c @MAKE_TEST_RULES@ diff --git a/dlls/msxml3/tests/xmlelem.c b/dlls/msxml3/tests/xmlelem.c new file mode 100644 index 00000000000..eea59f2a5a2 --- /dev/null +++ b/dlls/msxml3/tests/xmlelem.c @@ -0,0 +1,449 @@ +/* + * IXMLElement tests + * + * Copyright 2007 James Hawkins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include + +#include "windows.h" +#include "ole2.h" +#include "xmldom.h" +#include "msxml2.h" +#include "ocidl.h" + +#include "wine/test.h" + +static void test_xmlelem(void) +{ + HRESULT hr; + IXMLDocument *doc = NULL; + IXMLElement *element = NULL, *parent; + IXMLElement *child, *child2; + IXMLElementCollection *children; + VARIANT vType, vName; + VARIANT vIndex, vValue; + BSTR str, val; + long type, num_child; + + static const WCHAR propName[] = {'p','r','o','p',0}; + static const WCHAR propVal[] = {'v','a','l',0}; + static const WCHAR nextVal[] = {'n','e','x','t',0}; + static const WCHAR noexist[] = {'n','o','e','x','i','s','t',0}; + static const WCHAR crazyCase1[] = {'C','R','a','z','Y','c','A','S','E',0}; + static const WCHAR crazyCase2[] = {'C','R','A','Z','Y','C','A','S','E',0}; + + hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, + &IID_IXMLDocument, (LPVOID*)&doc); + if (FAILED(hr)) + { + skip("Failed to create XMLDocument instance\n"); + return; + } + + V_VT(&vType) = VT_I4; + V_I4(&vType) = XMLELEMTYPE_ELEMENT; + V_VT(&vName) = VT_NULL; + hr = IXMLDocument_createElement(doc, vType, vName, &element); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(element != NULL, "Expected non-NULL element\n"); + + hr = IXMLElement_get_tagName(element, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(lstrlenW(str) == 0, "Expected empty tag name\n"); + SysFreeString(str); + + parent = (IXMLElement *)0xdeadbeef; + hr = IXMLElement_get_parent(element, &parent); + ok(hr == 1, "Expected 1, got %d\n", hr); + ok(parent == NULL, "Expected NULL parent\n"); + + str = SysAllocString(noexist); + hr = IXMLElement_getAttribute(element, str, &vValue); + ok(hr == S_FALSE, "Expected S_FALSE, got %d\n", hr); + ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue)); + ok(lstrlenW(V_BSTR(&vValue)) == 0, "Expected empty value\n"); + VariantClear(&vValue); + SysFreeString(str); + + str = SysAllocString(crazyCase1); + val = SysAllocString(propVal); + V_VT(&vValue) = VT_BSTR; + V_BSTR(&vValue) = val; + hr = IXMLElement_setAttribute(element, str, vValue); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + SysFreeString(str); + SysFreeString(val); + + str = SysAllocString(crazyCase2); + hr = IXMLElement_getAttribute(element, str, &vValue); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue)); + ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n"); + VariantClear(&vValue); + SysFreeString(str); + + str = SysAllocString(propName); + val = SysAllocString(propVal); + V_VT(&vValue) = VT_BSTR; + V_BSTR(&vValue) = val; + hr = IXMLElement_setAttribute(element, str, vValue); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + SysFreeString(val); + + hr = IXMLElement_getAttribute(element, str, &vValue); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue)); + ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n"); + VariantClear(&vValue); + + hr = IXMLElement_removeAttribute(element, str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + + /* remove now non-existent attribute */ + hr = IXMLElement_removeAttribute(element, str); + ok(hr == S_FALSE, "Expected S_FALSE, got %d\n", hr); + + hr = IXMLElement_getAttribute(element, str, &vValue); + ok(hr == 1, "Expected 1, got %d\n", hr); + ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue)); + ok(!lstrlenW(V_BSTR(&vValue)), "Expected empty value\n"); + SysFreeString(str); + VariantClear(&vValue); + + children = (IXMLElementCollection *)0xdeadbeef; + hr = IXMLElement_get_children(element, &children); + ok(hr == 1, "Expected 1, got %d\n", hr); + ok(children == NULL, "Expected NULL collection\n"); + + hr = IXMLElement_get_type(element, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type); + + hr = IXMLElement_get_text(element, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(lstrlenW(str) == 0, "Expected empty text\n"); + SysFreeString(str); + + /* put_text with an ELEMENT */ + str = SysAllocString(propVal); + hr = IXMLElement_put_text(element, str); + ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %d\n", hr); + SysFreeString(str); + + V_VT(&vType) = VT_I4; + V_I4(&vType) = XMLELEMTYPE_TEXT; + V_VT(&vName) = VT_NULL; + hr = IXMLDocument_createElement(doc, vType, vName, &child); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(child != NULL, "Expected non-NULL child\n"); + + hr = IXMLElement_addChild(element, child, 0, -1); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + + str = SysAllocString(propVal); + hr = IXMLElement_put_text(child, str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + SysFreeString(str); + + parent = (IXMLElement *)0xdeadbeef; + hr = IXMLElement_get_parent(child, &parent); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(parent != element, "Expected parent != element\n"); + + hr = IXMLElement_get_type(parent, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type); + + children = (IXMLElementCollection *)0xdeadbeef; + hr = IXMLElement_get_children(element, &children); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(children != NULL, "Expected non-NULL collection\n"); + + hr = IXMLElementCollection_get_length(children, &num_child); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(num_child == 1, "Expected 1, got %ld\n", num_child); + + V_VT(&vIndex) = VT_I4; + V_I4(&vIndex) = 0; + V_VT(&vName) = VT_ERROR; + V_ERROR(&vName) = DISP_E_PARAMNOTFOUND; + hr = IXMLElementCollection_item(children, vIndex, vName, (IDispatch **)&child2); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(child2 != NULL, "Expected non-NULL child\n"); + + hr = IXMLElement_get_type(child2, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %ld\n", type); + + hr = IXMLElement_get_text(element, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, propVal), "Expected 'val'\n"); + SysFreeString(str); + + hr = IXMLElement_get_text(child2, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, propVal), "Expected 'val'\n"); + SysFreeString(str); + + /* try put_text on ELEMENT again, now that it has a text child */ + str = SysAllocString(nextVal); + hr = IXMLElement_put_text(element, str); + ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %d\n", hr); + SysFreeString(str); + + str = SysAllocString(nextVal); + hr = IXMLElement_put_text(child2, str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + SysFreeString(str); + + hr = IXMLElement_get_text(element, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, nextVal), "Expected 'val'\n"); + SysFreeString(str); + + IXMLElement_Release(child2); + IXMLElementCollection_Release(children); + IXMLElement_Release(parent); + IXMLElement_Release(child); + IXMLElement_Release(element); + IXMLDocument_Release(doc); +} + +static void append_str(char **str, const char *data) +{ + sprintf(*str, data); + *str += strlen(*str); +} + +static void create_xml_file(LPCSTR filename) +{ + char data[1024]; + char *ptr = data; + DWORD dwNumberOfBytesWritten; + HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + append_str(&ptr, "\n"); + append_str(&ptr, "\n"); + append_str(&ptr, " 1234\n"); + append_str(&ptr, " Captain Ahab\n"); + append_str(&ptr, "\n"); + + WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL); + CloseHandle(hf); +} + +static void test_xmlelem_collection(void) +{ + HRESULT hr; + IUnknown *unk = NULL; + IXMLDocument *doc = NULL; + IXMLElement *element = NULL, *child; + IXMLElementCollection *collection = NULL; + IEnumVARIANT *enumVar = NULL; + WCHAR path[MAX_PATH]; + long length, type; + ULONG num_vars; + VARIANT var, vIndex, vName; + BSTR url, str; + + static const WCHAR szBankXML[] = {'b','a','n','k','.','x','m','l',0}; + static const WCHAR szNumber[] = {'N','U','M','B','E','R',0}; + static const WCHAR szName[] = {'N','A','M','E',0}; + + hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, + &IID_IXMLDocument, (LPVOID*)&doc); + if (FAILED(hr)) + { + skip("Failed to create XMLDocument instance\n"); + return; + } + + create_xml_file("bank.xml"); + GetFullPathNameW(szBankXML, MAX_PATH, path, NULL); + + url = SysAllocString(path); + hr = IXMLDocument_put_URL(doc, url); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + SysFreeString(url); + + hr = IXMLDocument_get_root(doc, &element); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(element != NULL, "Expected non-NULL element\n"); + + hr = IXMLElement_get_children(element, &collection); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(collection != NULL, "Expected non-NULL collection\n"); + + hr = IXMLElementCollection_get_length(collection, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr); + + hr = IXMLElementCollection_get_length(collection, &length); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(length == 2, "Expected 2, got %ld\n", length); + + /* IXMLElementCollection:put_length does nothing */ + hr = IXMLElementCollection_put_length(collection, -1); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + + hr = IXMLElementCollection_put_length(collection, 0); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + + hr = IXMLElementCollection_put_length(collection, 1); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + + hr = IXMLElementCollection_put_length(collection, 2); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + + hr = IXMLElementCollection_put_length(collection, 3); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + + hr = IXMLElementCollection_put_length(collection, 50); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + + /* make sure the length hasn't changed */ + hr = IXMLElementCollection_get_length(collection, &length); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(length == 2, "Expected 2, got %ld\n", length); + + /* IXMLElementCollection implements IEnumVARIANT */ + hr = IXMLElementCollection_QueryInterface(collection, &IID_IEnumVARIANT, (LPVOID *)&enumVar); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(enumVar != NULL, "Expected non-NULL enumVar\n"); + IEnumVARIANT_Release(enumVar); + + hr = IXMLElementCollection_get__newEnum(collection, &unk); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(unk != NULL, "Expected non-NULL unk\n"); + + hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (LPVOID *)&enumVar); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(enumVar != NULL, "Expected non-NULL enumVar\n"); + IUnknown_Release(unk); + + /* 1234 */ + hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var)); + ok(num_vars == 1, "Expected 1, got %d\n", 1); + + hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(child != NULL, "Expected non-NULL child\n"); + + VariantClear(&var); + + hr = IXMLElement_get_type(child, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type); + + hr = IXMLElement_get_tagName(child, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n"); + SysFreeString(str); + IXMLElement_Release(child); + + /* Captain Ahab */ + hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var)); + ok(num_vars == 1, "Expected 1, got %d\n", 1); + + hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(child != NULL, "Expected non-NULL child\n"); + + VariantClear(&var); + + hr = IXMLElement_get_type(child, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type); + + hr = IXMLElement_get_tagName(child, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, szName), "Expected NAME\n"); + SysFreeString(str); + IXMLElement_Release(child); + + /* 1234 */ + V_VT(&vIndex) = VT_I4; + V_I4(&vIndex) = 0; + V_VT(&vName) = VT_ERROR; + V_ERROR(&vName) = DISP_E_PARAMNOTFOUND; + hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(child != NULL, "Expected non-NULL child\n"); + + hr = IXMLElement_get_type(child, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type); + + hr = IXMLElement_get_tagName(child, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n"); + SysFreeString(str); + IXMLElement_Release(child); + + /* Captain Ahab */ + V_VT(&vIndex) = VT_I4; + V_I4(&vIndex) = 1; + V_VT(&vName) = VT_ERROR; + V_ERROR(&vName) = DISP_E_PARAMNOTFOUND; + hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(child != NULL, "Expected non-NULL child\n"); + + hr = IXMLElement_get_type(child, &type); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %ld\n", type); + + hr = IXMLElement_get_tagName(child, &str); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + ok(!lstrcmpW(str, szName), "Expected NAME\n"); + SysFreeString(str); + IXMLElement_Release(child); + + V_I4(&vIndex) = 100; + hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child); + ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr); + ok(child == NULL, "Expected NULL child\n"); + + V_I4(&vIndex) = -1; + child = (IXMLElement *)0xdeadbeef; + hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr); + ok(child == NULL, "Expected NULL child\n"); + + IXMLElement_Release(element); + IXMLElementCollection_Release(collection); + IXMLDocument_Release(doc); + DeleteFileA("bank.xml"); +} + +START_TEST(xmlelem) +{ + HRESULT hr; + + hr = CoInitialize(NULL); + ok(hr == S_OK, "failed to init com\n"); + + test_xmlelem(); + test_xmlelem_collection(); +}