From 5e4dd0c0197f6273c61491a5b9a030c93f796a12 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 2 Nov 2024 15:55:58 +0100 Subject: add some tests --- backend/Player.cpp | 4 +-- backend/PtrList.hpp | 1 + backend/String.cpp | 8 ++--- backend/print.cpp | 2 +- backend/util.cpp | 38 +++++++++++++---------- backend/util.h | 2 +- test/CMakeLists.txt | 3 ++ test/list.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test/ptrlist.cpp | 27 +++++++++++++++++ test/util.cpp | 15 +++++++++ 10 files changed, 163 insertions(+), 24 deletions(-) create mode 100644 test/list.cpp create mode 100644 test/ptrlist.cpp create mode 100644 test/util.cpp 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 PtrList::~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(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(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(const_cast(ptr)); - safe_free(x); +void safe_free(const char ** ptr) { + // wow c++ casts so readable + auto a = const_cast(ptr); + auto b = static_cast(a); + auto c = reinterpret_cast(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 -void safe_free(T * & ptr) { - auto x = static_cast(ptr); - safe_free(x); +void safe_free(T ** ptr) { + auto a = static_cast(ptr); + auto b = reinterpret_cast(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 -void safe_free(T * & ptr); +void safe_free(T ** ptr); template 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 + +#include "backend/ListIterator.h" +#include "backend/List.h" + +static void add_test_items(List & foo) { + foo.push_back(1); + foo.push_back(2); + foo.push_back(3); +} + +TEST(ListTest, PushBack) { + List foo; + ASSERT_EQ(foo.size(), 0); + + add_test_items(foo); + + ASSERT_EQ(foo.size(), 3); +} + +TEST(ListTest, Clear) { + List foo; + foo.clear(); + + add_test_items(foo); + + foo.clear(); + ASSERT_EQ(foo.size(), 0); +} + +TEST(ListTest, Remove) { + List 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 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 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(malloc(3)); + char * ptr2 = static_cast(malloc(3)); + + { + List 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 + +#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 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 + +#include "backend/util.h" + +TEST(Util, SafeFree) { + char * str = static_cast(malloc(3)); + ASSERT_NE(str, nullptr); + + safe_free(&str); + ASSERT_EQ(str, nullptr); + + // this shouldn't cause double free() error: + safe_free(&str); +} + -- cgit v1.2.3