Skip to content

Commit

Permalink
Added Unit Testing and E2E Testing with Catch2:
Browse files Browse the repository at this point in the history
- Added Catch2 header file for Testing
- Added unit testing for all formatting functions
- Fixed bugs with boldify and italicize functions
- Added E2E testing, comparing files
- Updated CONTRIBUTING.md with Testing info
  • Loading branch information
joshuali7536 committed Nov 12, 2021
1 parent 85966b8 commit 1772302
Show file tree
Hide file tree
Showing 13 changed files with 18,221 additions and 12 deletions.
6 changes: 6 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
Checks: '-*,clang-analyzer-apiModeling.StdCLibraryFunctions,clang-analyzer-apiModeling.TrustNonnull,clang-analyzer-apiModeling.google.GTest,clang-analyzer-apiModeling.llvm.CastValue,clang-analyzer-apiModeling.llvm.ReturnValue,clang-analyzer-core.CallAndMessage,clang-analyzer-core.CallAndMessageModeling,clang-analyzer-core.DivideZero,clang-analyzer-core.DynamicTypePropagation,clang-analyzer-core.NonNullParamChecker,clang-analyzer-core.NonnilStringConstants,clang-analyzer-core.NullDereference,clang-analyzer-core.StackAddrEscapeBase,clang-analyzer-core.StackAddressEscape,clang-analyzer-core.UndefinedBinaryOperatorResult,clang-analyzer-core.VLASize,clang-analyzer-core.builtin.BuiltinFunctions,clang-analyzer-core.builtin.NoReturnFunctions,clang-analyzer-core.uninitialized.ArraySubscript,clang-analyzer-core.uninitialized.Assign,clang-analyzer-core.uninitialized.Branch,clang-analyzer-core.uninitialized.CapturedBlockVariable,clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-cplusplus.InnerPointer,clang-analyzer-cplusplus.Move,clang-analyzer-cplusplus.NewDelete,clang-analyzer-cplusplus.NewDeleteLeaks,clang-analyzer-cplusplus.PlacementNew,clang-analyzer-cplusplus.PureVirtualCall,clang-analyzer-cplusplus.SelfAssignment,clang-analyzer-cplusplus.SmartPtrModeling,clang-analyzer-cplusplus.VirtualCallModeling,clang-analyzer-deadcode.DeadStores,clang-analyzer-fuchsia.HandleChecker,clang-analyzer-nullability.NullPassedToNonnull,clang-analyzer-nullability.NullReturnedFromNonnull,clang-analyzer-nullability.NullabilityBase,clang-analyzer-nullability.NullableDereferenced,clang-analyzer-nullability.NullablePassedToNonnull,clang-analyzer-nullability.NullableReturnedFromNonnull,clang-analyzer-optin.cplusplus.UninitializedObject,clang-analyzer-optin.cplusplus.VirtualCall,clang-analyzer-optin.mpi.MPI-Checker,clang-analyzer-optin.osx.OSObjectCStyleCast,clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker,clang-analyzer-optin.performance.GCDAntipattern,clang-analyzer-optin.performance.Padding,clang-analyzer-optin.portability.UnixAPI,clang-analyzer-osx.API,clang-analyzer-osx.MIG,clang-analyzer-osx.NSOrCFErrorDerefChecker,clang-analyzer-osx.NumberObjectConversion,clang-analyzer-osx.OSObjectRetainCount,clang-analyzer-osx.ObjCProperty,clang-analyzer-osx.SecKeychainAPI,clang-analyzer-osx.cocoa.AtSync,clang-analyzer-osx.cocoa.AutoreleaseWrite,clang-analyzer-osx.cocoa.ClassRelease,clang-analyzer-osx.cocoa.Dealloc,clang-analyzer-osx.cocoa.IncompatibleMethodTypes,clang-analyzer-osx.cocoa.Loops,clang-analyzer-osx.cocoa.MissingSuperCall,clang-analyzer-osx.cocoa.NSAutoreleasePool,clang-analyzer-osx.cocoa.NSError,clang-analyzer-osx.cocoa.NilArg,clang-analyzer-osx.cocoa.NonNilReturnValue,clang-analyzer-osx.cocoa.ObjCGenerics,clang-analyzer-osx.cocoa.RetainCount,clang-analyzer-osx.cocoa.RetainCountBase,clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak,clang-analyzer-osx.cocoa.SelfInit,clang-analyzer-osx.cocoa.SuperDealloc,clang-analyzer-osx.cocoa.UnusedIvars,clang-analyzer-osx.cocoa.VariadicMethodTypes,clang-analyzer-osx.coreFoundation.CFError,clang-analyzer-osx.coreFoundation.CFNumber,clang-analyzer-osx.coreFoundation.CFRetainRelease,clang-analyzer-osx.coreFoundation.containers.OutOfBounds,clang-analyzer-osx.coreFoundation.containers.PointerSizedValues,clang-analyzer-security.FloatLoopCounter,clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,clang-analyzer-security.insecureAPI.SecuritySyntaxChecker,clang-analyzer-security.insecureAPI.UncheckedReturn,clang-analyzer-security.insecureAPI.bcmp,clang-analyzer-security.insecureAPI.bcopy,clang-analyzer-security.insecureAPI.bzero,clang-analyzer-security.insecureAPI.decodeValueOfObjCType,clang-analyzer-security.insecureAPI.getpw,clang-analyzer-security.insecureAPI.gets,clang-analyzer-security.insecureAPI.mkstemp,clang-analyzer-security.insecureAPI.mktemp,clang-analyzer-security.insecureAPI.rand,clang-analyzer-security.insecureAPI.strcpy,clang-analyzer-security.insecureAPI.vfork,clang-analyzer-unix.API,clang-analyzer-unix.DynamicMemoryModeling,clang-analyzer-unix.Malloc,clang-analyzer-unix.MallocSizeof,clang-analyzer-unix.MismatchedDeallocator,clang-analyzer-unix.Vfork,clang-analyzer-unix.cstring.BadSizeArg,clang-analyzer-unix.cstring.CStringModeling,clang-analyzer-unix.cstring.NullArg,clang-analyzer-valist.CopyToSelf,clang-analyzer-valist.Uninitialized,clang-analyzer-valist.Unterminated,clang-analyzer-valist.ValistBase,clang-analyzer-webkit.NoUncountedMemberChecker,clang-analyzer-webkit.RefCntblBaseVirtualDtor'
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
FormatStyle: 'file'
User: joshua
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,10 @@ This will display the lint that needs fixing in errors.
![image](https://user-images.githubusercontent.com/49960519/140455702-b7e2f2f9-6e50-4617-bc5b-6e6930b8e6b8.png)
1. Then you can view the lint that needs fixing in the warnings area below.
1. You can also make a quick fix by pressing the drop down beside the Tidy button or pressing Alt+X

## Testing
To run the testing checks for the application it is really simple, just run the application like normally but add `--test` or `-t` as an argument when running. Then it will run the Unit Testing feature of LENNAH making checks with each function and end with a E2E test.

```sh
$ C:\Users\User\LennahSSG\Debug\LennahSSG.exe --test
```
24 changes: 12 additions & 12 deletions LennahSSG/Formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
*/
string Formatter::italicize(string itLine)
{
while (itLine.find("*") != string::npos || itLine.find("_"))
while (itLine.find("*") != string::npos || itLine.find("_") != string::npos)
{
if (itLine.find("*") != string::npos && itLine.find("*") != itLine.find_last_of("*"))
if (itLine.find("*") != string::npos && itLine.find("*") != itLine.rfind("*"))
{
itLine.replace(itLine.find("*"), 1, "<i>");
itLine.replace(itLine.find_last_of("*"), 1, "</i>");
itLine.replace(itLine.rfind("*"), 1, "</i>");
}
else if (itLine.find("_") != string::npos && itLine.find("_") != itLine.find_last_of("*"))
else if (itLine.find("_") != string::npos && itLine.find("_") != itLine.rfind("_"))
{
itLine.replace(itLine.find("_"), 1, "<i>");
itLine.replace(itLine.find_last_of("_"), 1, "</i>");
itLine.replace(itLine.rfind("_"), 1, "</i>");
}
else
{
Expand All @@ -34,15 +34,15 @@ string Formatter::boldify(string boldLine)
{
while (boldLine.find("**") != string::npos || boldLine.find("__") != string::npos)
{
if (boldLine.find("**") != string::npos && boldLine.find("**") != boldLine.find_last_of("**"))
if (boldLine.find("**") != string::npos && boldLine.find("**") != boldLine.rfind("**"))
{
boldLine.replace(boldLine.find("**"), 2, "<b>");
boldLine.replace(boldLine.find_last_of("**") - 1, 2, "</b>");
boldLine.replace(boldLine.rfind("**"), 2, "</b>");
}
else if (boldLine.find("__") != string::npos && boldLine.find("__") != boldLine.find_last_of("__"))
else if (boldLine.find("__") != string::npos && boldLine.find("__") != boldLine.rfind("__"))
{
boldLine.replace(boldLine.find("__"), 1, "<b>");
boldLine.replace(boldLine.find_last_of("__"), 1, "</b>");
boldLine.replace(boldLine.find("__"), 2, "<b>");
boldLine.replace(boldLine.rfind("__"), 2, "</b>");
}
else
{
Expand Down Expand Up @@ -72,10 +72,10 @@ string Formatter::inlineCode(string line)
{
while (line.find("`") != string::npos)
{
if (line.find("`") != string::npos && line.find("`") != line.find_last_of("`"))
if (line.find("`") != string::npos && line.find("`") != line.rfind("`"))
{
line.replace(line.find("`"), 1, "<code>");
line.replace(line.find("`"), 1, "</code>");
line.replace(line.rfind("`"), 1, "</code>");
}
else
{
Expand Down
8 changes: 8 additions & 0 deletions LennahSSG/LennahSSG.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

#include <iostream>
#include <fstream>
#include <string>
Expand Down Expand Up @@ -38,6 +41,11 @@ int main(int argc, char **argv)
help_message();
return 0;
}
else if ((arg == "-t") || (arg == "--test"))
{
int result = Catch::Session().run();
return result;
}
else
{
cout << "Not using proper arguments";
Expand Down
2 changes: 2 additions & 0 deletions LennahSSG/LennahSSG.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,10 @@
<ClCompile Include="FileReader.cpp" />
<ClCompile Include="Formatter.cpp" />
<ClCompile Include="LennahSSG.cpp" />
<ClCompile Include="TestCases.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="catch.hpp" />
<ClInclude Include="Config.h" />
<ClInclude Include="FileReader.h" />
<ClInclude Include="Formatter.h" />
Expand Down
6 changes: 6 additions & 0 deletions LennahSSG/LennahSSG.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<ClCompile Include="FileReader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestCases.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Config.h">
Expand All @@ -38,5 +41,8 @@
<ClInclude Include="FileReader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="catch.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
140 changes: 140 additions & 0 deletions LennahSSG/TestCases.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//#define CATCH_CONFIG_MAIN

#include <iostream>
#include <fstream>
#include <string>
#include "catch.hpp"
#include "Formatter.h"

void inputManager(string input, string output);

bool filesMatch(string filePath1, string filePath2)
{
std::ifstream file1(filePath1);
std::ifstream file2(filePath2);

if (file1.fail() || file2.fail())
{
return false;
}

if (file1.tellg() != file2.tellg())
{
return false;
}

file1.seekg(0, std::ifstream::beg);
file2.seekg(0, std::ifstream::beg);

return std::equal(std::istreambuf_iterator<char>(file1.rdbuf()), std::istreambuf_iterator<char>(),
std::istreambuf_iterator<char>(file2.rdbuf()));
}

TEST_CASE("Italicize function", "[italics]")
{
Formatter test;
SECTION("Strings with * markdown")
{
REQUIRE(test.italicize("*Hello World*") == "<i>Hello World</i>");
REQUIRE(test.italicize("*Testing 123*") == "<i>Testing 123</i>");
}
SECTION("String with _ markdown")
{
REQUIRE(test.italicize("_This is a sentence_") == "<i>This is a sentence</i>");
}
SECTION("Empty string")
{
REQUIRE(test.italicize("") == "");
}
SECTION("String with one *")
{
REQUIRE(test.italicize("*Hello World") == "*Hello World");
}
SECTION("String with one _")
{
REQUIRE(test.italicize("_Hello World") == "_Hello World");
}
}

TEST_CASE("Boldify function", "[bold]")
{
Formatter test;
SECTION("Strings with ** markdown")
{
REQUIRE(test.boldify("**Hello World**") == "<b>Hello World</b>");
REQUIRE(test.boldify("**Testing 123**") == "<b>Testing 123</b>");
}
SECTION("String with _ markdown")
{
REQUIRE(test.boldify("__This is a sentence__") == "<b>This is a sentence</b>");
}
SECTION("Empty string")
{
REQUIRE(test.boldify("") == "");
}
SECTION("String with one **")
{
REQUIRE(test.boldify("**Hello World") == "**Hello World");
}
SECTION("String with one __")
{
REQUIRE(test.boldify("__Hello World") == "__Hello World");
}
}

TEST_CASE("Inline Code function", "[code]")
{
Formatter test;
SECTION("Strings with ` markdown")
{
REQUIRE(test.inlineCode("`Hello World`") == "<code>Hello World</code>");
REQUIRE(test.inlineCode("`Testing 123`") == "<code>Testing 123</code>");
}
SECTION("Empty string")
{
REQUIRE(test.inlineCode("") == "");
}
SECTION("String with one `")
{
REQUIRE(test.inlineCode("`Hello World") == "`Hello World");
}
}

TEST_CASE("Trim Whitespace function", "[trim]")
{
Formatter test;
SECTION("Strings with front and back whitespace")
{
REQUIRE(test.trim(" Hello World ") == "Hello World");
}
SECTION("Empty string")
{
REQUIRE(test.trim("") == "");
}
SECTION("String with only front whitespace")
{
REQUIRE(test.trim(" Hello World") == "Hello World");
}
SECTION("String with only back whitespace")
{
REQUIRE(test.trim("Hello World ") == "Hello World");
}
SECTION("String with no extra whitespace")
{
REQUIRE(test.trim("Hello World") == "Hello World");
}
}

TEST_CASE("E2E", "[E2E]")
{
SECTION("Check if TXT file matches snapshot")
{
inputManager("./test/test.txt", "./test/output/");
REQUIRE(filesMatch("./test/output/test.html", "./test/snapshotTXT.html"));
}
SECTION("Check if MD file matches snapshot")
{
inputManager("./test/test.md", "./test/output/");
REQUIRE(filesMatch("./test/output/test.html", "./test/snapshotMD.html"));
}
}
Loading

0 comments on commit 1772302

Please sign in to comment.