xmlelem.c 16.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * 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 <stdio.h>

#include "windows.h"
#include "ole2.h"
#include "xmldom.h"
#include "msxml2.h"
#include "ocidl.h"

#include "wine/test.h"

33 34
#define ERROR_URL_NOT_FOUND 0x800c0006

35 36 37 38 39 40 41 42 43 44
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;
45
    LONG type, num_child;
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

    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);
66
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
67 68 69
    ok(element != NULL, "Expected non-NULL element\n");

    hr = IXMLElement_get_tagName(element, &str);
70
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
71 72 73 74 75
    ok(lstrlenW(str) == 0, "Expected empty tag name\n");
    SysFreeString(str);

    parent = (IXMLElement *)0xdeadbeef;
    hr = IXMLElement_get_parent(element, &parent);
76
    ok(hr == 1, "Expected 1, got %08x\n", hr);
77 78 79 80
    ok(parent == NULL, "Expected NULL parent\n");

    str = SysAllocString(noexist);
    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 85 86 87 88 89 90 91
    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);
92
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
93 94 95 96 97
    SysFreeString(str);
    SysFreeString(val);

    str = SysAllocString(crazyCase2);
    hr = IXMLElement_getAttribute(element, str, &vValue);
98
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
99 100 101 102 103 104 105 106 107 108
    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);
109
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
110 111 112
    SysFreeString(val);

    hr = IXMLElement_getAttribute(element, str, &vValue);
113
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
114 115 116 117 118
    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);
119
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
120

121
    /* remove now nonexistent attribute */
122
    hr = IXMLElement_removeAttribute(element, str);
123
    ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
124 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");
129 130 131 132 133
    SysFreeString(str);
    VariantClear(&vValue);

    children = (IXMLElementCollection *)0xdeadbeef;
    hr = IXMLElement_get_children(element, &children);
134
    ok(hr == 1, "Expected 1, got %08x\n", hr);
135 136 137
    ok(children == NULL, "Expected NULL collection\n");

    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 %d\n", type);
140 141

    hr = IXMLElement_get_text(element, &str);
142
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
143 144 145 146 147 148
    ok(lstrlenW(str) == 0, "Expected empty text\n");
    SysFreeString(str);

    /* put_text with an ELEMENT */
    str = SysAllocString(propVal);
    hr = IXMLElement_put_text(element, str);
149
    ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
150 151 152 153 154 155 156 157 158 159
    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);
160
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
161 162 163

    str = SysAllocString(propVal);
    hr = IXMLElement_put_text(child, str);
164
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
165 166 167 168
    SysFreeString(str);

    parent = (IXMLElement *)0xdeadbeef;
    hr = IXMLElement_get_parent(child, &parent);
169
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
170 171 172
    ok(parent != element, "Expected parent != element\n");

    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 %d\n", type);
175 176 177

    children = (IXMLElementCollection *)0xdeadbeef;
    hr = IXMLElement_get_children(element, &children);
178
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
179 180 181
    ok(children != NULL, "Expected non-NULL collection\n");

    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 %d\n", num_child);
184 185 186 187 188 189

    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);
190
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
191 192 193
    ok(child2 != NULL, "Expected non-NULL child\n");

    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 %d\n", type);
196 197

    hr = IXMLElement_get_text(element, &str);
198
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
199 200 201 202
    ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
    SysFreeString(str);

    hr = IXMLElement_get_text(child2, &str);
203
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
204 205 206 207 208 209
    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);
210
    ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
211 212 213 214
    SysFreeString(str);

    str = SysAllocString(nextVal);
    hr = IXMLElement_put_text(child2, str);
215
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
216 217 218
    SysFreeString(str);

    hr = IXMLElement_get_text(element, &str);
219
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
    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 create_xml_file(LPCSTR filename)
{
    DWORD dwNumberOfBytesWritten;
    HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
                           CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

237 238 239 240 241 242
    static const char data[] =
        "<?xml version=\"1.0\" ?>\n"
        "<BankAccount>\n"
        "  <Number>1234</Number>\n"
        "  <Name>Captain Ahab</Name>\n"
        "</BankAccount>\n";
243

244
    WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
245 246 247 248 249 250 251 252 253 254 255
    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;
256
    CHAR pathA[MAX_PATH];
257
    WCHAR path[MAX_PATH];
258
    LONG length, type;
259 260 261
    ULONG num_vars;
    VARIANT var, vIndex, vName;
    BSTR url, str;
262
    static const CHAR szBankXML[] = "bank.xml";
263 264 265 266 267 268 269 270 271 272 273
    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;
    }

274 275 276
    create_xml_file(szBankXML);
    GetFullPathNameA(szBankXML, MAX_PATH, pathA, NULL);
    MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
277 278 279

    url = SysAllocString(path);
    hr = IXMLDocument_put_URL(doc, url);
280
    ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
281 282
    SysFreeString(url);

283
    if(hr != S_OK)
284 285
        goto cleanup;

286
    hr = IXMLDocument_get_root(doc, &element);
287
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
288 289 290
    ok(element != NULL, "Expected non-NULL element\n");

    hr = IXMLElement_get_children(element, &collection);
291
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
292 293 294
    ok(collection != NULL, "Expected non-NULL collection\n");

    hr = IXMLElementCollection_get_length(collection, NULL);
295
    ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
296 297

    hr = IXMLElementCollection_get_length(collection, &length);
298
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
299
    ok(length == 2, "Expected 2, got %d\n", length);
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

    /* 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);
322
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
323
    ok(length == 2, "Expected 2, got %d\n", length);
324 325 326

    /* IXMLElementCollection implements IEnumVARIANT */
    hr = IXMLElementCollection_QueryInterface(collection, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
327
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
328 329 330 331
    ok(enumVar != NULL, "Expected non-NULL enumVar\n");
    IEnumVARIANT_Release(enumVar);

    hr = IXMLElementCollection_get__newEnum(collection, &unk);
332
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
333 334 335
    ok(unk != NULL, "Expected non-NULL unk\n");

    hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
336
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
337 338 339 340 341
    ok(enumVar != NULL, "Expected non-NULL enumVar\n");
    IUnknown_Release(unk);

    /* <Number>1234</Number> */
    hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
342
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
343
    ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
344
    ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
345 346

    hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
347
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
348 349 350 351 352
    ok(child != NULL, "Expected non-NULL child\n");

    VariantClear(&var);

    hr = IXMLElement_get_type(child, &type);
353
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
354
    ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
355 356

    hr = IXMLElement_get_tagName(child, &str);
357
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
358 359 360 361 362 363
    ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
    SysFreeString(str);
    IXMLElement_Release(child);

    /* <Name>Captain Ahab</Name> */
    hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
364
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
365
    ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
366
    ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
367 368

    hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
369
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
370 371 372 373 374
    ok(child != NULL, "Expected non-NULL child\n");

    VariantClear(&var);

    hr = IXMLElement_get_type(child, &type);
375
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
376
    ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
377 378

    hr = IXMLElement_get_tagName(child, &str);
379
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
380 381 382 383 384 385 386 387 388 389
    ok(!lstrcmpW(str, szName), "Expected NAME\n");
    SysFreeString(str);
    IXMLElement_Release(child);

    /* <Number>1234</Number> */
    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);
390
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
391 392 393
    ok(child != NULL, "Expected non-NULL child\n");

    hr = IXMLElement_get_type(child, &type);
394
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
395
    ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
396 397

    hr = IXMLElement_get_tagName(child, &str);
398
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
399 400 401 402 403 404 405 406 407 408
    ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
    SysFreeString(str);
    IXMLElement_Release(child);

    /* <Name>Captain Ahab</Name> */
    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);
409
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
410 411 412
    ok(child != NULL, "Expected non-NULL child\n");

    hr = IXMLElement_get_type(child, &type);
413
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
414
    ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
415 416

    hr = IXMLElement_get_tagName(child, &str);
417
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
418 419 420 421 422 423 424 425 426 427 428 429
    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);
430
    ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
431 432
    ok(child == NULL, "Expected NULL child\n");

433
    IEnumVARIANT_Release(enumVar);
434 435
    IXMLElement_Release(element);
    IXMLElementCollection_Release(collection);
436
cleanup:
437 438 439 440 441 442 443 444 445 446 447 448 449
    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();
450 451

    CoUninitialize();
452
}