Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/tests/core/variant/test_dictionary.h
21240 views
1
/**************************************************************************/
2
/* test_dictionary.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/variant/typed_dictionary.h"
34
#include "tests/test_macros.h"
35
36
namespace TestDictionary {
37
TEST_CASE("[Dictionary] Assignment using bracket notation ([])") {
38
Dictionary map;
39
map["Hello"] = 0;
40
CHECK(int(map["Hello"]) == 0);
41
map["Hello"] = 3;
42
CHECK(int(map["Hello"]) == 3);
43
map["World!"] = 4;
44
CHECK(int(map["World!"]) == 4);
45
46
map[StringName("HelloName")] = 6;
47
CHECK(int(map[StringName("HelloName")]) == 6);
48
CHECK(int(map.find_key(6).get_type()) == Variant::STRING_NAME);
49
map[StringName("HelloName")] = 7;
50
CHECK(int(map[StringName("HelloName")]) == 7);
51
52
// Test String and StringName are equivalent.
53
map[StringName("Hello")] = 8;
54
CHECK(int(map["Hello"]) == 8);
55
map["Hello"] = 9;
56
CHECK(int(map[StringName("Hello")]) == 9);
57
58
// Test non-string keys, since keys can be of any Variant type.
59
map[12345] = -5;
60
CHECK(int(map[12345]) == -5);
61
map[false] = 128;
62
CHECK(int(map[false]) == 128);
63
map[Vector2(10, 20)] = 30;
64
CHECK(int(map[Vector2(10, 20)]) == 30);
65
map[0] = 400;
66
CHECK(int(map[0]) == 400);
67
// Check that assigning 0 doesn't overwrite the value for `false`.
68
CHECK(int(map[false]) == 128);
69
70
// Ensure read-only maps aren't modified by non-existing keys.
71
const int length = map.size();
72
map.make_read_only();
73
CHECK(int(map["This key does not exist"].get_type()) == Variant::NIL);
74
CHECK(map.size() == length);
75
}
76
77
TEST_CASE("[Dictionary] List init") {
78
Dictionary dict{
79
{ 0, "int" },
80
{ "packed_string_array", PackedStringArray({ "array", "of", "values" }) },
81
{ "key", Dictionary({ { "nested", 200 } }) },
82
{ Vector2(), "v2" },
83
};
84
CHECK(dict.size() == 4);
85
CHECK(dict[0] == "int");
86
CHECK(PackedStringArray(dict["packed_string_array"])[2] == "values");
87
CHECK(Dictionary(dict["key"])["nested"] == Variant(200));
88
CHECK(dict[Vector2()] == "v2");
89
90
TypedDictionary<double, double> tdict{
91
{ 0.0, 1.0 },
92
{ 5.0, 2.0 },
93
};
94
CHECK_EQ(tdict[0.0], Variant(1.0));
95
CHECK_EQ(tdict[5.0], Variant(2.0));
96
}
97
98
TEST_CASE("[Dictionary] get_key_list()") {
99
Dictionary map;
100
LocalVector<Variant> keys;
101
keys = map.get_key_list();
102
CHECK(keys.is_empty());
103
map[1] = 3;
104
keys = map.get_key_list();
105
CHECK(keys.size() == 1);
106
CHECK(int(keys[0]) == 1);
107
map[2] = 4;
108
keys = map.get_key_list();
109
CHECK(keys.size() == 2);
110
}
111
112
TEST_CASE("[Dictionary] get_key_at_index()") {
113
Dictionary map;
114
map[4] = 3;
115
Variant val = map.get_key_at_index(0);
116
CHECK(int(val) == 4);
117
map[3] = 1;
118
val = map.get_key_at_index(0);
119
CHECK(int(val) == 4);
120
val = map.get_key_at_index(1);
121
CHECK(int(val) == 3);
122
}
123
124
TEST_CASE("[Dictionary] getptr()") {
125
Dictionary map;
126
map[1] = 3;
127
Variant *key = map.getptr(1);
128
CHECK(int(*key) == 3);
129
key = map.getptr(2);
130
CHECK(key == nullptr);
131
}
132
133
TEST_CASE("[Dictionary] get_valid()") {
134
Dictionary map;
135
map[1] = 3;
136
Variant val = map.get_valid(1);
137
CHECK(int(val) == 3);
138
}
139
140
TEST_CASE("[Dictionary] set(), get(), and get_or_add()") {
141
Dictionary map;
142
143
map.set(1, 3);
144
Variant val = map.get(1, -1);
145
CHECK(int(val) == 3);
146
147
map.set(1, 5);
148
val = map.get(1, -1);
149
CHECK(int(val) == 5);
150
151
CHECK(int(map.get_or_add(1, 7)) == 5);
152
CHECK(int(map.get_or_add(2, 7)) == 7);
153
}
154
155
TEST_CASE("[Dictionary] make_read_only() and is_read_only()") {
156
Dictionary map;
157
CHECK_FALSE(map.is_read_only());
158
CHECK(map.set(1, 1));
159
160
map.make_read_only();
161
CHECK(map.is_read_only());
162
163
ERR_PRINT_OFF;
164
CHECK_FALSE(map.set(1, 2));
165
ERR_PRINT_ON;
166
}
167
168
TEST_CASE("[Dictionary] size(), is_empty() and clear()") {
169
Dictionary map;
170
CHECK(map.size() == 0);
171
CHECK(map.is_empty());
172
map[1] = 3;
173
CHECK(map.size() == 1);
174
CHECK(!map.is_empty());
175
map.clear();
176
CHECK(map.size() == 0);
177
CHECK(map.is_empty());
178
}
179
180
TEST_CASE("[Dictionary] has() and has_all()") {
181
Dictionary map;
182
CHECK(map.has(1) == false);
183
map[1] = 3;
184
CHECK(map.has(1));
185
Array keys;
186
keys.push_back(1);
187
CHECK(map.has_all(keys));
188
keys.push_back(2);
189
CHECK(map.has_all(keys) == false);
190
}
191
192
TEST_CASE("[Dictionary] keys() and values()") {
193
Dictionary map;
194
Array keys = map.keys();
195
Array values = map.values();
196
CHECK(keys.is_empty());
197
CHECK(values.is_empty());
198
map[1] = 3;
199
keys = map.keys();
200
values = map.values();
201
CHECK(int(keys[0]) == 1);
202
CHECK(int(values[0]) == 3);
203
}
204
205
TEST_CASE("[Dictionary] merge() and merged()") {
206
Dictionary d1 = {
207
{ "key1", 1 },
208
{ "key2", 2 },
209
};
210
Dictionary d2 = {
211
{ "key2", 200 },
212
{ "key3", 300 },
213
};
214
Dictionary expected_no_overwrite = {
215
{ "key1", 1 },
216
{ "key2", 2 },
217
{ "key3", 300 },
218
};
219
Dictionary expected_overwrite = {
220
{ "key1", 1 },
221
{ "key2", 200 },
222
{ "key3", 300 },
223
};
224
225
Dictionary d_test = d1.duplicate();
226
d_test.merge(d2, false);
227
CHECK_EQ(d_test, expected_no_overwrite);
228
229
d_test = d1.duplicate();
230
d_test.merge(d2, true);
231
CHECK_EQ(d_test, expected_overwrite);
232
233
CHECK_EQ(d1.merged(d2, false), expected_no_overwrite);
234
CHECK_EQ(d1.merged(d2, true), expected_overwrite);
235
}
236
237
TEST_CASE("[Dictionary] Duplicate dictionary") {
238
// d = {1: {1: 1}, {2: 2}: [2], [3]: 3}
239
Dictionary k2 = { { 2, 2 } };
240
Array k3 = { 3 };
241
Dictionary d = {
242
{ 1, Dictionary({ { 1, 1 } }) },
243
{ k2, Array({ 2 }) },
244
{ k3, 3 }
245
};
246
247
// Deep copy
248
Dictionary deep_d = d.duplicate(true);
249
CHECK_MESSAGE(deep_d.id() != d.id(), "Should create a new dictionary");
250
CHECK_MESSAGE(Dictionary(deep_d[1]).id() != Dictionary(d[1]).id(), "Should clone nested dictionary");
251
CHECK_MESSAGE(Array(deep_d[k2]).id() != Array(d[k2]).id(), "Should clone nested array");
252
CHECK_EQ(deep_d, d);
253
254
// Check that duplicate_deep matches duplicate(true)
255
Dictionary deep_d2 = d.duplicate_deep();
256
CHECK_EQ(deep_d, deep_d2);
257
258
deep_d[0] = 0;
259
CHECK_NE(deep_d, d);
260
deep_d.erase(0);
261
Dictionary(deep_d[1]).operator[](0) = 0;
262
CHECK_NE(deep_d, d);
263
Dictionary(deep_d[1]).erase(0);
264
CHECK_EQ(deep_d, d);
265
// Keys should also be copied
266
k2[0] = 0;
267
CHECK_NE(deep_d, d);
268
k2.erase(0);
269
CHECK_EQ(deep_d, d);
270
k3.push_back(0);
271
CHECK_NE(deep_d, d);
272
k3.pop_back();
273
CHECK_EQ(deep_d, d);
274
275
// Shallow copy
276
Dictionary shallow_d = d.duplicate(false);
277
CHECK_MESSAGE(shallow_d.id() != d.id(), "Should create a new array");
278
CHECK_MESSAGE(Dictionary(shallow_d[1]).id() == Dictionary(d[1]).id(), "Should keep nested dictionary");
279
CHECK_MESSAGE(Array(shallow_d[k2]).id() == Array(d[k2]).id(), "Should keep nested array");
280
CHECK_EQ(shallow_d, d);
281
shallow_d[0] = 0;
282
CHECK_NE(shallow_d, d);
283
shallow_d.erase(0);
284
#if 0 // TODO: recursion in dict key currently is buggy
285
// Keys should also be shallowed
286
k2[0] = 0;
287
CHECK_EQ(shallow_d, d);
288
k2.erase(0);
289
k3.push_back(0);
290
CHECK_EQ(shallow_d, d);
291
#endif
292
}
293
294
TEST_CASE("[Dictionary] Duplicate recursive dictionary") {
295
// Self recursive
296
Dictionary d;
297
d[1] = d;
298
299
Dictionary d_shallow = d.duplicate(false);
300
CHECK_EQ(d, d_shallow);
301
302
// Deep copy of recursive dictionary endup with recursion limit and return
303
// an invalid result (multiple nested dictionaries), the point is we should
304
// not end up with a segfault and an error log should be printed
305
ERR_PRINT_OFF;
306
d.duplicate(true);
307
ERR_PRINT_ON;
308
309
// Nested recursive
310
Dictionary d1;
311
Dictionary d2;
312
d1[2] = d2;
313
d2[1] = d1;
314
315
Dictionary d1_shallow = d1.duplicate(false);
316
CHECK_EQ(d1, d1_shallow);
317
318
// Same deep copy issue as above
319
ERR_PRINT_OFF;
320
d1.duplicate(true);
321
ERR_PRINT_ON;
322
323
// Break the recursivity otherwise Dictionary teardown will leak memory
324
d.clear();
325
d1.clear();
326
d2.clear();
327
}
328
329
#if 0 // TODO: duplicate recursion in dict key is currently buggy
330
TEST_CASE("[Dictionary] Duplicate recursive dictionary on keys") {
331
// Self recursive
332
Dictionary d;
333
d[d] = d;
334
335
Dictionary d_shallow = d.duplicate(false);
336
CHECK_EQ(d, d_shallow);
337
338
// Deep copy of recursive dictionary endup with recursion limit and return
339
// an invalid result (multiple nested dictionaries), the point is we should
340
// not end up with a segfault and an error log should be printed
341
ERR_PRINT_OFF;
342
d.duplicate(true);
343
ERR_PRINT_ON;
344
345
// Nested recursive
346
Dictionary d1;
347
Dictionary d2;
348
d1[d2] = d2;
349
d2[d1] = d1;
350
351
Dictionary d1_shallow = d1.duplicate(false);
352
CHECK_EQ(d1, d1_shallow);
353
354
// Same deep copy issue as above
355
ERR_PRINT_OFF;
356
d1.duplicate(true);
357
ERR_PRINT_ON;
358
359
// Break the recursivity otherwise Dictionary teardown will leak memory
360
d.clear();
361
d1.clear();
362
d2.clear();
363
}
364
#endif
365
366
TEST_CASE("[Dictionary] Hash dictionary") {
367
// d = {1: {1: 1}, {2: 2}: [2], [3]: 3}
368
Dictionary k2 = { { 2, 2 } };
369
Array k3 = { 3 };
370
Dictionary d = {
371
{ 1, Dictionary({ { 1, 1 } }) },
372
{ k2, Array({ 2 }) },
373
{ k3, 3 }
374
};
375
uint32_t original_hash = d.hash();
376
377
// Modify dict change the hash
378
d[0] = 0;
379
CHECK_NE(d.hash(), original_hash);
380
d.erase(0);
381
CHECK_EQ(d.hash(), original_hash);
382
383
// Modify nested item change the hash
384
Dictionary(d[1]).operator[](0) = 0;
385
CHECK_NE(d.hash(), original_hash);
386
Dictionary(d[1]).erase(0);
387
Array(d[k2]).push_back(0);
388
CHECK_NE(d.hash(), original_hash);
389
Array(d[k2]).pop_back();
390
391
// Modify a key change the hash
392
k2[0] = 0;
393
CHECK_NE(d.hash(), original_hash);
394
k2.erase(0);
395
CHECK_EQ(d.hash(), original_hash);
396
k3.push_back(0);
397
CHECK_NE(d.hash(), original_hash);
398
k3.pop_back();
399
CHECK_EQ(d.hash(), original_hash);
400
401
// Duplication doesn't change the hash
402
Dictionary d2 = d.duplicate(true);
403
CHECK_EQ(d2.hash(), original_hash);
404
}
405
406
TEST_CASE("[Dictionary] Hash recursive dictionary") {
407
Dictionary d;
408
d[1] = d;
409
410
// Hash should reach recursion limit, we just make sure this doesn't blow up
411
ERR_PRINT_OFF;
412
d.hash();
413
ERR_PRINT_ON;
414
415
// Break the recursivity otherwise Dictionary teardown will leak memory
416
d.clear();
417
}
418
419
#if 0 // TODO: recursion in dict key is currently buggy
420
TEST_CASE("[Dictionary] Hash recursive dictionary on keys") {
421
Dictionary d;
422
d[d] = 1;
423
424
// Hash should reach recursion limit, we just make sure this doesn't blow up
425
ERR_PRINT_OFF;
426
d.hash();
427
ERR_PRINT_ON;
428
429
// Break the recursivity otherwise Dictionary teardown will leak memory
430
d.clear();
431
}
432
#endif
433
434
TEST_CASE("[Dictionary] Empty comparison") {
435
Dictionary d1;
436
Dictionary d2;
437
438
// test both operator== and operator!=
439
CHECK_EQ(d1, d2);
440
CHECK_FALSE(d1 != d2);
441
}
442
443
TEST_CASE("[Dictionary] Flat comparison") {
444
Dictionary d1 = { { 1, 1 } };
445
Dictionary d2 = { { 1, 1 } };
446
Dictionary other_d = { { 2, 1 } };
447
448
// test both operator== and operator!=
449
CHECK_EQ(d1, d1); // compare self
450
CHECK_FALSE(d1 != d1);
451
CHECK_EQ(d1, d2); // different equivalent arrays
452
CHECK_FALSE(d1 != d2);
453
CHECK_NE(d1, other_d); // different arrays with different content
454
CHECK_FALSE(d1 == other_d);
455
}
456
457
TEST_CASE("[Dictionary] Nested dictionary comparison") {
458
// d1 = {1: {2: {3: 4}}}
459
Dictionary d1 = { { 1, Dictionary({ { 2, Dictionary({ { 3, 4 } }) } }) } };
460
461
Dictionary d2 = d1.duplicate(true);
462
463
// other_d = {1: {2: {3: 0}}}
464
Dictionary other_d = { { 1, Dictionary({ { 2, Dictionary({ { 3, 0 } }) } }) } };
465
466
// test both operator== and operator!=
467
CHECK_EQ(d1, d1); // compare self
468
CHECK_FALSE(d1 != d1);
469
CHECK_EQ(d1, d2); // different equivalent arrays
470
CHECK_FALSE(d1 != d2);
471
CHECK_NE(d1, other_d); // different arrays with different content
472
CHECK_FALSE(d1 == other_d);
473
}
474
475
TEST_CASE("[Dictionary] Nested array comparison") {
476
// d1 = {1: [2, 3]}
477
Dictionary d1 = { { 1, { 2, 3 } } };
478
479
Dictionary d2 = d1.duplicate(true);
480
481
// other_d = {1: [2, 0]}
482
Dictionary other_d = { { 1, { 2, 0 } } };
483
484
// test both operator== and operator!=
485
CHECK_EQ(d1, d1); // compare self
486
CHECK_FALSE(d1 != d1);
487
CHECK_EQ(d1, d2); // different equivalent arrays
488
CHECK_FALSE(d1 != d2);
489
CHECK_NE(d1, other_d); // different arrays with different content
490
CHECK_FALSE(d1 == other_d);
491
}
492
493
TEST_CASE("[Dictionary] Recursive comparison") {
494
Dictionary d1;
495
d1[1] = d1;
496
497
Dictionary d2;
498
d2[1] = d2;
499
500
// Comparison should reach recursion limit
501
ERR_PRINT_OFF;
502
CHECK_EQ(d1, d2);
503
CHECK_FALSE(d1 != d2);
504
ERR_PRINT_ON;
505
506
d1[2] = 2;
507
d2[2] = 2;
508
509
// Comparison should reach recursion limit
510
ERR_PRINT_OFF;
511
CHECK_EQ(d1, d2);
512
CHECK_FALSE(d1 != d2);
513
ERR_PRINT_ON;
514
515
d1[3] = 3;
516
d2[3] = 0;
517
518
// Comparison should reach recursion limit
519
ERR_PRINT_OFF;
520
CHECK_NE(d1, d2);
521
CHECK_FALSE(d1 == d2);
522
ERR_PRINT_ON;
523
524
// Break the recursivity otherwise Dictionary teardown will leak memory
525
d1.clear();
526
d2.clear();
527
}
528
529
#if 0 // TODO: recursion in dict key is currently buggy
530
TEST_CASE("[Dictionary] Recursive comparison on keys") {
531
Dictionary d1;
532
// Hash computation should reach recursion limit
533
ERR_PRINT_OFF;
534
d1[d1] = 1;
535
ERR_PRINT_ON;
536
537
Dictionary d2;
538
// Hash computation should reach recursion limit
539
ERR_PRINT_OFF;
540
d2[d2] = 1;
541
ERR_PRINT_ON;
542
543
// Comparison should reach recursion limit
544
ERR_PRINT_OFF;
545
CHECK_EQ(d1, d2);
546
CHECK_FALSE(d1 != d2);
547
ERR_PRINT_ON;
548
549
d1[2] = 2;
550
d2[2] = 2;
551
552
// Comparison should reach recursion limit
553
ERR_PRINT_OFF;
554
CHECK_EQ(d1, d2);
555
CHECK_FALSE(d1 != d2);
556
ERR_PRINT_ON;
557
558
d1[3] = 3;
559
d2[3] = 0;
560
561
// Comparison should reach recursion limit
562
ERR_PRINT_OFF;
563
CHECK_NE(d1, d2);
564
CHECK_FALSE(d1 == d2);
565
ERR_PRINT_ON;
566
567
// Break the recursivity otherwise Dictionary teardown will leak memory
568
d1.clear();
569
d2.clear();
570
}
571
#endif
572
573
TEST_CASE("[Dictionary] Recursive self comparison") {
574
Dictionary d1;
575
Dictionary d2;
576
d1[1] = d2;
577
d2[1] = d1;
578
579
CHECK_EQ(d1, d1);
580
CHECK_FALSE(d1 != d1);
581
582
// Break the recursivity otherwise Dictionary teardown will leak memory
583
d1.clear();
584
d2.clear();
585
}
586
587
TEST_CASE("[Dictionary] Order and find") {
588
Dictionary d;
589
d[4] = "four";
590
d[8] = "eight";
591
d[12] = "twelve";
592
d["4"] = "four";
593
594
Array keys = { 4, 8, 12, "4" };
595
596
CHECK_EQ(d.keys(), keys);
597
CHECK_EQ(d.find_key("four"), Variant(4));
598
CHECK_EQ(d.find_key("does not exist"), Variant());
599
}
600
601
TEST_CASE("[Dictionary] sort()") {
602
Dictionary d;
603
d[3] = 3;
604
d[2] = 2;
605
d[4] = 4;
606
d[1] = 1;
607
608
Array expected_unsorted = { 3, 2, 4, 1 };
609
CHECK_EQ(d.keys(), expected_unsorted);
610
611
d.sort();
612
Array expected_sorted = { 1, 2, 3, 4 };
613
CHECK_EQ(d.keys(), expected_sorted);
614
615
Dictionary d_str;
616
d_str["b"] = 2;
617
d_str["c"] = 3;
618
d_str["a"] = 1;
619
620
d_str.sort();
621
Array expected_str_sorted = { "a", "b", "c" };
622
CHECK_EQ(d_str.keys(), expected_str_sorted);
623
}
624
625
TEST_CASE("[Dictionary] assign()") {
626
Dictionary untyped;
627
untyped["key1"] = "value";
628
CHECK(untyped.size() == 1);
629
630
Dictionary typed;
631
typed.set_typed(Variant::STRING, StringName(), Variant(), Variant::STRING, StringName(), Variant());
632
typed.assign(untyped);
633
CHECK(typed.size() == 1);
634
typed["key2"] = "value";
635
636
untyped.assign(typed);
637
CHECK(untyped.size() == 2);
638
untyped["key3"] = 5;
639
CHECK(untyped.size() == 3);
640
641
ERR_PRINT_OFF;
642
typed.assign(untyped);
643
ERR_PRINT_ON;
644
CHECK(typed.size() == 2);
645
}
646
647
TEST_CASE("[Dictionary] Typed copying") {
648
TypedDictionary<int, int> d1;
649
d1[0] = 1;
650
651
TypedDictionary<double, double> d2;
652
d2[0] = 1.0;
653
654
Dictionary d3 = d1;
655
TypedDictionary<int, int> d4 = d3;
656
657
Dictionary d5 = d2;
658
TypedDictionary<int, int> d6 = d5;
659
660
d3[0] = 2;
661
d4[0] = 3;
662
663
// Same typed TypedDictionary should be shared.
664
CHECK_EQ(d1[0], Variant(3));
665
CHECK_EQ(d3[0], Variant(3));
666
CHECK_EQ(d4[0], Variant(3));
667
668
d5[0] = 2.0;
669
d6[0] = 3.0;
670
671
// Different typed TypedDictionary should not be shared.
672
CHECK_EQ(d2[0], Variant(2.0));
673
CHECK_EQ(d5[0], Variant(2.0));
674
CHECK_EQ(d6[0], Variant(3.0));
675
676
d1.clear();
677
d2.clear();
678
d3.clear();
679
d4.clear();
680
d5.clear();
681
d6.clear();
682
}
683
684
TEST_CASE("[Dictionary] Type checks/comparisons") {
685
Dictionary d1;
686
CHECK_FALSE(d1.is_typed());
687
CHECK_FALSE(d1.is_typed_key());
688
CHECK_FALSE(d1.is_typed_value());
689
690
d1.set_typed(Variant::STRING, StringName(), Variant(), Variant::OBJECT, "Node", Variant());
691
CHECK(d1.is_typed());
692
CHECK(d1.is_typed_key());
693
CHECK(d1.is_typed_value());
694
CHECK_EQ(d1.get_typed_key_builtin(), Variant::STRING);
695
CHECK_EQ(d1.get_typed_value_builtin(), Variant::OBJECT);
696
CHECK_EQ(d1.get_typed_value_class_name(), "Node");
697
698
Dictionary d2;
699
CHECK_FALSE(d1.is_same_typed(d2));
700
CHECK_FALSE(d1.is_same_typed_key(d2));
701
CHECK_FALSE(d1.is_same_typed_value(d2));
702
703
d2.set_typed(Variant::STRING, StringName(), Variant(), Variant::STRING, StringName(), Variant());
704
CHECK_FALSE(d1.is_same_typed(d2));
705
CHECK(d1.is_same_typed_key(d2));
706
CHECK_FALSE(d1.is_same_typed_value(d2));
707
}
708
709
TEST_CASE("[Dictionary] Iteration") {
710
Dictionary a1 = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
711
Dictionary a2 = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
712
713
int idx = 0;
714
715
for (const KeyValue<Variant, Variant> &kv : (const Dictionary &)a1) {
716
CHECK_EQ(int(a2[kv.key]), int(kv.value));
717
idx++;
718
}
719
720
CHECK_EQ(idx, a1.size());
721
722
a1.clear();
723
a2.clear();
724
}
725
726
TEST_CASE("[Dictionary] Object value init") {
727
Object *a = memnew(Object);
728
Object *b = memnew(Object);
729
TypedDictionary<double, Object *> tdict = {
730
{ 0.0, a },
731
{ 5.0, b },
732
};
733
CHECK_EQ(tdict[0.0], Variant(a));
734
CHECK_EQ(tdict[5.0], Variant(b));
735
memdelete(a);
736
memdelete(b);
737
}
738
739
TEST_CASE("[Dictionary] RefCounted value init") {
740
Ref<RefCounted> a = memnew(RefCounted);
741
Ref<RefCounted> b = memnew(RefCounted);
742
TypedDictionary<double, Ref<RefCounted>> tdict = {
743
{ 0.0, a },
744
{ 5.0, b },
745
};
746
CHECK_EQ(tdict[0.0], Variant(a));
747
CHECK_EQ(tdict[5.0], Variant(b));
748
}
749
750
} // namespace TestDictionary
751
752