Quellcode durchsuchen

fix(series): decrement n_items on node removal

The item counter was not being decremented when nodes were deleted
from the Series data structure, causing incorrect item counts.

Also add Catalogue integration tests to the test suite.
Billy Barrow vor 4 Wochen
Ursprung
Commit
51b9e6a249

+ 1 - 0
src/lib/DataStructures/Series.vala

@@ -161,6 +161,7 @@ namespace Invercargill.DataStructures {
                             previous->next = node->next;
                         }
                         delete node;
+                        n_items--;
                         if(first_only) {
                             break;
                         }

+ 333 - 0
src/tests/Integration/Catalogue.vala

@@ -0,0 +1,333 @@
+using Invercargill;
+using Invercargill.DataStructures;
+
+
+void catalogue_tests() {
+
+    Test.add_func("/invercargill/catalogue/add_single", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("even", 2);
+        catalogue.add("even", 4);
+        catalogue.add("odd", 1);
+        catalogue.add("odd", 3);
+
+        assert(catalogue.length == 4);
+        assert(catalogue.has("even"));
+        assert(catalogue.has("odd"));
+        assert(!catalogue.has("prime"));
+    });
+
+    Test.add_func("/invercargill/catalogue/try_get", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("even", 2);
+        catalogue.add("even", 4);
+        catalogue.add("odd", 1);
+
+        Grouping<string, int> even_group;
+        assert(catalogue.try_get("even", out even_group));
+        assert(even_group.count() == 2);
+        
+        assert(even_group.contains(2));
+        assert(even_group.contains(4));
+
+        Grouping<string, int> prime_group;
+        assert(!catalogue.try_get("prime", out prime_group));
+        assert(prime_group == null);
+    });
+
+    Test.add_func("/invercargill/catalogue/try_get_any", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("even", 2);
+        catalogue.add("even", 4);
+
+        int value;
+        assert(catalogue.try_get_any("even", out value));
+        assert(value == 2 || value == 4);
+
+        int missing_value;
+        assert(!catalogue.try_get_any("odd", out missing_value));
+        assert(missing_value == 0);
+    });
+
+    Test.add_func("/invercargill/catalogue/keys", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("a", 1);
+        catalogue.add("b", 2);
+        catalogue.add("c", 3);
+
+        var keys = catalogue.keys.to_array();
+        assert(keys.length == 3);
+        assert(catalogue.keys.contains("a"));
+        assert(catalogue.keys.contains("b"));
+        assert(catalogue.keys.contains("c"));
+    });
+
+    Test.add_func("/invercargill/catalogue/values", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("group1", 1);
+        catalogue.add("group1", 2);
+        catalogue.add("group2", 3);
+
+        assert(catalogue.values.count() == 3);
+        assert(catalogue.values.contains(1));
+        assert(catalogue.values.contains(2));
+        assert(catalogue.values.contains(3));
+    });
+
+    Test.add_func("/invercargill/catalogue/set", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("group", 1);
+        catalogue.add("group", 2);
+        
+        assert(catalogue.length == 2);
+
+        catalogue.set("group", Wrap.array(new int[] { 10, 20, 30 }));
+        assert(catalogue.length == 3);
+
+        Grouping<string, int> group;
+        assert(catalogue.try_get("group", out group));
+        assert(group.count() == 3);
+    });
+
+    Test.add_func("/invercargill/catalogue/set_replace", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("group", 1);
+        catalogue.add("group", 2);
+        catalogue.add("other", 5);
+        
+        assert(catalogue.length == 3);
+
+        catalogue.set("group", Wrap.array(new int[] { 10, 20 }));
+        assert(catalogue.length == 3); // 2 from new group + 1 from other
+
+        Grouping<string, int> group;
+        assert(catalogue.try_get("group", out group));
+        assert(group.count() == 2);
+        assert(group.contains(10));
+        assert(group.contains(20));
+    });
+
+    Test.add_func("/invercargill/catalogue/add_all", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add_all("numbers", Wrap.array(new int[] { 1, 2, 3 }));
+        
+        assert(catalogue.length == 3);
+
+        catalogue.add_all("numbers", Wrap.array(new int[] { 4, 5 }));
+        assert(catalogue.length == 5);
+
+        Grouping<string, int> group;
+        assert(catalogue.try_get("numbers", out group));
+        assert(group.count() == 5);
+    });
+
+    Test.add_func("/invercargill/catalogue/remove_from", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add_all("numbers", Wrap.array(new int[] { 1, 2, 3, 4, 5 }));
+        
+        assert(catalogue.length == 5);
+
+        catalogue.remove_from("numbers", 3);
+        assert(catalogue.length == 4);
+
+        Grouping<string, int> group;
+        assert(catalogue.try_get("numbers", out group));
+        assert(!group.contains(3));
+        assert(group.count() == 4);
+    });
+
+    Test.add_func("/invercargill/catalogue/remove_from_last_item", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("single", 42);
+        
+        assert(catalogue.length == 1);
+        assert(catalogue.has("single"));
+
+        catalogue.remove_from("single", 42);
+        assert(catalogue.length == 0);
+        assert(!catalogue.has("single")); // Key should be removed when empty
+    });
+
+    Test.add_func("/invercargill/catalogue/remove_all_from", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add_all("numbers", Wrap.array(new int[] { 1, 2, 3, 4, 5 }));
+        
+        assert(catalogue.length == 5);
+
+        catalogue.remove_all_from("numbers", Wrap.array(new int[] { 2, 4 }));
+        assert(catalogue.length == 3);
+
+        Grouping<string, int> group;
+        assert(catalogue.try_get("numbers", out group));
+        assert(!group.contains(2));
+        assert(!group.contains(4));
+        assert(group.contains(1));
+        assert(group.contains(3));
+        assert(group.contains(5));
+    });
+
+    Test.add_func("/invercargill/catalogue/remove", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("a", 1);
+        catalogue.add("a", 2);
+        catalogue.add("b", 2);
+        catalogue.add("b", 3);
+        catalogue.add("c", 2);
+        
+        assert(catalogue.length == 5);
+
+        catalogue.remove(2);
+        assert(catalogue.length == 2);
+
+        // Value 2 should be removed from all groups
+        assert(!catalogue.values.contains(2));
+        assert(catalogue.values.contains(1));
+        assert(catalogue.values.contains(3));
+    });
+
+    Test.add_func("/invercargill/catalogue/remove_all", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("a", 1);
+        catalogue.add("a", 2);
+        catalogue.add("b", 2);
+        catalogue.add("b", 3);
+        catalogue.add("c", 4);
+        
+        assert(catalogue.length == 5);
+
+        catalogue.remove_all(Wrap.array(new int[] { 2, 3 }));
+        assert(catalogue.length == 2);
+
+        assert(!catalogue.values.contains(2));
+        assert(!catalogue.values.contains(3));
+        assert(catalogue.values.contains(1));
+        assert(catalogue.values.contains(4));
+    });
+
+    Test.add_func("/invercargill/catalogue/clear_key", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("a", 1);
+        catalogue.add("b", 2);
+        catalogue.add("c", 3);
+        
+        assert(catalogue.length == 3);
+
+        assert(catalogue.clear_key("b"));
+        assert(catalogue.length == 2);
+        assert(!catalogue.has("b"));
+        assert(catalogue.has("a"));
+        assert(catalogue.has("c"));
+
+        assert(!catalogue.clear_key("nonexistent"));
+    });
+
+    Test.add_func("/invercargill/catalogue/clear", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("a", 1);
+        catalogue.add("b", 2);
+        catalogue.add("c", 3);
+        
+        assert(catalogue.length == 3);
+
+        catalogue.clear();
+        assert(catalogue.length == 0);
+        assert(!catalogue.has("a"));
+        assert(!catalogue.has("b"));
+        assert(!catalogue.has("c"));
+    });
+
+    Test.add_func("/invercargill/catalogue/iteration", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("even", 2);
+        catalogue.add("even", 4);
+        catalogue.add("odd", 1);
+        catalogue.add("odd", 3);
+
+        var group_count = 0;
+        var total_values = 0;
+        
+        foreach (var grouping in catalogue) {
+            group_count++;
+            foreach (var value in grouping) {
+                total_values++;
+            }
+        }
+
+        assert(group_count == 2);
+        assert(total_values == 4);
+    });
+
+    Test.add_func("/invercargill/catalogue/int_keys", () => {
+        var catalogue = new Catalogue<int, string>();
+        catalogue.add(1, "one");
+        catalogue.add(2, "two");
+        catalogue.add(1, "uno");
+
+        assert(catalogue.length == 3);
+        assert(catalogue.has(1));
+        assert(catalogue.has(2));
+
+        Grouping<int, string> group;
+        assert(catalogue.try_get(1, out group));
+        assert(group.count() == 2);
+    });
+
+    Test.add_func("/invercargill/catalogue/custom_hash", () => {
+        // Test with custom hash and equality functions
+        var catalogue = new Catalogue<string, int>(
+            (key) => key.hash(),
+            (a, b) => a == b
+        );
+        
+        catalogue.add("key1", 1);
+        catalogue.add("KEY1", 2); // Different key (case-sensitive)
+        catalogue.add("key1", 3);
+
+        assert(catalogue.length == 3);
+        assert(catalogue.has("key1"));
+        assert(catalogue.has("KEY1"));
+
+        Grouping<string, int> group;
+        assert(catalogue.try_get("key1", out group));
+        assert(group.count() == 2); // "key1" has 2 values
+    });
+
+    Test.add_func("/invercargill/catalogue/empty", () => {
+        var catalogue = new Catalogue<string, int>();
+        
+        assert(catalogue.length == 0);
+        assert(!catalogue.has("any"));
+        
+        Grouping<string, int> group;
+        assert(!catalogue.try_get("nonexistent", out group));
+        
+        int value;
+        assert(!catalogue.try_get_any("nonexistent", out value));
+    });
+
+    Test.add_func("/invercargill/catalogue/peek_count", () => {
+        var catalogue = new Catalogue<string, int>();
+        catalogue.add("a", 1);
+        catalogue.add("b", 2);
+        
+        var count = catalogue.peek_count();
+        assert(count == 2);
+    });
+
+    Test.add_func("/invercargill/catalogue/complex_objects", () => {
+        var catalogue = new Catalogue<string, string>();
+        catalogue.add("names", "Alice");
+        catalogue.add("names", "Bob");
+        catalogue.add("cities", "Auckland");
+        catalogue.add("cities", "Wellington");
+
+        assert(catalogue.length == 4);
+
+        Grouping<string, string> names;
+        assert(catalogue.try_get("names", out names));
+        
+        assert(names.contains("Alice"));
+        assert(names.contains("Bob"));
+    });
+
+}

+ 1 - 0
src/tests/TestRunner.vala

@@ -25,6 +25,7 @@ public static int main(string[] args) {
     promotion_tests();
     numbers_test();
     dictionary_tests();
+    catalogue_tests();
     property_mapper_tests();
     cache_tests();
     sorted_vector_tests();

+ 1 - 0
src/tests/meson.build

@@ -16,6 +16,7 @@ sources += files('Integration/Arrays.vala')
 sources += files('Integration/Promotion.vala')
 sources += files('Integration/Numbers.vala')
 sources += files('Integration/Dictionary.vala')
+sources += files('Integration/Catalogue.vala')
 sources += files('Integration/PropertyMapper.vala')
 sources += files('Integration/Cache.vala')
 sources += files('Integration/SortedVector.vala')