diff --git a/sources/Data/Collections/Tests/TEST_ArrayList.uc b/sources/Data/Collections/Tests/TEST_ArrayList.uc new file mode 100644 index 0000000..9834b5e --- /dev/null +++ b/sources/Data/Collections/Tests/TEST_ArrayList.uc @@ -0,0 +1,319 @@ +/** + * Set of tests for `ArrayList` 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 . + */ +class TEST_ArrayList extends TestCase + abstract; + +protected static function TESTS() +{ + Test_GetSet(); + Test_CreateItem(); + Test_Length(); + Test_Empty(); + Test_AddInsert(); + Test_Remove(); + Test_Find(); + Test_ReferenceManagementGet(); + Test_Take(); +} + +protected static function Test_GetSet() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing getters and setters for items of `ArrayList`."); + Issue("Setters do not correctly expand `ArrayList`."); + array.SetItem(0, __().box.int(-9)).SetItem(2, __().text.FromString("text")); + TEST_ExpectTrue(array.GetLength() == 3); + TEST_ExpectTrue(IntBox(array.GetItem(0)).Get() == -9); + TEST_ExpectNone(array.GetItem(1)); + TEST_ExpectTrue(Text(array.GetItem(2)).ToString() == "text"); + + Issue("Setters do not correctly overwrite items of `ArrayList`."); + array.SetItem(1, __().box.float(34.76)); + array.SetItem(2, none); + TEST_ExpectTrue(array.GetLength() == 3); + TEST_ExpectTrue(IntBox(array.GetItem(0)).Get() == -9); + TEST_ExpectTrue(FloatBox(array.GetItem(1)).Get() == 34.76); + TEST_ExpectNone(array.GetItem(2)); +} + +protected static function Test_CreateItem() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing creating brand new items for `ArrayList`."); + Issue("`CreateItem()` incorrectly adds new values to the" + @ "`ArrayList`."); + array.CreateItem(1, class'Text'); + array.CreateItem(3, class'IntRef'); + array.CreateItem(4, class'BoolBox'); + TEST_ExpectNone(array.GetItem(0)); + TEST_ExpectNone(array.GetItem(2)); + TEST_ExpectTrue(Text(array.GetItem(1)).ToString() == ""); + TEST_ExpectTrue(IntRef(array.GetItem(3)).Get() == 0); + TEST_ExpectFalse(BoolBox(array.GetItem(4)).Get()); + + Issue("`CreateItem()` incorrectly overrides existing values in the" + @ "`ArrayList`."); + array.SetItem(5, __().ref.int(7)); + array.CreateItem(5, class'StringRef'); + TEST_ExpectTrue(StringRef(array.GetItem(5)).Get() == ""); + + class'MockItem'.default.objectCount = 0; + Issue("`CreateItem()` creates new object even if it cannot be recorded at" + @ "a given index."); + array.CreateItem(-1, class'MockItem'); + TEST_ExpectTrue(class'MockItem'.default.objectCount == 0); +} + +protected static function Test_Length() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing length getter and setter for `ArrayList`."); + Issue("Length of just created `ArrayList` is not zero."); + TEST_ExpectTrue(array.GetLength() == 0); + + Issue("`SetLength()` incorrectly changes length of the `ArrayList`."); + array.SetLength(200).SetItem(198, __().box.int(25)); + TEST_ExpectTrue(array.GetLength() == 200); + TEST_ExpectTrue(IntBox(array.GetItem(198)).Get() == 25); + array.SetLength(0); + TEST_ExpectTrue(array.GetLength() == 0); + + Issue("Shrinking size of `ArrayList` does not remove recorded items."); + array.SetLength(1000); + TEST_ExpectNone(array.GetItem(198)); +} + +protected static function Test_Empty() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing emptying `ArrayList`."); + array.AddItem(__().box.int(1)).AddItem(__().box.int(3)) + .AddItem(__().box.int(1)).AddItem(__().box.int(3)); + Issue("`Empty()` does not produce an empty array."); + array.Empty(); + TEST_ExpectTrue(array.GetLength() == 0); +} + +protected static function Test_AddInsert() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing adding new items to `ArrayList`."); + Issue("`Add()`/`AddItem()` incorrectly add new items to" + @ "the `ArrayList`."); + array.AddItem(__().box.int(3)).Add(3).AddItem(__().box.byte(7)).Add(1); + TEST_ExpectTrue(array.GetLength() == 6); + TEST_ExpectNotNone(IntBox(array.GetItem(0))); + TEST_ExpectTrue(IntBox(array.GetItem(0)).Get() == 3); + TEST_ExpectNone(array.GetItem(1)); + TEST_ExpectNone(array.GetItem(2)); + TEST_ExpectNone(array.GetItem(3)); + TEST_ExpectNotNone(ByteBox(array.GetItem(4))); + TEST_ExpectTrue(ByteBox(array.GetItem(4)).Get() == 7); + TEST_ExpectNone(array.GetItem(5)); + + Issue("`Insert()`/`InsertItem()` incorrectly add new items to" + @ "the `ArrayList`."); + array.Insert(2, 2).InsertItem(0, __().ref.bool(true)); + TEST_ExpectTrue(array.GetLength() == 9); + TEST_ExpectNotNone(BoolRef(array.GetItem(0))); + TEST_ExpectTrue(BoolRef(array.GetItem(0)).Get()); + TEST_ExpectNotNone(IntBox(array.GetItem(1))); + TEST_ExpectTrue(IntBox(array.GetItem(1)).Get() == 3); + TEST_ExpectNone(array.GetItem(2)); + TEST_ExpectNone(array.GetItem(6)); + TEST_ExpectNotNone(ByteBox(array.GetItem(7))); + TEST_ExpectTrue(ByteBox(array.GetItem(7)).Get() == 7); + TEST_ExpectNone(array.GetItem(8)); +} + +protected static function Test_Remove() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing removing items from `ArrayList`."); + array.AddItem(__().box.int(1)).AddItem(__().box.int(3)) + .AddItem(__().box.int(1)).AddItem(__().box.int(3)) + .AddItem(__().box.int(5)).AddItem(__().box.int(2)) + .AddItem(__().box.int(4)).AddItem(__().box.int(7)) + .AddItem(__().box.int(5)).AddItem(__().box.int(1)) + .AddItem(__().box.int(5)).AddItem(__().box.int(0)); + Issue("`Remove()` incorrectly removes items from array."); + array.Remove(3, 2).Remove(0, 2).Remove(7, 9); + TEST_ExpectTrue(array.GetLength() == 7); + TEST_ExpectTrue(IntBox(array.GetItem(0)).Get() == 1); + TEST_ExpectTrue(IntBox(array.GetItem(1)).Get() == 2); + TEST_ExpectTrue(IntBox(array.GetItem(2)).Get() == 4); + TEST_ExpectTrue(IntBox(array.GetItem(3)).Get() == 7); + TEST_ExpectTrue(IntBox(array.GetItem(4)).Get() == 5); + TEST_ExpectTrue(IntBox(array.GetItem(5)).Get() == 1); + TEST_ExpectTrue(IntBox(array.GetItem(6)).Get() == 5); + + Issue("`RemoveItem()` incorrectly removes items from array."); + array.RemoveItem(__().box.int(1)).RemoveItem(__().box.int(5), true); + TEST_ExpectTrue(array.GetLength() == 4); + TEST_ExpectTrue(IntBox(array.GetItem(0)).Get() == 2); + TEST_ExpectTrue(IntBox(array.GetItem(1)).Get() == 4); + TEST_ExpectTrue(IntBox(array.GetItem(2)).Get() == 7); + TEST_ExpectTrue(IntBox(array.GetItem(3)).Get() == 5); + + Issue("`RemoveIndex()` incorrectly removes items from array."); + array.RemoveIndex(0).RemoveIndex(1).RemoveIndex(1); + TEST_ExpectTrue(array.GetLength() == 1); + TEST_ExpectTrue(IntBox(array.GetItem(0)).Get() == 4); +} + +protected static function Test_Find() +{ + local ArrayList array; + + array = ArrayList(__().memory.Allocate(class'ArrayList')); + Context("Testing searching for items in `ArrayList`."); + array.AddItem(__().box.int(1)).AddItem(__().box.int(3)) + .AddItem(__().box.int(1)).AddItem(__().box.int(3)) + .AddItem(__().box.int(5)).AddItem(__().box.bool(true)) + .AddItem(none).AddItem(__().box.float(72.54)) + .AddItem(__().box.int(5)).AddItem(__().box.int(1)) + .AddItem(__().box.int(5)).AddItem(__().box.int(0)); + Issue("`Find()` does not properly find indices of existing items."); + TEST_ExpectTrue(array.Find(__().box.int(5)) == 4); + TEST_ExpectTrue(array.Find(__().box.int(1)) == 0); + TEST_ExpectTrue(array.Find(__().box.int(0)) == 11); + TEST_ExpectTrue(array.Find(__().box.float(72.54)) == 7); + TEST_ExpectTrue(array.Find(__().box.bool(true)) == 5); + TEST_ExpectTrue(array.Find(none) == 6); + + Issue("`Find()` does not return `-1` on missing values."); + TEST_ExpectTrue(array.Find(__().box.int(42)) == -1); + TEST_ExpectTrue(array.Find(__().box.float(72.543)) == -1); + TEST_ExpectTrue(array.Find(__().box.bool(false)) == -1); + TEST_ExpectTrue(array.Find(__().box.byte(128)) == -1); +} + +protected static function MockItem NewMockItem() +{ + return MockItem(__().memory.Allocate(class'MockItem')); +} + +protected static function ArrayList NewMockArray( + int arrayLength, + out array allocatedItems) +{ + local int i; + local ArrayList array; + + class'MockItem'.default.objectCount = 0; + array = ArrayList(__().memory.Allocate(class'ArrayList')); + for (i = 0; i < arrayLength; i += 1) + { + allocatedItems[allocatedItems.length] = NewMockItem(); + array.AddItem(allocatedItems[allocatedItems.length - 1]); + } + // Get rid of references outside of array + __().memory.FreeMany(allocatedItems); + return array; +} + +protected static function Test_ReferenceManagementGet() +{ + local int i; + local ArrayList array; + local array allocatedItems; + + array = NewMockArray(20, allocatedItems); + Context("Testing how well `ArrayList` supports reference counting."); + Issue("`ArrayList` incorrectly increments reference count when storing" @ + "an item."); + for (i = 0; i < allocatedItems.length; i += 1) + { + TEST_ExpectTrue(allocatedItems[i]._getRefCount() == 1); + if (i % 3 == 0) { + allocatedItems[i].FreeSelf(); + } + } + + for (i = 0; i < allocatedItems.length; i += 1) + { + if (i % 3 == 0) + { + Issue("`ArrayList` does unnecessary handling of deallocated" + @ "items."); + TEST_ExpectNotNone(array.GetItem(i)); + TEST_ExpectFalse(array.GetItem(i).IsAllocated()); + } + else if (i % 3 == 1) + { + Issue("`ArrayList` does not increment reference count on" + @ "`GetItem()`"); + TEST_ExpectTrue(array.GetItem(i)._getRefCount() == 2); + } + else + { + Issue("`ArrayList` increments reference count on `TakeItem()`"); + TEST_ExpectTrue(array.TakeItem(i)._getRefCount() == 1); + } + } +} + +protected static function Test_Take() +{ + local int i; + local ArrayList array; + local array allocatedItems; + + array = NewMockArray(20, allocatedItems); + Context("Testing how well `ArrayList`'s `TakeItem()` command"); + Issue("`TakeItem()` return wrongs item."); + for (i = 0; i < allocatedItems.length; i += 1) + { + if (i % 2 == 0) { + TEST_ExpectTrue(array.TakeItem(i) == allocatedItems[i]); + } + } + for (i = 0; i < allocatedItems.length; i += 1) + { + if (i % 2 == 0) + { + Issue("`TakeItem()` does not remove items from collection."); + TEST_ExpectNone(array.TakeItem(i)); + } + else + { + Issue("`TakeItem()` affects other items in collection."); + TEST_ExpectTrue(array.TakeItem(i).IsAllocated()); + } + } +} + +defaultproperties +{ + caseGroup = "Collections" + caseName = "ArrayList" +} \ No newline at end of file diff --git a/sources/Manifest.uc b/sources/Manifest.uc index 4f5e9b7..a269e87 100644 --- a/sources/Manifest.uc +++ b/sources/Manifest.uc @@ -45,7 +45,7 @@ defaultproperties testCases(14) = class'TEST_TextTemplate' testCases(15) = class'TEST_User' testCases(16) = class'TEST_Memory' - testCases(17) = class'TEST_DynamicArray' + testCases(17) = class'TEST_ArrayList' testCases(18) = class'TEST_AssociativeArray' testCases(19) = class'TEST_CollectionsMixed' testCases(20) = class'TEST_Iterator'