From a1f111b6f3f21e3290e9fbbd8203d542bf655bd5 Mon Sep 17 00:00:00 2001
From: "Ewanseiha Odion (Student)"
 <ewanseiha2.odion@live.uwe.ac.uk@csctcloud.prxhn32zsyjupl12zde3wlfkch.cwx.internal.cloudapp.net>
Date: Tue, 2 Apr 2024 09:13:08 +0100
Subject: [PATCH] added files

---
 .gitgnore                      |   1 +
 .gitmodules                    |   6 +
 .vscode/configurationCache.log |   1 +
 .vscode/dryrun.log             |   7 +
 README.md                      | 109 +++++----
 build/app                      |   0
 build/app2                     |   0
 build/log.o                    |   0
 build/main.o                   |   0
 build/main_part2.o             |   0
 build/simpletest.o             |   0
 build/test                     |   0
 iot-starter-0                  |   1 +
 iot-starter-0-1                |   1 +
 log.in                         |   2 +
 makeFile                       |  75 +++++++
 screenshots/task 1.png         | Bin 0 -> 12093 bytes
 screenshots/task2.png          | Bin 0 -> 3388 bytes
 screenshots/task3.png          | Bin 0 -> 13006 bytes
 src/log.cpp                    |  86 ++++++++
 src/log.hpp                    |  15 ++
 src/main.cpp                   |  34 +++
 src/main_part2.cpp             |  34 +++
 src/simpletest.cpp             | 391 +++++++++++++++++++++++++++++++++
 src/simpletest.h               | 235 ++++++++++++++++++++
 src/unit_test.cpp              |  34 +++
 26 files changed, 973 insertions(+), 59 deletions(-)
 create mode 100644 .gitgnore
 create mode 100644 .gitmodules
 create mode 100644 .vscode/configurationCache.log
 create mode 100644 .vscode/dryrun.log
 create mode 100644 build/app
 create mode 100644 build/app2
 create mode 100644 build/log.o
 create mode 100644 build/main.o
 create mode 100644 build/main_part2.o
 create mode 100644 build/simpletest.o
 create mode 100644 build/test
 create mode 160000 iot-starter-0
 create mode 160000 iot-starter-0-1
 create mode 100644 log.in
 create mode 100644 makeFile
 create mode 100644 screenshots/task 1.png
 create mode 100644 screenshots/task2.png
 create mode 100644 screenshots/task3.png
 create mode 100644 src/log.cpp
 create mode 100644 src/log.hpp
 create mode 100644 src/main.cpp
 create mode 100644 src/main_part2.cpp
 create mode 100644 src/simpletest.cpp
 create mode 100644 src/simpletest.h
 create mode 100644 src/unit_test.cpp

diff --git a/.gitgnore b/.gitgnore
new file mode 100644
index 0000000..c795b05
--- /dev/null
+++ b/.gitgnore
@@ -0,0 +1 @@
+build
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..fdfd20e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "simpletest_test"]
+	path = simpletest_test
+	url = https://github.com/kudaba/simpletest_test.git
+[submodule "simpletest"]
+	path = simpletest
+	url = https://github.com/kudaba/simpletest.git
diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log
new file mode 100644
index 0000000..697d0b3
--- /dev/null
+++ b/.vscode/configurationCache.log
@@ -0,0 +1 @@
+{"buildTargets":["all","build","build/","build/app","build/app2","build/log.o","build/main.o","build/main_part2.o","build/simpletest.o","build/test","clean","log_level","log_message","run"],"launchTargets":["Makefile | /home/ewanseiha2.odion/iot_starter-1/build>app()"],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":["/home/ewanseiha2.odion/iot_starter-1/include","/home/ewanseiha2.odion/iot_starter-1/src"],"compilerArgs":["-lpthread","-o","build/app","./src/main.cpp","-lpthread","-o","build/app","./src/main.cpp","-lpthread","-o","build/app","./src/main.cpp","-lpthread","-o","build/app","./src/main.cpp","-lpthread","-o","build/app","./src/main.cpp","-lpthread","-o","build/app","./src/main.cpp","build/main_part2.o","-lpthread","-o","build/app","./src/main.cpp","build/main_part2.o","build/main.o","-lpthread","-o","build/app2","./src/main_part2.cpp","build/main_part2.o","build/main.o","-lpthread","-o","build/app2","./src/main_part2.cpp","build/log.o","-lpthread","-o","build/app2","./src/unit_test.cpp","build/log.o","build/simpletest.o"]},"fileIndex":[["/home/ewanseiha2.odion/iot_starter-1/src/main.cpp",{"uri":{"$mid":1,"fsPath":"/home/ewanseiha2.odion/iot_starter-1/src/main.cpp","path":"/home/ewanseiha2.odion/iot_starter-1/src/main.cpp","scheme":"file"},"configuration":{"defines":[],"standard":"c++17","includePath":["/home/ewanseiha2.odion/iot_starter-1/include"],"forcedInclude":[],"intelliSenseMode":"clang-x64","compilerPath":"/usr/bin/clang++","compilerArgs":["-lpthread","-o","build/app","./src/main.cpp","build/log.o"],"windowsSdkVersion":""},"compileCommand":{"command":"clang++ -std=c++17  -I./include  -lpthread -o build/app ./src/main.cpp build/log.o","directory":"/home/ewanseiha2.odion/iot_starter-1","file":"/home/ewanseiha2.odion/iot_starter-1/src/main.cpp"}}],["/home/ewanseiha2.odion/iot_starter-1/src/main_part2.cpp",{"uri":{"$mid":1,"fsPath":"/home/ewanseiha2.odion/iot_starter-1/src/main_part2.cpp","path":"/home/ewanseiha2.odion/iot_starter-1/src/main_part2.cpp","scheme":"file"},"configuration":{"defines":[],"standard":"c++17","includePath":["/home/ewanseiha2.odion/iot_starter-1/include"],"forcedInclude":[],"intelliSenseMode":"clang-x64","compilerPath":"/usr/bin/clang++","compilerArgs":["-lpthread","-o","build/app2","./src/main_part2.cpp","build/log.o"],"windowsSdkVersion":""},"compileCommand":{"command":"clang++ -std=c++17  -I./include  -lpthread -o build/app2 ./src/main_part2.cpp build/log.o","directory":"/home/ewanseiha2.odion/iot_starter-1","file":"/home/ewanseiha2.odion/iot_starter-1/src/main_part2.cpp"}}],["/home/ewanseiha2.odion/iot_starter-1/src/log.cpp",{"uri":{"$mid":1,"fsPath":"/home/ewanseiha2.odion/iot_starter-1/src/log.cpp","path":"/home/ewanseiha2.odion/iot_starter-1/src/log.cpp","scheme":"file"},"configuration":{"defines":[],"standard":"c++17","includePath":["/home/ewanseiha2.odion/iot_starter-1/include"],"forcedInclude":[],"intelliSenseMode":"clang-x64","compilerPath":"/usr/bin/clang++","compilerArgs":["-c","-o","build/log.o"],"windowsSdkVersion":""},"compileCommand":{"command":"clang++ -c -std=c++17  -I./include  ./src/log.cpp -o build/log.o","directory":"/home/ewanseiha2.odion/iot_starter-1","file":"/home/ewanseiha2.odion/iot_starter-1/src/log.cpp"}}],["/home/ewanseiha2.odion/iot_starter-1/src/unit_test.cpp",{"uri":{"$mid":1,"fsPath":"/home/ewanseiha2.odion/iot_starter-1/src/unit_test.cpp","path":"/home/ewanseiha2.odion/iot_starter-1/src/unit_test.cpp","scheme":"file"},"configuration":{"defines":[],"standard":"c++17","includePath":["/home/ewanseiha2.odion/iot_starter-1/include"],"forcedInclude":[],"intelliSenseMode":"clang-x64","compilerPath":"/usr/bin/clang++","compilerArgs":["-lpthread","-o","build/app2","./src/unit_test.cpp","build/log.o","build/simpletest.o"],"windowsSdkVersion":""},"compileCommand":{"command":"clang++ -std=c++17  -I./include  -lpthread -o build/app2 ./src/unit_test.cpp build/log.o build/simpletest.o","directory":"/home/ewanseiha2.odion/iot_starter-1","file":"/home/ewanseiha2.odion/iot_starter-1/src/unit_test.cpp"}}]]}}
\ No newline at end of file
diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log
new file mode 100644
index 0000000..5cd357d
--- /dev/null
+++ b/.vscode/dryrun.log
@@ -0,0 +1,7 @@
+make --dry-run --keep-going --print-directory
+make: Entering directory '/home/ewanseiha2.odion/iot_starter-1'
+ 
+make: Nothing to be done for 'all'.
+ 
+make: Leaving directory '/home/ewanseiha2.odion/iot_starter-1'
+ 
diff --git a/README.md b/README.md
index 54b5031..5bbc6c5 100644
--- a/README.md
+++ b/README.md
@@ -1,93 +1,84 @@
-# iot-starter-0
 
 
+The first task I worked with function, it was divided into three part
+In the first part I implemented a function "std::string line(std::string message);" that returns a log line'd message 
+"line("[ERROR]: Invalid operation")
+// => "Invalid operation""
+I added this line function in the main_part source file and then included some tests for the line fuction 
+    std::string logMessage = "[ERROR]: Invalid Operation";
+    std::string logMessage_2 = "[INFO]: This is a log message";
+After i saved changes ,built and ran the program.
+As i encountered minor issues i fixed it. At the end It  printed "Invalid operation" in the terminal.
+In the second part of the task I implemented the function "std::string level(std::string message);" that returns a log line's log level whuch should return  
+"level("[ERROR]: Invalid operation")
+// => "ERROR""
+Once again I added the line function in the main_part source file and include some tests for the level function then saved the changes.
 
-## Getting started
+Build and run the program, then fixed any issues.Once the program builds successfully, I ran it to verify that the level function behaves as expected. It should print "ERROR" to the console in uppercase.
 
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
 
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
 
-## Add your files
+For the third part, I implement was std::string reformat(std::string ) that reformat the log line, puttting the message first before and the log level after it in parentheses.
+firstly, i added the 'reformat' function to the main_part source file  and included some tests for the reformat function.Saved the changes followed up by building and run the program. If there were any issues, fixed them.
 
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+Once the program builds successfully,I ran it to verify that the reformat function behaves as expected. It should print success to the terminal.
 
-```
-cd existing_repo
-git remote add origin https://gitlab.uwe.ac.uk/eo2-odion/iot-starter-0.git
-git branch -M main
-git push -uf origin main
-```
+Below is a screenshot of the expected output
+![alt text](<screenshots/task 1.png>)
 
-## Integrate with your tools
 
-- [ ] [Set up project integrations](https://gitlab.uwe.ac.uk/eo2-odion/iot-starter-0/-/settings/integrations)
+For the second task I was expected to develop a simple class for process log files, intergrating the operations from task 1. For this i implemented  new files namely 'log.hpp' and 'log.cpp'
 
-## Collaborate with your team
+Firstly, I began by creating two new files, log.hpp and log.cpp, where the header file contains the interface for the logging API and the source file contains its implementation. Ensuring the header file starts with #pragma once to prevent multiple inclusions. Modifying the makefile to include these new source files by adding them to the CPP_SOURCES variable.
 
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
+ In the log.hpp file,I defined the Log class with methods for creating a log, navigating to the next message, retrieving the current line and level, and reformatting the log message. Unlike before, these methods don't take any arguments. Implementing each method in log.cpp using the Log::method_name(arguments) syntax.
 
-## Test and Deploy
+ The constructor Log() initializes the log object, while the destructor ~Log() closes the log file if it was opened successfully with create_log(). Implementing these appropriately in the log.cpp.
 
-Use the built-in continuous integration in GitLab.
+ I made use of file handling libraries such as <iostream> and <fstream> for C++ streams or <stdio.h> for C file handling to open and manipulate log files. The create_log() method opens the specified log file, returning true if successful and false otherwise.
 
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
+I implemented each method defined in the Log class, ensuring that they perform their intended functions, such as moving to the next message, retrieving the line and level, and reformatting the log message.
 
-***
+I created a new main_part2.cpp file to test the implementation of the Log class.I used this file to instantiate a Log object, call its methods, and verify that they work as expected.
 
-# Editing this README
+I added a new target in the makefile to build the app2 executable for testing the Log class implementation. Ensured that this rule compiles the main_part2.cpp file along with other necessary source files.
 
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
+I utilized a provided example log file (log.in) to test the implementation of the Log class and ensure that it handles log files correctly.
 
-## Suggestions for a good README
 
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
+Below is a screenshot of the expected output for this task
+![alt text](screenshots/task2.png)
 
-## Name
-Choose a self-explaining name for your project.
 
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
+For the third task I was expected to develop unit tests to validate the Log class implementation. For this i was expected to use the framework simpletest and add simpletest as a submodule to my git repo.
+Firstly, I added Simpletest as a submodule to your git repository using the command:
 
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
+csharp
+Copy code
+git submodule add repo-url
+Replacing repo-url with the URL of the Simpletest repository.
 
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
+I created a new file, simpletest_log.cpp, where I write unit tests for the Log class. Use the provided example as a template to structure the tests.
 
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
+I included the log.hpp header file and the simpletest.h header file in the test_log.cpp file.
 
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
+I define test groups as an array of character pointers. Each group represents a set of related tests.
 
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
+Wrote test functions using the DEFINE_TEST_G macro. Each test function should have a unique name and belong to a test group.
 
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
+ Inside each test function, I instantiate the Log class, perform operations, and use TEST_MESSAGE macro to assert conditions and report test results.
 
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
+I wrote the main function to execute all test groups. Iterate through each group, execute its tests, and aggregate the test results.
+
+I modified the makefile to include a new rule for building the tests. This rule should compile the test_log.cpp file along with the log.cpp and any other necessary source files.
+
+ Once everything was set up, I built and run the tests using the appropriate commands specified in the makefile. Ensure that all tests pass successfully.
+
+
+Below is a screenshot of the expected output for this task
+![alt text](screenshots/task3.png)
 
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
 
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
 
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
 
-## License
-For open source projects, say how it is licensed.
 
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
diff --git a/build/app b/build/app
new file mode 100644
index 0000000..e69de29
diff --git a/build/app2 b/build/app2
new file mode 100644
index 0000000..e69de29
diff --git a/build/log.o b/build/log.o
new file mode 100644
index 0000000..e69de29
diff --git a/build/main.o b/build/main.o
new file mode 100644
index 0000000..e69de29
diff --git a/build/main_part2.o b/build/main_part2.o
new file mode 100644
index 0000000..e69de29
diff --git a/build/simpletest.o b/build/simpletest.o
new file mode 100644
index 0000000..e69de29
diff --git a/build/test b/build/test
new file mode 100644
index 0000000..e69de29
diff --git a/iot-starter-0 b/iot-starter-0
new file mode 160000
index 0000000..f3dfeba
--- /dev/null
+++ b/iot-starter-0
@@ -0,0 +1 @@
+Subproject commit f3dfebab3c8e817ed2648a051e07f629739117b3
diff --git a/iot-starter-0-1 b/iot-starter-0-1
new file mode 160000
index 0000000..f3dfeba
--- /dev/null
+++ b/iot-starter-0-1
@@ -0,0 +1 @@
+Subproject commit f3dfebab3c8e817ed2648a051e07f629739117b3
diff --git a/log.in b/log.in
new file mode 100644
index 0000000..86571c0
--- /dev/null
+++ b/log.in
@@ -0,0 +1,2 @@
+[ERROR]: Invalid operation
+[INFO]: Operation completed
\ No newline at end of file
diff --git a/makeFile b/makeFile
new file mode 100644
index 0000000..7dc5177
--- /dev/null
+++ b/makeFile
@@ -0,0 +1,75 @@
+
+
+CC = clang++
+LD = clang++
+CPPFLAGS = -std=c++17  -I./include 
+LDFLAGS = -lpthread
+ROOTDIR = ./
+CP = cp
+ECHO = echo
+BUILD_DIR = build
+CPP_SOURCES = ./src/log.cpp ./simpletest/simpletest.cpp
+CPP_HEADERS = ./src/log.hpp ./simpletest/simpletest.h
+C_SOURCES = 
+APP = app
+APP2 = app2
+TEST = test
+
+
+
+OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
+
+vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
+vpath %.cpp src
+
+# OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
+# vpath %.c $(sort $(dir $(C_SOURCES)))
+
+$(BUILD_DIR)/%.o: %.cpp $(CPP_HEADERS) Makefile | $(BUILD_DIR)
+	$(ECHO) compiling $<
+	$(CC) -c $(CPPFLAGS) $< -o $@
+
+$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
+	$(ECHO) compiling $<
+	clang -c $(CFLAGS) $< -o $@
+
+all: $(BUILD_DIR) $(BUILD_DIR)/$(APP)  $(BUILD_DIR)/$(APP2) $(BUILD_DIR)/$(TEST) 
+
+run: $(BUILD_DIR)/$(APP) $(BUILD_DIR)/$(APP2) $(BUILD_DIR)/$(TEST) 
+	$(BUILD_DIR)/$(APP)
+	$(BUILD_DIR)/$(APP2)
+	$(BUILD_DIR)/$(TEST) 
+
+$(BUILD_DIR)/$(APP): main.cpp $(OBJECTS) Makefile
+	$(ECHO) linking $<
+	$(CC) $(CPPFLAGS) $(LDFLAGS) -o $@ ./src/main.cpp $(OBJECTS)
+	$(ECHO) success
+
+$(BUILD_DIR)/$(APP2): main_part2.cpp $(OBJECTS) Makefile
+	$(ECHO) linking $<
+	$(CC) $(CPPFLAGS) $(LDFLAGS) -o $@ ./src/main_part2.cpp $(OBJECTS)
+	$(ECHO) success
+
+$(BUILD_DIR)/$(TEST): unit_test.cpp $(OBJECTS) Makefile
+	$(ECHO) linking $<
+	$(CC) $(CPPFLAGS) $(LDFLAGS) -o $@ ./src/unit_test.cpp $(OBJECTS)
+	$(ECHO) success
+
+
+$(BUILD_DIR):
+	mkdir $@
+
+#######################################
+# Clean up
+#######################################
+clean:
+	-rm -fR $(BUILD_DIR)/$(APP) $(BUILD_DIR)/*.o
+
+#######################################
+# Dependencies
+#######################################
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+.PHONY: clean all
+
+
diff --git a/screenshots/task 1.png b/screenshots/task 1.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f6bc9bb7bee729c722fa2efcc414f71e7a66cee
GIT binary patch
literal 12093
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
S6=z^zVDNPHb6Mw<&;$T+ICx3`

literal 0
HcmV?d00001

diff --git a/screenshots/task2.png b/screenshots/task2.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b86dd5f0b4b04c74e14c9f592afcf81e11bb82a
GIT binary patch
literal 3388
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%0Af{Uhgt+Nvah
zb4+(rW^KLJ)BNV|->pY>U+T5|dgJEG;|ZG#Dhnl^A3j;~H10^kBtx;|`uC4aS>LLc
zmw#4vx!`pE)Op(88h(AjTb_SjuD)^pwf69JbEoOZh8yjZ%&b~d!&~!n$FpBIWnA+^
z+4cqP`qzD}Pd-X`-qcBR!nF){eyZ}D@=ZVL(vJNmn@<<lFO+%^8+giKdeg&6??3G0
ze5v>5)AyFuPpc0xB(JxZJ*%&9w{`CQRk5esv@coq&3(anfI$+o{8D=KpRwM3A45q)
R$Qw{Y-P6_2Wt~$(699IiM6>_^

literal 0
HcmV?d00001

diff --git a/screenshots/task3.png b/screenshots/task3.png
new file mode 100644
index 0000000000000000000000000000000000000000..7c338a1eaca723ebdd787ee49679c538861e17ca
GIT binary patch
literal 13006
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%0Df^zc26ejTbu$j?83W
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
BOLYJM

literal 0
HcmV?d00001

diff --git a/src/log.cpp b/src/log.cpp
new file mode 100644
index 0000000..9a268a9
--- /dev/null
+++ b/src/log.cpp
@@ -0,0 +1,86 @@
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <fstream>
+#include "log.hpp"
+
+Log::Log(){
+
+}
+Log::~Log(){
+
+}
+
+std::string Log::line(std::string message) {
+    size_t pos = message.find(':');
+    if (pos != std::string::npos) {
+        return message.substr(pos + 2);
+    } else {
+        return message;
+    }
+}
+
+
+std::string Log::level(std::string message) {
+    std::string level;
+    bool foundStart = false;
+
+    for (char& c : message) {
+        if (c == '[') {
+            foundStart = true;
+            continue;
+        }
+
+        if (c == ']' && foundStart) {
+            break;
+        }
+
+        if (foundStart) {
+            level += c;
+        }
+    }
+
+    return level;
+}
+std::string Log::reformat(std::string message) {
+    // Find the position of ':'
+    size_t colonPos = message.find(':');
+
+    if (colonPos != std::string::npos) {
+        // Extract the info between '[' and ']'
+        size_t bracketPos = message.find('[');
+        if (bracketPos != std::string::npos) {
+            std::string info = message.substr(bracketPos + 1, colonPos - bracketPos - 1);
+
+            // Remove trailing square brackets if present
+            size_t bracketEndPos = info.find(']');
+            if (bracketEndPos != std::string::npos) {
+                info.erase(bracketEndPos, 1);
+            }
+
+            // Extract the message after ':'
+            std::string msg = message.substr(colonPos + 2); // Skipping ': ' characters
+
+            // Construct the reformatted message
+            return msg + " (" + info + ")";
+        }
+    }
+
+    // Return original message if format is not as expected
+    return message;
+}
+
+bool Log::create_log(std::string filename) {
+        std::ifstream file(filename);
+        return file.good();
+    }
+
+bool Log::next(std::ifstream& file) {
+        std::string line;
+        while (std::getline(file, line)) {
+            if (!line.empty()) {
+                return true;
+            }
+        }
+        return false;
+    }
diff --git a/src/log.hpp b/src/log.hpp
new file mode 100644
index 0000000..fce7344
--- /dev/null
+++ b/src/log.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <string> 
+
+class Log {
+private:
+public:
+    Log();
+    ~Log();
+    bool create_log(std::string filename);
+    bool next(std::ifstream& file);
+    std::string line(std::string message);
+    std::string level(std::string message);
+    std::string reformat(std::string message);
+};
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..b007956
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,34 @@
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <fstream>
+#include "log.hpp"
+
+       
+
+int main() {
+
+    Log logger;
+
+    bool create = logger.create_log("log.in");
+    std::cout << create << std::endl;
+
+    std::ifstream file("log.in");
+
+    bool nxt = logger.next(file);
+    std::cout << nxt << std::endl;
+
+    std::string logMessage = "[ERROR]: Invalid Operation";
+    std::string logMessage_2 = "[INFO]: This is a log message";
+
+    std::string logLine = logger.line(logMessage);
+    std::cout << logLine << std::endl;
+
+    std::string logLine_2 = logger.level(logMessage);
+    std::cout << logLine_2 << std::endl;
+
+    std::string logLine_3 = logger.reformat(logMessage);
+    std::cout << logLine_3 << std::endl;
+
+    return 0;
+}
diff --git a/src/main_part2.cpp b/src/main_part2.cpp
new file mode 100644
index 0000000..b007956
--- /dev/null
+++ b/src/main_part2.cpp
@@ -0,0 +1,34 @@
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <fstream>
+#include "log.hpp"
+
+       
+
+int main() {
+
+    Log logger;
+
+    bool create = logger.create_log("log.in");
+    std::cout << create << std::endl;
+
+    std::ifstream file("log.in");
+
+    bool nxt = logger.next(file);
+    std::cout << nxt << std::endl;
+
+    std::string logMessage = "[ERROR]: Invalid Operation";
+    std::string logMessage_2 = "[INFO]: This is a log message";
+
+    std::string logLine = logger.line(logMessage);
+    std::cout << logLine << std::endl;
+
+    std::string logLine_2 = logger.level(logMessage);
+    std::cout << logLine_2 << std::endl;
+
+    std::string logLine_3 = logger.reformat(logMessage);
+    std::cout << logLine_3 << std::endl;
+
+    return 0;
+}
diff --git a/src/simpletest.cpp b/src/simpletest.cpp
new file mode 100644
index 0000000..85abbb4
--- /dev/null
+++ b/src/simpletest.cpp
@@ -0,0 +1,391 @@
+#include "simpletest.h"
+#include <stdio.h>
+#include <string.h>
+#include <cstdint>
+#include <stdarg.h>
+#include <time.h>
+
+//---------------------------------------------------------------------------------
+// statics
+//---------------------------------------------------------------------------------
+void DefaultPrint(char const* string) { printf("%s", string); }
+
+TestFixture* TestFixture::ourFirstTest;
+TestFixture* TestFixture::ourLastTest;
+thread_local TestFixture* TestFixture::ourCurrentTest;
+void (*TestFixture::Print)(char const* string) = DefaultPrint;
+
+//---------------------------------------------------------------------------------
+// Standard type printers
+//---------------------------------------------------------------------------------
+TempString::TempString(const TempString& other)
+{
+	if (other.myTextPointer == other.myTextBuffer)
+	{
+		strcpy(myTextBuffer, other.myTextBuffer);
+		myTextPointer = myTextBuffer;
+	}
+	else
+	{
+		myTextPointer = other.myTextPointer;
+	}
+}
+TempString TypeToString(int value)
+{
+	TempString tempString;
+	if (TestFixture::GetCurrentTest()->GetPrintMethod() == TestFixture::PrintHexadecimal)
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%08X", value);
+	else
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "%d", value);
+	return tempString;
+}
+TempString TypeToString(unsigned int value)
+{
+	TempString tempString;
+	if (TestFixture::GetCurrentTest()->GetPrintMethod() == TestFixture::PrintHexadecimal)
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%08X", value);
+	else
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "%u", value);
+	return tempString;
+}
+TempString TypeToString(long value)
+{
+	TempString tempString;
+	if (TestFixture::GetCurrentTest()->GetPrintMethod() == TestFixture::PrintHexadecimal)
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%016lX", value);
+	else
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "%ld", value);
+	return tempString;
+}
+TempString TypeToString(unsigned long value)
+{
+	TempString tempString;
+	if (TestFixture::GetCurrentTest()->GetPrintMethod() == TestFixture::PrintHexadecimal)
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%016lX", value);
+	else
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "%lu", value);
+	return tempString;
+}
+TempString TypeToString(long long value)
+{
+	TempString tempString;
+	if (TestFixture::GetCurrentTest()->GetPrintMethod() == TestFixture::PrintHexadecimal)
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%016llX", value);
+	else
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "%lld", value);
+	return tempString;
+}
+TempString TypeToString(unsigned long long value)
+{
+	TempString tempString;
+	if (TestFixture::GetCurrentTest()->GetPrintMethod() == TestFixture::PrintHexadecimal)
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%016llX", value);
+	else
+		snprintf(tempString.myTextBuffer, STRING_LENGTH, "%llu", value);
+	return tempString;
+}
+TempString TypeToString(float value)
+{
+	TempString tempString;
+	snprintf(tempString.myTextBuffer, STRING_LENGTH, "%.16g", value);
+	return tempString;
+}
+TempString TypeToString(double value)
+{
+	TempString tempString;
+	snprintf(tempString.myTextBuffer, STRING_LENGTH, "%.16g", value);
+	return tempString;
+}
+TempString TypeToString(bool value)
+{
+	return TempString(value ? "true" : "false");
+}
+TempString TypeToString(char const* value)
+{
+	return TempString(value ? value : "(nullptr)");
+}
+TempString TypeToString(void const* value)
+{
+	if (value == nullptr)
+		return TempString("(nullptr)");
+	TempString tempString;
+	snprintf(tempString.myTextBuffer, STRING_LENGTH, "0x%p", value);
+	return tempString;
+}
+TempString TypeToString(void const* value, char const* extra)
+{
+	if (value == nullptr)
+		return TempString("(nullptr)");
+	TempString tempString;
+	snprintf(tempString.myTextBuffer, STRING_LENGTH, "(0x%p) %s", value, extra);
+	return tempString;
+}
+
+//---------------------------------------------------------------------------------
+// Fixture implementation
+//---------------------------------------------------------------------------------
+TestFixture::TestFixture()
+	: myNextTest(nullptr)
+	, myNextError(nullptr)
+	, myNumTestsChecked(0)
+	, myNumErrors(0)
+	, myPrintMethod(PrintDefault)
+{
+	// global link list registration, add in order of discovery
+	if (ourFirstTest == nullptr)
+	{
+		ourFirstTest = this;
+		ourLastTest = this;
+	}
+	else
+	{
+		ourLastTest->myNextTest = this;
+		ourLastTest = this;
+	}
+}
+//---------------------------------------------------------------------------------
+bool TestFixture::ExecuteTest()
+{
+	myNumTestsChecked = myNumErrors = 0;
+	myNextError = (TestError*)myMessageSpace;
+
+	TestFixture* lastCurrent = ourCurrentTest;
+	ourCurrentTest = this;
+	Setup();
+	RunTest();
+	TearDown();
+	ourCurrentTest = lastCurrent;
+
+	return myNumErrors == 0;
+}
+//---------------------------------------------------------------------------------
+// Utility to print a part of a string to show where the error is and put elipse
+// where the string is truncated
+//---------------------------------------------------------------------------------
+static void locCopyStringWithElipse(char dest[STRING_EQ_PRINT_LENGTH], char const* string, size_t offset = 0)
+{
+	char const* start = string + offset - STRING_EQ_PRINT_LENGTH / 2;
+	if (start < string)
+		start = string;
+
+	int i = 0;
+	for (; i < STRING_EQ_PRINT_LENGTH - 1 && start[i]; ++i)
+	{
+		if (i < 3 && start > string)
+			dest[i] = '.';
+		else if (start[i] == '\r' || start[i] == '\n' || start[i] == '\t')
+			dest[i] = '\\'; // simply replace this with '\', we're just aiming for a general idea not an exact representation
+		else
+			dest[i] = start[i];
+	}
+
+	dest[i] = 0;
+
+	if (i == STRING_EQ_PRINT_LENGTH - 1 && start[i])
+	{
+		dest[i - 1] = '.';
+		dest[i - 2] = '.';
+		dest[i - 3] = '.';
+	}
+}
+//---------------------------------------------------------------------------------
+// Instead of just check for error and printing the string, try go be smart about
+// how the information is written out:
+// ... quick brown fox jumps over ...
+//                      ^
+// ... quick brown fox jamps over ...
+//---------------------------------------------------------------------------------
+bool TestFixture::TestStrings(char const* left, char const* right, char const* prefix, char const* condition)
+{
+	AddTest();
+	if (left == right)
+	{
+		return true;
+	}
+
+	char leftLine[STRING_EQ_PRINT_LENGTH];
+	char rightLine[STRING_EQ_PRINT_LENGTH];
+	char locationLine[STRING_EQ_PRINT_LENGTH];
+
+	if (left == nullptr || right == nullptr)
+	{
+		locationLine[0] = '^';
+		locationLine[1] = 0;
+		if (left == nullptr)
+		{
+			strcpy(leftLine, "nullptr");
+			locCopyStringWithElipse(rightLine, right);
+		}
+		else
+		{
+			locCopyStringWithElipse(leftLine, left);
+			strcpy(rightLine, "nullptr");
+		}
+	}
+	else
+	{
+		char const* testLeft = left;
+		char const* testRight = right;
+
+		int offset = 0;
+		for (; *testLeft && *testRight; ++offset, ++testLeft, ++testRight)
+		{
+			if (*testLeft != *testRight)
+				break;
+		}
+
+		// reached the end of both strings, so they're the same
+		if (!*testLeft && !*testRight)
+			return true;
+
+		locCopyStringWithElipse(leftLine, left, offset);
+		locCopyStringWithElipse(rightLine, right, offset);
+
+		if (offset > STRING_EQ_PRINT_LENGTH / 2)
+			offset = STRING_EQ_PRINT_LENGTH / 2;
+
+		memset(locationLine, ' ', offset);
+		locationLine[offset] = '^';
+		locationLine[offset + 1] = 0;
+	}
+
+	AddError();
+	LogMessage(prefix, condition, leftLine, locationLine, rightLine);
+	return false;
+}
+//---------------------------------------------------------------------------------
+// Write error into current error object and advance pointer if there's still enough space
+//---------------------------------------------------------------------------------
+void TestFixture::LogMessage(char const* string, ...)
+{
+	uintptr_t spaceLeft = (myMessageSpace + MESSAGE_SPACE) - (char*)myNextError;
+
+	if (spaceLeft == 0)
+	{
+		return;
+	}
+
+	spaceLeft -= sizeof(TestError);
+
+	va_list args;
+
+	va_start(args, string);
+
+	int printedChars = vsnprintf(myNextError->message, spaceLeft, string, args);
+
+	va_end(args);
+
+	// if there isn't a reasonable amount of space left then just advance to end and stop printing errors
+	if (printedChars < (int)(spaceLeft - sizeof(TestError) - 64))
+	{
+		uintptr_t nextOffset = (uintptr_t(myNextError->message) + printedChars + sizeof(TestError) * 2 - 1);
+		nextOffset -= nextOffset % alignof(TestError);
+		TestError* next = (TestError*)(nextOffset);
+		myNextError->next = next;
+	}
+	else
+	{
+		myNextError->next = (TestError*)(myMessageSpace + MESSAGE_SPACE);
+	}
+
+	myNextError = myNextError->next;
+}
+TestFixture const* TestFixture::LinkTest(TestFixture* test)
+{
+	test->myNextTest = TestFixture::ourFirstTest;
+	TestFixture::ourFirstTest = test;
+	return test;
+}
+
+//---------------------------------------------------------------------------------
+// Standard / Example runners
+//---------------------------------------------------------------------------------
+static bool locExecuteTest(TestFixture* test, TestFixture::OutputMode output)
+{
+	clock_t start = 0;
+	if (output == TestFixture::Verbose)
+	{
+		TestFixture::Printf("Running [%s/%s]", test->TestGroup(), test->TestName());
+		start = clock();
+	}
+
+	if (test->ExecuteTest())
+	{
+		if (output == TestFixture::Verbose)
+		{
+			clock_t end = clock();
+			TestFixture::Printf(": Passed %d out of %d tests in %g seconds\n", test->NumTests(), test->NumTests(), float(end - start) / (float)CLOCKS_PER_SEC);
+		}
+		return true;
+	}
+
+	if (output != TestFixture::Silent)
+	{
+		if (output != TestFixture::Verbose)
+			TestFixture::Printf("[%s/%s]", test->TestGroup(), test->TestName());
+
+		TestFixture::Printf(": Failed %d out of %d tests\n", test->NumErrors(), test->NumTests());
+
+		for (TestError const* err = test->GetFirstError(), *e = test->GetLastError(); err != e; err = err->next)
+		{
+			TestFixture::Printf("%s\n", err->message);
+		}
+	}
+
+	return false;
+}
+void TestFixture::Printf(char const* string, ...)
+{
+	char tempSpace[4096];
+	va_list args;
+
+	va_start(args, string);
+
+	vsnprintf(tempSpace, sizeof(tempSpace), string, args);
+
+	va_end(args);
+
+	TestFixture::Print(tempSpace);
+}
+bool TestFixture::ExecuteAllTests(char const* groupFilter, char const* nameFilter, OutputMode output)
+{
+	if (output != Silent)
+	{
+		if (groupFilter == nullptr && nameFilter == nullptr)
+			Printf("Running all tests.\n");
+		else if (groupFilter != nullptr && nameFilter == nullptr)
+			Printf("Running all tests in groups [%s].\n", groupFilter);
+		else if (groupFilter == nullptr && nameFilter != nullptr)
+			Printf("Running all tests named [%s].\n", nameFilter);
+		else
+			Printf("Running all tests named [%s/%s].\n", groupFilter, nameFilter);
+	}
+
+	int count = 0;
+	int passes = 0;
+	int fails = 0;
+	bool passed = true;
+	for (auto i = TestFixture::GetFirstTest(); i; i = i->GetNextTest())
+	{
+		bool matchGroup = groupFilter == nullptr || strcmp(groupFilter, i->TestGroup()) == 0;
+		bool matchName = nameFilter == nullptr || strcmp(nameFilter, i->TestName()) == 0;
+		if (matchGroup && matchName)
+		{
+			++count;
+			passed &= locExecuteTest(i, output);
+			passes += i->NumTests();
+			fails += i->NumErrors();
+		}
+	}
+
+	if (output != Silent)
+	{
+		if (count == 0)
+			Printf("Failed to find any tests.\n");
+		else if (passed)
+			Printf("%d Tests finished. All %d assertions are passing.\n", count, passes);
+		else
+			Printf("%d Tests finished, %d of %d assertions failed. Some tests are reporting errors.\n", count, fails, passes);
+	}
+	return passed;
+}
diff --git a/src/simpletest.h b/src/simpletest.h
new file mode 100644
index 0000000..4659561
--- /dev/null
+++ b/src/simpletest.h
@@ -0,0 +1,235 @@
+#pragma once
+
+//---------------------------------------------------------------------------------
+// Config
+//---------------------------------------------------------------------------------
+#if !defined(MESSAGE_SPACE)
+#define MESSAGE_SPACE 10 * 1024 // default 10k of message space is reserved per test
+#endif
+#if !defined(STRING_LENGTH)
+#define STRING_LENGTH 64 // size of temp strings for converting types
+#endif
+#if !defined(STRING_EQ_PRINT_LENGTH)
+#define STRING_EQ_PRINT_LENGTH 80 // max line length to show when comparing two strings
+#endif
+#if !defined(BASE_FIXTURE)
+#define BASE_FIXTURE TestFixture // use TestFixture as the test base class by default
+#endif
+#if !defined(ERROR_ACTION)
+#define ERROR_ACTION // Defined any code to run on error. You can use this to debug break or do anything really
+#endif
+
+//---------------------------------------------------------------------------------
+// Link list of errors build into MESSAGE_SPACE
+//---------------------------------------------------------------------------------
+struct TestError
+{
+	TestError* next;
+	char message[1];
+};
+
+//---------------------------------------------------------------------------------
+// simple converter of basic types to text
+// TODO: Use a global template function for conversion so users can override this
+//---------------------------------------------------------------------------------
+struct TempString
+{
+	TempString() : myTextPointer(myTextBuffer) { myTextBuffer[0] = 0; }
+	TempString(const TempString& other);
+	TempString(char const* string) : myTextPointer(string) {}
+
+	char const* operator*() const { return myTextPointer; }
+
+	char const* myTextPointer;
+	char myTextBuffer[STRING_LENGTH];
+};
+
+TempString TypeToString(int value);
+TempString TypeToString(unsigned int value);
+TempString TypeToString(long value);
+TempString TypeToString(unsigned long value);
+TempString TypeToString(long long value);
+TempString TypeToString(unsigned long long value);
+TempString TypeToString(float value);
+TempString TypeToString(double value);
+TempString TypeToString(bool value);
+TempString TypeToString(char const* value);
+TempString TypeToString(void const* value);
+TempString TypeToString(void const* value, char const* extra);
+
+inline TempString TypeToString(char value) { return TypeToString((int)value); }
+inline TempString TypeToString(unsigned char value) { return TypeToString((unsigned int)value); }
+inline TempString TypeToString(short value) { return TypeToString((int)value); }
+inline TempString TypeToString(unsigned short value) { return TypeToString((unsigned int)value); }
+inline TempString TypeToString(char* value) { return TypeToString((char const*)value); }
+inline TempString TypeToString(void* value) { return TypeToString((void const*)value); }
+
+// if nothing specified then print some memory
+template<typename T>
+TempString TypeToString(T const&) { return TempString(); }
+
+template<typename T>
+TempString TypeToString(T const* pointer)
+{
+	return pointer == nullptr ?
+		TypeToString((void const*)pointer) :
+		TypeToString((void const*)pointer, *TypeToString(*pointer));
+}
+
+template<typename T>
+TempString TypeToString(T* pointer) { return TypeToString((T const*)pointer); }
+
+inline TempString TypeToStringFallback(TempString string, char const* fallback) { return (*string)[0] ?  string : TempString(fallback); }
+
+//---------------------------------------------------------------------------------
+// Test fixture is the core of SimpleTest. It provides fixture behavior, access
+// to registered tests and stores the results of a test run
+// Everything is local here so tests can be multithreaded without any extra work
+//---------------------------------------------------------------------------------
+class TestFixture
+{
+public:
+	TestFixture();
+	virtual ~TestFixture() {};
+
+	virtual bool ExecuteTest();
+
+	virtual char const* TestName() const = 0;
+	virtual char const* TestGroup() const = 0;
+
+	// Reporting used during testing process
+	void AddTest() { ++myNumTestsChecked; }
+	void AddError() { ++myNumErrors; }
+	void LogMessage(char const* string, ...);
+
+	// Custom test for strings to print out where the comparison failed
+	bool TestStrings(char const* left, char const* right, char const* prefix, char const* condition);
+
+	// Stats from execution
+	int NumTests() const { return myNumTestsChecked; }
+	int NumErrors() const { return myNumErrors; }
+
+	// Access to any errrors generated
+	TestError const* GetFirstError() const { return (TestError*)myMessageSpace; }
+	TestError const* GetLastError() const { return myNextError; }
+
+	// Access to registered tests
+	static TestFixture* GetFirstTest() { return ourFirstTest; }
+	static TestFixture* GetCurrentTest() { return ourCurrentTest; }
+	TestFixture* GetNextTest() const { return myNextTest; }
+
+	enum OutputMode
+	{
+		Silent,
+		Normal,
+		Verbose
+	};
+
+	enum PrintMethod
+	{
+		PrintDefault,
+		PrintHexadecimal,
+	};
+
+	PrintMethod GetPrintMethod() const { return myPrintMethod; }
+	void SetPrintMethod(PrintMethod aPrintMethod) { myPrintMethod = aPrintMethod; }
+
+	// Default execution implementation
+	static void (*Print)(char const* string);
+	static void Printf(char const* string, ...);
+
+	static bool ExecuteAllTests(char const* groupFilter = nullptr, char const* nameFilter = nullptr, OutputMode output = Normal);
+	static bool ExecuteAllTests(OutputMode output) { return ExecuteAllTests(nullptr, nullptr, output); }
+
+	static bool ExecuteTestGroup(char const* groupFilter, OutputMode output = Normal) { return ExecuteAllTests(groupFilter, nullptr, output); }
+
+protected:
+	virtual void RunTest() = 0;
+	virtual void Setup() {}
+	virtual void TearDown() {}
+	
+	// Test registration
+	static TestFixture const* LinkTest(TestFixture* test);
+	static TestFixture* ourFirstTest;
+	static TestFixture* ourLastTest;
+
+	TestFixture* myNextTest;
+	TestError* myNextError;
+
+	int myNumTestsChecked;
+	int myNumErrors;
+
+	PrintMethod myPrintMethod;
+
+	char myMessageSpace[MESSAGE_SPACE];
+
+	// allow access to current test outside of main code block
+	static thread_local TestFixture* ourCurrentTest;
+};
+
+//---------------------------------------------------------------------------------
+// Test definition macros
+//---------------------------------------------------------------------------------
+#define DEFINE_TEST_FULL(name, group, fixture) \
+struct TOK(group, name) final : public fixture { \
+	char const* TestName() const override { return #name; } \
+	char const* TestGroup() const override { return #group; } \
+	void RunTest() override; \
+} TOK(TOK(group, name), Instance); \
+void TOK(group, name)::RunTest()
+
+#define DEFINE_TEST(name) DEFINE_TEST_FULL(name, Global, BASE_FIXTURE)
+#define DEFINE_TEST_G(name, group) DEFINE_TEST_FULL(name, group, BASE_FIXTURE)
+#define DEFINE_TEST_F(name, fixture) DEFINE_TEST_FULL(name, Global, fixture)
+#define DEFINE_TEST_GF(name, group, fixture) DEFINE_TEST_FULL(name, group, fixture)
+
+//---------------------------------------------------------------------------------
+// Utils
+//---------------------------------------------------------------------------------
+template <typename T>
+T TestDifference(T const& a, T const& b) { return a > b ? a - b : b - a; }
+
+// why are these still needed?
+#define STR2(x) #x
+#define STR(x) STR2(x)
+
+#define TOK2(a, b) a ## b
+#define TOK(a, b) TOK2(a, b)
+
+//---------------------------------------------------------------------------------
+// Error reporting and setup, don't call directly
+//---------------------------------------------------------------------------------
+#define TEST_TYPE_TO_STRING(var, arg) *TypeToStringFallback(TypeToString(var), STR(arg))
+#define TEST_ERROR_PREFIX_ __FILE__ "(" STR(__LINE__) "): Condition [%s] Failed. "
+#define TEST_ERROR_(message, ...) do { TestFixture* __fx = TestFixture::GetCurrentTest(); __fx->AddError(); __fx->LogMessage(TEST_ERROR_PREFIX_ message, ##__VA_ARGS__); ERROR_ACTION; } while(0)
+#define TEST_BEGIN_(a) do { auto const& test_value_ = a
+#define TEST_CHECK_(cond, condtext, message, ...) do { TestFixture::GetCurrentTest()->AddTest(); if (!(cond)) TEST_ERROR_(message, condtext, ##__VA_ARGS__); } while(0)
+#define TEST_END_ } while(0)
+
+//---------------------------------------------------------------------------------
+// Tests
+//
+// Note: Value caching is only enabled on left hand side. This splits the difference
+// between preventing side effects (i.e. x++ double incrementing) and allowing the
+// compiler to infer values (i.e. TEST_EQ(unsigned(1), 1) will try to cache 1 as an int then omit a compile warning).
+// This means that the right hand side will get evaluated multiple times, so please avoid
+// expressions like: TEST_EQ(a++, b++) as they won't work. Tests should always be written
+// as following:
+// TEST_EQ(expression, constant)
+//---------------------------------------------------------------------------------
+#define TEST_OPERATOR(a, b, op1, op2) TEST_BEGIN_(a); TEST_CHECK_((test_value_) op1 (b), STR(a) " " STR(op1) " " STR(b), "'%s' " STR(op2) " '%s'", TEST_TYPE_TO_STRING(test_value_, a), TEST_TYPE_TO_STRING(b, b)); TEST_END_
+
+#define TEST(cond) TEST_EQ(cond, true)
+#define TEST_FAIL(cond) TEST_EQ(cond, false)
+
+#define TEST_EQ(a, b) TEST_OPERATOR(a, b, ==, !=)
+#define TEST_NEQ(a, b) TEST_OPERATOR(a, b, !=, ==)
+#define TEST_GREATER(a, b) TEST_OPERATOR(a, b, >, <=)
+#define TEST_GREATER_EQUAL(a, b) TEST_OPERATOR(a, b, >=, <)
+#define TEST_LESS(a, b) TEST_OPERATOR(a, b, <, >=)
+#define TEST_LESS_EQUAL(a, b) TEST_OPERATOR(a, b, <=, >)
+
+#define TEST_STR_EQ(a, b) do { if(!TestFixture::GetCurrentTest()->TestStrings(a, b, TEST_ERROR_PREFIX_ "\n%s\n%s\n%s", STR(a) " == " STR(b))) { ERROR_ACTION; } } while(0)
+#define TEST_CLOSE(a, b, eps) TEST_BEGIN_(TestDifference(a, b)); TEST_CHECK_(test_value_ <= eps, STR(a) " Close to " STR(b), "Difference of %s is greater than expected amount of " STR(eps) " when comparing %s and %s", TEST_TYPE_TO_STRING(test_value_, TestDifference(a, b)), TEST_TYPE_TO_STRING(a, a), TEST_TYPE_TO_STRING(b, b)); TEST_END_
+#define TEST_DIFFERS(a, b, eps) TEST_BEGIN_(TestDifference(a, b)); TEST_CHECK_(test_value_ >= eps, STR(a) " Differs from " STR(b), "Difference of %s is less than expected amount of " STR(eps) " when comparing %s and %s", TEST_TYPE_TO_STRING(test_value_, TestDifference(a, b)), TEST_TYPE_TO_STRING(a, a), TEST_TYPE_TO_STRING(b, b)); TEST_END_
+#define TEST_MESSAGE(cond, message, ...) TEST_BEGIN_(cond); TEST_CHECK_(test_value_, STR(cond), message, ##__VA_ARGS__); TEST_END_
diff --git a/src/unit_test.cpp b/src/unit_test.cpp
new file mode 100644
index 0000000..4d21a93
--- /dev/null
+++ b/src/unit_test.cpp
@@ -0,0 +1,34 @@
+#include "log.hpp"
+#include "simpletest.h"
+#include <iostream>
+#include <fstream>
+
+DEFINE_TEST_G(Log, LogTests) {
+    Log log;
+    bool success = log.create_log("./log.in");
+    TEST_MESSAGE(success == true, "Failed to open log!!!!");
+    std::cout << success << std::endl;
+
+    // Open the file before passing it to the next function
+    std::ifstream file("./log.in");
+    success = log.next(file); // Pass the file object to the next function
+    std::cout  << success << std::endl;
+    TEST_MESSAGE(success == true, "Failed to read log!!!!");
+
+    std::string line = log.line("[ERROR]: Invalid operation");
+    std::cout  << line << std::endl;
+    TEST_MESSAGE(line.compare(" Invalid operation") == 0, "Expecting Invalid operation!!!!");
+
+    std::string level = log.level("[ERROR]: Invalid operation");
+    std::cout << level << std::endl;
+    TEST_MESSAGE(level.compare("ERROR") == 0, "Expecting ERROR level!!!!");
+
+    std::string reformatted = log.reformat("[INFO]: This is a log message");
+    std::cout << reformatted << std::endl;
+    TEST_MESSAGE(reformatted.compare("This is a log message (INFO)") == 0, "Expecting reformatted message!!!!");
+}
+
+int main() {
+    TestFixture::ExecuteTestGroup("LogTests", TestFixture::Verbose);
+    return 0;
+}
\ No newline at end of file
-- 
GitLab