Browse Source

stack + tests, feedback in list if add works, remove from list is safe
with any index

Kajetan Johannes Hammerle 3 years ago
parent
commit
1586ab7509
8 changed files with 207 additions and 34 deletions
  1. 2 0
      Main.cpp
  2. 1 1
      meson.build
  3. 39 12
      tests/ListTests.cpp
  4. 21 7
      tests/SplitStringTests.cpp
  5. 69 0
      tests/StackTests.cpp
  6. 8 0
      tests/StackTests.h
  7. 16 14
      utils/List.h
  8. 51 0
      utils/Stack.h

+ 2 - 0
Main.cpp

@@ -8,6 +8,7 @@
 #include "tests/SplitStringTests.h"
 #include "tests/VectorTests.h"
 #include "tests/MatrixTests.h"
+#include "tests/StackTests.h"
 
 int main() {
     ArrayTests::test();
@@ -20,5 +21,6 @@ int main() {
     SplitStringTests::test();
     VectorTests::test();
     MatrixTests::test();
+    StackTests::test();
     return 0;
 }

+ 1 - 1
meson.build

@@ -1,6 +1,6 @@
 project('gaming core tests', 'cpp')
 
-sources = ['Main.cpp', 'tests/Test.cpp', 'tests/ArrayTests.cpp', 'tests/HashMapTests.cpp', 'tests/ListTests.cpp', 'tests/BitArrayTests.cpp', 'tests/StringBufferTests.cpp', 'tests/RandomTests.cpp', 'utils/Random.cpp', 'tests/RingBufferTests.cpp', 'tests/SplitStringTests.cpp', 'tests/VectorTests.cpp', 'math/Vector.cpp', 'math/Matrix.cpp', 'tests/MatrixTests.cpp']
+sources = ['Main.cpp', 'tests/Test.cpp', 'tests/ArrayTests.cpp', 'tests/HashMapTests.cpp', 'tests/ListTests.cpp', 'tests/BitArrayTests.cpp', 'tests/StringBufferTests.cpp', 'tests/RandomTests.cpp', 'utils/Random.cpp', 'tests/RingBufferTests.cpp', 'tests/SplitStringTests.cpp', 'tests/VectorTests.cpp', 'math/Vector.cpp', 'math/Matrix.cpp', 'tests/MatrixTests.cpp', 'tests/StackTests.cpp']
 
 executable('tests', 
     sources: sources,

+ 39 - 12
tests/ListTests.cpp

@@ -16,10 +16,12 @@ static void testAdd(Test& test) {
 
 static void testMultipleAdd(Test& test) {
     IntList list;
-    list.add(4).add(3).add(2);
-    test.checkEqual(4, list[0], "contains added value");
-    test.checkEqual(3, list[1], "contains added value");
-    test.checkEqual(2, list[2], "contains added value");
+    list.add(4);
+    list.add(3);
+    list.add(2);
+    test.checkEqual(4, list[0], "contains added value 1");
+    test.checkEqual(3, list[1], "contains added value 2");
+    test.checkEqual(2, list[2], "contains added value 3");
     test.checkEqual(3, list.getLength(), "sizes is increased by add");
 }
 
@@ -32,14 +34,19 @@ static void testAddReplace(Test& test) {
 
 static void testClear(Test& test) {
     IntList list;
-    list.add(5).add(4).clear();
+    list.add(5);
+    list.add(4);
+    list.clear();
     test.checkEqual(0, list.getLength(), "length is 0 after clear");
 }
 
 static void testOverflow(Test& test) {
     IntList list;
+    for(int i = 0; i < 20; i++) {
+        test.checkEqual(false, list.add(i), "add returns false without overflow");
+    }
     for(int i = 0; i < 1000000; i++) {
-        list.add(i);
+        test.checkEqual(true, list.add(i), "add returns true with overflow");
     }
     for(int i = 0; i < list.getLength(); i++) {
         test.checkEqual(i, list[i], "still contains values after overflow");
@@ -49,7 +56,9 @@ static void testOverflow(Test& test) {
 
 static void testCopy(Test& test) {
     IntList list;
-    list.add(1).add(2).add(3);
+    list.add(1);
+    list.add(2);
+    list.add(3);
 
     IntList copy(list);
     test.checkEqual(list.getLength(), copy.getLength(), "copy has same length");
@@ -60,7 +69,9 @@ static void testCopy(Test& test) {
 
 static void testCopyAssignment(Test& test) {
     IntList list;
-    list.add(1).add(2).add(3);
+    list.add(1);
+    list.add(2);
+    list.add(3);
 
     IntList copy;
     copy = list;
@@ -72,7 +83,9 @@ static void testCopyAssignment(Test& test) {
 
 static void testMove(Test& test) {
     IntList list;
-    list.add(1).add(2).add(3);
+    list.add(1);
+    list.add(2);
+    list.add(3);
 
     IntList move(std::move(list));
     test.checkEqual(0, list.getLength(), "moved has length 0");
@@ -84,7 +97,9 @@ static void testMove(Test& test) {
 
 static void testMoveAssignment(Test& test) {
     IntList list;
-    list.add(1).add(2).add(3);
+    list.add(1);
+    list.add(2);
+    list.add(3);
 
     IntList move;
     move = std::move(list);
@@ -97,7 +112,9 @@ static void testMoveAssignment(Test& test) {
 
 static void testToString1(Test& test) {
     IntList list;
-    list.add(1).add(243).add(-423);
+    list.add(1);
+    list.add(243);
+    list.add(-423);
     test.checkEqual(String("[1, 243, -423]"), String(list), "to string 1");
 }
 
@@ -114,7 +131,9 @@ static void testToString3(Test& test) {
 
 static void testRemove(Test& test) {
     IntList list;
-    list.add(4).add(3).add(2);
+    list.add(4);
+    list.add(3);
+    list.add(2);
     list.remove(0);
     test.checkEqual(2, list[0], "remove 1");
     test.checkEqual(3, list[1], "remove 2");
@@ -126,6 +145,13 @@ static void testRemove(Test& test) {
     test.checkEqual(0, list.getLength(), "remove 6");
 }
 
+static void testRemoveIsSafe(Test& test) {
+    IntList list;
+    for(int i = -500000; i < 500000; i++) {
+        test.checkEqual(true, list.remove(i), "removing from empty list is safe");
+    }
+}
+
 void ListTests::test() {
     Test test("List");
     testAdd(test);
@@ -141,5 +167,6 @@ void ListTests::test() {
     testToString2(test);
     testToString3(test);
     testRemove(test);
+    testRemoveIsSafe(test);
     test.finalize();
 }

+ 21 - 7
tests/SplitStringTests.cpp

@@ -24,13 +24,18 @@ static void testOneArgument(Test& test) {
 
 static void testThreeArguments(Test& test) {
     StringList list;
-    list.add("test").add("aaa").add("bbbb");
+    list.add("test");
+    list.add("aaa");
+    list.add("bbbb");
     checkList(test, "test aaa bbbb", list, "three arguments");
 }
 
 static void testFourArguments(Test& test) {
     StringList list;
-    list.add("test").add("aaa").add("bbbb").add("ccccc");
+    list.add("test");
+    list.add("aaa");
+    list.add("bbbb");
+    list.add("ccccc");
     checkList(test, "test aaa bbbb ccccc", list, "four arguments");
 }
 
@@ -42,31 +47,40 @@ static void testOneArgumentWithSpaces(Test& test) {
 
 static void testThreeArgumentsWithSpaces(Test& test) {
     StringList list;
-    list.add("test").add("aaa").add("bbbb");
+    list.add("test");
+    list.add("aaa");
+    list.add("bbbb");
     checkList(test, "test  aaa   bbbb", list, "three arguments and spaces");
 }
 
 static void testTwoArgumentsWithQuotationMarks(Test& test) {
     StringList list;
-    list.add("test").add("aaa bbbb");
+    list.add("test");
+    list.add("aaa bbbb");
     checkList(test, "test \"aaa bbbb\"", list, "two arguments and quotation marks");
 }
 
 static void testThreeArgumentsWithQuotationMarks(Test& test) {
     StringList list;
-    list.add("test").add("aaa bbbb").add("ccc");
+    list.add("test");
+    list.add("aaa bbbb");
+    list.add("ccc");
     checkList(test, "test \"aaa bbbb\" ccc", list, "three arguments and quotation marks");
 }
 
 static void testFourArgumentsWithQuotationMarks(Test& test) {
     StringList list;
-    list.add("test").add("ddd").add("aaa bbbb").add("ccc");
+    list.add("test");
+    list.add("ddd");
+    list.add("aaa bbbb");
+    list.add("ccc");
     checkList(test, "test ddd \"aaa bbbb\" ccc", list, "four arguments and quotation marks");
 }
 
 static void testEmptyArgument(Test& test) {
     StringList list;
-    list.add("test").add("");
+    list.add("test");
+    list.add("");
     checkList(test, "test \"\"", list, "empty argument");
 }
 

+ 69 - 0
tests/StackTests.cpp

@@ -0,0 +1,69 @@
+#include "tests/StackTests.h"
+#include "tests/Test.h"
+#include "utils/StringBuffer.h"
+#include "utils/Stack.h"
+
+typedef Stack<int, 10> IntStack;
+typedef StringBuffer<50> String;
+
+static void testPushPopPeek(Test& test) {
+    IntStack stack;
+    stack.push(1);
+    stack.push(2);
+    stack.push(3);
+    test.checkEqual(3, stack.peek(), "push pop peek 1");
+    test.checkEqual(false, stack.pop(), "pop without error 1");
+    test.checkEqual(2, stack.peek(), "push pop peek 2");
+    test.checkEqual(false, stack.pop(), "pop without error 2");
+    test.checkEqual(1, stack.peek(), "push pop peek 3");
+    test.checkEqual(false, stack.pop(), "pop without error 3");
+    test.checkEqual(true, stack.isEmpty(), "empty after popping all");
+}
+
+static void testOverflow(Test& test) {
+    IntStack stack;
+    for(int i = 0; i < 10; i++) {
+        test.checkEqual(false, stack.push(i), "push returns false without overflow");
+    }
+    for(int i = 0; i < 1000000; i++) {
+        test.checkEqual(true, stack.push(i), "push returns true with overflow");
+    }
+    test.checkEqual(true, true, "survives overflow");
+}
+
+static void testToString1(Test& test) {
+    IntStack stack;
+    stack.push(1);
+    stack.push(243);
+    stack.push(-423);
+    test.checkEqual(String("[1, 243, -423]"), String(stack), "to string 1");
+}
+
+static void testToString2(Test& test) {
+    IntStack stack;
+    stack.push(1);
+    test.checkEqual(String("[1]"), String(stack), "to string 2");
+}
+
+static void testToString3(Test& test) {
+    IntStack stack;
+    test.checkEqual(String("[]"), String(stack), "to string 3");
+}
+
+static void testPop(Test& test) {
+    IntStack stack;
+    for(int i = 0; i < 1000000; i++) {
+        test.checkEqual(true, stack.pop(), "popping empty stack is safe");
+    }
+}
+
+void StackTests::test() {
+    Test test("Stack");
+    testPushPopPeek(test);
+    testOverflow(test);
+    testToString1(test);
+    testToString2(test);
+    testToString3(test);
+    testPop(test);
+    test.finalize();
+}

+ 8 - 0
tests/StackTests.h

@@ -0,0 +1,8 @@
+#ifndef STACKTESTS_H
+#define STACKTESTS_H
+
+namespace StackTests {
+    void test();
+}
+
+#endif

+ 16 - 14
utils/List.h

@@ -25,12 +25,11 @@ class List final {
 public:
     List() = default;
 
-    List& clear() {
+    void clear() {
         for(int i = 0; i < length; i++) {
             (*this)[i].~T();
         }
         length = 0;
-        return *this;
     }
 
     ~List() {
@@ -79,32 +78,32 @@ public:
         return reinterpret_cast<const T*> (data) + length;
     }
 
-    List& add(const T& t) {
+    bool add(const T& t) {
         if(length >= N) {
-            return *this;
+            return true;
         }
         new (end()) T(t);
         length++;
-        return *this;
+        return false;
     }
 
-    List& add(T&& t) {
+    bool add(T&& t) {
         if(length >= N) {
-            return *this;
+            return true;
         }
         new (end()) T(std::move(t));
         length++;
-        return *this;
+        return false;
     }
 
     template<typename... Args>
-    List& add(Args&&... args) {
+    bool add(Args&&... args) {
         if(length >= N) {
-            return *this;
+            return true;
         }
         new (end()) T(std::forward<Args>(args)...);
         length++;
-        return *this;
+        return false;
     }
 
     T& operator[](int index) {
@@ -132,15 +131,18 @@ public:
         s.append("]");
     }
 
-    void remove(int index) {
-        if(index + 1 == length) {
+    bool remove(int index) {
+        if(index < 0 || index >= length) {
+            return true;
+        } else if(index + 1 == length) {
             (*this)[index].~T();
             length--;
-            return;
+            return false;
         }
         (*this)[index] = std::move((*this)[length - 1]);
         (*this)[length - 1].~T();
         length--;
+        return false;
     }
 };
 

+ 51 - 0
utils/Stack.h

@@ -0,0 +1,51 @@
+#ifndef STACK_H
+#define STACK_H
+
+#include "utils/List.h"
+
+template<typename T, int N>
+class Stack final {
+    List<T, N> data;
+
+public:
+
+    bool push(const T& t) {
+        return data.add(t);
+    }
+
+    bool push(T&& t) {
+        return data.add(std::move(t));
+    }
+
+    template<typename... Args>
+    bool push(Args&&... args) {
+        return data.add(std::forward<Args>(args)...);
+    }
+
+    void clear() {
+        data.clear();
+    }
+
+    bool pop() {
+        return data.remove(data.getLength() - 1);
+    }
+
+    bool isEmpty() const {
+        return data.getLength() == 0;
+    }
+
+    T& peek() {
+        return data[data.getLength() - 1];
+    }
+
+    const T& peek() const {
+        return data[data.getLength() - 1];
+    }
+    
+    template<int L>
+    void toString(StringBuffer<L>& s) const {
+        s.append(data);
+    }
+};
+
+#endif