Anton Tarasenko
2 years ago
3 changed files with 563 additions and 2 deletions
@ -0,0 +1,561 @@
|
||||
/** |
||||
* Set of tests for `HashTable` class. |
||||
* Copyright 2022 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia 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 General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class TEST_HashTable extends TestCase |
||||
abstract; |
||||
|
||||
var private array<IntBox> keys; |
||||
var private array<MockItem> mockedItems; |
||||
|
||||
protected static function TESTS() |
||||
{ |
||||
Test_GetSet(); |
||||
Test_HasKey(); |
||||
Test_GetKeys(); |
||||
Test_GetTextKeys(); |
||||
Test_Remove(); |
||||
Test_CreateItem(); |
||||
Test_Empty(); |
||||
Test_Length(); |
||||
Test_ReferenceManagement(); |
||||
Test_Take(); |
||||
Test_LargeArray(); |
||||
} |
||||
|
||||
protected static function AcediaObject NewKey(int value) |
||||
{ |
||||
local IntBox newBox; |
||||
|
||||
newBox = __().box.int(value); |
||||
default.keys[default.keys.length] = newBox; |
||||
return newBox; |
||||
} |
||||
|
||||
protected static function MockItem NewMockItem() |
||||
{ |
||||
local MockItem newItem; |
||||
|
||||
newItem = MockItem(__().memory.Allocate(class'MockItem')); |
||||
default.mockedItems[default.mockedItems.length] = newItem; |
||||
return newItem; |
||||
} |
||||
|
||||
protected static function Test_GetSet() |
||||
{ |
||||
local Text textObject; |
||||
local HashTable array; |
||||
|
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
Context("Testing getters and setters for items of `HashTable`."); |
||||
Issue("`SetItem()` does not correctly set new items."); |
||||
textObject = __().text.FromString("value"); |
||||
array.SetItem(__().text.FromString("key"), textObject); |
||||
array.SetItem(__().box.int(13), __().text.FromString("value #2")); |
||||
array.SetItem(__().box.float(345.2), __().box.bool(true)); |
||||
TEST_ExpectTrue( Text(array.GetItem(__().box.int(13))).ToString() |
||||
== "value #2"); |
||||
TEST_ExpectTrue(array.GetItem(__().text.FromString("key")) == textObject); |
||||
TEST_ExpectTrue(BoolBox(array.GetItem(__().box.float(345.2))).Get()); |
||||
|
||||
Issue("`SetItem()` does not correctly overwrite new items."); |
||||
array.SetItem(__().text.FromString("key"), __().text.FromString("value")); |
||||
array.SetItem(__().box.int(13), __().box.int(11)); |
||||
TEST_ExpectFalse(array.GetItem(__().text.FromString("key")) == textObject); |
||||
TEST_ExpectTrue( Text(array.GetItem(__().text.FromString("key"))) |
||||
.ToString() == "value"); |
||||
TEST_ExpectTrue( IntBox(array.GetItem(__().box.int(13))).Get() |
||||
== 11); |
||||
|
||||
Issue("`GetItem()` does not return `none` for non-existing keys."); |
||||
TEST_ExpectNone(array.GetItem(__().box.int(12))); |
||||
TEST_ExpectNone(array.GetItem(__().box.byte(67))); |
||||
TEST_ExpectNone(array.GetItem(__().box.float(43.1234))); |
||||
TEST_ExpectNone(array.GetItem(__().text.FromString("Some random stuff"))); |
||||
} |
||||
|
||||
protected static function Test_HasKey() |
||||
{ |
||||
local HashTable array; |
||||
|
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
Context("Testing `HasKey()` method for `HashTable`."); |
||||
array.SetItem(__().text.FromString("key"), __().text.FromString("value")); |
||||
array.SetItem(__().box.int(13), __().text.FromString("value #2")); |
||||
array.SetItem(__().box.float(345.2), __().box.bool(true)); |
||||
Issue("`HasKey()` reports that added keys do not exist in" |
||||
@ "`HashTable`."); |
||||
TEST_ExpectTrue(array.HasKey(__().text.FromString("key"))); |
||||
TEST_ExpectTrue(array.HasKey(__().box.int(13))); |
||||
TEST_ExpectTrue(array.HasKey(__().box.float(345.2))); |
||||
|
||||
Issue("`HasKey()` reports that `HashTable` contains keys that" |
||||
@ "were never added."); |
||||
TEST_ExpectFalse(array.HasKey(none)); |
||||
TEST_ExpectFalse(array.HasKey(__().box.float(13))); |
||||
TEST_ExpectFalse(array.HasKey(__().box.byte(139))); |
||||
} |
||||
|
||||
protected static function Test_GetKeys() |
||||
{ |
||||
local int i; |
||||
local AcediaObject key1, key2, key3; |
||||
local array<AcediaObject> keys; |
||||
local HashTable array; |
||||
|
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
Context("Testing `GetKeys()` method for `HashTable`."); |
||||
key1 = __().text.FromString("key"); |
||||
key2 = __().box.int(13); |
||||
key3 = __().box.float(345.2); |
||||
array.SetItem(key1, __().text.FromString("value")); |
||||
array.SetItem(key2, __().text.FromString("value #2")); |
||||
array.SetItem(key3, __().box.bool(true)); |
||||
keys = array.GetKeys(); |
||||
Issue("`GetKeys()` returns array with wrong amount of elements."); |
||||
TEST_ExpectTrue(keys.length == 3); |
||||
|
||||
Issue("`GetKeys()` returns array with duplicate keys."); |
||||
TEST_ExpectTrue(keys[0] != keys[1]); |
||||
TEST_ExpectTrue(keys[0] != keys[2]); |
||||
TEST_ExpectTrue(keys[1] != keys[2]); |
||||
|
||||
Issue("`GetKeys()` returns array with incorrect keys."); |
||||
for (i = 0; i < 3; i += 1) { |
||||
TEST_ExpectTrue(keys[i] == key1 || keys[i] == key2 || keys[i] == key3); |
||||
} |
||||
|
||||
keys = array.RemoveItem(key1).GetKeys(); |
||||
Issue("`GetKeys()` returns array with incorrect keys after removing" |
||||
@ "an element."); |
||||
TEST_ExpectTrue(keys.length == 2); |
||||
TEST_ExpectTrue(keys[0] != keys[1]); |
||||
for (i = 0; i < 2; i += 1) { |
||||
TEST_ExpectTrue(keys[i] == key2 || keys[i] == key3); |
||||
} |
||||
} |
||||
|
||||
protected static function Test_GetTextKeys() |
||||
{ |
||||
local array<AcediaObject> allKeys; |
||||
local array<Text> keys; |
||||
local HashTable array; |
||||
|
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
Context("Testing `GetTextKeys()` method for `HashTable`."); |
||||
array.SetItem(__().text.FromString("key"), __().text.FromString("value")); |
||||
array.SetItem(__().box.int(13), __().text.FromString("value #2")); |
||||
array.SetItem(__().box.float(-925.274), __().text.FromString("value #2")); |
||||
array.SetItem(__().text.FromString("second key"), __().box.bool(true)); |
||||
|
||||
Issue("`GetTextKeys()` does not return correct set of keys."); |
||||
keys = array.GetTextKeys(); |
||||
TEST_ExpectTrue(keys.length == 2); |
||||
TEST_ExpectTrue( |
||||
(keys[0].ToString() == "key" |
||||
&& keys[1].ToString() == "second key") |
||||
|| (keys[0].ToString() == "second key" |
||||
&& keys[1].ToString() == "key")); |
||||
|
||||
Issue("Deallocating keys returned by `GetTextKeys()` affects their" |
||||
@ "source collection."); |
||||
allKeys = array.GetKeys(); |
||||
TEST_ExpectTrue(allKeys.length == 4); |
||||
TEST_ExpectNotNone(array.GetItem(__().text.FromString("key"))); |
||||
TEST_ExpectNotNone(array.GetItem(__().text.FromString("second key"))); |
||||
TEST_ExpectTrue( |
||||
array.GetText(__().text.FromString("key")).ToString() == "value"); |
||||
} |
||||
|
||||
protected static function Test_Remove() |
||||
{ |
||||
local AcediaObject key1, key2, key3; |
||||
local array<AcediaObject> keys; |
||||
local HashTable array; |
||||
|
||||
Context("Testing removing elements from `HashTable`."); |
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
key1 = __().text.FromString("some key"); |
||||
key2 = __().box.int(25); |
||||
key3 = __().box.float(0.07); |
||||
array.SetItem(key1, __().text.FromString("value")); |
||||
array.SetItem(key2, __().text.FromString("value #2")); |
||||
array.SetItem(key3, __().box.bool(true)); |
||||
|
||||
Issue("Elements are not properly removed from `HashTable`."); |
||||
array.RemoveItem(key1) |
||||
.RemoveItem(__().box.int(25)) |
||||
.RemoveItem(__().box.float(0.06)); |
||||
keys = array.GetKeys(); |
||||
TEST_ExpectTrue(array.GetLength() == 1); |
||||
TEST_ExpectTrue(keys.length == 1); |
||||
TEST_ExpectTrue(keys[0] == key3); |
||||
} |
||||
|
||||
protected static function Test_CreateItem() |
||||
{ |
||||
local HashTable array; |
||||
|
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
Context("Testing creating brand new items for `HashTable`."); |
||||
Issue("`CreateItem()` incorrectly adds new values to the" |
||||
@ "`HashTable`."); |
||||
array.CreateItem(__().text.FromString("key"), class'Text'); |
||||
array.CreateItem(__().box.float(17.895), class'IntRef'); |
||||
array.CreateItem(__().text.FromString("key #2"), class'BoolBox'); |
||||
TEST_ExpectTrue(Text(array.GetItem(__().text.FromString("key"))) |
||||
.ToString() == ""); |
||||
TEST_ExpectTrue( IntRef(array.GetItem(__().box.float(17.895))).Get() |
||||
== 0); |
||||
TEST_ExpectFalse(BoolBox(array.GetItem(__().text.FromString("key #2"))) |
||||
.Get()); |
||||
|
||||
Issue("`CreateItem()` incorrectly overrides existing values in the" |
||||
@ "`HashTable`."); |
||||
array.SetItem(__().box.int(13), __().ref.int(7)); |
||||
array.CreateItem(__().box.int(13), class'StringRef'); |
||||
TEST_ExpectTrue( StringRef(array.GetItem(__().box.int(13))).Get() |
||||
== ""); |
||||
|
||||
class'MockItem'.default.objectCount = 0; |
||||
Issue("`CreateItem()` creates new object even if it cannot be recorded with" |
||||
@ "a given key."); |
||||
array.CreateItem(none, class'MockItem'); |
||||
TEST_ExpectTrue(class'MockItem'.default.objectCount == 0); |
||||
} |
||||
|
||||
protected static function Test_Empty() |
||||
{ |
||||
local AcediaObject key1, key2, key3; |
||||
local HashTable array; |
||||
|
||||
key1 = __().text.FromString("key"); |
||||
key2 = __().box.int(13); |
||||
key3 = __().box.float(345.2); |
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
array.SetItem(key1, __().text.FromString("value")); |
||||
array.SetItem(key2, __().text.FromString("value #2")); |
||||
array.SetItem(key3, __().box.bool(true)); |
||||
|
||||
Context("Testing `Empty()` method for `HashTable`."); |
||||
Issue("`HashTable` still contains elements after being emptied."); |
||||
array.Empty(); |
||||
TEST_ExpectTrue(array.GetKeys().length == 0); |
||||
TEST_ExpectTrue(array.GetLength() == 0); |
||||
|
||||
Issue("`HashTable` still contains elements after being emptied."); |
||||
array.SetItem(key1, __().text.FromString("value")); |
||||
array.SetItem(key2, __().text.FromString("value #2")); |
||||
array.SetItem(key3, __().box.bool(true)); |
||||
array.Empty(); |
||||
TEST_ExpectTrue(array.GetKeys().length == 0); |
||||
TEST_ExpectTrue(array.GetLength() == 0); |
||||
} |
||||
|
||||
protected static function Test_Length() |
||||
{ |
||||
local HashTable array; |
||||
|
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
Context("Testing computing length of `HashTable`."); |
||||
Issue("Length is not zero for newly created `HashTable`."); |
||||
TEST_ExpectTrue(array.GetLength() == 0); |
||||
|
||||
Issue("Length is incorrectly computed after adding elements to" |
||||
@ "`HashTable`."); |
||||
array.SetItem(__().text.FromString("key"), __().text.FromString("value")); |
||||
array.SetItem(__().box.int(4563), __().text.FromString("value #2")); |
||||
array.SetItem(__().box.float(3425.243), __().box.byte(23)); |
||||
TEST_ExpectTrue(array.GetLength() == 3); |
||||
|
||||
Issue("Length is incorrectly computed after removing elements from" |
||||
@ "`HashTable`."); |
||||
array.RemoveItem(__().box.int(4563)); |
||||
TEST_ExpectTrue(array.GetLength() == 2); |
||||
} |
||||
|
||||
protected static function HashTable RecreateTestHashTable() |
||||
{ |
||||
local HashTable table; |
||||
|
||||
class'MockItem'.default.objectCount = 0; |
||||
default.mockedItems.length = 0; |
||||
default.keys.length = 0; |
||||
table = HashTable(__().memory.Allocate(class'HashTable')); |
||||
table.SetItem(NewKey(0), NewMockItem()); |
||||
table.SetItem(NewKey(1), NewMockItem()); |
||||
table.SetItem(NewKey(2), NewMockItem()); |
||||
table.SetItem(NewKey(3), NewMockItem()); |
||||
table.SetItem(NewKey(4), NewMockItem()); |
||||
table.SetItem(NewKey(5), NewMockItem()); |
||||
table.CreateItem(NewKey(6), class'MockItem'); |
||||
table.CreateItem(NewKey(7), class'MockItem'); |
||||
table.CreateItem(NewKey(8), class'MockItem'); |
||||
return table; |
||||
} |
||||
|
||||
protected static function Test_ReferenceManagement() |
||||
{ |
||||
Context("Testing how `HashTable` handles reference counting."); |
||||
SubTest_IncorrectGetRefCount(RecreateTestHashTable()); |
||||
SubTest_IncorrectTakeRefCount(RecreateTestHashTable()); |
||||
SubTest_IncorrectGetEntryRefCount(RecreateTestHashTable()); |
||||
SubTest_IncorrectTakeEntryRefCount(RecreateTestHashTable()); |
||||
SubTest_IncorrectEmptyRefCount(RecreateTestHashTable()); |
||||
SubTest_IncorrectGetKeysRefCount(RecreateTestHashTable()); |
||||
} |
||||
|
||||
protected static function SubTest_IncorrectGetRefCount(HashTable table) |
||||
{ |
||||
Issue("`HashTable` incorrectly handles reference count when storing" @ |
||||
"an item."); |
||||
// 1 ref after creation + 1 ref in `HastTable` => 2 |
||||
TEST_ExpectTrue(default.mockedItems[0]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.mockedItems[1]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.mockedItems[2]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.mockedItems[3]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.mockedItems[4]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.mockedItems[5]._getRefCount() == 2); |
||||
|
||||
Issue("`HashTable` incorrectly handles reference count when returning" |
||||
@ "an item with `GetItem()`."); |
||||
// 1 ref after creation + 1 ref in `HastTable` + 1 after `GetItem()` => 3 |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(0))._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(1))._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(2))._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(3))._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(4))._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(5))._getRefCount() == 3); |
||||
// 1 ref in `HastTable` + 1 after `GetItem()` => 2 |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(6))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(7))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.GetItem(__().box.int(8))._getRefCount() == 2); |
||||
// 1 ref after creation + 1 ref in `HastTable` => 2 |
||||
Issue("`HashTable` incorrectly handles reference count for keys when" |
||||
@ "using `GetItem()."); |
||||
TEST_ExpectTrue(default.keys[0]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[1]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[2]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[3]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[4]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[5]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[6]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[7]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[8]._getRefCount() == 2); |
||||
} |
||||
|
||||
protected static function SubTest_IncorrectTakeRefCount(HashTable table) |
||||
{ |
||||
Issue("`HashTable` incorrectly handles reference count when returning" |
||||
@ "an item with `TakeItem()`."); |
||||
// 1 ref after creation + 1 ref in `HastTable` => 2 |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(0))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(1))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(2))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(3))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(4))._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(5))._getRefCount() == 2); |
||||
// 1 ref in `HastTable` => 1 |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(6))._getRefCount() == 1); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(7))._getRefCount() == 1); |
||||
TEST_ExpectTrue(table.TakeItem(__().box.int(8))._getRefCount() == 1); |
||||
// Keys should get their refs decreased after the `Take()` command |
||||
TEST_ExpectTrue(default.keys[0]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[1]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[2]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[3]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[4]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[5]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[6]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[7]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[8]._getRefCount() == 1); |
||||
} |
||||
|
||||
protected static function SubTest_IncorrectGetEntryRefCount(HashTable table) |
||||
{ |
||||
Issue("`HashTable` incorrectly handles reference count when storing" @ |
||||
"an item."); |
||||
Issue("`HashTable` incorrectly handles reference count when returning" |
||||
@ "an item with `GetEntry()`."); |
||||
// 1 ref after creation + 1 ref in `HastTable` + 1 from `GetEntry()` => 3 |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(0)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(1)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(2)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(3)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(4)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(5)).key._getRefCount() == 3); |
||||
// 1ref after creation + 1 ref in `HastTable` + 1 after `GetEntry()` => 3 |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(6)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(7)).key._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(8)).key._getRefCount() == 3); |
||||
|
||||
// 1 ref after creation + 1 ref in `HastTable` |
||||
// + 2 from two `GetEntry()`s => 4 |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(0)).value._getRefCount() == 4); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(1)).value._getRefCount() == 4); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(2)).value._getRefCount() == 4); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(3)).value._getRefCount() == 4); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(4)).value._getRefCount() == 4); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(5)).value._getRefCount() == 4); |
||||
// 1 ref in `HastTable` + 2 from two `GetEntry()`s => 3 |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(6)).value._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(7)).value._getRefCount() == 3); |
||||
TEST_ExpectTrue(table.GetEntry(__().box.int(8)).value._getRefCount() == 3); |
||||
} |
||||
|
||||
protected static function SubTest_IncorrectTakeEntryRefCount(HashTable table) |
||||
{ |
||||
Issue("`HashTable` incorrectly handles reference count when returning" |
||||
@ "an item with `TakeEntry()`."); |
||||
// 1 ref after creation + 1 ref in `HastTable` => 2 |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(0)).value._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(1)).value._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(2)).value._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(3)).value._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(4)).value._getRefCount() == 2); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(5)).value._getRefCount() == 2); |
||||
// 1 ref in `HastTable` => 1 |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(6)).value._getRefCount() == 1); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(7)).value._getRefCount() == 1); |
||||
TEST_ExpectTrue(table.TakeEntry(__().box.int(8)).value._getRefCount() == 1); |
||||
// Keys should get their refs unchanged after the `TakeEntry()` command |
||||
TEST_ExpectTrue(default.keys[0]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[1]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[2]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[3]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[4]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[5]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[6]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[7]._getRefCount() == 2); |
||||
TEST_ExpectTrue(default.keys[8]._getRefCount() == 2); |
||||
} |
||||
|
||||
protected static function SubTest_IncorrectEmptyRefCount(HashTable table) |
||||
{ |
||||
Issue("`HashTable` incorrectly handles reference count when emptying" |
||||
@ "`HashTable` with `Empty()`."); |
||||
table.Empty(); |
||||
// 1 ref after creation + now 0 ref in `HastTable` => 1 |
||||
TEST_ExpectTrue(default.mockedItems[0]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.mockedItems[1]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.mockedItems[2]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.mockedItems[3]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.mockedItems[4]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.mockedItems[5]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[0]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[1]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[2]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[3]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[4]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[5]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[6]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[7]._getRefCount() == 1); |
||||
TEST_ExpectTrue(default.keys[8]._getRefCount() == 1); |
||||
} |
||||
|
||||
protected static function SubTest_IncorrectGetKeysRefCount(HashTable table) |
||||
{ |
||||
Issue("`HashTable` incorrectly handles reference count when returning" |
||||
@ "keys with `GetKeys()`."); |
||||
table.GetKeys(); |
||||
// 1 ref after creation + 1 ref in `HastTable` + 1 after `GetKeys()` => 3 |
||||
TEST_ExpectTrue(default.keys[0]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[1]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[2]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[3]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[4]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[5]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[6]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[7]._getRefCount() == 3); |
||||
TEST_ExpectTrue(default.keys[8]._getRefCount() == 3); |
||||
} |
||||
|
||||
protected static function Test_Take() |
||||
{ |
||||
local HashTable.Entry entry; |
||||
local HashTable array; |
||||
local array<AcediaObject> keys; |
||||
|
||||
class'MockItem'.default.objectCount = 0; |
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
array.SetItem(__().box.int(0), NewMockItem()); |
||||
array.SetItem(__().box.int(1), NewMockItem()); |
||||
array.SetItem(__().box.int(2), NewMockItem()); |
||||
array.CreateItem(__().box.int(3), class'MockItem'); |
||||
array.CreateItem(__().box.int(4), class'MockItem'); |
||||
Context("Testing `TakeItem()`and `TakeEntry()` methods of `HashTable`."); |
||||
Issue("`TakeItem()` does not return stored value."); |
||||
TEST_ExpectTrue(array.TakeItem(__().box.int(0)).class == class'MockItem'); |
||||
TEST_ExpectTrue(array.TakeItem(__().box.int(3)).class == class'MockItem'); |
||||
|
||||
Issue("`TakeItem()` does not remove value from the hash table."); |
||||
TEST_ExpectNone(array.GetItem(__().box.int(0))); |
||||
TEST_ExpectNone(array.GetItem(__().box.int(3))); |
||||
|
||||
Issue("`TakeEntry()` does not return stored key / value."); |
||||
entry = array.TakeEntry(__().box.int(1)); |
||||
TEST_ExpectTrue(IntBox(entry.key).Get() == 1); |
||||
TEST_ExpectTrue(entry.value.class == class'MockItem'); |
||||
entry = array.TakeEntry(__().box.int(4)); |
||||
TEST_ExpectTrue(IntBox(entry.key).Get() == 4); |
||||
TEST_ExpectTrue(entry.value.class == class'MockItem'); |
||||
|
||||
Issue("`TakeEntry()` does not remove value from the hash table."); |
||||
TEST_ExpectNone(array.GetItem(__().box.int(1))); |
||||
TEST_ExpectNone(array.GetItem(__().box.int(4))); |
||||
|
||||
Issue("Keys are not removed by `Take()` / `TakeEntry()` commands."); |
||||
keys = array.GetKeys(); |
||||
TEST_ExpectTrue(keys.length == 1); |
||||
TEST_ExpectTrue(IntBox(keys[0]).Get() == 2); |
||||
} |
||||
|
||||
protected static function Test_LargeArray() |
||||
{ |
||||
local int i; |
||||
local AcediaObject nextKey; |
||||
local HashTable array; |
||||
|
||||
Context("Testing storing large amount of elements in `HashTable`."); |
||||
Issue("`HashTable` cannot handle large amount of elements."); |
||||
array = HashTable(__().memory.Allocate(class'HashTable')); |
||||
for (i = 0; i < 5000; i += 1) { |
||||
if (i % 2 == 0) { |
||||
nextKey = __().text.FromString("var" @ i); |
||||
} |
||||
else { |
||||
nextKey = __().box.int(i * 56 - 435632); |
||||
} |
||||
array.SetItem(nextKey, __().ref.int(i)); |
||||
} |
||||
for (i = 0; i < 5000; i += 1) { |
||||
if (i % 2 == 0) { |
||||
nextKey = __().text.FromString("var" @ i); |
||||
} |
||||
else { |
||||
nextKey = __().box.int(i * 56 - 435632); |
||||
} |
||||
TEST_ExpectTrue(IntRef(array.GetItem(nextKey)).Get() == i); |
||||
} |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
caseGroup = "Collections" |
||||
caseName = "HashTable" |
||||
} |
Loading…
Reference in new issue