|
| 1 | +/* |
| 2 | + * XML test |
| 3 | + * |
| 4 | + * Copyright 2005 Mike McCormack for CodeWeavers |
| 5 | + * Copyright 2007-2008 Alistair Leslie-Hughes |
| 6 | + * Copyright 2010-2011 Adam Martinson for CodeWeavers |
| 7 | + * Copyright 2010-2013 Nikolay Sivov for CodeWeavers |
| 8 | + * Copyright 2023 Daniel Lehman |
| 9 | + * |
| 10 | + * This library is free software; you can redistribute it and/or |
| 11 | + * modify it under the terms of the GNU Lesser General Public |
| 12 | + * License as published by the Free Software Foundation; either |
| 13 | + * version 2.1 of the License, or (at your option) any later version. |
| 14 | + * |
| 15 | + * This library is distributed in the hope that it will be useful, |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 18 | + * Lesser General Public License for more details. |
| 19 | + * |
| 20 | + * You should have received a copy of the GNU Lesser General Public |
| 21 | + * License along with this library; if not, write to the Free Software |
| 22 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| 23 | + */ |
| 24 | + |
| 25 | + |
| 26 | +#define COBJMACROS |
| 27 | +#define CONST_VTABLE |
| 28 | + |
| 29 | +#include <stdio.h> |
| 30 | +#include <assert.h> |
| 31 | + |
| 32 | +#include "windows.h" |
| 33 | + |
| 34 | +#include "initguid.h" |
| 35 | +#include "msxml2.h" |
| 36 | + |
| 37 | +#include "wine/test.h" |
| 38 | + |
| 39 | +static BSTR alloced_bstrs[256]; |
| 40 | +static int alloced_bstrs_count; |
| 41 | + |
| 42 | +static BSTR _bstr_(const WCHAR *str) |
| 43 | +{ |
| 44 | + assert(alloced_bstrs_count < ARRAY_SIZE(alloced_bstrs)); |
| 45 | + alloced_bstrs[alloced_bstrs_count] = SysAllocString(str); |
| 46 | + return alloced_bstrs[alloced_bstrs_count++]; |
| 47 | +} |
| 48 | + |
| 49 | +static void free_bstrs(void) |
| 50 | +{ |
| 51 | + int i; |
| 52 | + for (i = 0; i < alloced_bstrs_count; i++) |
| 53 | + SysFreeString(alloced_bstrs[i]); |
| 54 | + alloced_bstrs_count = 0; |
| 55 | +} |
| 56 | + |
| 57 | +struct attrtest_t { |
| 58 | + const WCHAR *name; |
| 59 | + const WCHAR *uri; |
| 60 | + const WCHAR *prefix; |
| 61 | + const WCHAR *href; |
| 62 | +}; |
| 63 | + |
| 64 | +static struct attrtest_t attrtests[] = { |
| 65 | + { L"xmlns", L"http://www.w3.org/2000/xmlns/", L"xmlns", L"xmlns" }, |
| 66 | + { L"xmlns", L"nondefaulturi", L"xmlns", L"xmlns" }, |
| 67 | + { L"c", L"http://www.w3.org/2000/xmlns/", NULL, L"http://www.w3.org/2000/xmlns/" }, |
| 68 | + { L"c", L"nsref1", NULL, L"nsref1" }, |
| 69 | + { L"ns:c", L"nsref1", L"ns", L"nsref1" }, |
| 70 | + { L"xmlns:c", L"http://www.w3.org/2000/xmlns/", L"xmlns", L"" }, |
| 71 | + { L"xmlns:c", L"nondefaulturi", L"xmlns", L"" }, |
| 72 | + { 0 } |
| 73 | +}; |
| 74 | + |
| 75 | +/* see dlls/msxml[36]/tests/domdoc.c */ |
| 76 | +static void test_create_attribute(void) |
| 77 | +{ |
| 78 | + struct attrtest_t *ptr = attrtests; |
| 79 | + IXMLDOMElement *el; |
| 80 | + IXMLDOMDocument2 *doc; |
| 81 | + IXMLDOMNode *node; |
| 82 | + VARIANT var; |
| 83 | + HRESULT hr; |
| 84 | + int i = 0; |
| 85 | + BSTR str; |
| 86 | + |
| 87 | + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); |
| 88 | + ok(hr == S_OK, "Failed to create DOMDocument40, hr %#lx.\n", hr); |
| 89 | + |
| 90 | + while (ptr->name) |
| 91 | + { |
| 92 | + V_VT(&var) = VT_I1; |
| 93 | + V_I1(&var) = NODE_ATTRIBUTE; |
| 94 | + hr = IXMLDOMDocument2_createNode(doc, var, _bstr_(ptr->name), _bstr_(ptr->uri), &node); |
| 95 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 96 | + |
| 97 | + str = NULL; |
| 98 | + hr = IXMLDOMNode_get_prefix(node, &str); |
| 99 | + if (ptr->prefix) |
| 100 | + { |
| 101 | + /* MSXML4 can report different results with different service packs */ |
| 102 | + ok(hr == S_OK || broken(hr == S_FALSE), "Failed to get prefix, hr %#lx.\n", hr); |
| 103 | + ok(!lstrcmpW(str, _bstr_(ptr->prefix)) || broken(!str), "got %s\n", wine_dbgstr_w(str)); |
| 104 | + } |
| 105 | + else |
| 106 | + { |
| 107 | + ok(hr == S_FALSE, "%d: unexpected hr %#lx\n", i, hr); |
| 108 | + ok(str == NULL, "%d: got prefix %s\n", i, wine_dbgstr_w(str)); |
| 109 | + } |
| 110 | + SysFreeString(str); |
| 111 | + |
| 112 | + str = NULL; |
| 113 | + hr = IXMLDOMNode_get_namespaceURI(node, &str); |
| 114 | + ok(hr == S_OK, "%d: unexpected hr %#lx\n", i, hr); |
| 115 | + ok(!lstrcmpW(str, _bstr_(ptr->href)), "%d: got uri %s, expected %s\n", |
| 116 | + i, wine_dbgstr_w(str), wine_dbgstr_w(ptr->href)); |
| 117 | + SysFreeString(str); |
| 118 | + |
| 119 | + IXMLDOMNode_Release(node); |
| 120 | + free_bstrs(); |
| 121 | + |
| 122 | + i++; |
| 123 | + ptr++; |
| 124 | + } |
| 125 | + |
| 126 | + V_VT(&var) = VT_I1; |
| 127 | + V_I1(&var) = NODE_ELEMENT; |
| 128 | + hr = IXMLDOMDocument2_createNode(doc, var, _bstr_(L"e"), NULL, &node); |
| 129 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 130 | + |
| 131 | + hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&el); |
| 132 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 133 | + IXMLDOMNode_Release(node); |
| 134 | + |
| 135 | + V_VT(&var) = VT_I1; |
| 136 | + V_I1(&var) = NODE_ATTRIBUTE; |
| 137 | + hr = IXMLDOMDocument2_createNode(doc, var, _bstr_(L"xmlns:a"), |
| 138 | + _bstr_(L"http://www.w3.org/2000/xmlns/"), &node); |
| 139 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 140 | + |
| 141 | + hr = IXMLDOMElement_setAttributeNode(el, (IXMLDOMAttribute*)node, NULL); |
| 142 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 143 | + |
| 144 | + /* for some reason default namespace uri is not reported */ |
| 145 | + hr = IXMLDOMNode_get_namespaceURI(node, &str); |
| 146 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 147 | + ok(!lstrcmpW(str, L""), "got uri %s\n", wine_dbgstr_w(str)); |
| 148 | + SysFreeString(str); |
| 149 | + |
| 150 | + IXMLDOMNode_Release(node); |
| 151 | + IXMLDOMElement_Release(el); |
| 152 | + IXMLDOMDocument2_Release(doc); |
| 153 | + free_bstrs(); |
| 154 | +} |
| 155 | + |
| 156 | +/* see dlls/msxml[36]/tests/domdoc.c */ |
| 157 | +static void test_namespaces_as_attributes(void) |
| 158 | +{ |
| 159 | + struct test |
| 160 | + { |
| 161 | + const WCHAR *xml; |
| 162 | + int explen; |
| 163 | + const WCHAR *names[3]; |
| 164 | + const WCHAR *prefixes[3]; |
| 165 | + const WCHAR *basenames[3]; |
| 166 | + const WCHAR *uris[3]; |
| 167 | + const WCHAR *texts[3]; |
| 168 | + const WCHAR *xmls[3]; |
| 169 | + }; |
| 170 | + static const struct test tests[] = |
| 171 | + { |
| 172 | + { |
| 173 | + L"<a ns:b=\"b attr\" d=\"d attr\" xmlns:ns=\"nshref\" />", 3, |
| 174 | + { L"ns:b", L"d", L"xmlns:ns" }, /* nodeName */ |
| 175 | + { L"ns", NULL, L"xmlns" }, /* prefix */ |
| 176 | + { L"b", L"d", L"ns" }, /* baseName */ |
| 177 | + { L"nshref", NULL, L"" }, /* namespaceURI */ |
| 178 | + { L"b attr", L"d attr", L"nshref" }, /* text */ |
| 179 | + { L"ns:b=\"b attr\"", L"d=\"d attr\"", L"xmlns:ns=\"nshref\"" }, /* xml */ |
| 180 | + }, |
| 181 | + /* property only */ |
| 182 | + { |
| 183 | + L"<a d=\"d attr\" />", 1, |
| 184 | + { L"d" }, /* nodeName */ |
| 185 | + { NULL }, /* prefix */ |
| 186 | + { L"d" }, /* baseName */ |
| 187 | + { NULL }, /* namespaceURI */ |
| 188 | + { L"d attr" }, /* text */ |
| 189 | + { L"d=\"d attr\"" }, /* xml */ |
| 190 | + }, |
| 191 | + /* namespace only */ |
| 192 | + { |
| 193 | + L"<a xmlns:ns=\"nshref\" />", 1, |
| 194 | + { L"xmlns:ns" }, /* nodeName */ |
| 195 | + { L"xmlns" }, /* prefix */ |
| 196 | + { L"ns" }, /* baseName */ |
| 197 | + { L"" }, /* namespaceURI */ |
| 198 | + { L"nshref" }, /* text */ |
| 199 | + { L"xmlns:ns=\"nshref\"" }, /* xml */ |
| 200 | + }, |
| 201 | + /* default namespace */ |
| 202 | + { |
| 203 | + L"<a xmlns=\"nshref\" />", 1, |
| 204 | + { L"xmlns" }, /* nodeName */ |
| 205 | + { L"xmlns" }, /* prefix */ |
| 206 | + { L"" }, /* baseName */ |
| 207 | + { L"" }, /* namespaceURI */ |
| 208 | + { L"nshref" }, /* text */ |
| 209 | + { L"xmlns=\"nshref\"" }, /* xml */ |
| 210 | + }, |
| 211 | + /* no properties or namespaces */ |
| 212 | + { |
| 213 | + L"<a />", 0, |
| 214 | + }, |
| 215 | + |
| 216 | + { NULL } |
| 217 | + }; |
| 218 | + const struct test *test; |
| 219 | + IXMLDOMNamedNodeMap *map; |
| 220 | + IXMLDOMNode *node, *item; |
| 221 | + IXMLDOMDocument2 *doc; |
| 222 | + VARIANT_BOOL b; |
| 223 | + LONG len, i; |
| 224 | + HRESULT hr; |
| 225 | + BSTR str; |
| 226 | + |
| 227 | + test = tests; |
| 228 | + while (test->xml) |
| 229 | + { |
| 230 | + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); |
| 231 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 232 | + |
| 233 | + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(test->xml), &b); |
| 234 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 235 | + |
| 236 | + node = NULL; |
| 237 | + hr = IXMLDOMDocument2_get_firstChild(doc, &node); |
| 238 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 239 | + |
| 240 | + hr = IXMLDOMNode_get_attributes(node, &map); |
| 241 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 242 | + |
| 243 | + len = -1; |
| 244 | + hr = IXMLDOMNamedNodeMap_get_length(map, &len); |
| 245 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 246 | + ok(len == test->explen, "got %ld\n", len); |
| 247 | + |
| 248 | + item = NULL; |
| 249 | + hr = IXMLDOMNamedNodeMap_get_item(map, test->explen+1, &item); |
| 250 | + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); |
| 251 | + ok(!item, "Item should be NULL\n"); |
| 252 | + |
| 253 | + for (i = 0; i < len; i++) |
| 254 | + { |
| 255 | + item = NULL; |
| 256 | + hr = IXMLDOMNamedNodeMap_get_item(map, i, &item); |
| 257 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 258 | + |
| 259 | + str = NULL; |
| 260 | + hr = IXMLDOMNode_get_nodeName(item, &str); |
| 261 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 262 | + ok(!lstrcmpW(str, test->names[i]), "got %s\n", wine_dbgstr_w(str)); |
| 263 | + SysFreeString(str); |
| 264 | + |
| 265 | + str = NULL; |
| 266 | + hr = IXMLDOMNode_get_prefix(item, &str); |
| 267 | + if (test->prefixes[i]) |
| 268 | + { |
| 269 | + /* MSXML4 can report different results with different service packs */ |
| 270 | + ok(hr == S_OK || broken(hr == S_FALSE), "Unexpected hr %#lx.\n", hr); |
| 271 | + ok(!lstrcmpW(str, test->prefixes[i]) || broken(!str), |
| 272 | + "got %s\n", wine_dbgstr_w(str)); |
| 273 | + SysFreeString(str); |
| 274 | + } |
| 275 | + else |
| 276 | + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr ); |
| 277 | + |
| 278 | + str = NULL; |
| 279 | + hr = IXMLDOMNode_get_baseName(item, &str); |
| 280 | + /* MSXML4 can report different results with different service packs */ |
| 281 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 282 | + ok(!lstrcmpW(str, test->basenames[i]) || broken(!lstrcmpW(str, L"xmlns")), |
| 283 | + "got %s\n", wine_dbgstr_w(str)); |
| 284 | + SysFreeString(str); |
| 285 | + |
| 286 | + str = NULL; |
| 287 | + hr = IXMLDOMNode_get_namespaceURI(item, &str); |
| 288 | + if (test->uris[i]) |
| 289 | + { |
| 290 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 291 | + if (test->prefixes[i] && !lstrcmpW(test->prefixes[i], L"xmlns")) |
| 292 | + ok(!lstrcmpW(str, L""), "got %s\n", wine_dbgstr_w(str)); |
| 293 | + else |
| 294 | + ok(!lstrcmpW(str, test->uris[i]), "got %s\n", wine_dbgstr_w(str)); |
| 295 | + SysFreeString(str); |
| 296 | + } |
| 297 | + else |
| 298 | + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr ); |
| 299 | + |
| 300 | + str = NULL; |
| 301 | + hr = IXMLDOMNode_get_text(item, &str); |
| 302 | + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); |
| 303 | + ok(!lstrcmpW(str, test->texts[i]), "got %s\n", wine_dbgstr_w(str)); |
| 304 | + SysFreeString(str); |
| 305 | + |
| 306 | + str = NULL; |
| 307 | + hr = IXMLDOMNode_get_xml(item, &str); |
| 308 | + ok(SUCCEEDED(hr), "Failed to get node xml, hr %#lx.\n", hr); |
| 309 | + ok(!lstrcmpW(str, test->xmls[i]), "got %s\n", wine_dbgstr_w(str)); |
| 310 | + SysFreeString(str); |
| 311 | + |
| 312 | + IXMLDOMNode_Release(item); |
| 313 | + } |
| 314 | + |
| 315 | + IXMLDOMNamedNodeMap_Release(map); |
| 316 | + IXMLDOMNode_Release(node); |
| 317 | + IXMLDOMDocument2_Release(doc); |
| 318 | + |
| 319 | + test++; |
| 320 | + } |
| 321 | + free_bstrs(); |
| 322 | +} |
| 323 | + |
| 324 | +START_TEST(domdoc) |
| 325 | +{ |
| 326 | + HRESULT hr; |
| 327 | + IXMLDOMDocument2 *doc; |
| 328 | + |
| 329 | + hr = CoInitialize(NULL); |
| 330 | + ok(hr == S_OK, "failed to init com\n"); |
| 331 | + |
| 332 | + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); |
| 333 | + if (hr != S_OK) |
| 334 | + { |
| 335 | + win_skip("class &CLSID_DOMDocument40 not supported\n"); |
| 336 | + return; |
| 337 | + } |
| 338 | + IXMLDOMDocument2_Release(doc); |
| 339 | + |
| 340 | + test_namespaces_as_attributes(); |
| 341 | + test_create_attribute(); |
| 342 | + |
| 343 | + CoUninitialize(); |
| 344 | +} |
0 commit comments