From 021750a13589e2ff8a088c7f7906aa727cd56f7c Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 24 Jun 2019 13:38:41 +0200 Subject: [PATCH] Fix all valgrind leak issues in tests Signed-off-by: Deukhoofd --- src/Evaluator/EvalValues/EvalValue.cpp | 23 ++- src/Evaluator/Iterator/Iterator.hpp | 2 +- .../ParsedStatements/ParsedStatement.hpp | 4 + src/Parser/Parser.cpp | 5 +- src/UserData/UserData.hpp | 21 ++- src/UserData/UserDataScriptType.hpp | 6 +- src/UserData/UserDataStorage.hpp | 25 ++- src/UserData/UserDataValue.hpp | 6 +- tests/integration/LogicalOperationsTests.cpp | 1 + .../integration/NumericalOperationsTests.cpp | 1 + tests/integration/UserDataTests.cpp | 26 +-- tests/parser/LexerTests.cpp | 151 +++++++++++++++--- tests/parser/ParserTests.cpp | 87 ++++++++-- 13 files changed, 295 insertions(+), 63 deletions(-) diff --git a/src/Evaluator/EvalValues/EvalValue.cpp b/src/Evaluator/EvalValues/EvalValue.cpp index 681c927..ce8390a 100644 --- a/src/Evaluator/EvalValues/EvalValue.cpp +++ b/src/Evaluator/EvalValues/EvalValue.cpp @@ -23,8 +23,18 @@ namespace Porygon::Evaluation { return v->EvaluateBool(); } - const char16_t *EvaluateEvalValueString(EvalValue *v) { - return (new u16string(v->EvaluateString()))->c_str(); + size_t GetEvalValueStringLength(EvalValue *v) { + auto result = v->EvaluateString(); + return result.size(); + } + + int EvaluateEvalValueString(EvalValue *v, char16_t dst[]){ + auto result = v->EvaluateString(); + for (int i = 0; i < result.size(); i++){ + dst[i] = result[i]; + } + dst[result.size() + 1] = '\0'; + return 0; } @@ -52,13 +62,18 @@ namespace Porygon::Evaluation { TEST_CASE( "Evaluate String", "[integration]" ) { - auto script = Porygon::Script::Create(u"\"foo bar\""); + auto sc = new u16string(u"\"foo bar\""); + auto script = Porygon::Script::Create(*sc); REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - auto s = u16string(EvaluateEvalValueString(lastValue)); + size_t size = GetEvalValueStringLength(lastValue); + char16_t dst[size + 1]; + EvaluateEvalValueString(lastValue, dst); + auto s = u16string(dst); REQUIRE(s == u"foo bar"); delete script; + delete sc; } diff --git a/src/Evaluator/Iterator/Iterator.hpp b/src/Evaluator/Iterator/Iterator.hpp index 7962723..4f5e381 100644 --- a/src/Evaluator/Iterator/Iterator.hpp +++ b/src/Evaluator/Iterator/Iterator.hpp @@ -25,7 +25,7 @@ namespace Porygon::Evaluation{ : _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){} shared_ptr GetCurrent() final{ - return make_shared(_iterator->first.GetString()); + return make_shared(*_iterator->first.GetString()); } bool MoveNext() final{ diff --git a/src/Parser/ParsedStatements/ParsedStatement.hpp b/src/Parser/ParsedStatements/ParsedStatement.hpp index eb60b1b..c3be5cf 100644 --- a/src/Parser/ParsedStatements/ParsedStatement.hpp +++ b/src/Parser/ParsedStatements/ParsedStatement.hpp @@ -111,6 +111,10 @@ namespace Porygon::Parser { delete _expression; } + void NullifyExpression(){ + _expression = nullptr; + } + const ParsedStatementKind GetKind() const final { return ParsedStatementKind::Expression; } diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index fbb28a6..640a77d 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -525,7 +525,10 @@ namespace Porygon::Parser { // If the first item is an expression, and is followed by a comma, we're dealing with a simple {1, 2, 3} kind of array if (firstItem->GetKind() == ParsedStatementKind::Expression && (this->Peek()->GetKind() == TokenKind::CommaToken)) { - auto expr = ((ParsedExpressionStatement *) firstItem)->GetExpression(); + auto statement = ((ParsedExpressionStatement *) firstItem); + auto expr = statement->GetExpression(); + statement->NullifyExpression(); + delete statement; auto expressions = vector{expr}; auto n = this->Next(); // consume the comma bool hasErrors = false; diff --git a/src/UserData/UserData.hpp b/src/UserData/UserData.hpp index c6df473..dab7ee3 100644 --- a/src/UserData/UserData.hpp +++ b/src/UserData/UserData.hpp @@ -1,3 +1,5 @@ +#include + #ifndef PORYGONLANG_USERDATA_HPP #define PORYGONLANG_USERDATA_HPP @@ -9,23 +11,30 @@ namespace Porygon::UserData { class UserData { std::unordered_map _fields; public: - explicit UserData(std::unordered_map fields) { - _fields = std::move(fields); + explicit UserData(std::unordered_map fields) + : _fields(std::move(fields)) + { } - bool ContainsField(uint32_t fieldId) { + ~UserData(){ + for (auto f: _fields){ + delete f.second; + } + } + + bool ContainsField(uint32_t fieldId) const{ return _fields.find(fieldId) != _fields.end(); } - UserDataField *GetField(uint32_t fieldId) { - return _fields[fieldId]; + UserDataField *GetField(uint32_t fieldId) const { + return _fields.at(fieldId); } void CreateField(uint32_t fieldId, UserDataField *field) { _fields.insert({fieldId, field}); } - int32_t GetFieldCount() { + int32_t GetFieldCount() const{ return _fields.size(); } }; diff --git a/src/UserData/UserDataScriptType.hpp b/src/UserData/UserDataScriptType.hpp index 165d07e..a7ef803 100644 --- a/src/UserData/UserDataScriptType.hpp +++ b/src/UserData/UserDataScriptType.hpp @@ -10,14 +10,14 @@ namespace Porygon::UserData { class UserDataScriptType : public ScriptType { - shared_ptr _userData; + UserData* _userData; public: explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData) { _userData = UserDataStorage::GetUserDataType(id); } - explicit UserDataScriptType(shared_ptr ud) : ScriptType(TypeClass::UserData) { - _userData = std::move(ud); + explicit UserDataScriptType(UserData* ud) : ScriptType(TypeClass::UserData) { + _userData = ud; } const bool CanBeIndexedWith(ScriptType *indexer) const final { diff --git a/src/UserData/UserDataStorage.hpp b/src/UserData/UserDataStorage.hpp index 319e833..782242e 100644 --- a/src/UserData/UserDataStorage.hpp +++ b/src/UserData/UserDataStorage.hpp @@ -3,27 +3,46 @@ #define PORYGONLANG_USERDATASTORAGE_HPP #include +#include #include "UserData.hpp" namespace Porygon::UserData { class UserDataStorage { class _internalDataStorage { public: - std::unordered_map> _userData; + std::unordered_map _userData; + std::mutex _userDataMutex; + + ~_internalDataStorage(){ + std::lock_guard guard(_userDataMutex); + for (auto u: _userData){ + delete u.second; + } + _userData.clear(); + } }; static _internalDataStorage _internal; public: static void RegisterType(uint32_t i, UserData *ud) { - UserDataStorage::_internal._userData.insert({i, shared_ptr(ud)}); + std::lock_guard guard(_internal._userDataMutex); + UserDataStorage::_internal._userData.insert({i, ud}); + } + + static void ClearTypes(){ + std::lock_guard guard(_internal._userDataMutex); + for (auto u: _internal._userData){ + delete u.second; + } + _internal._userData.clear(); } static bool HasUserDataType(uint32_t i) { return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end(); } - static shared_ptr GetUserDataType(uint32_t i) { + static UserData* GetUserDataType(uint32_t i) { return UserDataStorage::_internal._userData[i]; } }; diff --git a/src/UserData/UserDataValue.hpp b/src/UserData/UserDataValue.hpp index 65eee12..2343703 100644 --- a/src/UserData/UserDataValue.hpp +++ b/src/UserData/UserDataValue.hpp @@ -9,11 +9,11 @@ namespace Porygon::UserData { class UserDataValue : public Evaluation::EvalValue { - const shared_ptr _userData; + const UserData* _userData; void *_obj; public: - UserDataValue(shared_ptr userData, void *obj) - : _userData(std::move(userData)) { + UserDataValue(const UserData* userData, void *obj) + : _userData(userData) { _obj = obj; } diff --git a/tests/integration/LogicalOperationsTests.cpp b/tests/integration/LogicalOperationsTests.cpp index c7c1dd4..d6e13da 100644 --- a/tests/integration/LogicalOperationsTests.cpp +++ b/tests/integration/LogicalOperationsTests.cpp @@ -68,6 +68,7 @@ TEST_CASE( "True or False", "[integration]" ) { script->Evaluate(); auto lastValue = script->GetLastValue(); REQUIRE(lastValue->EvaluateBool()); + delete script; } TEST_CASE( "False or True", "[integration]" ) { auto script = Script::Create("false or true"); diff --git a/tests/integration/NumericalOperationsTests.cpp b/tests/integration/NumericalOperationsTests.cpp index 22febc4..5d33a10 100644 --- a/tests/integration/NumericalOperationsTests.cpp +++ b/tests/integration/NumericalOperationsTests.cpp @@ -34,6 +34,7 @@ TEST_CASE( "Integer Subtraction", "[integration]" ) { script->Evaluate(); auto lastValue = script->GetLastValue(); REQUIRE(lastValue->EvaluateInteger() == -4); + delete script; } TEST_CASE( "Integer Multiplication", "[integration]" ) { auto script = Script::Create("5 * 8"); diff --git a/tests/integration/UserDataTests.cpp b/tests/integration/UserDataTests.cpp index 3e90921..f288dd6 100644 --- a/tests/integration/UserDataTests.cpp +++ b/tests/integration/UserDataTests.cpp @@ -47,7 +47,7 @@ private: )); } - static GenericFunctionScriptType* AdditionFunctionType; + static GenericFunctionScriptType* AdditionFunctionType(); static EvalValue* GetAdditionFunction(void* obj){ return new UserDataFunction(CallAddition, obj); @@ -66,18 +66,19 @@ public: }, { HashedString::ConstHash("Addition"), - new UserDataField(AdditionFunctionType, GetAdditionFunction, nullptr) + new UserDataField(AdditionFunctionType(), GetAdditionFunction, nullptr) } }); } }; -GenericFunctionScriptType* UserDataTestObject::AdditionFunctionType = - new UserDataFunctionType(make_shared(true, false), - vector>{ - make_shared(true, false), - make_shared(true, false) - }); +GenericFunctionScriptType* UserDataTestObject::AdditionFunctionType(){ + return new UserDataFunctionType(make_shared(true, false), + vector>{ + make_shared(true, false), + make_shared(true, false) + }); +} TEST_CASE( "Gets UserData value", "[integration]" ) { UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::CreateData()); @@ -88,11 +89,15 @@ end )"); REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); - auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), new UserDataTestObject()); + auto par = new UserDataTestObject(); + auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), par); auto variable = script->CallFunction(u"testFunc", {parameter}); REQUIRE(variable != nullptr); REQUIRE(variable->EvaluateInteger() == 10); + delete par; + delete parameter; delete script; + UserDataStorage::ClearTypes(); } TEST_CASE( "Sets UserData value", "[integration]" ) { @@ -111,6 +116,7 @@ end REQUIRE(obj->foo == 5000); delete obj; delete parameter; + UserDataStorage::ClearTypes(); } TEST_CASE( "Calls UserData function", "[integration]" ) { @@ -129,6 +135,7 @@ end delete script; delete obj; delete parameter; + UserDataStorage::ClearTypes(); } TEST_CASE( "Calls UserData function with parameters", "[integration]" ) { @@ -147,6 +154,7 @@ end delete script; delete obj; delete parameter; + UserDataStorage::ClearTypes(); } diff --git a/tests/parser/LexerTests.cpp b/tests/parser/LexerTests.cpp index 5e5d7ac..d101ad0 100644 --- a/tests/parser/LexerTests.cpp +++ b/tests/parser/LexerTests.cpp @@ -16,6 +16,7 @@ TEST_CASE( "Peek doesn't advance", "[lexer]" ) { REQUIRE(lexer.Peek() == '5'); REQUIRE(lexer.Peek() == '5'); REQUIRE(lexer.Peek() == '5'); + delete script; } TEST_CASE( "Next does advance", "[lexer]" ) { @@ -27,36 +28,49 @@ TEST_CASE( "Next does advance", "[lexer]" ) { REQUIRE(lexer.Next() == ' '); REQUIRE(lexer.Next() == '5'); REQUIRE(lexer.Next() == '\0'); + delete script; } TEST_CASE( "Lex Null Terminator as EOF", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - REQUIRE(lexer.LexNext('\0') -> GetKind() == TokenKind::EndOfFile); + auto next = lexer.LexNext('\0'); + REQUIRE(next -> GetKind() == TokenKind::EndOfFile); + delete next; } TEST_CASE( "Lex Plus Token", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - REQUIRE(lexer.LexNext('+') -> GetKind() == TokenKind::PlusToken); + auto next = lexer.LexNext('+'); + REQUIRE(next -> GetKind() == TokenKind::PlusToken); + delete next; } TEST_CASE( "Lex Minus Token", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - REQUIRE(lexer.LexNext('-') -> GetKind() == TokenKind::MinusToken); + auto next = lexer.LexNext('-'); + REQUIRE(next -> GetKind() == TokenKind::MinusToken); + delete next; } TEST_CASE( "Lex Slash Token", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - REQUIRE(lexer.LexNext('/') -> GetKind() == TokenKind::SlashToken); + auto next = lexer.LexNext('/'); + REQUIRE(next -> GetKind() == TokenKind::SlashToken); + delete next; } TEST_CASE( "Lex Star Token", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - REQUIRE(lexer.LexNext('*') -> GetKind() == TokenKind::StarToken); + auto next = lexer.LexNext('*'); + REQUIRE(next -> GetKind() == TokenKind::StarToken); + delete next; } TEST_CASE( "Lex Assignment Token", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - REQUIRE(lexer.LexNext('=') -> GetKind() == TokenKind::AssignmentToken); + auto next = lexer.LexNext('='); + REQUIRE(next -> GetKind() == TokenKind::AssignmentToken); + delete next; } TEST_CASE( "Lex Equality Token", "[lexer]" ) { @@ -65,30 +79,30 @@ TEST_CASE( "Lex Equality Token", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::EqualityToken); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex Whitespace", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - CHECK(lexer.LexNext(' ') -> GetKind() == TokenKind::WhiteSpace); - CHECK(lexer.LexNext('\t') -> GetKind() == TokenKind::WhiteSpace); - CHECK(lexer.LexNext('\n') -> GetKind() == TokenKind::WhiteSpace); - CHECK(lexer.LexNext('\r') -> GetKind() == TokenKind::WhiteSpace); - CHECK(lexer.LexNext('\v') -> GetKind() == TokenKind::WhiteSpace); - CHECK(lexer.LexNext('\f') -> GetKind() == TokenKind::WhiteSpace); + + vector whitespace {' ', '\t', '\n', '\r', '\v', '\f'}; + for (char c: whitespace){ + auto t = lexer.LexNext(c); + CHECK(t -> GetKind() == TokenKind::WhiteSpace); + delete t; + } } TEST_CASE( "Lex Basic Digits", "[lexer]" ) { Lexer lexer = Lexer(u"", nullptr); - CHECK(lexer.LexNext('0') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('1') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('2') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('3') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('4') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('5') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('6') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('7') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('8') -> GetKind() == TokenKind::Integer); - CHECK(lexer.LexNext('9') -> GetKind() == TokenKind::Integer); + vector ints {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + for (char c: ints){ + auto t = lexer.LexNext(c); + CHECK(t -> GetKind() == TokenKind::Integer); + delete t; + } } std::u16string to_u16string(long const &i) { @@ -107,6 +121,10 @@ TEST_CASE( "Lex Longer Integers", "[lexer]" ) { REQUIRE(firstToken -> GetKind() == TokenKind::Integer); auto* integerToken = (IntegerToken *)firstToken; CHECK(integerToken -> GetValue() == integer); + + for (auto t: tokens){ + delete t; + } } } @@ -125,6 +143,10 @@ TEST_CASE( "Lex Floats", "[lexer]" ) { REQUIRE(firstToken -> GetKind() == TokenKind::Float); auto* floatToken = (FloatToken *)firstToken; CHECK(floatToken -> GetValue() == Approx(f)); + + for (auto t: tokens){ + delete t; + } } } @@ -134,6 +156,9 @@ TEST_CASE( "Lex And Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::AndKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex Break Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"break", nullptr); @@ -141,6 +166,9 @@ TEST_CASE( "Lex Break Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::BreakKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex Do Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"do", nullptr); @@ -148,6 +176,9 @@ TEST_CASE( "Lex Do Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::DoKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex else Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"else", nullptr); @@ -155,6 +186,9 @@ TEST_CASE( "Lex else Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::ElseKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex else if Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"elseif", nullptr); @@ -162,6 +196,9 @@ TEST_CASE( "Lex else if Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::ElseIfKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex end Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"end", nullptr); @@ -169,6 +206,9 @@ TEST_CASE( "Lex end Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::EndKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex false Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"false", nullptr); @@ -176,6 +216,9 @@ TEST_CASE( "Lex false Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::FalseKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex for Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"for", nullptr); @@ -183,6 +226,9 @@ TEST_CASE( "Lex for Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::ForKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex function Keyword", "[lexer]" ) { auto s = new u16string(u"function"); @@ -191,6 +237,10 @@ TEST_CASE( "Lex function Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::FunctionKeyword); + for (auto t: tokens){ + delete t; + } + delete s; } TEST_CASE( "Lex if Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"if", nullptr); @@ -198,6 +248,9 @@ TEST_CASE( "Lex if Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::IfKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex in Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"in", nullptr); @@ -205,6 +258,9 @@ TEST_CASE( "Lex in Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::InKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex local Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"local", nullptr); @@ -212,6 +268,9 @@ TEST_CASE( "Lex local Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::LocalKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex nil Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"nil", nullptr); @@ -219,6 +278,9 @@ TEST_CASE( "Lex nil Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::NilKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex not Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"not", nullptr); @@ -226,6 +288,9 @@ TEST_CASE( "Lex not Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::NotKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex or Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"or", nullptr); @@ -233,6 +298,9 @@ TEST_CASE( "Lex or Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::OrKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex return Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"return", nullptr); @@ -240,6 +308,9 @@ TEST_CASE( "Lex return Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::ReturnKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex then Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"then", nullptr); @@ -247,6 +318,9 @@ TEST_CASE( "Lex then Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::ThenKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex true Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"true", nullptr); @@ -254,6 +328,9 @@ TEST_CASE( "Lex true Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::TrueKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex while Keyword", "[lexer]" ) { Lexer lexer = Lexer(u"while", nullptr); @@ -261,6 +338,9 @@ TEST_CASE( "Lex while Keyword", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::WhileKeyword); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex identifier", "[lexer]" ) { @@ -270,6 +350,9 @@ TEST_CASE( "Lex identifier", "[lexer]" ) { const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::Identifier); REQUIRE(((IdentifierToken*)firstToken) -> GetValue() == HashedString("foo")); + for (auto t: tokens){ + delete t; + } } TEST_CASE( "Lex Start Position", "[lexer]" ) { @@ -282,6 +365,10 @@ TEST_CASE( "Lex Start Position", "[lexer]" ) { CHECK(((IdentifierToken*)tokens[2]) -> GetStartPosition() == 4); CHECK(((IdentifierToken*)tokens[3]) -> GetStartPosition() == 8); CHECK(((IdentifierToken*)tokens[4]) -> GetStartPosition() == 12); + for (auto t: tokens){ + delete t; + } + delete s; } TEST_CASE( "Lex End Position", "[lexer]" ) { @@ -294,6 +381,10 @@ TEST_CASE( "Lex End Position", "[lexer]" ) { CHECK(((IdentifierToken*)tokens[2]) -> GetEndPosition() == 6); CHECK(((IdentifierToken*)tokens[3]) -> GetEndPosition() == 11); CHECK(((IdentifierToken*)tokens[4]) -> GetEndPosition() == 12); + for (auto t: tokens){ + delete t; + } + delete s; } TEST_CASE("Lex Double Quote String", "[lexer]") { @@ -304,6 +395,10 @@ TEST_CASE("Lex Double Quote String", "[lexer]") { const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::String); REQUIRE(((StringToken*)firstToken) -> GetValue() == u"foo bar"); + for (auto t: tokens){ + delete t; + } + delete s; } TEST_CASE("Lex Single Quote String", "[lexer]") { @@ -314,6 +409,10 @@ TEST_CASE("Lex Single Quote String", "[lexer]") { const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::String); REQUIRE(((StringToken*)firstToken) -> GetValue() == u"foo bar"); + for (auto t: tokens){ + delete t; + } + delete s; } TEST_CASE("Lex Double Quote String, Escape Quote", "[lexer]") { @@ -324,6 +423,10 @@ TEST_CASE("Lex Double Quote String, Escape Quote", "[lexer]") { const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::String); REQUIRE(((StringToken*)firstToken) -> GetValue() == u"foo\"bar"); + for (auto t: tokens){ + delete t; + } + delete s; } TEST_CASE("Lex String with newline", "[lexer]") { @@ -334,6 +437,10 @@ TEST_CASE("Lex String with newline", "[lexer]") { const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::String); REQUIRE(((StringToken*)firstToken) -> GetValue() == u"foo\nbar"); + for (auto t: tokens){ + delete t; + } + delete s; } diff --git a/tests/parser/ParserTests.cpp b/tests/parser/ParserTests.cpp index b791094..78537f2 100644 --- a/tests/parser/ParserTests.cpp +++ b/tests/parser/ParserTests.cpp @@ -8,7 +8,8 @@ using namespace Porygon::Parser; TEST_CASE( "Parse single true keyword", "[parser]" ) { vector v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)}; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -16,12 +17,18 @@ TEST_CASE( "Parse single true keyword", "[parser]" ) { REQUIRE(expression -> GetKind() == ParsedExpressionKind::LiteralBool); auto boolean = ((LiteralBoolExpression*)expression); REQUIRE(boolean->GetValue()); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse single false keyword", "[parser]" ) { vector v {new SimpleToken(TokenKind::FalseKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)}; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -29,6 +36,11 @@ TEST_CASE( "Parse single false keyword", "[parser]" ) { REQUIRE(expression -> GetKind() == ParsedExpressionKind::LiteralBool); auto boolean = ((LiteralBoolExpression*)expression); REQUIRE_FALSE(boolean->GetValue()); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse simple addition", "[parser]" ) { @@ -39,7 +51,8 @@ TEST_CASE( "Parse simple addition", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -53,6 +66,11 @@ TEST_CASE( "Parse simple addition", "[parser]" ) { REQUIRE(right->GetKind() == ParsedExpressionKind::LiteralInteger); CHECK(((LiteralIntegerExpression*)left)->GetValue() == 5); CHECK(((LiteralIntegerExpression*)right)->GetValue() == 10); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse simple negation", "[parser]" ) { @@ -62,7 +80,8 @@ TEST_CASE( "Parse simple negation", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -73,6 +92,10 @@ TEST_CASE( "Parse simple negation", "[parser]" ) { auto operand = unary->GetOperand(); REQUIRE(operand->GetKind() == ParsedExpressionKind::LiteralInteger); CHECK(((LiteralIntegerExpression*)operand)->GetValue() == 10); + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse logical negation", "[parser]" ) { @@ -82,7 +105,8 @@ TEST_CASE( "Parse logical negation", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -93,6 +117,10 @@ TEST_CASE( "Parse logical negation", "[parser]" ) { auto operand = unary->GetOperand(); REQUIRE(operand->GetKind() == ParsedExpressionKind::LiteralBool); CHECK_FALSE(((LiteralBoolExpression*)operand)->GetValue()); + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Are parenthesized expressions valid", "[parser]" ) { @@ -105,7 +133,8 @@ TEST_CASE( "Are parenthesized expressions valid", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -122,6 +151,11 @@ TEST_CASE( "Are parenthesized expressions valid", "[parser]" ) { right = ((BinaryExpression*)right)->GetRight(); CHECK(((LiteralIntegerExpression*)left)->GetValue() == 10); CHECK(((LiteralIntegerExpression*)right)->GetValue() == 6); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Assert binary precedence", "[parser]" ) { @@ -132,7 +166,8 @@ TEST_CASE( "Assert binary precedence", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -140,12 +175,18 @@ TEST_CASE( "Assert binary precedence", "[parser]" ) { REQUIRE(expression -> GetKind() == ParsedExpressionKind::Parenthesized); auto innerExpression = ((ParenthesizedExpression*)expression) -> GetInnerExpression(); REQUIRE(innerExpression -> GetKind() == ParsedExpressionKind::LiteralInteger); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse String Tokens", "[parser]" ) { vector v {new StringToken(u"foo bar", 0,0), new SimpleToken(TokenKind::EndOfFile,0,0)}; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression); @@ -153,6 +194,11 @@ TEST_CASE( "Parse String Tokens", "[parser]" ) { REQUIRE(expression -> GetKind() == ParsedExpressionKind::LiteralString); auto boolean = ((LiteralStringExpression*)expression); REQUIRE(boolean->GetValue() == u"foo bar"); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse Global Assignment", "[parser]" ) { @@ -163,7 +209,8 @@ TEST_CASE( "Parse Global Assignment", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment); @@ -171,6 +218,11 @@ TEST_CASE( "Parse Global Assignment", "[parser]" ) { REQUIRE(!assignment -> IsLocal()); REQUIRE(assignment->GetIdentifier().GetHash() == HashedString("foo").GetHash()); REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue()); + + for (auto t : v){ + delete t; + } + delete parsedScript; } TEST_CASE( "Parse local Assignment", "[parser]" ) { @@ -182,7 +234,8 @@ TEST_CASE( "Parse local Assignment", "[parser]" ) { new SimpleToken(TokenKind::EndOfFile,0,0) }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment); @@ -190,6 +243,12 @@ TEST_CASE( "Parse local Assignment", "[parser]" ) { REQUIRE(assignment -> IsLocal()); REQUIRE(assignment->GetIdentifier().GetHash() == HashedString("foo").GetHash()); REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue()); + + for (auto t : v){ + delete t; + } + delete parsedScript; + } TEST_CASE( "Parse function declaration", "[parser]" ){ @@ -210,7 +269,8 @@ TEST_CASE( "Parse function declaration", "[parser]" ){ new SimpleToken(TokenKind::EndOfFile,0,0), }; Parser parser = Parser(v, nullptr); - auto parsedStatements = parser.Parse() -> GetStatements(); + auto parsedScript = parser.Parse(); + auto parsedStatements = parsedScript -> GetStatements(); REQUIRE(parsedStatements->size() == 1); auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::FunctionDeclaration); @@ -221,6 +281,11 @@ TEST_CASE( "Parse function declaration", "[parser]" ){ CHECK(parameters -> at(0) ->GetIdentifier() == HashedString("bar")); CHECK(parameters -> at(1) ->GetType() == HashedString("number")); CHECK(parameters -> at(1) ->GetIdentifier() == HashedString("par")); + + for (auto t : v){ + delete t; + } + delete parsedScript; }