aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/Player.cpp4
-rw-r--r--backend/PtrList.hpp1
-rw-r--r--backend/String.cpp8
-rw-r--r--backend/print.cpp2
-rw-r--r--backend/util.cpp38
-rw-r--r--backend/util.h2
-rw-r--r--test/CMakeLists.txt3
-rw-r--r--test/list.cpp87
-rw-r--r--test/ptrlist.cpp27
-rw-r--r--test/util.cpp15
10 files changed, 163 insertions, 24 deletions
diff --git a/backend/Player.cpp b/backend/Player.cpp
index 5e3e030..8a44a3a 100644
--- a/backend/Player.cpp
+++ b/backend/Player.cpp
@@ -7,8 +7,8 @@
Player::Player(Dungeon & dungeon) : dungeon(dungeon) { }
Player::~Player() {
- safe_free(this->weapon);
- safe_free(this->armor);
+ safe_free(&this->weapon);
+ safe_free(&this->armor);
}
float Player::get_attack() const {
diff --git a/backend/PtrList.hpp b/backend/PtrList.hpp
index cbfd6e0..6969533 100644
--- a/backend/PtrList.hpp
+++ b/backend/PtrList.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "PtrList.h"
+#include "ListIterator.h"
template <typename T>
PtrList<T>::~PtrList() {
diff --git a/backend/String.cpp b/backend/String.cpp
index e5512bf..84dc2ec 100644
--- a/backend/String.cpp
+++ b/backend/String.cpp
@@ -26,7 +26,7 @@ String::String(String && other) {
}
String & String::operator = (String && other) {
if (this == &other) return *this;
- safe_free(this->_data);
+ safe_free(&this->_data);
this->_data = other._data;
this->_data_len = other._data_len;
other._data = nullptr;
@@ -58,14 +58,14 @@ String String::va_fmt(va_list args, const char * fmt) {
out._data_len = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
- safe_free(out._data);
+ safe_free(&out._data);
out._data = static_cast<char *>(malloc(out._data_len + 1));
vsnprintf(out._data, out._data_len + 1, fmt, args);
return out;
}
String::~String() {
- safe_free(this->_data);
+ safe_free(&this->_data);
}
void String::set(const char * data) {
@@ -73,7 +73,7 @@ void String::set(const char * data) {
}
void String::set(const char * data, size_t data_len) {
- safe_free(this->_data);
+ safe_free(&this->_data);
this->_data = static_cast<char *>(malloc(data_len + 1));
this->_data_len = data_len;
memcpy(this->_data, data, data_len);
diff --git a/backend/print.cpp b/backend/print.cpp
index 1cb6a75..edf7989 100644
--- a/backend/print.cpp
+++ b/backend/print.cpp
@@ -31,7 +31,7 @@ SessionLog::SessionLog() {
}
SessionLog::~SessionLog() {
- safe_free(this->file);
+ safe_free(&this->file);
}
void SessionLog::append(const String & str) const {
diff --git a/backend/util.cpp b/backend/util.cpp
index 557df4c..edf9539 100644
--- a/backend/util.cpp
+++ b/backend/util.cpp
@@ -7,35 +7,41 @@
#include "ArmorObject.h"
template <>
-void safe_free(void * & ptr) {
- if (ptr == nullptr) return;
- free(ptr);
- ptr = nullptr;
+void safe_free(void ** ptr) {
+ if (*ptr == nullptr) return;
+ free(*ptr);
+ *ptr = nullptr;
}
template <>
-void safe_free(const char * & ptr) {
- auto x = static_cast<void *>(const_cast<char *>(ptr));
- safe_free(x);
+void safe_free(const char ** ptr) {
+ // wow c++ casts so readable
+ auto a = const_cast<char **>(ptr);
+ auto b = static_cast<void *>(a);
+ auto c = reinterpret_cast<void**>(b);
+ safe_free(c);
}
template <>
-void safe_free(WeaponObject * & ptr) {
- delete ptr;
+void safe_free(WeaponObject ** ptr) {
+ delete *ptr;
+ *ptr = nullptr;
}
template <>
-void safe_free(ArmorObject * & ptr) {
- delete ptr;
+void safe_free(ArmorObject ** ptr) {
+ delete *ptr;
+ *ptr = nullptr;
}
template <typename T>
-void safe_free(T * & ptr) {
- auto x = static_cast<void *>(ptr);
- safe_free(x);
+void safe_free(T ** ptr) {
+ auto a = static_cast<void *>(ptr);
+ auto b = reinterpret_cast<void **>(ptr);
+ safe_free(b);
}
-template void safe_free(char * &);
-template void safe_free(FILE * &);
+template void safe_free(char **);
+template void safe_free(FILE **);
diff --git a/backend/util.h b/backend/util.h
index d278eb1..f1e7bab 100644
--- a/backend/util.h
+++ b/backend/util.h
@@ -1,7 +1,7 @@
#pragma once
template <typename T>
-void safe_free(T * & ptr);
+void safe_free(T ** ptr);
template <typename T>
inline T min(const T &, const T &);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index bba1d07..96c0e95 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,3 +1,6 @@
target_sources(test_main PUBLIC
string.cpp
+ list.cpp
+ ptrlist.cpp
+ util.cpp
)
diff --git a/test/list.cpp b/test/list.cpp
new file mode 100644
index 0000000..cdb0bc1
--- /dev/null
+++ b/test/list.cpp
@@ -0,0 +1,87 @@
+#include <gtest/gtest.h>
+
+#include "backend/ListIterator.h"
+#include "backend/List.h"
+
+static void add_test_items(List<int> & foo) {
+ foo.push_back(1);
+ foo.push_back(2);
+ foo.push_back(3);
+}
+
+TEST(ListTest, PushBack) {
+ List<int> foo;
+ ASSERT_EQ(foo.size(), 0);
+
+ add_test_items(foo);
+
+ ASSERT_EQ(foo.size(), 3);
+}
+
+TEST(ListTest, Clear) {
+ List<int> foo;
+ foo.clear();
+
+ add_test_items(foo);
+
+ foo.clear();
+ ASSERT_EQ(foo.size(), 0);
+}
+
+TEST(ListTest, Remove) {
+ List<int> foo;
+ add_test_items(foo);
+
+ ASSERT_EQ(foo.size(), 3);
+ foo.remove(2);
+ ASSERT_EQ(foo.size(), 2);
+ foo.remove(2);
+ ASSERT_EQ(foo.size(), 2);
+}
+
+TEST(ListTest, RemoveDuplicates) {
+ List<int> foo;
+
+ add_test_items(foo);
+ foo.push_back(2);
+
+ ASSERT_EQ(foo.size(), 4);
+ foo.remove(2);
+ ASSERT_EQ(foo.size(), 3);
+ foo.remove(2);
+ ASSERT_EQ(foo.size(), 2);
+}
+
+TEST(ListTest, RemoveDuringIterator) {
+ List<int> foo;
+ add_test_items(foo);
+
+ for (int & value : foo) {
+ if (value == 2)
+ foo.remove(value);
+ }
+
+ ASSERT_EQ(foo.size(), 2);
+}
+
+TEST(ListTest, UnmanagedPointers) {
+ char * ptr1 = static_cast<char *>(malloc(3));
+ char * ptr2 = static_cast<char *>(malloc(3));
+
+ {
+ List<char *> foo;
+
+ foo.push_back(ptr1);
+ foo.push_back(ptr2);
+
+ // this destructor shouldn't free ptr1 and ptr2
+ }
+
+ ASSERT_NE(ptr1, nullptr);
+ ASSERT_NE(ptr2, nullptr);
+
+ // thus, these shouldn't cause double free() errors:
+ free(ptr1);
+ free(ptr2);
+}
+
diff --git a/test/ptrlist.cpp b/test/ptrlist.cpp
new file mode 100644
index 0000000..ba955c5
--- /dev/null
+++ b/test/ptrlist.cpp
@@ -0,0 +1,27 @@
+#include <gtest/gtest.h>
+
+#include "backend/PtrList.h"
+
+class FooBar {
+ int val = 3;
+ bool other = 4;
+};
+
+TEST(PtrListTest, FreePointers) {
+ // PtrList only works on classes:
+ FooBar * ptr1 = new FooBar();
+ FooBar * ptr2 = new FooBar();
+
+ {
+ PtrList<FooBar> foo;
+
+ foo.push_back(ptr1);
+ foo.push_back(ptr2);
+
+ // this destructor SHOULD free ptr1 and ptr2
+ }
+
+ ASSERT_NE(ptr1, nullptr);
+ ASSERT_NE(ptr2, nullptr);
+}
+
diff --git a/test/util.cpp b/test/util.cpp
new file mode 100644
index 0000000..e90882a
--- /dev/null
+++ b/test/util.cpp
@@ -0,0 +1,15 @@
+#include <gtest/gtest.h>
+
+#include "backend/util.h"
+
+TEST(Util, SafeFree) {
+ char * str = static_cast<char *>(malloc(3));
+ ASSERT_NE(str, nullptr);
+
+ safe_free(&str);
+ ASSERT_EQ(str, nullptr);
+
+ // this shouldn't cause double free() error:
+ safe_free(&str);
+}
+