diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2da357dc015d8f927476603fa55ad5935987ae2d..6f35ada2ca5f210505520aab5288777ee3d538d9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,14 +1,14 @@
 image: rikorose/gcc-cmake
 
+stages:
+  - build
+  - test
+
 before_script:
-  - apt-get update -qq && apt-get install -y -qq cppcheck vera++ clang-tidy-4.0
   - g++ --version
-  - cppcheck --version
-  - vera++ --version
-  - clang-tidy-4.0 --version
-  - cp ci/vera.profile /usr/lib/vera++/profiles/custom
 
 build:
+  stage: build
   script:
     - cmake . -DCMAKE_CXX_FLAGS="-Werror"
     - make -j4
@@ -16,14 +16,41 @@ build:
     - cmake . -DCMAKE_CXX_FLAGS="-Wall -Wextra" # Build again, but with more warnings
     - make -j4
 
+tests:
+  stage: test
+  variables:
+    GIT_SUBMODULE_STRATEGY: normal
+  script:
+    - cmake .
+    - make tests -j4
+    - ./tests --use-colour yes
+  after_script:
+    - ./tests -r junit -o junit.xml
+  artifacts:
+    reports:
+      junit: junit.xml
+
 cppcheck:
+  stage: build
+  before_script:
+    - apt-get update -qq && apt-get install -y -qq cppcheck
+    - cppcheck --version
   script:
     - bash -x ci/cppcheck.sh
 
 vera:
+  stage: build
+  before_script:
+    - apt-get update -qq && apt-get install -y -qq vera++
+    - vera++ --version
+    - cp ci/vera.profile /usr/lib/vera++/profiles/custom
   script:
     - bash -x ci/vera.sh
 
 clang-tidy:
+  stage: build
+  before_script:
+    - apt-get update -qq && apt-get install -y -qq clang-tidy-4.0
+    - clang-tidy-4.0 --version
   script:
     - bash -x ci/clang-tidy.sh
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..d49fb0620ae4893df6f92e7f878d7202c37cf84b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/Catch2"]
+	path = lib/Catch2
+	url = https://github.com/catchorg/Catch2.git
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index efd791e85b4902d773897aeb8ae48aa37dfc243b..5b44ac96da73d9acc2af3bb992aa3611e574d766 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,6 +1,7 @@
 <component name="ProjectCodeStyleConfiguration">
   <code_scheme name="Project" version="173">
     <option name="RIGHT_MARGIN" value="100" />
+    <option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
     <Objective-C-extensions>
       <file>
         <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 79b3c94830bab93d40d0770f2765540fe24ed423..91d4361702769bdfe6326464a61298263c79e5e3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
+  <component name="CidrRootsConfiguration">
+    <sourceRoots>
+      <file path="$PROJECT_DIR$/inc" />
+      <file path="$PROJECT_DIR$/src" />
+    </sourceRoots>
+    <libraryRoots>
+      <file path="$PROJECT_DIR$/lib" />
+    </libraryRoots>
+  </component>
 </project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7f4cb416c083d265558da75d457237d671..76ade6edd581314bf32ea0f3fd0e76c366ce9100 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="$PROJECT_DIR$" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/lib/Catch2" vcs="Git" />
   </component>
 </project>
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5024e08c5e64ff5389687520541565c70fd16a81..4ee0466937f6439a8ab12dd476a285c05929f32a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,4 +14,14 @@ add_custom_target(check
         WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/ci")
 
 # Specify the .cpp files for the executables
-add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp src/Services/TestService.cpp inc/Services/ParameterService.hpp src/Services/ParameterService.cpp)
+add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp
+        src/Services/TestService.cpp src/Services/RequestVerificationService.cpp src/Services/ParameterService.cpp)
+
+IF (EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt")
+    add_subdirectory(lib/Catch2)
+    add_executable(tests src/Message.cpp src/Services/TestService.cpp
+            src/Services/RequestVerificationService.cpp test/tests.cpp
+            test/Message.cpp test/TestPlatform.cpp test/Services/TestService.cpp
+            test/Services/RequestVerificationService.cpp)
+    target_link_libraries(tests Catch2::Catch2)
+ENDIF ()
diff --git a/CMakeLists.txt.orig b/CMakeLists.txt.orig
new file mode 100644
index 0000000000000000000000000000000000000000..fde62d5c6eda08ea7719cb6268dc327931d43f79
--- /dev/null
+++ b/CMakeLists.txt.orig
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.7)
+project(ecss_services)
+
+# Set C++ version to c++17
+set(CMAKE_CXX_STANDARD 17)
+
+# Specify the directories for #includes
+include_directories("${PROJECT_SOURCE_DIR}/inc")
+
+add_custom_target(check
+        COMMAND ./cppcheck.sh
+        COMMAND ./vera.sh
+        COMMAND ./clang-tidy.sh
+        WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/ci")
+
+# Specify the .cpp files for the executables
+<<<<<<< HEAD
+add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp src/Services/TestService.cpp inc/Services/ParameterService.hpp src/Services/ParameterService.cpp)
+=======
+add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp
+        src/Services/TestService.cpp src/Services/RequestVerificationService.cpp)
+
+IF (EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt")
+    add_subdirectory(lib/Catch2)
+    add_executable(tests src/Message.cpp src/Services/TestService.cpp
+            src/Services/RequestVerificationService.cpp test/tests.cpp
+            test/Message.cpp test/TestPlatform.cpp test/Services/TestService.cpp
+            test/Services/RequestVerificationService.cpp)
+    target_link_libraries(tests Catch2::Catch2)
+ENDIF ()
+>>>>>>> master
diff --git a/ci/clang-tidy.sh b/ci/clang-tidy.sh
index 8a0c19301fe7e7efc7ff350cd9119e5c4b9c97a5..1e676ce2d6926d700576c3a0fe69bad656c16389 100755
--- a/ci/clang-tidy.sh
+++ b/ci/clang-tidy.sh
@@ -11,4 +11,4 @@ echo -e "\033[0;34mRunning clang-tidy...\033[0m"
 
 cd "$(dirname "$0")"
 clang-tidy-4.0 `find ../src/ -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'` \
-    -- -std=c++14 -I../inc
+    -extra-arg=-fcolor-diagnostics -- -std=c++14 -I../inc
diff --git a/ci/cppcheck.sh b/ci/cppcheck.sh
index a8335c61296643714ec50b402b322253be41c254..3b8d4cf3f1ee124eaa6787290a505837e7fefbaf 100755
--- a/ci/cppcheck.sh
+++ b/ci/cppcheck.sh
@@ -10,4 +10,4 @@
 echo -e "\033[0;34mRunning cppcheck...\033[0m"
 
 cd "$(dirname "$0")/.."
-cppcheck --enable=all --error-exitcode=1 -I inc src
+cppcheck --enable=all --suppress=unusedFunction --suppress=missingIncludeSystem --error-exitcode=1 -I inc src tests
diff --git a/ci/vera.sh b/ci/vera.sh
index 9f7d0b6a391c7554bc73fe6b1baab1278e49e868..b758842ff8b395ee548e6389a8f6b08426fbaf87 100755
--- a/ci/vera.sh
+++ b/ci/vera.sh
@@ -10,4 +10,4 @@
 echo -e "\033[0;34mRunning vera++...\033[0m"
 
 cd "$(dirname "$0")/.."
-vera++ --error --profile custom `find src inc -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'`
+vera++ --error --profile custom `find src inc tests -type f -regextype posix-egrep -regex '.*\.(cpp|hpp|c|h)'`
diff --git a/inc/Message.hpp b/inc/Message.hpp
index 268af02f6780a11e17d3a655e3fce29c96589358..28ba738b09ab3babeb2173514da8704d892a5301 100644
--- a/inc/Message.hpp
+++ b/inc/Message.hpp
@@ -335,6 +335,8 @@ public:
 	 * Fetches an 4-byte single-precision floating point number from the current position in the
 	 * message
 	 *
+	 * @todo Check if endianness matters for this
+	 *
 	 * PTC = 5, PFC = 1
 	 */
 	float readFloat() {
@@ -344,6 +346,11 @@ public:
 		uint32_t value = readWord();
 		return reinterpret_cast<float &>(value);
 	}
+
+	/**
+	 * Reset the message reading status, and start reading data from it again
+	 */
+	void resetRead();
 };
 
 
diff --git a/inc/Services/RequestVerificationService.hpp b/inc/Services/RequestVerificationService.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1d2bf9210a97e69bd6f2f6e2938bb1bd4ddb7e9
--- /dev/null
+++ b/inc/Services/RequestVerificationService.hpp
@@ -0,0 +1,98 @@
+#ifndef ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP
+#define ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP
+
+#include "Service.hpp"
+
+/**
+ * Implementation of the ST[01] request verification service
+ *
+ * @todo All telemetry packets shall have a telemetry packet secondary header
+ * @todo See if it would be more efficient to use Messages as arguments instead of individual
+ * parameters
+ */
+class RequestVerificationService : public Service {
+public:
+	RequestVerificationService() {
+		serviceType = 1;
+	}
+
+	/**
+	 * TM[1,1] successful acceptance verification report
+	 * Send report when the Cubesat accepts successfully commands
+	 *
+	 * Note:The parameters are the necessary information, defined from the standard, that the report
+	 * should contain
+	 *
+	 * @param apid Application process ID
+	 * @param seqFlag Sequence flags
+	 * @param packetSeqCount Packet sequence count
+	 */
+	void successAcceptanceVerification(Message::PacketType packetType, bool secondaryHeaderFlag,
+	                                   uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount);
+
+	/**
+	 * TM[1,2] failed acceptance verification report
+	 *Send report when the Cubesat don't accept commands
+	 *
+	 * Note:The parameters are the necessary information, defined from the standard, that the report
+	 * should contain
+	 *
+	 * @param apid Application process ID
+	 * @param seqFlag Sequence flags
+	 * @param packetSeqCount Packet sequence count
+	 */
+	void failAcceptanceVerification(Message::PacketType packetType, bool secondaryHeaderFlag,
+	                                uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount,
+	                                uint16_t errorCode);
+
+
+	/**
+ 	*  TM[1,7] successful completion of execution verification report
+	 *  Send report when the Cubesat completes an execution
+	 *
+	 * Note:The parameters are the necessary information, defined from the standard, that the report
+	 * should contain
+	 *
+	 * @param apid Application process ID
+	 * @param seqFlag Sequence flags
+	 * @param packetSeqCount Packet sequence count
+ 	*/
+	void successExecutionVerification(Message::PacketType packetType, bool secondaryHeaderFlag,
+	                                  uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount);
+
+	/**
+ 	*  TM[1,8] failed completion of execution verification report
+	 *  Send report when the Cubesat don't complete an execution
+	 *
+	 * Note:The parameters are the necessary information, defined from the standard, that the report
+	 * should contain
+	 *
+	 * @param apid Application process ID
+	 * @param seqFlag Sequence flags
+	 * @param packetSeqCount Packet sequence count
+ 	*/
+	void failExecutionVerification(Message::PacketType packetType,
+	                               bool secondaryHeaderFlag,
+	                               uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount,
+	                               uint16_t errorCode);
+
+	/**
+ 	*  TM[1,10] failed routing verification report
+	 *  Send report when the routing of a request has failed
+	 *
+	 * Note:The parameters are the necessary information, defined from the standard, that the report
+	 * should contain
+	 *
+	 * @param apid Application process ID
+	 * @param seqFlag Sequence flags
+	 * @param packetSeqCount Packet sequence count
+ 	*/
+	void failRoutingVerification(Message::PacketType packetType,
+	                             bool secondaryHeaderFlag,
+	                             uint16_t apid, uint8_t seqFlag, uint16_t packetSeqCount,
+	                             uint16_t errorCode);
+
+
+};
+
+#endif //ECSS_SERVICES_REQUESTVERIFICATIONSERVICE_HPP
diff --git a/inc/Services/TestService.hpp b/inc/Services/TestService.hpp
index 1d367e9563701083e0c10efd9c1c82b3a9c34ae8..a3704aa16a0ca3b7d7a19c9d639983614f5d91fd 100644
--- a/inc/Services/TestService.hpp
+++ b/inc/Services/TestService.hpp
@@ -15,14 +15,14 @@ public:
 	/**
 	 * TC[17,1] perform an are-you-alive connection test
 	 */
-	void areYouAlive(Message & request);
+	void areYouAlive(Message &request);
 
 	/**
 	 * TC[17,3] perform an on-board connection test
 	 *
 	 * @todo Only respond if we have the correct APID
 	 */
-	void onBoardConnection(Message & request);
+	void onBoardConnection(Message &request);
 };
 
 
diff --git a/lib/Catch2 b/lib/Catch2
new file mode 160000
index 0000000000000000000000000000000000000000..62460fafe6b54c3173bc5cbc46d05a5f071017ff
--- /dev/null
+++ b/lib/Catch2
@@ -0,0 +1 @@
+Subproject commit 62460fafe6b54c3173bc5cbc46d05a5f071017ff
diff --git a/src/Message.cpp b/src/Message.cpp
index d17eb0f5c003792d37fe66975425ae15d4e7a92d..15baf5f217098562171fc6ff63a0705b0e212f7c 100644
--- a/src/Message.cpp
+++ b/src/Message.cpp
@@ -1,6 +1,5 @@
 #include "Message.hpp"
 #include <cstring>
-#include <Message.hpp>
 
 
 Message::Message(uint8_t serviceType, uint8_t messageType, Message::PacketType packetType,
@@ -139,3 +138,8 @@ void Message::readString(char *string, uint8_t size) {
 
 	readPosition += size;
 }
+
+void Message::resetRead() {
+	readPosition = 0;
+	currentBit = 0;
+}
diff --git a/src/Service.cpp b/src/Service.cpp
index 27a9f4746007488ac3a881c5afda77d88adb581d..07403e438e1ff884b430c5eafff7d92a7d63c63c 100644
--- a/src/Service.cpp
+++ b/src/Service.cpp
@@ -7,9 +7,10 @@ void Service::storeMessage(const Message &message) {
 	std::cout << "New " << ((message.packetType == Message::TM) ? "TM" : "TC") << "[" << std::dec
 	          << static_cast<int>(message.serviceType) << ","
 	          << static_cast<int>(message.messageType) << "] message!\n";
-	std::cout << std::hex << std::setfill('0') << std::setw(2);
+	//std::cout << std::hex << std::setfill('0') << std::setw(2);
 	for (int i = 0; i < message.dataSize; i++) {
 		std::cout << static_cast<int>(message.data[i]);
+		std::cout << " ";
 	}
 	std::cout << std::endl;
 }
diff --git a/src/Services/RequestVerificationService.cpp b/src/Services/RequestVerificationService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccacfb591ee31076c14501d29792e5b560c8130a
--- /dev/null
+++ b/src/Services/RequestVerificationService.cpp
@@ -0,0 +1,126 @@
+#include "Services/RequestVerificationService.hpp"
+#include "Message.hpp"
+
+void RequestVerificationService::successAcceptanceVerification(Message::PacketType packetType,
+                                                               bool secondaryHeaderFlag,
+                                                               uint16_t apid, uint8_t seqFlag,
+                                                               uint16_t packetSeqCount) {
+	// TM[1,1] successful acceptance verification report
+
+	// parameters have max values defined from standard
+	assert(apid < 2048);
+	assert(seqFlag < 4);
+	assert(packetSeqCount < 16384);
+
+	Message report = createTM(1);
+
+	report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number
+	report.appendEnumerated(1, packetType);
+	report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag));
+	report.appendEnumerated(11, apid);
+	report.appendEnumerated(2, seqFlag);
+	report.appendBits(14, packetSeqCount);
+
+	storeMessage(report);
+}
+
+void
+RequestVerificationService::failAcceptanceVerification(Message::PacketType packetType,
+                                                       bool secondaryHeaderFlag,
+                                                       uint16_t apid, uint8_t seqFlag,
+                                                       uint16_t packetSeqCount,
+                                                       uint16_t errorCode) {
+	// TM[1,2] failed acceptance verification report
+
+	// parameters have max values defined from standard
+	assert(apid < 2048);
+	assert(seqFlag < 4);
+	assert(packetSeqCount < 16384);
+
+	Message report = createTM(2);
+
+	report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number
+	report.appendEnumerated(1, packetType);
+	report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag));
+	report.appendEnumerated(11, apid);
+	report.appendEnumerated(2, seqFlag);
+	report.appendBits(14, packetSeqCount);
+	report.appendEnum16(errorCode);
+
+	storeMessage(report);
+}
+
+void RequestVerificationService::successExecutionVerification(Message::PacketType packetType,
+                                                              bool secondaryHeaderFlag,
+                                                              uint16_t apid, uint8_t seqFlag,
+                                                              uint16_t packetSeqCount) {
+	// TM[1,7] successful completion of execution verification report
+
+	// parameters have max values defined from standard
+	assert(apid < 2048);
+	assert(seqFlag < 4);
+	assert(packetSeqCount < 16384);
+
+	Message report = createTM(7);
+
+	report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number
+	report.appendEnumerated(1, packetType);
+	report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag));
+	report.appendEnumerated(11, apid);
+	report.appendEnumerated(2, seqFlag);
+	report.appendBits(14, packetSeqCount);
+
+	storeMessage(report);
+}
+
+void
+RequestVerificationService::failExecutionVerification(Message::PacketType packetType,
+                                                      bool secondaryHeaderFlag,
+                                                      uint16_t apid, uint8_t seqFlag,
+                                                      uint16_t packetSeqCount,
+                                                      uint16_t errorCode) {
+	// TM[1,8] failed completion of execution verification report
+
+	// parameters have max values defined from standard
+	assert(apid < 2048);
+	assert(seqFlag < 4);
+	assert(packetSeqCount < 16384);
+
+	Message report = createTM(8);
+
+	report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number
+	report.appendEnumerated(1, packetType);
+	report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag));
+	report.appendEnumerated(11, apid);
+	report.appendEnumerated(2, seqFlag);
+	report.appendBits(14, packetSeqCount);
+	report.appendEnum16(errorCode);
+
+	storeMessage(report);
+}
+
+void
+RequestVerificationService::failRoutingVerification(Message::PacketType packetType,
+                                                    bool secondaryHeaderFlag,
+                                                    uint16_t apid, uint8_t seqFlag,
+                                                    uint16_t packetSeqCount,
+                                                    uint16_t errorCode) {
+	// TM[1,10] failed routing verification report
+
+	// parameters have max values defined from standard
+	assert(apid < 2048);
+	assert(seqFlag < 4);
+	assert(packetSeqCount < 16384);
+
+	Message report = createTM(10);
+
+	report.appendEnumerated(3, ECSS_PUS_VERSION); // packet version number
+	report.appendEnumerated(1, packetType);
+	report.appendBits(1, static_cast<uint8_t >(secondaryHeaderFlag));
+	report.appendEnumerated(11, apid);
+	report.appendEnumerated(2, seqFlag);
+	report.appendBits(14, packetSeqCount);
+	report.appendEnum16(errorCode);
+
+	storeMessage(report);
+}
diff --git a/src/Services/TestService.cpp b/src/Services/TestService.cpp
index 06f60263866d9ed9192dc95385e7570b174a1bea..670a8e2fe18cdf1403490b7393d7e7e9030b01d9 100644
--- a/src/Services/TestService.cpp
+++ b/src/Services/TestService.cpp
@@ -12,6 +12,6 @@ void TestService::onBoardConnection(Message &request) {
 	Message report = createTM(4);
 
 	report.appendUint16(request.readUint16());
-
+	// just print it on the screen
 	storeMessage(report);
 }
diff --git a/src/main.cpp b/src/main.cpp
index 20b53961763c52f86c0ded09fe8cdc8de8b7fdc4..f11acf2130d3b6891d18b120066b65c905d81e7f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <Services/TestService.hpp>
 #include "Services/ParameterService.hpp"
+#include <Services/RequestVerificationService.hpp>
 #include "Message.hpp"
 
 int main() {
@@ -72,5 +73,13 @@ int main() {
 
 	}
 
+// ST[01] test
+	// parameters take random values and works as expected
+	RequestVerificationService reqVerifService;
+	reqVerifService.successAcceptanceVerification(Message::TC, true, 2, 2, 10);
+	reqVerifService.failAcceptanceVerification(Message::TC, true, 2, 2, 10, 5);
+	reqVerifService.successExecutionVerification(Message::TC, true, 2, 2, 10);
+	reqVerifService.failExecutionVerification(Message::TC, true, 2, 2, 10, 6);
+	reqVerifService.failRoutingVerification(Message::TC, true, 2, 2, 10, 7);
 	return 0;
 }
diff --git a/src/main.cpp.orig b/src/main.cpp.orig
new file mode 100644
index 0000000000000000000000000000000000000000..1fe56064df00e8f7b486bd7ca3da24b0abf41ca8
--- /dev/null
+++ b/src/main.cpp.orig
@@ -0,0 +1,91 @@
+#include <iostream>
+#include <Services/TestService.hpp>
+<<<<<<< HEAD
+#include "Services/ParameterService.hpp"
+=======
+#include <Services/RequestVerificationService.hpp>
+>>>>>>> master
+#include "Message.hpp"
+
+int main() {
+	Message packet = Message(0, 0, Message::TC, 1);
+
+	packet.appendString(5, "hello");
+	packet.appendBits(15, 0x28a8);
+	packet.appendBits(1, 1);
+	packet.appendFloat(5.7);
+	packet.appendSint32(-123456789);
+
+	std::cout << "Hello, World!" << std::endl;
+	std::cout << std::hex << packet.data << std::endl; // packet data must be 'helloQQ'
+
+	char string[6];
+	packet.readString(string, 5);
+	std::cout << "Word: " << string << " " << packet.readBits(15) << packet.readBits(1)
+	          << std::endl;
+	std::cout << packet.readFloat() << " " << std::dec << packet.readSint32() << std::endl;
+
+	// ST[17] test
+	TestService testService;
+	Message receivedPacket = Message(17, 1, Message::TC, 1);
+	testService.areYouAlive(receivedPacket);
+	receivedPacket = Message(17, 3, Message::TC, 1);
+	receivedPacket.appendUint16(7);
+	testService.onBoardConnection(receivedPacket);
+
+<<<<<<< HEAD
+	//ST[20] test
+	ParameterService paramService;
+
+	//Test code for reportParameter
+	Message sentPacket = Message(20, 1, Message::TC, 1);  //application id is a dummy number (1)
+	sentPacket.appendUint16(2);  //number of contained IDs
+	sentPacket.appendUint16(0);  //first ID
+	sentPacket.appendUint16(1);  //second ID
+	Message returnedPacket = paramService.reportParameterIds(sentPacket);
+
+	uint16_t numOfIds = returnedPacket.readUint16();
+
+	std::cout << std::endl << "Number of contained configs: " << numOfIds << std::endl;
+
+	for (int i = 0; i < numOfIds; i++) {
+
+		std::cout << "Parameter ID: " << std::dec << returnedPacket.readUint16() << std::endl
+		          << "Parameter value: " << std::dec << returnedPacket.readUint32() << std::endl;
+
+	}
+
+	std::cout << std::endl << "(First value is hours, second is minutes)" << std::endl;
+
+	//Test code for setParameter
+	Message sentPacket2 = Message(20, 3, Message::TC, 1);  //application id is a dummy number (1)
+	sentPacket2.appendUint16(2);  //number of contained IDs
+	sentPacket2.appendUint16(0);  //first parameter ID
+	sentPacket2.appendUint32(63238);  //settings for first parameter
+	sentPacket2.appendUint16(1);  //2nd parameter ID
+	sentPacket2.appendUint32(45823);  //settings for 2nd parameter
+
+	paramService.setParameterIds(sentPacket2);
+	returnedPacket = paramService.reportParameterIds(sentPacket);
+
+	numOfIds = returnedPacket.readUint16();
+
+	for (int i = 0; i < numOfIds; i++) {
+
+		std::cout << "Parameter ID: " << std::dec << returnedPacket.readUint16() << std::endl
+		          << "Parameter value: " << std::dec << returnedPacket.readUint32() << std::endl;
+
+	}
+=======
+	// ST[01] test
+	// parameters take random values and works as expected
+	RequestVerificationService reqVerifService;
+	reqVerifService.successAcceptanceVerification(Message::TC, true, 2, 2, 10);
+	reqVerifService.failAcceptanceVerification(Message::TC, true, 2, 2, 10, 5);
+	reqVerifService.successExecutionVerification(Message::TC, true, 2, 2, 10);
+	reqVerifService.failExecutionVerification(Message::TC, true, 2, 2, 10, 6);
+	reqVerifService.failRoutingVerification(Message::TC, true, 2, 2, 10, 7);
+>>>>>>> master
+
+	return 0;
+}
diff --git a/test/Message.cpp b/test/Message.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4a745e04e5c1bdf8cf449996f5bff135fb1312bf
--- /dev/null
+++ b/test/Message.cpp
@@ -0,0 +1,173 @@
+#include <catch2/catch.hpp>
+#include <Message.hpp>
+
+TEST_CASE("Message is usable", "[message]") {
+	Message message(5, 17, Message::TC, 3);
+
+	REQUIRE(message.serviceType == 5);
+	REQUIRE(message.messageType == 17);
+	REQUIRE(message.packetType == Message::TC);
+	REQUIRE(message.applicationId == 3);
+	REQUIRE(message.dataSize == 0);
+
+	message.appendByte(250);
+	REQUIRE(message.dataSize == 1);
+	REQUIRE(message.readByte() == 250);
+}
+
+TEST_CASE("Bit manipulations", "[message]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendBits(10, 0x357);
+	message.appendBits(4, 0xb);
+	message.appendBits(2, 0);
+	message.appendByte(248);
+	message.appendBits(7, 0x16);
+	message.appendBits(1, 0x1);
+	message.appendBits(8, 0xff);
+
+	REQUIRE(message.dataSize == 5);
+
+	CHECK(message.readBits(10) == 0x357);
+	CHECK(message.readBits(4) == 0xb);
+	CHECK(message.readBits(2) == 0);
+	CHECK(message.readBits(5) == 0x1f);
+	CHECK(message.readBits(3) == 0);
+	CHECK(message.readByte() == 0x2d);
+	CHECK(message.readByte() == 0xff);
+
+	message.resetRead();
+
+	CHECK(message.readUint32() == 0xd5ecf82d);
+	CHECK(message.readBits(8) == 0xff);
+}
+
+TEST_CASE("Requirement 5.3.1", "[message][ecss]") {
+	SECTION("5.3.1a") {
+
+	}
+
+	SECTION("5.3.1b") {
+		REQUIRE(sizeof(Message::serviceType) == 1);
+	}
+
+	SECTION("5.3.1c") {
+		// TODO: Unimplemented
+	}
+
+	SECTION("5.3.1d") {
+		// TODO: Unimplemented
+	}
+}
+
+TEST_CASE("Requirement 7.3.2 (Boolean)", "[message][ecss]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendBoolean(false);
+	message.appendBoolean(true);
+
+	REQUIRE(message.dataSize == 2);
+
+	CHECK_FALSE(message.readBoolean());
+	CHECK(message.readBoolean());
+}
+
+TEST_CASE("Requirement 7.3.3 (Enumerated)", "[message][ecss]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendEnum8(230);
+	message.appendEnum16(15933);
+	message.appendEnum32(2000001);
+	message.appendEnumerated(12, 2052);
+	message.appendEnumerated(4, 10);
+
+	REQUIRE(message.dataSize == 1 + 2 + 4 + 2);
+
+	CHECK(message.readEnum8() == 230);
+	CHECK(message.readEnum16() == 15933);
+	CHECK(message.readEnum32() == 2000001);
+	CHECK(message.readEnumerated(12) == 2052);
+	CHECK(message.readEnumerated(4) == 10);
+}
+
+TEST_CASE("Requirement 7.3.4 (Unsigned integer)", "[message][ecss]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendUint8(230);
+	message.appendUint16(15933);
+	message.appendUint32(2000001);
+
+	REQUIRE(message.dataSize == 1 + 2 + 4);
+
+	CHECK(message.readUint8() == 230);
+	CHECK(message.readUint16() == 15933);
+	CHECK(message.readUint32() == 2000001);
+
+	SECTION("7.4.3") {
+		/**
+		 * Make sure the endianness of the message data is correct.
+		 * As per the ECSS standard, stored data should be big-endian. However, ARM and x86
+		 * processors store data in little endian format. As a result, special care needs to be
+		 * taken for compliance.
+		 */
+		CHECK(message.data[1] == 0x3e);
+		CHECK(message.data[2] == 0x3d);
+	}
+}
+
+TEST_CASE("Requirement 7.3.5 (Signed integer)", "[message][ecss]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendSint8(-16);
+	message.appendSint16(-7009);
+	message.appendSint32(-2000001);
+	message.appendSint32(15839011);
+
+	REQUIRE(message.dataSize == 1 + 2 + 4 + 4);
+
+	CHECK(message.readSint8() == -16);
+	CHECK(message.readSint16() == -7009);
+	CHECK(message.readSint32() == -2000001);
+	CHECK(message.readSint32() == 15839011);
+
+	SECTION("7.4.3") {
+		// Make sure the endianness of the message data is correct
+		// As per the ECSS standard, stored data should be big-endian. However, ARM and x86
+		// processors store data in little endian format. As a result, special care needs to be
+		// taken for compliance.
+		CHECK(message.data[1] == 0xe4);
+		CHECK(message.data[2] == 0x9f);
+	}
+}
+
+TEST_CASE("Requirement 7.3.6 (Real)", "[message][ecss]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendFloat(7.209f);
+	message.appendFloat(-9003.53135f);
+
+	REQUIRE(message.dataSize == 8);
+
+	CHECK(message.readFloat() == 7.209f);
+	CHECK(message.readFloat() == -9003.53135f);
+}
+
+TEST_CASE("Requirement 7.3.8 (Octet-string)", "[message][ecss]") {
+	Message message(0, 0, Message::TC, 0);
+
+	message.appendString(4, "test");
+
+	REQUIRE(message.dataSize == 4);
+
+	char string[5];
+	message.readString(string, 4);
+	CHECK_THAT(string, Catch::Matchers::Equals("test"));
+}
+
+TEST_CASE("Requirement 7.3.13 (Packet)", "[message][ecss]") {
+	Message telemetry(0, 0, Message::TM, 0);
+	Message telecommand(0, 0, Message::TC, 0);
+
+	CHECK(static_cast<int>(telemetry.packetType) == 0);
+	CHECK(static_cast<int>(telecommand.packetType) == 1);
+}
diff --git a/test/Services/RequestVerificationService.cpp b/test/Services/RequestVerificationService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c9e3c8ccda90deb72c48e62f585f6dd9394a7ba
--- /dev/null
+++ b/test/Services/RequestVerificationService.cpp
@@ -0,0 +1,113 @@
+#include <catch2/catch.hpp>
+#include <Services/RequestVerificationService.hpp>
+#include <Message.hpp>
+#include "ServiceTests.hpp"
+
+TEST_CASE("TM[1,1]", "[service][st01]") {
+	RequestVerificationService reqVerifService;
+	reqVerifService.successAcceptanceVerification(Message::TC, true, 2, 2, 10);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	// Checks for the data-members of the object response
+	CHECK(response.serviceType == 1);
+	CHECK(response.messageType == 1);
+	CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1)
+	CHECK(response.applicationId == 0);
+	REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array
+	// Check for the value that is stored in <<data>> array(data-member of object response)
+	CHECK(response.readEnumerated(3) == 2); // packet version number
+	CHECK(response.readEnumerated(1) == 1); // packet type
+	CHECK(response.readBits(1) == true); // secondary header flag
+	CHECK(response.readEnumerated(11) == 2); // application process ID
+	CHECK(response.readEnumerated(2) == 2); // sequence flags
+	CHECK(response.readBits(14) == 10); // packet sequence count
+}
+
+TEST_CASE("TM[1,2]", "[service][st01]") {
+	RequestVerificationService reqVerifService;
+	reqVerifService.failAcceptanceVerification(Message::TC, true, 2, 2, 10, 5);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	// Checks for the data-members of the object response
+	CHECK(response.serviceType == 1);
+	CHECK(response.messageType == 2);
+	CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1)
+	CHECK(response.applicationId == 0);
+	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
+	// Check for the value that is stored in <<data>> array(data-member of object response)
+	CHECK(response.readEnumerated(3) == 2); // packet version number
+	CHECK(response.readEnumerated(1) == 1); // packet type
+	CHECK(response.readBits(1) == true); // secondary header flag
+	CHECK(response.readEnumerated(11) == 2); // application process ID
+	CHECK(response.readEnumerated(2) == 2); // sequence flags
+	CHECK(response.readBits(14) == 10); // packet sequence count
+	CHECK(response.readEnum16() == 5); // error code
+}
+
+TEST_CASE("TM[1,7]", "[service][st01]") {
+	RequestVerificationService reqVerifService;
+	reqVerifService.successExecutionVerification(Message::TC, true, 2, 2, 10);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	// Checks for the data-members of the object response
+	CHECK(response.serviceType == 1);
+	CHECK(response.messageType == 7);
+	CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1)
+	CHECK(response.applicationId == 0);
+	REQUIRE(response.dataSize == 4); // dataSize is the number of bytes of data array
+	// Check for the value that is stored in <<data>> array(data-member of object response)
+	CHECK(response.readEnumerated(3) == 2); // packet version number
+	CHECK(response.readEnumerated(1) == 1); // packet type
+	CHECK(response.readBits(1) == true); // secondary header flag
+	CHECK(response.readEnumerated(11) == 2); // application process ID
+	CHECK(response.readEnumerated(2) == 2); // sequence flags
+	CHECK(response.readBits(14) == 10); // packet sequence count
+}
+
+TEST_CASE("TM[1,8]", "[service][st01]") {
+	RequestVerificationService reqVerifService;
+	reqVerifService.failExecutionVerification(Message::TC, true, 2, 2, 10, 6);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	// Checks for the data-members of the object response
+	CHECK(response.serviceType == 1);
+	CHECK(response.messageType == 8);
+	CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1)
+	CHECK(response.applicationId == 0);
+	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
+	// Check for the value that is stored in <<data>> array(data-member of object response)
+	CHECK(response.readEnumerated(3) == 2); // packet version number
+	CHECK(response.readEnumerated(1) == 1); // packet type
+	CHECK(response.readBits(1) == true); // secondary header flag
+	CHECK(response.readEnumerated(11) == 2); // application process ID
+	CHECK(response.readEnumerated(2) == 2); // sequence flags
+	CHECK(response.readBits(14) == 10); // packet sequence count
+	CHECK(response.readEnum16() == 6); // error code
+}
+
+TEST_CASE("TM[1,10]", "[service][st01]") {
+	RequestVerificationService reqVerifService;
+	reqVerifService.failRoutingVerification(Message::TC, true, 2, 2, 10, 7);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	// Checks for the data-members of the object response
+	CHECK(response.serviceType == 1);
+	CHECK(response.messageType == 10);
+	CHECK(response.packetType == 0); // packet type(TM = 0, TC = 1)
+	CHECK(response.applicationId == 0);
+	REQUIRE(response.dataSize == 6); // dataSize is the number of bytes of data array
+	// Check for the value that is stored in <<data>> array(data-member of object response)
+	CHECK(response.readEnumerated(3) == 2); // packet version number
+	CHECK(response.readEnumerated(1) == 1); // packet type
+	CHECK(response.readBits(1) == true); // secondary header flag
+	CHECK(response.readEnumerated(11) == 2); // application process ID
+	CHECK(response.readEnumerated(2) == 2); // sequence flags
+	CHECK(response.readBits(14) == 10); // packet sequence count
+	CHECK(response.readEnum16() == 7); // error code
+}
+
diff --git a/test/Services/ServiceTests.hpp b/test/Services/ServiceTests.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a160558a0aac56d215ae6af329ce7b690c0b2f4d
--- /dev/null
+++ b/test/Services/ServiceTests.hpp
@@ -0,0 +1,53 @@
+#ifndef ECSS_SERVICES_TESTS_SERVICES_SERVICETESTS_HPP
+#define ECSS_SERVICES_TESTS_SERVICES_SERVICETESTS_HPP
+
+#include <vector>
+#include <Message.hpp>
+
+/**
+ * Supporting class for tests against ECSS services
+ *
+ * @todo See if members of this class can be made non-static
+ */
+class ServiceTests {
+	static std::vector<Message> queuedMessages;
+
+public:
+	/**
+	 * Get a message from the list of queued messages to send
+	 * @param number The number of the message, starting from 0 in chronological order
+	 */
+	static Message &get(uint64_t number) {
+		return queuedMessages.at(number);
+	}
+
+	/**
+	 * Add a message to the queue of messages to be sent
+	 */
+	static void queue(const Message &message) {
+		queuedMessages.push_back(message);
+	}
+
+	/**
+	 * Counts the number of messages in the queue
+	 */
+	static uint64_t count() {
+		return queuedMessages.size();
+	}
+
+	/**
+	 * Checks that there is *exactly* one message in the list of queued messages
+	 */
+	static bool hasOneMessage() {
+		return count() == 1;
+	}
+
+	/**
+	 * Remove all the queued messages from the list, starting over from 0 items again
+	 */
+	static void reset() {
+		queuedMessages.clear();
+	}
+};
+
+#endif //ECSS_SERVICES_TESTS_SERVICES_SERVICETESTS_HPP
diff --git a/test/Services/TestService.cpp b/test/Services/TestService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a94934ad20836620ec2ab1779d4ce0107798d08c
--- /dev/null
+++ b/test/Services/TestService.cpp
@@ -0,0 +1,32 @@
+#include <catch2/catch.hpp>
+#include <Services/TestService.hpp>
+#include <Message.hpp>
+#include "ServiceTests.hpp"
+
+TEST_CASE("TM[17,1]", "[service][st17]") {
+	TestService testService;
+
+	Message receivedPacket = Message(17, 1, Message::TC, 1);
+	testService.areYouAlive(receivedPacket);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	CHECK(response.serviceType == 17);
+	CHECK(response.messageType == 2);
+	REQUIRE(response.dataSize == 0);
+}
+
+TEST_CASE("TM[17,3]", "[service][st17]") {
+	TestService testService;
+
+	Message receivedPacket = Message(17, 3, Message::TC, 1);
+	receivedPacket.appendEnum16(40);
+	testService.onBoardConnection(receivedPacket);
+	REQUIRE(ServiceTests::hasOneMessage());
+
+	Message response = ServiceTests::get(0);
+	CHECK(response.serviceType == 17);
+	CHECK(response.messageType == 4);
+	REQUIRE(response.dataSize == 2);
+	CHECK(response.readEnum16() == 40);
+}
diff --git a/test/TestPlatform.cpp b/test/TestPlatform.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..10f9cdf366fd4950138248a6564b33c7d8dd0a10
--- /dev/null
+++ b/test/TestPlatform.cpp
@@ -0,0 +1,22 @@
+#define CATCH_CONFIG_EXTERNAL_INTERFACES
+
+#include <catch2/catch.hpp>
+#include <Message.hpp>
+#include <Service.hpp>
+#include "Services/ServiceTests.hpp"
+
+std::vector<Message> ServiceTests::queuedMessages = std::vector<Message>();
+
+void Service::storeMessage(const Message &message) {
+	ServiceTests::queue(message);
+}
+
+struct ServiceTestsListener : Catch::TestEventListenerBase {
+	using TestEventListenerBase::TestEventListenerBase; // inherit constructor
+
+	void testCaseEnded(Catch::TestCaseStats const &testCaseStats) override {
+		// Tear-down after a test case is run
+		ServiceTests::reset();
+	}
+};
+CATCH_REGISTER_LISTENER(ServiceTestsListener)
diff --git a/test/tests.cpp b/test/tests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f481b16fe25e9b620f1dcf078a53f4f357d466c5
--- /dev/null
+++ b/test/tests.cpp
@@ -0,0 +1,3 @@
+#define CATCH_CONFIG_MAIN
+
+#include <catch2/catch.hpp>