diff --git a/sources/Data/Collections/Tests/TEST_Iterator.uc b/sources/Data/Collections/Tests/TEST_Iterator.uc
index af0760b..2495e9f 100644
--- a/sources/Data/Collections/Tests/TEST_Iterator.uc
+++ b/sources/Data/Collections/Tests/TEST_Iterator.uc
@@ -1,6 +1,6 @@
/**
* Set of tests for `Iterator` classes.
- * Copyright 2020 Anton Tarasenko
+ * Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@@ -28,6 +28,7 @@ protected static function CreateItems()
{
local int i;
ResetFlags();
+ default.items.length = 0;
for (i = 0; i < default.TESTED_ITEMS_AMOUNT; i += 1) {
default.items[default.items.length] = __().ref.float(i*2 + 1/i);
}
@@ -39,15 +40,30 @@ protected static function ResetFlags()
default.seenFlags.length = default.TESTED_ITEMS_AMOUNT;
}
-protected static function DoTestIterator(Iter iter)
+protected static function DoTestIterator(
+ string issueSubjectAllocation,
+ string issueSubjectAmount,
+ Iter iter)
{
local int i;
local int seenCount;
local AcediaObject nextObject;
+
ResetFlags();
+ Issue(issueSubjectAllocation);
while (!iter.HasFinished())
{
nextObject = iter.Get();
+ // Create + insert into collection + get reference
+ TEST_ExpectTrue(nextObject._getRefCount() == 3);
+ if (iter.class == class'ArrayListIterator') {
+ // `ArrayList` creates keys to return on-the-fly
+ TEST_ExpectTrue(iter.GetKey()._getRefCount() == 1);
+ }
+ else {
+ // Create + insert into collection + get reference
+ TEST_ExpectTrue(iter.GetKey()._getRefCount() == 3);
+ }
for (i = 0; i < default.items.length; i += 1)
{
if (default.items[i] == nextObject)
@@ -61,33 +77,35 @@ protected static function DoTestIterator(Iter iter)
}
iter.Next();
}
+ Issue(issueSubjectAmount);
TEST_ExpectTrue(seenCount == default.TESTED_ITEMS_AMOUNT);
}
protected static function TESTS()
{
- // Prepare
CreateItems();
- // Test
- Test_DynamicArray();
- Test_AssociativeArray();
+ Test_ArrayList();
+ CreateItems();
+ Test_HashTable();
+ Test_IterationAndNone();
}
-protected static function Test_DynamicArray()
+protected static function Test_ArrayList()
{
- local int i;
- local Iter iter;
- local DynamicArray array;
- array = DynamicArray(__().memory.Allocate(class'DynamicArray'));
+ local int i;
+ local Iter iter;
+ local ArrayList array;
+
+ array = ArrayList(__().memory.Allocate(class'ArrayList'));
iter = array.Iterate();
- Context("Testing iterator for `DynamicArray`");
- Issue("`DynamicArray` returns `none` iterator.");
+ Context("Testing iterator for `ArrayList`");
+ Issue("`ArrayList` returns `none` iterator.");
TEST_ExpectNotNone(iter);
- Issue("Iterator for empty `DynamicArray` is not finished by default.");
+ Issue("Iterator for empty `ArrayList` is not finished by default.");
TEST_ExpectTrue(iter.HasFinished());
- Issue("Iterator for empty `DynamicArray` does not return `none` as"
+ Issue("Iterator for empty `ArrayList` does not return `none` as"
@ "a current item.");
TEST_ExpectNone(iter.Get());
TEST_ExpectNone(iter.Next().Get());
@@ -96,28 +114,32 @@ protected static function Test_DynamicArray()
array.AddItem(default.items[i]);
}
iter = array.Iterate();
- Issue("`DynamicArray` returns `none` iterator.");
+ Issue("`ArrayList` returns `none` iterator.");
TEST_ExpectNotNone(iter);
- Issue("`DynamicArray`'s iterator iterates over incorrect set of items.");
- DoTestIterator(iter);
+ Issue("`ArrayList`'s iterator iterates over incorrect set of items.");
+ DoTestIterator(
+ "`ArrayList`'s iterator incorrectly handles reference counting.",
+ "`ArrayList`'s iterator iterates over incorrect set of items.",
+ iter);
}
-protected static function Test_AssociativeArray()
+protected static function Test_HashTable()
{
- local int i;
- local Iter iter;
- local AssociativeArray array;
- array = AssociativeArray(__().memory.Allocate(class'AssociativeArray'));
+ local int i;
+ local Iter iter;
+ local HashTable array;
+
+ array = HashTable(__().memory.Allocate(class'HashTable'));
iter = array.Iterate();
- Context("Testing iterator for `AssociativeArray`");
- Issue("`AssociativeArray` returns `none` iterator.");
+ Context("Testing iterator for `HashTable`");
+ Issue("`HashTable` returns `none` iterator.");
TEST_ExpectNotNone(iter);
- Issue("Iterator for empty `AssociativeArray` is not finished by default.");
+ Issue("Iterator for empty `HashTable` is not finished by default.");
TEST_ExpectTrue(iter.HasFinished());
- Issue("Iterator for empty `AssociativeArray` does not return `none` as"
+ Issue("Iterator for empty `HashTable` does not return `none` as"
@ "a current item.");
TEST_ExpectNone(iter.Get());
TEST_ExpectNone(iter.Next().Get());
@@ -126,17 +148,103 @@ protected static function Test_AssociativeArray()
array.SetItem(__().box.int(i), default.items[i]);
}
iter = array.Iterate();
- Issue("`AssociativeArray` returns `none` iterator.");
+ Issue("`HashTable` returns `none` iterator.");
TEST_ExpectNotNone(iter);
- Issue("`AssociativeArray`'s iterator iterates over incorrect set of"
- @ "items.");
- DoTestIterator(iter);
+ DoTestIterator(
+ "`HashTable`'s iterator incorrectly handles reference counting.",
+ "`HashTable`'s iterator iterates over incorrect set of items.",
+ iter);
+}
+
+protected static function Test_IterationAndNone()
+{
+ Context("Testing how collections iterate over `none` references.");
+ SubTest_ArrayListIterationAndNone();
+ SubTest_HashTableIterationAndNone();
+}
+
+protected static function SubTest_ArrayListIterationAndNone()
+{
+ local bool sawNone;
+ local int counter;
+ local Iter iter;
+ local ArrayList list;
+
+ list = __().collections.EmptyArrayList();
+ list.AddItem(__().box.int(1));
+ list.AddItem(none);
+ list.AddItem(__().box.int(3));
+ list.AddItem(none);
+ list.AddItem(__().box.int(5));
+ Issue("`ArrayList` doesn't properly iterate over `none` items by default.");
+ iter = list.Iterate();
+ while (!iter.HasFinished())
+ {
+ sawNone = sawNone || (iter.Get() == none);
+ counter += 1;
+ iter.Next();
+ }
+ TEST_ExpectTrue(sawNone);
+ TEST_ExpectTrue(counter == 5);
+
+ Issue("`ArrayList` iterates over `none` items even after"
+ @ "`LeaveOnlyNotNone()` call.");
+ sawNone = false;
+ counter = 0;
+ iter = list.Iterate().LeaveOnlyNotNone();
+ while (!iter.HasFinished())
+ {
+ sawNone = sawNone || (iter.Get() == none);
+ counter += 1;
+ iter.Next();
+ }
+ TEST_ExpectFalse(sawNone);
+ TEST_ExpectTrue(counter == 3);
+}
+
+protected static function SubTest_HashTableIterationAndNone()
+{
+ local bool sawNone;
+ local int counter;
+ local Iter iter;
+ local HashTable table;
+
+ table = __().collections.EmptyHashTable();
+ table.SetItem(__().box.float(1.0), __().box.int(1));
+ table.SetItem(__().box.float(0.3453), none);
+ table.SetItem(__().box.float(423.3), __().box.int(3));
+ table.SetItem(__().box.float(7), none);
+ table.SetItem(__().box.float(1.1), __().box.int(5));
+ Issue("`HashTable` doesn't properly iterate over `none` items by default.");
+ iter = table.Iterate();
+ while (!iter.HasFinished())
+ {
+ sawNone = sawNone || (iter.Get() == none);
+ counter += 1;
+ iter.Next();
+ }
+ TEST_ExpectTrue(sawNone);
+ TEST_ExpectTrue(counter == 5);
+
+ Issue("`HashTable` iterates over `none` items even after"
+ @ "`LeaveOnlyNotNone()` call.");
+ sawNone = false;
+ counter = 0;
+ iter = table.Iterate().LeaveOnlyNotNone();
+ while (!iter.HasFinished())
+ {
+ sawNone = sawNone || (iter.Get() == none);
+ counter += 1;
+ iter.Next();
+ }
+ TEST_ExpectFalse(sawNone);
+ TEST_ExpectTrue(counter == 3);
}
defaultproperties
{
- caseGroup = "Collections"
- caseName = "Iterator"
+ caseGroup = "Collections"
+ caseName = "Iterator"
TESTED_ITEMS_AMOUNT = 100
}
\ No newline at end of file
diff --git a/sources/Data/Collections/Tests/TEST_IteratorOld.uc b/sources/Data/Collections/Tests/TEST_IteratorOld.uc
new file mode 100644
index 0000000..52198d2
--- /dev/null
+++ b/sources/Data/Collections/Tests/TEST_IteratorOld.uc
@@ -0,0 +1,142 @@
+/**
+ * Set of tests for `Iterator` classes.
+ * Copyright 2020 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_IteratorOld extends TestCase
+ abstract;
+
+var const int TESTED_ITEMS_AMOUNT;
+var array items;
+var array seenFlags;
+
+protected static function CreateItems()
+{
+ local int i;
+ ResetFlags();
+ for (i = 0; i < default.TESTED_ITEMS_AMOUNT; i += 1) {
+ default.items[default.items.length] = __().ref.float(i*2 + 1/i);
+ }
+}
+
+protected static function ResetFlags()
+{
+ default.seenFlags.length = 0;
+ default.seenFlags.length = default.TESTED_ITEMS_AMOUNT;
+}
+
+protected static function DoTestIterator(Iter iter)
+{
+ local int i;
+ local int seenCount;
+ local AcediaObject nextObject;
+ ResetFlags();
+ while (!iter.HasFinished())
+ {
+ nextObject = iter.Get();
+ for (i = 0; i < default.items.length; i += 1)
+ {
+ if (default.items[i] == nextObject)
+ {
+ if (default.seenFlags[i] == 0) {
+ seenCount += 1;
+ }
+ default.seenFlags[i] = 1;
+ continue;
+ }
+ }
+ iter.Next();
+ }
+ TEST_ExpectTrue(seenCount == default.TESTED_ITEMS_AMOUNT);
+}
+
+protected static function TESTS()
+{
+ // Prepare
+ CreateItems();
+ // Test
+ Test_DynamicArray();
+ Test_AssociativeArray();
+}
+
+protected static function Test_DynamicArray()
+{
+ local int i;
+ local Iter iter;
+ local DynamicArray array;
+ array = DynamicArray(__().memory.Allocate(class'DynamicArray'));
+ iter = array.Iterate();
+ Context("Testing iterator for `DynamicArray`");
+ Issue("`DynamicArray` returns `none` iterator.");
+ TEST_ExpectNotNone(iter);
+
+ Issue("Iterator for empty `DynamicArray` is not finished by default.");
+ TEST_ExpectTrue(iter.HasFinished());
+
+ Issue("Iterator for empty `DynamicArray` does not return `none` as"
+ @ "a current item.");
+ TEST_ExpectNone(iter.Get());
+ TEST_ExpectNone(iter.Next().Get());
+
+ for (i = 0; i < default.items.length; i += 1) {
+ array.AddItem(default.items[i]);
+ }
+ iter = array.Iterate();
+ Issue("`DynamicArray` returns `none` iterator.");
+ TEST_ExpectNotNone(iter);
+
+ Issue("`DynamicArray`'s iterator iterates over incorrect set of items.");
+ DoTestIterator(iter);
+}
+
+protected static function Test_AssociativeArray()
+{
+ local int i;
+ local Iter iter;
+ local AssociativeArray array;
+ array = AssociativeArray(__().memory.Allocate(class'AssociativeArray'));
+ iter = array.Iterate();
+ Context("Testing iterator for `AssociativeArray`");
+ Issue("`AssociativeArray` returns `none` iterator.");
+ TEST_ExpectNotNone(iter);
+
+ Issue("Iterator for empty `AssociativeArray` is not finished by default.");
+ TEST_ExpectTrue(iter.HasFinished());
+
+ Issue("Iterator for empty `AssociativeArray` does not return `none` as"
+ @ "a current item.");
+ TEST_ExpectNone(iter.Get());
+ TEST_ExpectNone(iter.Next().Get());
+
+ for (i = 0; i < default.items.length; i += 1) {
+ array.SetItem(__().box.int(i), default.items[i]);
+ }
+ iter = array.Iterate();
+ Issue("`AssociativeArray` returns `none` iterator.");
+ TEST_ExpectNotNone(iter);
+
+ Issue("`AssociativeArray`'s iterator iterates over incorrect set of"
+ @ "items.");
+ DoTestIterator(iter);
+}
+
+defaultproperties
+{
+ caseGroup = "Collections"
+ caseName = "IteratorOld"
+ TESTED_ITEMS_AMOUNT = 100
+}
\ No newline at end of file