2 * Copyright (C) 2012 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/test.h"
32 static void test_interfaces(void)
34 static const WCHAR key_add
[] = {'a', 0};
35 static const WCHAR key_add_value
[] = {'a', 0};
36 static const WCHAR key_non_exist
[] = {'b', 0};
41 IObjectWithSite
*site
;
46 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
47 &IID_IDispatch
, (void**)&disp
);
48 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
53 hr
= IDispatch_QueryInterface(disp
, &IID_IDictionary
, (void**)&dict
);
54 ok(hr
== S_OK
, "got 0x%08x, expected 0x%08x\n", hr
, S_OK
);
56 hr
= IDispatch_QueryInterface(disp
, &IID_IObjectWithSite
, (void**)&site
);
57 ok(hr
== E_NOINTERFACE
, "got 0x%08x, expected 0x%08x\n", hr
, E_NOINTERFACE
);
59 hr
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
60 ok(hr
== E_NOINTERFACE
, "got 0x%08x, expected 0x%08x\n", hr
, E_NOINTERFACE
);
63 V_BSTR(&key
) = SysAllocString(key_add
);
64 V_VT(&value
) = VT_BSTR
;
65 V_BSTR(&value
) = SysAllocString(key_add_value
);
66 hr
= IDictionary_Add(dict
, &key
, &value
);
67 ok(hr
== S_OK
, "got 0x%08x, expected 0x%08x\n", hr
, S_OK
);
70 exists
= VARIANT_FALSE
;
71 hr
= IDictionary_Exists(dict
, &key
, &exists
);
72 todo_wine
ok(hr
== S_OK
, "got 0x%08x, expected 0x%08x\n", hr
, S_OK
);
73 todo_wine
ok(exists
== VARIANT_TRUE
, "Expected TRUE but got FALSE.\n");
76 exists
= VARIANT_TRUE
;
78 V_BSTR(&key
) = SysAllocString(key_non_exist
);
79 hr
= IDictionary_Exists(dict
, &key
, &exists
);
80 todo_wine
ok(hr
== S_OK
, "got 0x%08x, expected 0x%08x\n", hr
, S_OK
);
81 todo_wine
ok(exists
== VARIANT_FALSE
, "Expected FALSE but got TRUE.\n");
84 hr
= IDictionary_get_Count(dict
, &count
);
85 ok(hr
== S_OK
, "got 0x%08x, expected 0x%08x\n", hr
, S_OK
);
86 ok(count
== 1, "got %d, expected 1\n", count
);
88 IDictionary_Release(dict
);
89 IDispatch_Release(disp
);
92 static void test_comparemode(void)
99 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
100 &IID_IDictionary
, (void**)&dict
);
101 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
103 if (0) /* crashes on native */
104 hr
= IDictionary_get_CompareMode(dict
, NULL
);
107 hr
= IDictionary_get_CompareMode(dict
, &method
);
108 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
109 ok(method
== BinaryCompare
, "got %d\n", method
);
111 /* invalid mode value is not checked */
112 hr
= IDictionary_put_CompareMode(dict
, 10);
113 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
115 hr
= IDictionary_get_CompareMode(dict
, &method
);
116 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
117 ok(method
== 10, "got %d\n", method
);
119 hr
= IDictionary_put_CompareMode(dict
, DatabaseCompare
);
120 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
122 hr
= IDictionary_get_CompareMode(dict
, &method
);
123 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
124 ok(method
== DatabaseCompare
, "got %d\n", method
);
126 /* try to change mode of a non-empty dict */
130 hr
= IDictionary_Add(dict
, &key
, &item
);
131 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
133 hr
= IDictionary_put_CompareMode(dict
, BinaryCompare
);
134 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
, "got 0x%08x\n", hr
);
136 IDictionary_Release(dict
);
139 static DWORD
get_str_hash(const WCHAR
*str
, CompareMethod method
)
146 if (method
== TextCompare
|| method
== DatabaseCompare
)
147 ch
= PtrToInt(CharLowerW(IntToPtr(*str
)));
151 hash
+= (hash
<< 4) + ch
;
158 static DWORD
get_num_hash(FLOAT num
)
160 return (*((DWORD
*)&num
)) % 1201;
168 unsigned int exp_bias
: 8;
169 unsigned int sign
: 1;
178 unsigned int m_lo
: 32; /* 52 bits of precision */
179 unsigned int m_hi
: 20;
180 unsigned int exp_bias
: 11; /* bias == 1023 */
181 unsigned int sign
: 1;
186 static void test_hash_value(void)
188 /* string test data */
189 static const WCHAR str_hash_tests
[][10] = {
191 {'a','B','C','d','1',0},
198 static const int int_hash_tests
[] = {
202 static const FLOAT float_hash_tests
[] = {
203 0.0, -1.0, 100.0, 1.0, 255.0, 1.234
213 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
214 &IID_IDictionary
, (void**)&dict
);
215 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
217 V_VT(&key
) = VT_BSTR
;
220 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
221 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
222 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
223 ok(V_I4(&hash
) == 0, "got %d\n", V_I4(&hash
));
225 for (i
= 0; i
< sizeof(str_hash_tests
)/sizeof(str_hash_tests
[0]); i
++) {
226 DWORD expected
= get_str_hash(str_hash_tests
[i
], BinaryCompare
);
228 hr
= IDictionary_put_CompareMode(dict
, BinaryCompare
);
229 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
231 V_VT(&key
) = VT_BSTR
;
232 V_BSTR(&key
) = SysAllocString(str_hash_tests
[i
]);
234 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
235 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
236 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
237 ok(V_I4(&hash
) == expected
, "%d: binary mode: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
241 expected
= get_str_hash(str_hash_tests
[i
], TextCompare
);
242 hr
= IDictionary_put_CompareMode(dict
, TextCompare
);
243 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
245 V_VT(&key
) = VT_BSTR
;
246 V_BSTR(&key
) = SysAllocString(str_hash_tests
[i
]);
248 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
249 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
250 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
251 ok(V_I4(&hash
) == expected
, "%d: text mode: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
255 expected
= get_str_hash(str_hash_tests
[i
], DatabaseCompare
);
256 hr
= IDictionary_put_CompareMode(dict
, DatabaseCompare
);
257 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
259 V_VT(&key
) = VT_BSTR
;
260 V_BSTR(&key
) = SysAllocString(str_hash_tests
[i
]);
262 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
263 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
264 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
265 ok(V_I4(&hash
) == expected
, "%d: db mode: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
273 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
274 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
275 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
276 ok(V_I4(&hash
) == ~0u, "got hash 0x%08x\n", V_I4(&hash
));
278 V_VT(&key
) = VT_UINT
;
281 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
282 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
283 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
284 ok(V_I4(&hash
) == ~0u, "got hash 0x%08x\n", V_I4(&hash
));
289 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
290 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
291 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
292 ok(V_I4(&hash
) == ~0u || broken(V_I4(&hash
) == 0xa1), "got hash 0x%08x\n", V_I4(&hash
));
297 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
298 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
299 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
300 ok(V_I4(&hash
) == ~0u, "got hash 0x%08x\n", V_I4(&hash
));
305 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
306 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
307 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
308 ok(V_I4(&hash
) == ~0u, "got hash 0x%08x\n", V_I4(&hash
));
313 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
314 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
315 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
316 ok(V_I4(&hash
) == ~0u, "got hash 0x%08x\n", V_I4(&hash
));
318 for (i
= 0; i
< sizeof(int_hash_tests
)/sizeof(int_hash_tests
[0]); i
++) {
319 DWORD expected
= get_num_hash(int_hash_tests
[i
]);
322 V_I2(&key
) = int_hash_tests
[i
];
324 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
325 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
326 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
327 ok(V_I4(&hash
) == expected
, "%d: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
331 V_I4(&key
) = int_hash_tests
[i
];
333 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
334 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
335 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
336 ok(V_I4(&hash
) == expected
, "%d: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
339 expected
= get_num_hash((FLOAT
)(BYTE
)int_hash_tests
[i
]);
341 V_UI1(&key
) = int_hash_tests
[i
];
343 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
344 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
345 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
346 ok(V_I4(&hash
) == expected
, "%d: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
352 fx4
.i
.exp_bias
= 0xff;
357 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
358 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
359 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
360 ok(V_I4(&hash
) == ~0u || broken(V_I4(&hash
) == 0 /* win2k */ ||
361 V_I4(&hash
) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash
));
366 fx4
.i
.exp_bias
= 0xff;
371 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
372 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
373 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
374 ok(V_I4(&hash
) == 0, "got hash 0x%08x\n", V_I4(&hash
));
378 fx8
.i
.exp_bias
= 0x7ff;
383 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
384 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
|| broken(hr
== S_OK
) /* win2k, win2k3 */, "got 0x%08x\n", hr
);
385 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
386 ok(V_I4(&hash
) == ~0u || broken(V_I4(&hash
) == 0 /* win2k */ ||
387 V_I4(&hash
) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash
));
393 fx8
.i
.exp_bias
= 0x7ff;
398 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
399 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
400 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
401 ok(V_I4(&hash
) == 0, "got hash 0x%08x\n", V_I4(&hash
));
403 for (i
= 0; i
< sizeof(float_hash_tests
)/sizeof(float_hash_tests
[0]); i
++) {
404 DWORD expected
= get_num_hash(float_hash_tests
[i
]);
407 V_R4(&key
) = float_hash_tests
[i
];
409 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
410 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
411 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
412 ok(V_I4(&hash
) == expected
, "%d: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
416 V_R8(&key
) = float_hash_tests
[i
];
418 hr
= IDictionary_get_HashVal(dict
, &key
, &hash
);
419 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
420 ok(V_VT(&hash
) == VT_I4
, "got %d\n", V_VT(&hash
));
421 ok(V_I4(&hash
) == expected
, "%d: got hash 0x%08x, expected 0x%08x\n", i
, V_I4(&hash
),
425 IDictionary_Release(dict
);
428 static void test_Exists(void)
435 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
436 &IID_IDictionary
, (void**)&dict
);
437 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
439 if (0) /* crashes on native */
440 hr
= IDictionary_Exists(dict
, NULL
, NULL
);
444 hr
= IDictionary_Exists(dict
, &key
, NULL
);
446 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
, "got 0x%08x\n", hr
);
450 exists
= VARIANT_TRUE
;
451 hr
= IDictionary_Exists(dict
, &key
, &exists
);
453 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
454 ok(exists
== VARIANT_FALSE
, "got %x\n", exists
);
457 hr
= IDictionary_Add(dict
, &key
, &item
);
458 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
462 hr
= IDictionary_Add(dict
, &key
, &item
);
463 ok(hr
== CTL_E_KEY_ALREADY_EXISTS
, "got 0x%08x\n", hr
);
467 hr
= IDictionary_Exists(dict
, &key
, NULL
);
469 ok(hr
== CTL_E_ILLEGALFUNCTIONCALL
, "got 0x%08x\n", hr
);
473 exists
= VARIANT_FALSE
;
474 hr
= IDictionary_Exists(dict
, &key
, &exists
);
476 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
477 ok(exists
== VARIANT_TRUE
, "got %x\n", exists
);
479 /* key of different type, but resolves to same hash value */
482 exists
= VARIANT_FALSE
;
483 hr
= IDictionary_Exists(dict
, &key
, &exists
);
485 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
486 ok(exists
== VARIANT_TRUE
, "got %x\n", exists
);
488 IDictionary_Release(dict
);
491 static void test_Keys(void)
493 VARIANT key
, keys
, item
;
498 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
499 &IID_IDictionary
, (void**)&dict
);
500 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
502 hr
= IDictionary_Keys(dict
, NULL
);
504 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
507 hr
= IDictionary_Keys(dict
, &keys
);
509 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
510 ok(V_VT(&keys
) == (VT_ARRAY
|VT_VARIANT
), "got %d\n", V_VT(&keys
));
517 hr
= IDictionary_Add(dict
, &key
, &item
);
518 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
521 hr
= IDictionary_Keys(dict
, &keys
);
523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
524 ok(V_VT(&keys
) == (VT_ARRAY
|VT_VARIANT
), "got %d\n", V_VT(&keys
));
530 hr
= SafeArrayGetElement(V_ARRAY(&keys
), &index
, &key
);
531 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
532 ok(V_VT(&key
) == VT_R4
, "got %d\n", V_VT(&key
));
534 index
= SafeArrayGetDim(V_ARRAY(&keys
));
535 ok(index
== 1, "got %d\n", index
);
537 hr
= SafeArrayGetUBound(V_ARRAY(&keys
), 1, &index
);
538 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
539 ok(index
== 0, "got %d\n", index
);
543 IDictionary_Release(dict
);
546 static void test_Remove(void)
552 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
553 &IID_IDictionary
, (void**)&dict
);
554 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
557 hr
= IDictionary_Remove(dict
, NULL
);
559 /* nothing added yet */
562 hr
= IDictionary_Remove(dict
, &key
);
564 ok(hr
== CTL_E_ELEMENT_NOT_FOUND
, "got 0x%08x\n", hr
);
567 hr
= IDictionary_Add(dict
, &key
, &item
);
568 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
570 hr
= IDictionary_Remove(dict
, &key
);
572 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
574 IDictionary_Release(dict
);
577 static void test_Item(void)
583 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
584 &IID_IDictionary
, (void**)&dict
);
585 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
591 hr
= IDictionary_get_Item(dict
, &key
, &item
);
592 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
593 ok(V_VT(&item
) == VT_EMPTY
, "got %d\n", V_VT(&item
));
598 hr
= IDictionary_get_Item(dict
, &key
, &item
);
599 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
600 ok(V_VT(&item
) == VT_EMPTY
, "got %d\n", V_VT(&item
));
602 IDictionary_Release(dict
);
605 START_TEST(dictionary
)
612 hr
= CoCreateInstance(&CLSID_Dictionary
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
613 &IID_IDispatch
, (void**)&disp
);
615 win_skip("Dictionary object is not supported: %08x\n", hr
);
619 IDispatch_Release(disp
);