From e7da7acc0828018a12fdbfa767542982206c59e5 Mon Sep 17 00:00:00 2001 From: Speiger Date: Sun, 22 May 2022 15:13:29 +0200 Subject: [PATCH] Started massive unit testing library these are the first fixes. -Fixed: AbstractCollection.retainAll didn't push removed values through the consumer. -Fixed: AbstractCollection.toArray wouldn't reset the last entry if the input array was larger then the elements in the collection. -Fixed: SubList didn't check for ranges properly or didn't use parent list to validate changes. -Fixed: ArrayList.addElements didn't check input array fully and used the wrong variable to move the elements around. -Fixed: LinkedList.addElements(EmptyInput) would crash. -Fixed: LinkedList.swapRemove didn't account for if the removed element was the prelast one. -Fixed: LinkedList.removeElements would break the implementation if the list was almost empty and the middle element was removed. -Fixed: LinkedHashSet.addAndMoveToFirst wouldn't move elements to the first place. --- build.gradle | 2 +- .../collections/AbstractCollection.template | 2 + .../templates/lists/AbstractList.template | 10 +-- .../templates/lists/ArrayList.template | 3 +- .../templates/lists/CopyOnWriteList.template | 11 ++-- .../templates/lists/LinkedList.template | 63 +++++++++++-------- .../sets/LinkedOpenCustomHashSet.template | 2 + .../templates/sets/LinkedOpenHashSet.template | 2 + 8 files changed, 57 insertions(+), 38 deletions(-) diff --git a/build.gradle b/build.gradle index 26e88391..88dde8f1 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ repositories { } archivesBaseName = 'Primitive Collections' -version = '0.6.1'; +version = '0.6.1.10'; sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = JavaVersion.current(); diff --git a/src/builder/resources/speiger/assets/collections/templates/collections/AbstractCollection.template b/src/builder/resources/speiger/assets/collections/templates/collections/AbstractCollection.template index d895a620..2a96ba75 100644 --- a/src/builder/resources/speiger/assets/collections/templates/collections/AbstractCollection.template +++ b/src/builder/resources/speiger/assets/collections/templates/collections/AbstractCollection.template @@ -230,6 +230,7 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) { KEY_TYPE e = iter.NEXT(); if(!c.contains(e)) { + r.accept(e); iter.remove(); modified = true; } @@ -256,6 +257,7 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) { if(a == null || a.length < size()) a = new KEY_TYPE[size()]; ITERATORS.unwrap(a, iterator()); + if (a.length > size()) a[size()] = EMPTY_KEY_VALUE; return a; } #endif diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template b/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template index 24d62a66..c678ef2f 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template @@ -315,7 +315,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION public void removeElements(int from, int to) { if(to-from <= 0) return; checkSubRange(from); - checkSubRange(to); + checkAddSubRange(to); list.removeElements(from+parentOffset, to+parentOffset); size -= to - from; } @@ -324,9 +324,9 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION @Override public K[] extractElements(int from, int to, Class type) { checkSubRange(from); - checkSubRange(to); + checkAddSubRange(to); K[] result = list.extractElements(from+parentOffset, to+parentOffset, type); - size -= to - from; + size -= result.length; return result; } @@ -334,9 +334,9 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION @Override public KEY_TYPE[] extractElements(int from, int to) { checkSubRange(from); - checkSubRange(to); + checkAddSubRange(to); KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset); - size -= to - from; + size -= result.length; return result; } diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template index 80d3b3e5..6a193d4f 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template @@ -324,8 +324,9 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE public void addElements(int from, KEY_TYPE[] a, int offset, int length) { if(length <= 0) return; checkAddRange(from); + SanityChecks.checkArrayCapacity(a.length, offset, length); grow(size + length); - if(from != size) System.arraycopy(data, from, data, from+length, size - length); + if(from != size) System.arraycopy(data, from, data, from+length, size - from); size+=length; System.arraycopy(a, offset, data, from, length); } diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/CopyOnWriteList.template b/src/builder/resources/speiger/assets/collections/templates/lists/CopyOnWriteList.template index 7fcd016f..70e7ee7c 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/CopyOnWriteList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/CopyOnWriteList.template @@ -365,6 +365,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER KEY_TYPE[] data = this.data; int size = data.length; if(from < 0 || from > size) throw new IndexOutOfBoundsException("Index: " + from + ", Size: " + size); + SanityChecks.checkArrayCapacity(a.length, offset, length); KEY_TYPE[] newElements; if(from == size) { newElements = Arrays.copyOf(data, size+length); @@ -1580,7 +1581,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER lock.lock(); try { checkSubRange(from); - checkSubRange(to); + checkAddSubRange(to); list.removeElements(from+parentOffset, to+parentOffset); size -= to - from; } @@ -1596,9 +1597,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER lock.lock(); try { checkSubRange(from); - checkSubRange(to); + checkAddSubRange(to); K[] result = list.extractElements(from+parentOffset, to+parentOffset, type); - size -= to - from; + size -= result.length; return result; } finally { @@ -1613,9 +1614,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER lock.lock(); try { checkSubRange(from); - checkSubRange(to); + checkAddSubRange(to); KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset); - size -= to - from; + size -= result.length; return result; } finally { diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template b/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template index a77f9f6c..167d5724 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template @@ -276,6 +276,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE @Override public void addElements(int from, KEY_TYPE[] a, int offset, int length) { + if(length <= 0) return; SanityChecks.checkArrayCapacity(a.length, offset, length); checkAddRange(from); Entry KEY_GENERIC_TYPE next; @@ -617,12 +618,14 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE first = temp; return result; } - Entry KEY_GENERIC_TYPE temp = last; - last = temp.prev; - last.next = null; - temp.next = before.next; - temp.prev = before; - before.next = temp; + else if(before.next != last) { + Entry KEY_GENERIC_TYPE temp = last; + last = temp.prev; + last.next = null; + temp.next = before.next; + temp.prev = before; + before.next = temp; + } return result; } @@ -647,12 +650,14 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE first = temp; return true; } - Entry KEY_GENERIC_TYPE temp = last; - last = temp.prev; - last.next = null; - temp.next = before.next; - temp.prev = before; - before.next = temp; + else if(before.next != last) { + Entry KEY_GENERIC_TYPE temp = last; + last = temp.prev; + last.next = null; + temp.next = before.next; + temp.prev = before; + before.next = temp; + } return true; } } @@ -695,16 +700,18 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE if(from < size - to) { Entry KEY_GENERIC_TYPE entry = getNode(from); while(length > 0) { - entry = entry.next; - unlink(entry.prev); + Entry KEY_GENERIC_TYPE next = entry.next; + unlink(entry); + entry = next; length--; } return; } Entry KEY_GENERIC_TYPE entry = getNode(to); while(length > 0) { - entry = entry.prev; - unlink(entry.next); + Entry KEY_GENERIC_TYPE prev = entry.prev; + unlink(entry); + entry = prev; length--; } } @@ -720,15 +727,17 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE if(from < size - to) { Entry KEY_GENERIC_TYPE entry = getNode(from); for(int i = 0;length > 0;i++, length--) { - entry = entry.next; - a[i] = (K)unlink(entry.prev); + Entry KEY_GENERIC_TYPE next = entry.next; + a[i] = (K)unlink(entry); + entry = next; } return a; } Entry KEY_GENERIC_TYPE entry = getNode(to); - for(int i = length-1;length > 0;i--) { - entry = entry.prev; - a[i] = (K)unlink(entry.next); + for(int i = length-1;length > 0;i--, length--) { + Entry KEY_GENERIC_TYPE prev = entry.prev; + a[i] = (K)unlink(entry); + entry = prev; } return a; } @@ -744,15 +753,17 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE if(from < size - to) { Entry KEY_GENERIC_TYPE entry = getNode(from); for(int i = 0;length > 0;i++, length--) { - entry = entry.next; - d[i] = unlink(entry.prev); + Entry KEY_GENERIC_TYPE next = entry.next; + d[i] = unlink(entry); + entry = next; } return d; } Entry KEY_GENERIC_TYPE entry = getNode(to); - for(int i = length-1;length > 0;i--) { - entry = entry.prev; - d[i] = unlink(entry.next); + for(int i = length-1;length > 0;i--, length--) { + Entry KEY_GENERIC_TYPE prev = entry.prev; + d[i] = unlink(entry); + entry = prev; } return d; } diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template index 00af8625..3780fe88 100644 --- a/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template +++ b/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template @@ -237,6 +237,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY } containsNull = true; onNodeAdded(nullIndex); + moveToFirstIndex(nullIndex); } else { int pos = HashUtil.mix(strategy.hashCode(o)) & mask; @@ -249,6 +250,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY } keys[pos] = o; onNodeAdded(pos); + moveToFirstIndex(pos); } if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor)); return true; diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template index 3288e3c9..9b08a6f3 100644 --- a/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template +++ b/src/builder/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template @@ -208,6 +208,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE } containsNull = true; onNodeAdded(nullIndex); + moveToFirstIndex(nullIndex); } else { int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask; @@ -220,6 +221,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE } keys[pos] = o; onNodeAdded(pos); + moveToFirstIndex(pos); } if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor)); return true;