diff --git a/Master_Slave_Management/Master_Slave_Management/ImageFromSlave.cpp b/Master_Slave_Management/Master_Slave_Management/ImageFromSlave.cpp
new file mode 100644
index 0000000..1b5e5cd
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/ImageFromSlave.cpp
@@ -0,0 +1,4 @@
+#include "ImageFromSlave.h"
+
+int ImageFromSlave::counterForImage = 0;
+
diff --git a/Master_Slave_Management/Master_Slave_Management/ImageFromSlave.h b/Master_Slave_Management/Master_Slave_Management/ImageFromSlave.h
new file mode 100644
index 0000000..7861bee
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/ImageFromSlave.h
@@ -0,0 +1,65 @@
+#pragma once
+#include "PointForSlave.h"
+class ImageFromSlave
+{
+private:
+ int id;
+ static int counterForImage;
+ PointForSlave TL;
+ PointForSlave BR;
+ int slaveId;
+ int ReqId;
+
+public:
+ ImageFromSlave() {};
+
+ ImageFromSlave(float top, float left, float bottom, float right, int slavenum, int reqId) :
+ BR(bottom, right),
+ TL(top, left),
+ slaveId(slavenum),
+ ReqId(reqId),
+ id(counterForImage++) {};
+
+ PointForSlave GetBR()
+ {
+ return this->BR;
+ }
+
+ PointForSlave GetTL()
+ {
+ return this->TL;
+ }
+
+ int GetSlaveId()
+ {
+ return this->slaveId;
+ };
+
+ int GetReqId()
+ {
+ return this->ReqId;
+ }
+
+ void SetReqId(int reqID)
+ {
+ this->ReqId = reqID;
+ }
+ int GetId()
+ {
+ return this->id;
+ }
+ int getCounter()
+ {
+ return this->counterForImage;
+ }
+ void setSlaveId(int id)
+ {
+ this->slaveId = id;
+ }
+
+
+
+
+};
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj
index af34aad..913f53b 100644
--- a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj
+++ b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj
@@ -17,7 +17,31 @@
Release
x64
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
16.0
@@ -53,27 +77,24 @@
true
Unicode
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Level3
@@ -130,9 +151,7 @@
true
-
-
-
+
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters
index 814a456..d8fe69c 100644
--- a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters
+++ b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters
@@ -62,4 +62,71 @@
{2854cb75-ba29-441b-8dff-4947a76a6041}
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
+ Header Files\MapCreator
+
+
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Message.cpp b/Master_Slave_Management/Master_Slave_Management/Message.cpp
new file mode 100644
index 0000000..8fc25bf
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Message.cpp
@@ -0,0 +1,3 @@
+#include "Message.h"
+
+int Message::counterForMsg = 0;
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Message.h b/Master_Slave_Management/Master_Slave_Management/Message.h
new file mode 100644
index 0000000..8308eda
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Message.h
@@ -0,0 +1,34 @@
+#pragma once
+#include "MessageParams.h"
+#include "Priority.h"
+struct Message
+{
+ int messageId;
+ int reqId;
+ MessageType messageType;
+ int droneId;
+ MessageParams* messageParams;
+ Priority priority;
+ Message() :messageId(counterForMsg++), messageParams(new MessageParams) {};
+ ~Message() { delete messageParams; };
+ // Copy constructor
+ /*Message(const Message& message)
+ : messageId(counter++),reqId(message.reqId),messageType(message.messageType),droneId(message.droneId),
+ messageParams(message.messageParams),priority(message.priority)
+ {}*/
+ Message& operator=(const Message& other)
+ {
+ if (this != &other)
+ {
+ // Note: messageId should remain unique, so we do not copy it.
+ reqId = other.reqId;
+ messageType = other.messageType;
+ droneId = other.droneId;
+ messageParams = other.messageParams; // Assuming proper copy behavior in MessageParams
+ priority = other.priority;
+ }
+ return *this;
+ }
+private:
+ int static counterForMsg;
+};
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/MessageParams.h b/Master_Slave_Management/Master_Slave_Management/MessageParams.h
new file mode 100644
index 0000000..d374a5f
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/MessageParams.h
@@ -0,0 +1,197 @@
+#pragma once
+#include
+#include "Priority.h"
+#include "event.h"
+#include "MessageType.h"
+//#include "RealImage.h"
+#include "PointForSlave.h"
+#include "ImageFromSlave.h"
+#include "mapRequest.h"
+#include "RealImage.h"
+using namespace std;
+struct M_GOT_REQ_PARAMS {
+ mapRequest mp;
+ //MESSAGE_TYPE:M_GOT_REQ
+ //handling function: SlavesManager::getARequestForAMap
+};
+struct MTS_ASK_FOR_IMAGES_PROP_PARAMS {
+ PointForSlave pfs;
+ int slaveId;
+ int reqId;
+ //MESSAGE_TYPE:MTS_ASK_FOR_IMAGES
+ //handling function: SlavesManager::sendRequestForImageInSpecificPoint
+};
+//שינתי
+struct STM_SEND_IMAGES_PROP_PARAMS
+{
+ int reqID;
+ int slaveID;
+ bool HaveOrNot_Image;
+ bool communication = false;
+ vector imgRes = {};
+ //MESSAGE_TYPE:STM_SEND_IMAGE_PROP
+ //handling function: Slave::GetAStructForImageInPoint
+};
+struct MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS {
+ ImageFromSlave img;
+ //MESSAGE_TYPE:MTS_GIVE_THE_CHOSEN_IMAGE
+ //handling function:sendRequestToSlaveToGetRealImage
+};
+struct STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS {
+ RealImage realImg;
+ //MESSAGE_TYPE:STM_RESPONSE_TO_THE_CHOSEN_IMAGE
+ //handling function:return_of_an_image_by_its_properties
+};
+struct MTS_REQ_FOR_PHOTO_PARAMS {
+ PointForSlave pfs;
+};
+struct MTIP_REQ_FOR_REAL_MAP_PARAMS {
+ //vector realImages;
+};
+struct MTM_NO_COMMUNICATION_AT_ALL_PARAMS
+{
+ string msg22;
+ //MESSAGE_TYPE:MTM_NO_COMMUNICATION_AT_ALL,-MessageOfNoCommuincationBetwwenAllSlaves
+ //handling function:__________________
+};
+struct MTM_SLAVES_NOT_COMMUNICATE_PARAMS
+{
+ vector SlavesWithNoCommunication;
+ //MESSAGE_TYPE:MTM_SLAVES_NOT_COMMUNICATE,-GetTheSlavesThatDidntCommunicate
+ //handling function:SlavesManager::getTheSlavesThatDidntCommunicate
+};
+struct MTS_SEND_LOCATION_PARAMS {
+ int second;
+};
+struct MTS_MOVE_OUT_OF_THIS_EREA_PARAMS {};
+struct MTS_STOP_SEND_LOCATION_PARAMS {};
+struct MTS_STOP_AT_PLACE_PARAMS {};
+struct MTS_BACK_TO_STARTING_POINT_PARAMS {};
+struct STM_LOCATION_PARAMS {
+ float x; float y;
+};
+struct MTS_SEND_EVENTS_PARAMS {
+ tm startTime;
+ tm endTime;
+ size_t maxSize;
+};
+struct STM_GET_EVENTS_PARAMS {
+ vector events;
+};
+
+
+union MessageParams
+{
+ M_GOT_REQ_PARAMS M_GOT_REQ_PARAMS;
+ MTS_ASK_FOR_IMAGES_PROP_PARAMS MTS_ASK_FOR_IMAGES_PROP_PARAMS;
+ STM_SEND_IMAGES_PROP_PARAMS STM_SEND_IMAGES_PROP_PARAMS;
+ MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS;
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS;
+ MTIP_REQ_FOR_REAL_MAP_PARAMS MTIP_REQ_FOR_REAL_MAP_PARAMS;
+ MTS_REQ_FOR_PHOTO_PARAMS MTS_REQ_FOR_PHOTO_PARAMS;
+ MTM_NO_COMMUNICATION_AT_ALL_PARAMS MTM_NO_COMMUNICATION_AT_ALL_PARAMS;
+ MTM_SLAVES_NOT_COMMUNICATE_PARAMS MTM_SLAVES_NOT_COMMUNICATE_PARAMS;
+ MTS_SEND_LOCATION_PARAMS MTS_SEND_LOCATION_PARAMS;
+ MTS_MOVE_OUT_OF_THIS_EREA_PARAMS MTS_MOVE_OUT_OF_THIS_EREA_PARAMS;
+ MTS_STOP_SEND_LOCATION_PARAMS MTS_STOP_SEND_LOCATION_PARAMS;
+ STM_LOCATION_PARAMS STM_LOCATION_PARAMS;
+ MTS_STOP_AT_PLACE_PARAMS MTS_STOP_AT_PLACE_PARAMS;
+ MTS_BACK_TO_STARTING_POINT_PARAMS MTS_BACK_TO_STARTING_POINT_PARAMS;
+ MTS_SEND_EVENTS_PARAMS MTS_SEND_EVENTS_PARAMS;
+ STM_GET_EVENTS_PARAMS STM_GET_EVENTS_PARAMS;
+
+ // בנאי ברירת מחדל
+ MessageParams() {}
+ ~MessageParams() {}
+
+ // סימון השדה הפעל
+ //MessageType activeField;
+
+
+// // מיישם אופרטור השמה
+// MessageParams& operator=(const MessageParams& other)
+// {
+// if (this != &other) {
+// // לנקות את השדה הנוכחי לפני השמה חדשה
+// destroyCurrentActiveField();
+//
+// activeField = other.activeField;
+// switch (activeField) {
+// case MessageType::M_GOT_REQ:
+// new (&M_GOT_REQ_PARAMS)struct M_GOT_REQ_PARAMS(other.M_GOT_REQ_PARAMS);
+// break;
+// case MessageType::MTS_ASK_FOR_IMAGES:
+// new (&MTS_ASK_FOR_IMAGES_PARAMS)struct MTS_ASK_FOR_IMAGES_PARAMS(other.MTS_ASK_FOR_IMAGES_PARAMS);
+// break;
+// case MessageType::STM_SEND_IMAGES_PROP:
+// new (&STM_SEND_IMAGES_PROP_PARAMS)struct STM_SEND_IMAGES_PROP_PARAMS(other.STM_SEND_IMAGES_PROP_PARAMS);
+// break;
+// case MessageType::MTS_GIVE_THE_CHOSEN_IMAGE:
+// new (&MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS)struct MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS(other.MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS);
+// break;
+// case MessageType::STM_RESPONSE_TO_THE_CHOSEN_IMAGE:
+// new (&STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS) struct STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS(other.STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS);
+// break;
+// case MessageType::MTS_SEND_LOCATION:
+// new(&MTS_SEND_LOCATION_PARAMS)struct MTS_SEND_LOCATION_PARAMS(other.MTS_SEND_LOCATION_PARAMS);
+// break;
+// case MessageType::MTS_MOVE_OUT_OF_THIS_EREA:
+// new (&MTS_MOVE_OUT_OF_THIS_EREA_PARAMS) struct MTS_MOVE_OUT_OF_THIS_EREA_PARAMS(other.MTS_MOVE_OUT_OF_THIS_EREA_PARAMS);
+// break;
+// case MessageType::MTS_STOP_SEND_LOCATION:
+// new (&MTS_STOP_SEND_LOCATION_PARAMS)struct MTS_STOP_SEND_LOCATION_PARAMS(other.MTS_STOP_SEND_LOCATION_PARAMS);
+// break;
+// case MessageType::MTS_STOP_AT_PLACE:
+// new (&MTS_STOP_AT_PLACE_PARAMS) struct MTS_STOP_AT_PLACE_PARAMS(other.MTS_STOP_AT_PLACE_PARAMS);
+// break;
+// case MessageType::MTS_BACK_TO_STARTING_POINT:
+// new (&MTS_BACK_TO_STARTING_POINT_PARAMS)struct MTS_BACK_TO_STARTING_POINT_PARAMS(other.MTS_BACK_TO_STARTING_POINT_PARAMS);
+// break;
+// case MessageType::MTS_SEND_EVENTS:
+// new (&MTS_SEND_EVENTS_PARAMS) struct MTS_SEND_EVENTS_PARAMS(other.MTS_SEND_EVENTS_PARAMS);
+// break;
+// case MessageType::STM_GET_EVENTS:
+// new (&STM_GET_EVENTS_PARAMS)struct STM_GET_EVENTS_PARAMS(other.STM_GET_EVENTS_PARAMS);
+// break;
+// default:
+// // לא שדה פעיל
+// activeField = MessageType::size;
+// break;
+// }
+// }
+// return *this;
+// }
+//
+// // הרס אופרטור
+// ~MessageParams()
+// {
+// destroyCurrentActiveField();
+// }
+//
+//private:
+// void destroyCurrentActiveField()
+// {
+// switch (activeField) {
+// case 0:
+// M_GOT_REQ_PARAMS.~M_GOT_REQ_PARAMS();
+// break;
+// case 1:
+// MTS_ASK_FOR_IMAGES_PARAMS.~MTS_ASK_FOR_IMAGES_PARAMS();
+// break;
+// case 2:
+// STM_SEND_IMAGES_PROP_PARAMS.~STM_SEND_IMAGES_PROP_PARAMS();
+// break;
+// // הוסף עוד מקרים לכל שדה ב-union
+// // ...
+// default:
+// break;
+// }
+// }
+
+
+};
+
+
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/MessageType.h b/Master_Slave_Management/Master_Slave_Management/MessageType.h
new file mode 100644
index 0000000..8e9a22c
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/MessageType.h
@@ -0,0 +1,25 @@
+#pragma once
+enum class MessageType
+{
+ M_GOT_REQ,
+ MTS_ASK_FOR_IMAGES,
+ STM_SEND_IMAGES_PROP,
+ MTS_GIVE_THE_CHOSEN_IMAGE,
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE,
+ MTS_REQ_FOR_PHOTO,
+ MTIP_REQ_FOR_REAL_MAP,
+ MTM_NO_COMMUNICATION_AT_ALL,
+ MTM_SLAVES_NOT_COMMUNICATE,
+ //IPTM_SEND_THE_IMAGES,
+ MTS_SEND_LOCATION,
+ MTS_MOVE_OUT_OF_THIS_EREA,
+ MTS_STOP_SEND_LOCATION,
+ STM_LOCATION,
+ MTS_STOP_AT_PLACE,
+ MTS_BACK_TO_STARTING_POINT,
+ MTS_SEND_EVENTS,
+ STM_GET_EVENTS,
+ size
+};
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/PointForSlave.cpp b/Master_Slave_Management/Master_Slave_Management/PointForSlave.cpp
new file mode 100644
index 0000000..0bd3d1c
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/PointForSlave.cpp
@@ -0,0 +1 @@
+#include "PointForSlave.h"
diff --git a/Master_Slave_Management/Master_Slave_Management/PointForSlave.h b/Master_Slave_Management/Master_Slave_Management/PointForSlave.h
new file mode 100644
index 0000000..1488c64
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/PointForSlave.h
@@ -0,0 +1,25 @@
+#pragma once
+class PointForSlave
+{
+private:
+ float x;
+ float y;
+public:
+ PointForSlave() {};
+
+ PointForSlave(float x, float y)
+ {
+ this->x = x;
+ this->y = y;
+ }
+
+ float GetX()
+ {
+ return this->x;
+ }
+ float GetY()
+ {
+ return this->y;
+ }
+};
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Priority.h b/Master_Slave_Management/Master_Slave_Management/Priority.h
new file mode 100644
index 0000000..1df7c62
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Priority.h
@@ -0,0 +1,9 @@
+#pragma once
+enum class Priority
+{
+ Low, // Low priority - tasks that are not urgent and can be addressed later.
+ MediumLow, // Medium-Low priority - tasks that are less urgent than medium priority tasks.
+ Medium, // Medium priority - tasks that are somewhat urgent but not the highest priority.
+ MediumHigh, // Medium-High priority - tasks that are more urgent and require timely attention.
+ High // High priority - tasks that are the most urgent and require immediate attention.
+};
diff --git a/Master_Slave_Management/Master_Slave_Management/RealImage.cpp b/Master_Slave_Management/Master_Slave_Management/RealImage.cpp
new file mode 100644
index 0000000..a1ebd68
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/RealImage.cpp
@@ -0,0 +1 @@
+#include "RealImage.h"
diff --git a/Master_Slave_Management/Master_Slave_Management/RealImage.h b/Master_Slave_Management/Master_Slave_Management/RealImage.h
new file mode 100644
index 0000000..5434012
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/RealImage.h
@@ -0,0 +1,56 @@
+#pragma once
+#include "opencv2/opencv.hpp"
+
+using namespace std;
+using namespace cv;
+
+#ifdef _DEBUG
+// the debug version that corresponds to the opencv_world420d.dll:
+#pragma comment(lib, "opencv_world454d.lib")
+#else
+// the release version that corresponds to the opencv_world420.dll:
+#pragma comment(lib, "opencv_world454.lib")
+#endif
+
+class RealImage
+{
+private:
+ Mat img;
+ int id;
+ int slaveId;
+public:
+ RealImage()
+ {
+ this->slaveId = -1;
+ }
+
+ RealImage(int id, int slaveId, Mat img)
+ {
+ this->id = id;
+ this->slaveId = slaveId;
+ this->img = img;
+ //for (int y = 0; y < img.rows; ++y) {
+ // for (int x = 0; x < img.cols; ++x) {
+ // Vec3b pixel = img.at(y, x);
+ // Vec3b pixel1 = this->img.at(y, x);
+ // pixel1[0] = pixel[0];
+ // pixel1[1] = pixel[1];
+ // pixel1[2] = pixel[2];
+ // }
+ //}
+ }
+ int getId()
+ {
+ return this->id;
+ }
+ int getSlaveId()
+ {
+ return this->slaveId;
+ }
+ Mat getImg()
+ {
+ return this->img;
+ }
+};
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Slave.cpp b/Master_Slave_Management/Master_Slave_Management/Slave.cpp
new file mode 100644
index 0000000..7956a67
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Slave.cpp
@@ -0,0 +1,242 @@
+#include "Slave.h"
+#include "SlavesManager.h"
+#include
+
+int Slave::Counter = 0;
+using namespace std;
+
+Mat m1 = imread("C:\\Users\\User\\Desktop\\פרקטיקיץ\\images\\צילום מסך 2024 - 07 - 25 121434.png");
+RealImage r1 = { 0, 0, m1 };
+RealImage r2 = { 1, 1, m1 };
+RealImage r3 = { 2, 2, m1 };
+RealImage r4 = { 3, 3, m1 };
+RealImage r5 = { 4, 4, m1 };
+RealImage r6 = { 5, 5, m1 };
+RealImage r7 = { 6, 6, m1 };
+RealImage r8 = { 7, 7, m1 };
+RealImage r9 = { 8, 8, m1 };
+RealImage r10 = { 9, 9, m1 };
+RealImage r11 = { 10, 10, m1 };
+RealImage r12 = { 11, 0, m1 };
+RealImage r13 = { 12, 1, m1 };
+RealImage r14 = { 13, 2, m1 };
+RealImage r15 = { 14, 3, m1 };
+RealImage r16 = { 15, 4, m1 };
+RealImage r30 = { 30, 4, m1 };
+RealImage r36 = { 36, 4, m1 };
+RealImage r45 = { 45, 4, m1 };
+vector imgs = { r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,r30,r36,r45 };
+ImageFromSlave temporary0[6] =
+{
+ { 31.8200,35.1766,31.8000,35.2075,1,0},
+ { 31.8000,35.1766,31.7961,35.2075,2,0},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 31.8200, 35.1766, 31.6060, 35.1930,2,0 },
+ { 31.8140, 35.1860, 31.8000, 35.2025,3,0 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,4,0 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,0 }
+};
+ImageFromSlave temporary1[6] =
+{
+ { 31.8200,35.1766,31.8000,35.2075,1,1},
+ { 31.8000,35.1766,31.7961,35.2075,2,1},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 31.8200, 35.1766, 31.6060, 35.1930,2,1 },
+ { 31.8140, 35.1860, 31.8000, 35.2025,3,1 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,4,1 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,1 }
+};
+ImageFromSlave temporary2[6] =
+{
+ { 31.8200,35.1766,31.8000,35.2075,1,2},
+ { 31.8000,35.1766,31.7961,35.2075,2,2},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 31.8200, 35.1766, 31.6060, 35.1930,2,2 },
+ { 31.8140, 35.1860, 31.8000, 35.2025,3,2 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,4,2 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,2 }
+};
+
+ImageFromSlave temporary3[6] =
+{
+ { 100,100,100,100,1,3},
+ { 100,100,100,100,2,3},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 100,100,100,100,2,3 },
+ { 100,100,100,100,3,3 },
+ { 100,100,100,100,4,3 },
+ { 100,100,100,100,5,3 }
+};
+
+ImageFromSlave temporary6[6] = {
+ //31.8200, 35.1766);
+ //31.7961, 35.2075);
+ { 31.8200, 35.1766,31.7961, 35.2075,1,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,3,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,4,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,5,6},
+};
+ImageFromSlave temporary7[6] = {
+ //31.8200, 35.1766);
+ //31.7961, 35.2075);
+ { 31.8200, 35.1766,31.7961, 35.2075,0,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,3,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,4,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,5,7},
+};
+
+ImageFromSlave temporary8[6] = {
+ //31.8200, 35.1766);
+ //31.7961, 35.2075);
+ { 31.8200, 35.1766,31.7961, 35.2075,0,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,0,8},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,8},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,8},
+};
+ImageFromSlave temporaryforme[5] =
+{
+ { 32.7897f, 35.5785f, 32.7915f, 35.5809f,1,8 },
+ { 32.7880f, 35.5733f, 32.7902f, 35.5757f,1,8 },
+ { 32.7925f, 35.5769f, 32.7948f, 35.5792f,3,8 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,3,8 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,8 }
+};
+vector Slave::CheckIfIHaveImage(PointForSlave p, ImageFromSlave MyArrOfImages[])
+{
+ vector ans;
+ for (int i = 0; i < 6; i++)
+ {
+ if (MyArrOfImages[i].GetSlaveId() == GlobalData::theCurrentAnswer.slaveID && MyArrOfImages[i].GetReqId() == GlobalData::static_current_ID)
+ {
+ if (isPointInImage(p, MyArrOfImages[i]))
+ {
+ ans.push_back(MyArrOfImages[i]);
+ }
+ }
+ }
+ return ans;
+}
+
+bool Slave::isPointInImage(PointForSlave p, ImageFromSlave img)
+{
+ //&& p.GetX() <= img.GetBR().GetX()
+ //&& p.GetY() <= img.GetBR().GetY()
+ if (p.GetX() >= img.GetTL().GetX() &&
+ p.GetY() <= img.GetTL().GetY())
+ return true;
+ else {
+ return false;
+ }
+}
+//void GetAStructForImageInPoint(Message* message) {};//STM_SEND_IMAGE_PROP
+
+void Slave::GetAStructForImageInPoint(Message* message)
+{
+ SlavesManager manager;
+ manager.addEvent("slave handle the request to get image in specific point");
+ //ResponseToGetImageFromSlave res;
+ GlobalData::theCurrentAnswer.HaveOrNot_Image = NULL;
+ vector ans;
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 0)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary0);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 1)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary1);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 2)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary2);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 3)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary3);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 4)
+ {
+ //ans = CheckIfIHaveImage(msg.pfs, temporary5);
+ GlobalData::theCurrentAnswer.communication = false;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 6)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary6);
+ srand(time(0));
+ // יצירת ערך אקראי בין true ל-false
+ //bool randomBool = std::rand() % 2;
+ if (temporary6->GetSlaveId() % 2 == 1)
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 7)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary7);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 8)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporary8);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId == 56)
+ {
+ ans = CheckIfIHaveImage(message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs, temporaryforme);
+ GlobalData::theCurrentAnswer.communication = true;
+ GlobalData::theCurrentAnswer.slaveID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId;
+ GlobalData::theCurrentAnswer.reqID = message->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId;
+ }
+ if (ans.empty())
+ GlobalData::theCurrentAnswer.HaveOrNot_Image = false;
+ else
+ GlobalData::theCurrentAnswer.HaveOrNot_Image = true;
+ GlobalData::theCurrentAnswer.imgRes = ans;
+}
+
+void Slave::return_of_an_image_by_its_properties(Message* message)
+{
+ SlavesManager manager;
+ string result = format("slave {} handling the request to get real image ", message->messageParams->MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS.img.GetSlaveId());
+ manager.addEvent(result);
+ for (RealImage img : imgs)
+ {
+ if (message->messageParams->MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS.img.GetId() == img.getId())
+ {
+ GlobalData::theCurrentRealImageResFromSlave.realImg = img;
+ return;
+ }
+ }
+ RealImage img1;
+ GlobalData::theCurrentRealImageResFromSlave.realImg = img1;
+}
+
+//פונקציה במסטר לא קראת לפונקציה בסלייב.
+//יש לשים לב שכל מה שצריך לקראת גם באמיתי נמצא בקוד ולא בקובץ טסט.
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Slave.h b/Master_Slave_Management/Master_Slave_Management/Slave.h
new file mode 100644
index 0000000..94f5c16
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Slave.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "ImageFromSlave.h"
+#include "Structs.h"
+#include
+#include "Message.h"
+
+using namespace std;
+
+class Slave
+{
+private:
+ int id;
+ static int Counter;
+public:
+ Slave()
+ {
+ Counter++;
+ this->id = Counter;
+ };
+ int GetId()
+ {
+ return this->id;
+ };
+ int GetSlaveId()
+ {
+ return Counter;
+ }
+ void setId(int id)
+ {
+ this->id = id;
+
+ }
+
+ vector CheckIfIHaveImage(PointForSlave p, ImageFromSlave MyArrOfImages[]);
+ bool isPointInImage(PointForSlave p, ImageFromSlave img);
+ void GetAStructForImageInPoint(Message* message);//STM_SEND_IMAGE_PROP
+
+ void return_of_an_image_by_its_properties(Message* message);
+
+
+};
+
diff --git a/Master_Slave_Management/Master_Slave_Management/SlavesManager.cpp b/Master_Slave_Management/Master_Slave_Management/SlavesManager.cpp
new file mode 100644
index 0000000..1e5584c
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/SlavesManager.cpp
@@ -0,0 +1,414 @@
+#include "SlavesManager.h"
+#include "stdio.h"
+#include "iostream"
+#include "Slave.h"
+#include
+#include
+using namespace std;
+
+
+#define ARRAYSIZE 5
+
+int GlobalData::static_current_ID = -1;
+vector GlobalData::TheImagesFromSlaves = { {0,0,0,0,0,0} };
+int GlobalData::NumOfSlaves_HasToAnswer = ARRAYSIZE;
+vector GlobalData::theBoolAnswers = {};
+float GlobalData::MinimumLine = -2;
+vector GlobalData::TheOptimals;
+PointForSlave GlobalData::pfs;
+mapRequest GlobalData::mapReqGlobal;
+vector GlobalData::RealImagesV;
+vector GlobalData::queueForReqToMap;
+bool GlobalData::IsInProcess;
+int GlobalData::didntCommunicate = 0;
+vector GlobalData::SlavesThatDiDntCommunicate;
+STM_SEND_IMAGES_PROP_PARAMS GlobalData::theCurrentAnswer;
+STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS GlobalData::theCurrentRealImageResFromSlave;
+
+
+
+
+
+void handleMassage1(Message* msg)
+{
+
+ Slave slave;
+ slave.setId(msg->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId);
+ slave.GetAStructForImageInPoint(msg);
+}
+
+void handleMassage2()
+{
+ SlavesManager manager1;
+ manager1.getResponse_ImageFromSlave();
+}
+
+void handleMessage3(Message* msg)
+{
+ Slave s;
+ s.setId(msg->messageParams->MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS.img.GetSlaveId());
+ s.return_of_an_image_by_its_properties(msg);
+}
+
+void handleMessage4()
+{
+ SlavesManager manager2;
+ manager2.getTheRealImageFromSlave();
+}
+
+
+void SlavesManager::addEvent(string event)
+{
+}
+
+bool SlavesManager::handle_photo_request()
+{
+ for (bool response : GlobalData::theBoolAnswers) {
+ if (response == true) {
+ return false; // If any slave has a photo, no need to take another
+ }
+ }
+ return true; // No slave has a photo, take a new one
+}
+
+bool SlavesManager::verify_photo(bool photo_taken)
+{
+ return photo_taken;
+}
+
+bool SlavesManager::no_comments()
+{
+ if (GlobalData::NumOfSlaves_HasToAnswer == 5)
+ return false;
+ return true;
+}
+
+bool SlavesManager::forCaseSeveralDidntAnswer(int numOfSlaves)
+{
+ if (numOfSlaves <= 5)
+ return false;
+ return true;
+}
+
+
+int SlavesManager::belongs_to_the_current_process(int ID, int current_ID, int number_of_slaves)
+{
+ if (ID == current_ID) {
+ number_of_slaves--;
+ return number_of_slaves;
+ }
+
+ else
+ return number_of_slaves;
+}
+
+bool SlavesManager::the_irrelevant_images_did_not_enter_the_array(const vector& IDresponses, int ID)
+{
+ for (int id : IDresponses) {
+ if (id == ID)
+ return false;
+ }
+ return true;
+}
+
+bool SlavesManager::request_for_a_map_arrived(bool map_request)
+{
+ return map_request;
+}
+
+bool SlavesManager::Enter_the_queue(int map_request_ID)
+{
+ for (M_GOT_REQ_PARAMS req : GlobalData::queueForReqToMap)
+ {
+ if (req.mp.getReqId() == map_request_ID)
+ return true;
+ }
+ return false;
+}
+
+bool SlavesManager::The_request_is_processed(int map_request_ID)
+{
+ if (GlobalData::static_current_ID == map_request_ID)
+ {
+ cout << "Request number" << map_request_ID << "is being processed";
+ return true;
+ }
+ return false;
+}
+
+ImageFromSlave SlavesManager::ChooseTheOptimalImage()
+{
+ float right = GlobalData::TheImagesFromSlaves[0].GetBR().GetY();
+ int image_place = 0;
+ for (size_t i = 1; i < GlobalData::TheImagesFromSlaves.size(); i++)
+ {
+ if (right < GlobalData::TheImagesFromSlaves[i].GetBR().GetY())
+ {
+ right = GlobalData::TheImagesFromSlaves[i].GetBR().GetY();
+ image_place = i;
+ }
+ }
+ GlobalData::TheOptimals.push_back(GlobalData::TheImagesFromSlaves[image_place]);
+ return GlobalData::TheImagesFromSlaves[image_place];
+};
+
+PointForSlave SlavesManager::next_point_to_send(ImageFromSlave selected_image, float next_minimum_line)
+{
+ next_minimum_line = selected_image.GetBR().GetX();
+ float R;
+ if (selected_image.GetBR().GetY() >= GlobalData::mapReqGlobal.GetBR().GetY())
+ {
+ if (selected_image.GetBR().GetX() <= GlobalData::mapReqGlobal.GetBR().GetX())
+ {
+ PointForSlave P = PointForSlave(-1, -1);
+ return P;
+ }
+ GlobalData::MinimumLine = next_minimum_line;
+ R = GlobalData::mapReqGlobal.GetTL().GetY();
+ }
+ else
+ {
+ R = selected_image.GetBR().GetY();
+ }
+ PointForSlave P = PointForSlave(GlobalData::MinimumLine, R);
+ return P;
+}
+
+vector SlavesManager::random_slaves_for_getting_images(ImageFromSlave temporary[])
+{
+ vectorTheAnswersFromSlaves = { {} };
+ for (int i = 0; i < 5; i++)
+ {
+ Slave s;
+
+ //לקרוא
+ if (s.GetId() > 5)
+ s.setId(temporary[i].GetSlaveId());
+ vector ansFromOne = s.CheckIfIHaveImage(GlobalData::pfs, temporary);
+ //שליחה למאסטר אם יש או אין ואם יש לשלוח וקטור
+ //להשתמש struct של לשלוח הודעה
+ for (int j = 0; j < ansFromOne.size(); j++)
+ {
+ if (TheAnswersFromSlaves[0].GetSlaveId() == 0)
+ TheAnswersFromSlaves.clear();
+ TheAnswersFromSlaves.push_back(ansFromOne[j]);
+ }
+ }
+ return TheAnswersFromSlaves;
+}
+
+
+void SlavesManager::getARequestForAMap(Message* message)
+{
+ if (GlobalData::IsInProcess == true)
+ {
+ //לקרא לטסט שבודק שבאמת נכנס לתור
+ GlobalData::queueForReqToMap.push_back(message->messageParams->M_GOT_REQ_PARAMS);
+ return;
+ }
+ GlobalData::IsInProcess = true;
+ GlobalData::mapReqGlobal = message->messageParams->M_GOT_REQ_PARAMS.mp;
+ GlobalData::static_current_ID = message->messageParams->M_GOT_REQ_PARAMS.mp.getReqId();
+ GlobalData::MinimumLine = message->messageParams->M_GOT_REQ_PARAMS.mp.GetTL().GetX();
+ PointForSlave pfs1(message->messageParams->M_GOT_REQ_PARAMS.mp.GetTL().GetX(), message->messageParams->M_GOT_REQ_PARAMS.mp.GetTL().GetY());
+ GlobalData::pfs = pfs1;
+ this->TheWhileFunc();
+}
+
+
+void SlavesManager::getResponse_ImageFromSlave()
+{
+
+ //string result = format("handling the response from slave number: {}, in request ID: {}", ResFromSlave.slaveID, ResFromSlave.reqID);
+ //this->addEvent(result);
+ if (GlobalData::theCurrentAnswer.HaveOrNot_Image)
+ if (this->The_request_is_processed(GlobalData::theCurrentAnswer.imgRes.at(0).GetReqId()) == false)
+ {
+ return;
+ }
+ if (GlobalData::theCurrentAnswer.communication)
+ {
+ GlobalData::NumOfSlaves_HasToAnswer--;
+ if (GlobalData::theCurrentAnswer.HaveOrNot_Image)
+ GlobalData::theBoolAnswers[GlobalData::NumOfSlaves_HasToAnswer] = true;
+ for (int i = 0; i < GlobalData::theCurrentAnswer.imgRes.size(); i++)
+ {
+ GlobalData::TheImagesFromSlaves.push_back(GlobalData::theCurrentAnswer.imgRes[i]);
+ }
+ }
+ else
+ {
+ GlobalData::didntCommunicate++;
+ GlobalData::SlavesThatDiDntCommunicate.push_back(GlobalData::theCurrentAnswer.slaveID);
+ //שליחה לטסט לבדיקה של הפונקציה:
+ // forCaseSeveralDidntAnswer
+ Message* msg = new Message;
+ msg->messageParams = new MessageParams;
+ msg->messageParams->MTM_SLAVES_NOT_COMMUNICATE_PARAMS.SlavesWithNoCommunication = GlobalData::SlavesThatDiDntCommunicate;
+ //אמור להיות פונקציה ששולחת לאופרטור!? את מי שלא ענה
+ this->getTheSlavesThatDidntCommunicate(msg);
+ //????? GlobalData::IsInProcess = false;
+
+ }
+ if (GlobalData::didntCommunicate == ARRAYSIZE)
+ {
+
+ //שליחה לטסט לבדיקה של הפונקציה no comments
+ //
+ string toMsg = "everyone didnt communicate";
+ MessageOfNoCommuincationBetwwenAllSlaves msgOfNoCom{ toMsg };
+
+ //אמור להיות פונקציה ששולחת לאופרטור!? את מי שלא ענה
+ //צריך פה פונקציה שמקבלת את ההודעה?
+ GlobalData::IsInProcess = false;
+ }
+ //צריך לשאול האם עברה שניה ולא האם זה שווה 0
+ if (GlobalData::NumOfSlaves_HasToAnswer == 0)
+ {
+ bool ThereIsAnImage = false;
+ for (size_t i = 0; i < GlobalData::theBoolAnswers.size(); i++)
+ {
+ if (GlobalData::theBoolAnswers.at(i) == true)
+ {
+ ThereIsAnImage = true;
+ break;
+ }
+ }
+ if (ThereIsAnImage == false)
+ {
+ Message* msg = new Message;
+ msg->messageParams = new MessageParams;
+
+ msg->messageParams->MTS_REQ_FOR_PHOTO_PARAMS.pfs = GlobalData::pfs;
+ this->sendMessageToTakeAPicture(msg);
+ //איך ממשיכים מפה?
+ GlobalData::IsInProcess = false;
+ return;
+ }
+ this->addEvent("Choose the optimal image from the vector of responses");
+ ImageFromSlave TheChosenImage = this->ChooseTheOptimalImage();
+ this->addEvent("Calculate the next point to send to slaves & quot");
+ GlobalData::pfs = this->next_point_to_send(TheChosenImage, TheChosenImage.GetBR().GetX());
+ if (GlobalData::pfs.GetX() == -1 && GlobalData::pfs.GetY() == -1)
+ {
+ for (size_t i = 0; i < GlobalData::TheOptimals.size(); i++)
+ {
+ // string result = format("Send message to slave {} to get real image by it's properties ", GlobalData::TheOptimals.at(i).GetSlaveId());
+ //this->addEvent(result);
+ Message* msg = new Message;
+ msg->messageParams = new MessageParams;
+ msg->messageParams->MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS.img = GlobalData::TheOptimals.at(i);
+ //שליחה לתקשורת
+ //SendMessage(mtsR);
+ this->sendRequestToSlaveToGetRealImage(msg);
+ }
+ //שולח בקשות לסלייבים לקבלת תמונות אמיתיות
+ }
+ else
+ {
+ this->TheWhileFunc();
+ }
+ }
+
+}
+void SlavesManager::sendRequestToSlaveToGetRealImage(Message* message)
+{
+ //for (size_t i = 0; i < GlobalData::TheOptimals.size(); i++)
+ //{
+ // // string result = format("Send message to slave {} to get real image by it's properties ", GlobalData::TheOptimals.at(i).GetSlaveId());
+ // //this->addEvent(result);
+ // messageToSlaveToGetRealImage mtsR{ GlobalData::TheOptimals.at(i) };
+ // //שליחה לתקשורת
+ // //SendMessage(mtsR);
+
+ // ResponseToGetRealImageFromSlave res = handleMessage3(mtsR);
+ // handleMessage4(res);
+ //}
+
+ handleMessage3(message);
+ handleMessage4();
+}
+
+
+void SlavesManager::getTheRealImageFromSlave()
+{
+ //string result = std::format("handling the response of real image from slave {} ", resFromSlave.realImg.getSlaveId());
+ //this->addEvent(result);
+ if (GlobalData::theCurrentRealImageResFromSlave.realImg.getSlaveId() != -1)
+ GlobalData::RealImagesV.push_back(GlobalData::theCurrentRealImageResFromSlave.realImg);
+ if (GlobalData::RealImagesV.size() == GlobalData::TheOptimals.size())
+ {
+ this->addEvent("Send the parts of the map to openCV API");
+ //שליחה לפונקציה של OpenCV
+ //שמקבלת וקטור של תמונות אמיתיות ומחזירה את המפה השלמה בתצורה של וקטור על וקטור
+ //שליחת המפה השלמה לאופרטור
+ GlobalData::RealImagesV.clear();
+ GlobalData::TheOptimals.clear();
+ GlobalData::IsInProcess = false;
+ if (!GlobalData::queueForReqToMap.empty())
+ {
+ Message* mesg = new Message;
+ mesg->messageParams = new MessageParams;
+ mesg->messageParams->M_GOT_REQ_PARAMS = GlobalData::queueForReqToMap.at(0);
+ this->getARequestForAMap(mesg);
+ GlobalData::queueForReqToMap.erase(GlobalData::queueForReqToMap.begin());
+ }
+ }
+}
+
+bool SlavesManager::checking_if_there_is_a_real_picture(ResponseToGetRealImageFromSlave RealI)
+{
+ if (RealI.realImg.getSlaveId() == -1)
+ return false;
+ return true;
+}
+
+void SlavesManager::sendMessageToTakeAPicture(Message* message)
+{
+ for (size_t i = 0; i < 5; i++)
+ {
+ MTS_REQ_FOR_PHOTO_PARAMS rfp{ GlobalData::pfs };
+ }
+}
+
+
+
+void SlavesManager::getTheSlavesThatDidntCommunicate(Message* message)
+{
+ //get the slaves that didnt communicate and send to the api that take care of it.
+};
+
+void SlavesManager::TheWhileFunc()
+{
+ GlobalData::NumOfSlaves_HasToAnswer = ARRAYSIZE;
+ GlobalData::theBoolAnswers = { false, false, false, false, false };
+ GlobalData::TheImagesFromSlaves.clear();
+ GlobalData::SlavesThatDiDntCommunicate.clear();
+ GlobalData::didntCommunicate = 0;
+ Slave mySlaves[ARRAYSIZE];
+ for (int i = 0; i < ARRAYSIZE; i++)
+ {
+ if (mySlaves[i].GetId() > 5)
+ mySlaves[i].setId(i);
+ // string result = format("message to slave {} to get image properties in specific point ", mySlaves[i].GetId());
+ // this->addEvent(result);
+
+ Message* mesg = new Message;
+ mesg->messageParams = new MessageParams;
+ mesg->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.pfs = GlobalData::pfs;
+ mesg->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.reqId = GlobalData::static_current_ID;
+ mesg->messageParams->MTS_ASK_FOR_IMAGES_PROP_PARAMS.slaveId = i;
+
+
+
+ //שליחה לתקשורת
+ //SendMessage(msg);
+
+ handleMassage1(mesg);
+ handleMassage2();
+ }
+};
+
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/SlavesManager.h b/Master_Slave_Management/Master_Slave_Management/SlavesManager.h
new file mode 100644
index 0000000..77712d7
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/SlavesManager.h
@@ -0,0 +1,74 @@
+#include
+#include "ImageFromSlave.h"
+#include "mapRequest.h"
+#include "Structs.h"
+#include "Message.h"
+
+using namespace std;
+
+
+struct GlobalData {
+ static int static_current_ID;
+ static vector TheImagesFromSlaves;
+ static STM_SEND_IMAGES_PROP_PARAMS theCurrentAnswer;
+ static STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS theCurrentRealImageResFromSlave;
+ static int NumOfSlaves_HasToAnswer;
+ static vector theBoolAnswers;
+ static float MinimumLine;
+ static vector TheOptimals;
+ static PointForSlave pfs;
+ static mapRequest mapReqGlobal;
+ static vector RealImagesV;
+ static bool IsInProcess;
+ static vector queueForReqToMap;
+ static int didntCommunicate;
+ static vectorSlavesThatDiDntCommunicate;
+
+
+
+
+};
+
+
+class SlavesManager {
+public:
+ void addEvent(string event);
+ bool handle_photo_request();
+ bool verify_photo(bool photo_taken);
+ bool no_comments();
+ int belongs_to_the_current_process(int ID, int current_ID, int number_of_slaves);
+ bool the_irrelevant_images_did_not_enter_the_array(const vector& IDresponses, int current_ID);
+ bool request_for_a_map_arrived(bool map_request);
+ bool Enter_the_queue(int map_request_ID);
+ bool The_request_is_processed(int map_request_ID);
+
+ ImageFromSlave ChooseTheOptimalImage();
+
+ PointForSlave next_point_to_send(ImageFromSlave selected_image, float next_minimum_line);
+
+ vectorrandom_slaves_for_getting_images(ImageFromSlave temporary[]);
+ void getARequestForAMap(Message* message);
+
+
+ void getResponse_ImageFromSlave();
+ void sendRequestToSlaveToGetRealImage(Message* message);//MTS_GIVE_THE_CHOSEN_IMAGE
+
+ void getTheRealImageFromSlave();
+
+ bool checking_if_there_is_a_real_picture(ResponseToGetRealImageFromSlave RealI);
+ void sendMessageToTakeAPicture(Message* message);
+ bool forCaseSeveralDidntAnswer(int numOfSlaves);
+
+ void getTheSlavesThatDidntCommunicate(Message* message);
+ void TheWhileFunc();
+};
+
+
+
+//void getARequestForAMap(Message* message) {};//M_GOT_REQ
+//void sendRequestForImageInSpecificPoint(Message* message) {};//MTS_ASK_FOR_IMAGES
+//void GetAStructForImageInPoint(Message* message) {};//STM_SEND_IMAGE_PROP
+//void sendRequestToSlaveToGetRealImage(Message* message) {};//MTS_GIVE_THE_CHOSEN_IMAGE
+//void return_of_an_image_by_its_properties(Message* message) {};//STM_RESPONSE_TO_THE_CHOSEN_IMAGE
+//void sendMessageToTakeAPicture(Message* message) {};//MTS_REQ_FOR_PHOTO
+//void getTheSlavesThatDidntCommunicate(Message* message) {};//MTM_SLAVES_NOT_COMMUNICATE
diff --git a/Master_Slave_Management/Master_Slave_Management/Structs.h b/Master_Slave_Management/Master_Slave_Management/Structs.h
new file mode 100644
index 0000000..38edc60
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Structs.h
@@ -0,0 +1,113 @@
+#pragma once
+#include "ImageFromSlave.h"
+
+#include
+#include "mapRequest.h"
+#include "RealImage.h"
+
+using namespace std;
+
+enum MessageTypesForReq
+{
+ M_GOT_REQ,
+ MTS_ASK_FOR_IMAGES,
+ STM_SEND_IMAGE_PROP,
+ MTS_GIVE_THE_CHOSEN_IMAGE,
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE,
+ MTIP_REQ_FOR_REAL_MAP,
+ MTS_REQ_FOR_PHOTO,
+ MTM_NO_COMMUNICATION_AT_ALL,
+ MTM_SLAVES_NOT_COMMUNICATE,
+ //IPTM_SEND_THE_IMAGES,
+};
+
+struct getRequestForMap
+{
+ mapRequest mp;
+ //MESSAGE_TYPE:M_GOT_REQ
+ //handling function: SlavesManager::getARequestForAMap
+};
+struct messageToSlaveToGetImage
+{
+ PointForSlave pfs;
+ int slaveId;
+ int reqId;
+
+ //MESSAGE_TYPE:MTS_ASK_FOR_IMAGES
+ //handling function: Slave::GetAStructForImageInPoint
+};
+struct ResponseToGetImageFromSlave
+{
+ int reqID;
+ int slaveID;
+ bool HaveOrNot_Image;
+ bool communication = false;
+ vector imgRes = {};
+ //MESSAGE_TYPE:STM_SEND_IMAGE_PROP
+ //handling function: SlaveManager::getResponse_ImageFromSlave
+};
+
+
+struct messageToSlaveToGetRealImage
+{
+ ImageFromSlave img;
+ //MESSAGE_TYPE:MTS_GIVE_THE_CHOSEN_IMAGE
+ //handling function:Slave::return_of_an_image_by_its_properties
+};
+
+struct ResponseToGetRealImageFromSlave
+{
+ RealImage realImg;
+ //MESSAGE_TYPE:STM_RESPONSE_TO_THE_CHOSEN_IMAGE
+ //handling function:SlaveManager::getTheRealImageFromSlave
+};
+
+struct RequestToReceiveAMapFromOpenCV
+{
+ vector realImages;
+ //MESSAGE_TYPE: MTIP_REQ_FOR_REAL_MAP,
+ //handling function:openCV API has to get the message and handle it.
+};
+
+struct CallARequestForAPhoto
+{
+ PointForSlave pfs;
+ //MESSAGE_TYPE:MTS_REQ_FOR_PHOTO,
+ //handling function:SlavesManager::sendMessageToTakeAPicture(PointForSlave pfs)
+};
+
+struct MessageOfNoCommuincationBetwwenAllSlaves
+{
+ string msg22;
+ //MESSAGE_TYPE:MTM_NO_COMMUNICATION_AT_ALL,
+ //handling function:__________________
+};
+struct GetTheSlavesThatDidntCommunicate
+{
+ vector SlavesWithNoCommunication;
+ //MESSAGE_TYPE:MTM_SLAVES_NOT_COMMUNICATE
+ //handling function:SlavesManager::getTheSlavesThatDidntCommunicate
+};
+
+
+//void getARequestForAMap(Message* message) {};//M_GOT_REQ
+//void sendRequestForImageInSpecificPoint(Message* message) {};//MTS_ASK_FOR_IMAGES
+//void GetAStructForImageInPoint(Message* message) {};//STM_SEND_IMAGE_PROP
+//void sendRequestToSlaveToGetRealImage(Message* message) {};//MTS_GIVE_THE_CHOSEN_IMAGE
+//void return_of_an_image_by_its_properties(Message* message) {};//STM_RESPONSE_TO_THE_CHOSEN_IMAGE
+//void sendMessageToTakeAPicture(Message* message) {};//MTS_REQ_FOR_PHOTO
+//void getTheSlavesThatDidntCommunicate(Message* message) {};//MTM_SLAVES_NOT_COMMUNICATE
+//void receiveEventsFromSlave(Message* message) {};//STM_GET_EVENTS_PARAMS
+//void getEvents(Message* message) {};//MTS_SEND_EVENTS_PARAMS
+//void handleLocation(Message* message) {};//MTS_SEND_LOCATIONint sec
+//void moveFromYourPlaceSafely(Message* message) {};//MTS_MOVE_OUT_OF_THIS_AREA
+//void setSendLocation(Message* message) {};//MTS_STOP_SEND_LOCATION
+//void updateDroneLocation(Message* message) {};//STM_LOCATION
+//
+
+
+
+
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Test.cpp b/Master_Slave_Management/Master_Slave_Management/Test.cpp
new file mode 100644
index 0000000..b5452d1
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Test.cpp
@@ -0,0 +1,456 @@
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+#include "docTest.h"
+#include
+#include
+#include
+#include
+#include "ImageFromSlave.h"
+#include "Slave.h"
+#include "mapRequest.h"
+#include "SlavesManager.h"
+
+using namespace std;
+
+ImageFromSlave Temporary0[6] =
+{
+ { 31.8200,35.1766,31.8000,35.2075,1,0},
+ { 31.8000,35.1766,31.7961,35.2075,2,0},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 31.8200, 35.1766, 31.6060, 35.1930,2,0 },
+ { 31.8140, 35.1860, 31.8000, 35.2025,3,0 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,4,0 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,0 }
+};
+ImageFromSlave Temporary1[6] =
+{
+ { 31.8200,35.1766,31.8000,35.2075,1,1},
+ { 31.8000,35.1766,31.7961,35.2075,2,1},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 31.8200, 35.1766, 31.6060, 35.1930,2,1 },
+ { 31.8140, 35.1860, 31.8000, 35.2025,3,1 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,4,1 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,1 }
+};
+ImageFromSlave Temporary2[6] =
+{
+ { 31.8200,35.1766,31.8000,35.2075,1,2},
+ { 31.8000,35.1766,31.7961,35.2075,2,2},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 31.8200, 35.1766, 31.6060, 35.1930,2,2 },
+ { 31.8140, 35.1860, 31.8000, 35.2025,3,2 },
+ { 32.7941f, 35.5812f, 32.7963f, 35.5841f,4,2 },
+ { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,2 }
+};
+
+ImageFromSlave Temporary3[6] =
+{
+ { 100,100,100,100,1,3},
+ { 100,100,100,100,2,3},
+ //{ 31.8200, 35.1766, 31.7961, 35.2075,1,12 },
+ { 100,100,100,100,2,3 },
+ { 100,100,100,100,3,3 },
+ { 100,100,100,100,4,3 },
+ { 100,100,100,100,5,3 }
+};
+
+ImageFromSlave Temporary6[6] = {
+ //31.8200, 35.1766);
+ //31.7961, 35.2075);
+ { 31.8200, 35.1766,31.7961, 35.2075,1,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,3,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,4,6},
+ { 31.8200, 35.1766,31.7961, 35.2075,5,6},
+};
+ImageFromSlave Temporary7[6] = {
+ //31.8200, 35.1766);
+ //31.7961, 35.2075);
+ { 31.8200, 35.1766,31.7961, 35.2075,0,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,3,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,4,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,5,7},
+};
+
+ImageFromSlave Temporary8[6] = {
+ //31.8200, 35.1766);
+ //31.7961, 35.2075);
+ { 31.8200, 35.1766,31.7961, 35.2075,0,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,7},
+ { 31.8200, 35.1766,31.7961, 35.2075,0,8},
+ { 31.8200, 35.1766,31.7961, 35.2075,1,8},
+ { 31.8200, 35.1766,31.7961, 35.2075,2,8},
+};
+
+//addEvent(".........")
+//הכל יתרחש בתוך פחות משניה.
+TEST_CASE("test end to end")
+{
+ SlavesManager manager;
+ mapRequest MapReq;
+ Message* message = new Message;
+ message->messageParams = new MessageParams;
+ message->messageParams->M_GOT_REQ_PARAMS.mp = MapReq;
+ manager.addEvent("get request for a map");
+ manager.getARequestForAMap(message);
+
+ CHECK(manager.The_request_is_processed(GlobalData::mapReqGlobal.getReqId()) == true);
+
+ //check that at least one answered yet
+ //CHECK(manager.handle_photo_request() == false);
+
+ //check that everyone answered
+ //CHECK(manager.no_comments() == true);
+
+ //CHECK(GlobalData::TheOptimals[0].GetBR().GetY() == Temporary0[0].GetBR().GetY());
+ //CHECK(GlobalData::TheOptimals[0].GetBR().GetX() == Temporary0[0].GetBR().GetX());
+ //CHECK(GlobalData::TheOptimals[0].GetTL().GetY() == Temporary0[0].GetTL().GetY());
+ //CHECK(GlobalData::TheOptimals[0].GetTL().GetX() == Temporary0[0].GetTL().GetX());
+ //
+ //CHECK(GlobalData::TheOptimals[1].GetBR().GetY() == Temporary0[1].GetBR().GetY());
+ //CHECK(GlobalData::TheOptimals[1].GetBR().GetX() == Temporary0[1].GetBR().GetX());
+ //CHECK(GlobalData::TheOptimals[1].GetTL().GetY() == Temporary0[1].GetTL().GetY());
+ //CHECK(GlobalData::TheOptimals[1].GetTL().GetX() == Temporary0[1].GetTL().GetX());
+}
+
+
+//Several requests to map at the same time
+TEST_CASE("test end to end - case several requests to map at the same time")
+{
+ SlavesManager manager;
+ mapRequest MapReq;
+ Message* message = new Message;
+ message->messageParams = new MessageParams;
+ message->messageParams->M_GOT_REQ_PARAMS.mp = MapReq;
+ manager.addEvent("get request for a map");
+ manager.getARequestForAMap(message);
+
+
+
+ Message* message1 = new Message;
+ message->messageParams->M_GOT_REQ_PARAMS.mp = MapReq;
+ manager.addEvent("get request for a map");
+ manager.getARequestForAMap(message1);
+
+
+ CHECK(manager.The_request_is_processed(GlobalData::mapReqGlobal.getReqId()) == true);
+
+ //CHECK(manager.Enter_the_queue(getreqMap1.mp.getReqId()) == true);
+
+
+ //CHECK(GlobalData::TheOptimals[0].GetBR().GetY() == Temporary1[0].GetBR().GetY());
+ //CHECK(GlobalData::TheOptimals[0].GetBR().GetX() == Temporary1[0].GetBR().GetX());
+ //CHECK(GlobalData::TheOptimals[0].GetTL().GetY() == Temporary1[0].GetTL().GetY());
+ //CHECK(GlobalData::TheOptimals[0].GetTL().GetX() == Temporary1[0].GetTL().GetX());
+ //
+ //CHECK(GlobalData::TheOptimals[1].GetBR().GetY() == Temporary1[1].GetBR().GetY());
+ //CHECK(GlobalData::TheOptimals[1].GetBR().GetX() == Temporary1[1].GetBR().GetX());
+ //CHECK(GlobalData::TheOptimals[1].GetTL().GetY() == Temporary1[1].GetTL().GetY());
+ //CHECK(GlobalData::TheOptimals[1].GetTL().GetX() == Temporary1[1].GetTL().GetX());
+
+ //CHECK(manager.The_request_is_processed(GlobalData::mapReqGlobal.getReqId()) == true);
+
+
+ //CHECK(GlobalData::TheOptimals[0].GetBR().GetY() == Temporary2[0].GetBR().GetY());
+ //CHECK(GlobalData::TheOptimals[0].GetBR().GetX() == Temporary2[0].GetBR().GetX());
+ //CHECK(GlobalData::TheOptimals[0].GetTL().GetY() == Temporary2[0].GetTL().GetY());
+ //CHECK(GlobalData::TheOptimals[0].GetTL().GetX() == Temporary2[0].GetTL().GetX());
+ //
+ //CHECK(GlobalData::TheOptimals[1].GetBR().GetY() == Temporary2[1].GetBR().GetY());
+ //CHECK(GlobalData::TheOptimals[1].GetBR().GetX() == Temporary2[1].GetBR().GetX());
+ //CHECK(GlobalData::TheOptimals[1].GetTL().GetY() == Temporary2[1].GetTL().GetY());
+ //CHECK(GlobalData::TheOptimals[1].GetTL().GetX() == Temporary2[1].GetTL().GetX());
+
+}
+
+
+////Everyone sends a negative answer
+
+TEST_CASE("test end to end - case everyone sends a negative answer")
+{
+ SlavesManager manager;
+ mapRequest MapReq;
+ Message* message = new Message;
+ message->messageParams = new MessageParams;
+ message->messageParams->M_GOT_REQ_PARAMS.mp = MapReq;
+ manager.addEvent("get request for a map");
+ manager.getARequestForAMap(message);
+
+
+ CHECK(manager.The_request_is_processed(GlobalData::mapReqGlobal.getReqId()) == true);
+
+ ////check that everyone answered
+ //CHECK(manager.no_comments(NumOfSlaves_HasToAnswer) == true);
+
+ ////check that at least one answered yet
+ //CHECK(manager.handle_photo_request(theBoolAnswers) == true);
+
+}
+
+
+//Several photo requests that are not answered
+
+TEST_CASE("test end to end - case everyone didn't answered")
+{
+ SlavesManager manager;
+ mapRequest MapReq;
+ Message* message = new Message;
+ message->messageParams = new MessageParams;
+ message->messageParams->M_GOT_REQ_PARAMS.mp = MapReq;
+ manager.addEvent("get request for a map");
+ manager.getARequestForAMap(message);
+
+ CHECK(manager.The_request_is_processed(GlobalData::mapReqGlobal.getReqId()) == true);
+
+ //check that everyone answered
+ //CHECK(manager.no_comments(NumOfSlaves_HasToAnswer) == false);
+
+}
+
+
+//case several didnt communicate
+//TEST_CASE("test end to end - case several requests not answered")
+//{
+// SlavesManager manager;
+// mapRequest MapReq;
+// Message* message = new Message;
+// message->messageParams = new MessageParams;
+// message->messageParams->M_GOT_REQ_PARAMS.mp = MapReq;
+// manager.addEvent("get request for a map");
+// manager.getARequestForAMap(message);
+//
+// CHECK(manager.The_request_is_processed(GlobalData::mapReqGlobal.getReqId()) == true);
+//
+// //CHECK(manager.forCaseSeveralDidntAnswer(NumOfSlaves_HasToAnswer) == false);
+//
+// //CHECK(manager.no_comments(NumOfSlaves_HasToAnswer) == true);
+//
+// //CHECK(manager.handle_photo_request(theBoolAnswers) == false);
+//
+// //CHECK(TheOptimals[0].GetBR().GetY() == Temporary6[0].GetBR().GetY());
+// //CHECK(TheOptimals[0].GetBR().GetX() == Temporary6[0].GetBR().GetX());
+// //CHECK(TheOptimals[0].GetTL().GetY() == Temporary6[0].GetTL().GetY());
+// //CHECK(TheOptimals[0].GetTL().GetX() == Temporary6[0].GetTL().GetX());
+//}
+
+
+////Test response handling after timer
+//
+//TEST_CASE("test end to end - case response handling after timer")
+//{
+// vector realImages;
+// vector TheOptimals;
+// mapRequest MapReq;
+// SlavesManager manager;
+// float MinimumLine;
+// getRequestForMap getreqMap = { MapReq };
+// PointForSlave pfs = manager.getARequestForAMap(getreqMap, MinimumLine);
+//
+// CHECK(manager.The_request_is_processed(MapReq.getReqId()) == true);
+//
+//#define INVALIDNUM -1
+//
+// while (pfs.GetX() != INVALIDNUM && pfs.GetY() != INVALIDNUM)//כל עוד זה לא סוף התמונה
+// {
+// vector TheImagesFromSlaves = { {0,0,0,0,0,0} };
+// vector resultFromSlaves = {};
+//
+//#define ARRAYSIZE 5
+// vector theBoolAnswers(ARRAYSIZE, false);
+//
+// int NumOfSlaves_HasToAnswer = ARRAYSIZE;
+//
+// Slave mySlaves[ARRAYSIZE];
+// auto startTime = chrono::steady_clock::now();
+// auto endTime = startTime + chrono::seconds(1);
+// while (chrono::steady_clock::now() < endTime)
+// {
+// for (int i = 0; i < ARRAYSIZE; i++)
+// {
+// if (mySlaves[i].GetId() > 5)
+// mySlaves[i].setId(i);
+//
+// messageToSlaveToGetImage msg = { pfs,i, MapReq.getReqId() };
+// ResponseToGetImageFromSlave resFromSlaveToTheMaster = mySlaves[i].GetAStructForImageInPoint(msg);
+// if (resFromSlaveToTheMaster.HaveOrNot_Image)
+// CHECK(manager.The_request_is_processed(resFromSlaveToTheMaster.imgRes.at(0).GetReqId()) == true);
+// ResponseToGetImageFromSlave res =
+// manager.getResponse_ImageFromSlave(resFromSlaveToTheMaster, TheImagesFromSlaves,
+// NumOfSlaves_HasToAnswer, theBoolAnswers);
+// auto startTime = chrono::steady_clock::now();
+// auto endTime = startTime + chrono::seconds(1);
+// while (chrono::steady_clock::now() < endTime) {}
+// }
+// }
+// //check that at least one answered yet
+// CHECK(manager.handle_photo_request(theBoolAnswers) == false);
+//
+// //check that everyone answered
+// CHECK(manager.no_comments(NumOfSlaves_HasToAnswer) == true);
+//
+// ImageFromSlave TheChosenImage = manager.ChooseTheOptimalImage(TheImagesFromSlaves, TheOptimals);
+// pfs = manager.next_point_to_send(TheChosenImage,
+// MapReq, MinimumLine, TheChosenImage.GetBR().GetX());
+// }
+//
+// CHECK(TheOptimals[0].GetBR().GetY() == Temporary7[0].GetBR().GetY());
+// CHECK(TheOptimals[0].GetBR().GetX() == Temporary7[0].GetBR().GetX());
+// CHECK(TheOptimals[0].GetTL().GetY() == Temporary7[0].GetTL().GetY());
+// CHECK(TheOptimals[0].GetTL().GetX() == Temporary7[0].GetTL().GetX());
+//
+//
+// Slave mySlaves[10] = {};
+// for (int i = 0; i < 10; i++)
+// {
+// mySlaves[i].setId(i);
+// }
+// for (size_t i = 0; i < TheOptimals.size(); i++)
+// {
+// messageToSlaveToGetRealImage mtsR{ TheOptimals.at(i) };
+// ResponseToGetRealImageFromSlave RealI = mySlaves[TheOptimals.at(i).GetSlaveId()].return_of_an_image_by_its_properties(mtsR);
+// CHECK(manager.checking_if_there_is_a_real_picture(RealI) == true);
+// manager.getTheRealImageFromSlave(RealI, realImages);
+// }
+// RequestToReceiveAMapFromOpenCV ROpenCV{ realImages };
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////
+// vector realImages1;
+// vector TheOptimals1;
+// mapRequest MapReq1;
+// SlavesManager manager1;
+// float MinimumLine1;
+// getRequestForMap getreqMap1 = { MapReq1 };
+// PointForSlave pfs1 = manager1.getARequestForAMap(getreqMap1, MinimumLine1);
+//
+// CHECK(manager1.The_request_is_processed(MapReq1.getReqId()) == true);
+//
+//#define INVALIDNUM -1
+//
+// while (pfs1.GetX() != INVALIDNUM && pfs1.GetY() != INVALIDNUM)//כל עוד זה לא סוף התמונה
+// {
+// vector TheImagesFromSlaves = { {0,0,0,0,0,0} };
+// vector resultFromSlaves = {};
+//
+//#define ARRAYSIZE 5
+// vector theBoolAnswers(ARRAYSIZE, false);
+//
+// int NumOfSlaves_HasToAnswer = ARRAYSIZE;
+//
+// Slave mySlaves[ARRAYSIZE];
+// for (int i = 0; i < ARRAYSIZE; i++)
+// {
+// if (mySlaves[i].GetId() > 5)
+// mySlaves[i].setId(i);
+//
+// messageToSlaveToGetImage msg = { pfs1,i, MapReq1.getReqId() };
+// ResponseToGetImageFromSlave resFromSlaveToTheMaster = mySlaves[i].GetAStructForImageInPoint(msg);
+// if (resFromSlaveToTheMaster.HaveOrNot_Image)
+// CHECK(manager1.The_request_is_processed(resFromSlaveToTheMaster.imgRes.at(0).GetReqId()) == true);
+// ResponseToGetImageFromSlave res =
+// manager1.getResponse_ImageFromSlave(resFromSlaveToTheMaster, TheImagesFromSlaves,
+// NumOfSlaves_HasToAnswer, theBoolAnswers);
+// }
+//
+// //check that at least one answered yet
+// CHECK(manager1.handle_photo_request(theBoolAnswers) == false);
+//
+// //check that everyone answered
+// CHECK(manager1.no_comments(NumOfSlaves_HasToAnswer) == true);
+//
+// ImageFromSlave TheChosenImage = manager1.ChooseTheOptimalImage(TheImagesFromSlaves, TheOptimals1);
+// pfs1 = manager1.next_point_to_send(TheChosenImage,
+// MapReq1, MinimumLine1, TheChosenImage.GetBR().GetX());
+// }
+//
+// CHECK(TheOptimals1[0].GetBR().GetY() == Temporary8[0].GetBR().GetY());
+// CHECK(TheOptimals1[0].GetBR().GetX() == Temporary8[0].GetBR().GetX());
+// CHECK(TheOptimals1[0].GetTL().GetY() == Temporary8[0].GetTL().GetY());
+// CHECK(TheOptimals1[0].GetTL().GetX() == Temporary8[0].GetTL().GetX());
+//
+//
+// Slave mySlaves1[10] = {};
+// for (int i = 0; i < 10; i++)
+// {
+// mySlaves1[i].setId(i);
+// }
+// for (size_t i = 0; i < TheOptimals1.size(); i++)
+// {
+// messageToSlaveToGetRealImage mtsR{ TheOptimals1.at(i) };
+// ResponseToGetRealImageFromSlave RealI = mySlaves1[TheOptimals1.at(i).GetSlaveId()].return_of_an_image_by_its_properties(mtsR);
+// CHECK(manager1.checking_if_there_is_a_real_picture(RealI) == true);
+// manager1.getTheRealImageFromSlave(RealI, realImages1);
+// }
+// RequestToReceiveAMapFromOpenCV ROpenCV1{ realImages1 };
+// //קבלת המפה
+//}
+//
+////טסטים על פונקציות בנפרד
+//
+////בדיקה האם הרחפן מטפל כראוי וידע להחזיר תמונה כאשר היא קיימת.
+//TEST_CASE("slave handle the request well")
+//{
+// ImageFromSlave temporaryforme[5] =
+// {
+// { 32.7897f, 35.5785f, 32.7915f, 35.5809f,1,8 },
+// { 32.7880f, 35.5733f, 32.7902f, 35.5757f,1,8 },
+// { 32.7925f, 35.5769f, 32.7948f, 35.5792f,3,8 },
+// { 32.7941f, 35.5812f, 32.7963f, 35.5841f,3,8 },
+// { 32.7893f, 35.5749f, 32.7916f, 35.5780f,5,8 }
+// };
+//
+// ImageFromSlave ansimg[1] =
+// {
+// { 32.7897f, 35.5785f, 32.7915f, 35.5809f,1,8 },
+// };
+//
+//
+// Slave s;
+// s.setId(1);
+//
+// PointForSlave p(32.7897f, 35.5785f);
+// vector img;
+// messageToSlaveToGetImage m{ p,1,56 };
+// ResponseToGetImageFromSlave res = s.GetAStructForImageInPoint(m);
+//
+// /*ImageFromSlave forCounter;
+// int fC = forCounter.getCounter();*/
+//
+//
+//
+//
+// CHECK(res.imgRes[0].GetBR().GetY() == ansimg[0].GetBR().GetY());
+// CHECK(res.imgRes[0].GetBR().GetX() == ansimg[0].GetBR().GetX());
+// CHECK(res.imgRes[0].GetTL().GetY() == ansimg[0].GetTL().GetY());
+// CHECK(res.imgRes[0].GetTL().GetX() == ansimg[0].GetTL().GetX());
+//
+//}
+////
+////
+////
+//// שנבחרה התמונה האופטימלית בדיקה
+//TEST_CASE("check that the optimal image chosen")
+//{
+// vector TheOptimal;
+// vector TheImgProp =
+// {
+// { 32.7897f, 35.5785f, 32.7915f, 35.5809f,4,8 },
+// { 32.7880f, 35.5733f, 32.7902f, 35.5757f,9,8 },
+// { 32.7925f, 35.5769f, 32.7948f, 35.5792f,3,8 },
+// { 32.7941f, 35.5812f, 32.7963f, 35.5841f,7,8 },
+// { 32.7893f, 35.5749f, 32.7916f, 35.5780f,4,8 }
+// };
+//
+// SlavesManager manager;
+// ImageFromSlave img = manager.ChooseTheOptimalImage(TheImgProp,TheOptimal);
+//
+//
+// CHECK(img.GetSlaveId() == 7);
+//
+//}
+//
+
diff --git a/Master_Slave_Management/Master_Slave_Management/doctest.h b/Master_Slave_Management/Master_Slave_Management/doctest.h
new file mode 100644
index 0000000..692eb13
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/doctest.h
@@ -0,0 +1,7165 @@
+#pragma once
+
+// ====================================================================== lgtm [cpp/missing-header-guard]
+// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
+// ======================================================================
+//
+// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
+//
+// Copyright (c) 2016-2023 Viktor Kirilov
+//
+// Distributed under the MIT Software License
+// See accompanying file LICENSE.txt or copy at
+// https://opensource.org/licenses/MIT
+//
+// The documentation can be found at the library's page:
+// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+//
+// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt
+//
+// The concept of subcases (sections in Catch) and expression decomposition are from there.
+// Some parts of the code are taken directly:
+// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
+// - the Approx() helper class for floating point comparison
+// - colors in the console
+// - breaking into a debugger
+// - signal / SEH handling
+// - timer
+// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste)
+//
+// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+
+#ifndef DOCTEST_LIBRARY_INCLUDED
+#define DOCTEST_LIBRARY_INCLUDED
+
+// =================================================================================================
+// == VERSION ======================================================================================
+// =================================================================================================
+
+#define DOCTEST_VERSION_MAJOR 2
+#define DOCTEST_VERSION_MINOR 4
+#define DOCTEST_VERSION_PATCH 11
+
+// util we need here
+#define DOCTEST_TOSTR_IMPL(x) #x
+#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
+
+#define DOCTEST_VERSION_STR \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
+
+#define DOCTEST_VERSION \
+ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
+
+// =================================================================================================
+// == COMPILER VERSION =============================================================================
+// =================================================================================================
+
+// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
+
+#ifdef _MSC_VER
+#define DOCTEST_CPLUSPLUS _MSVC_LANG
+#else
+#define DOCTEST_CPLUSPLUS __cplusplus
+#endif
+
+#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
+
+// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
+#if defined(_MSC_VER) && defined(_MSC_FULL_VER)
+#if _MSC_VER == _MSC_FULL_VER / 10000
+#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
+#else // MSVC
+#define DOCTEST_MSVC \
+ DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
+#endif // MSVC
+#endif // MSVC
+#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
+ !defined(__INTEL_COMPILER)
+#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#endif // GCC
+#if defined(__INTEL_COMPILER)
+#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif // ICC
+
+#ifndef DOCTEST_MSVC
+#define DOCTEST_MSVC 0
+#endif // DOCTEST_MSVC
+#ifndef DOCTEST_CLANG
+#define DOCTEST_CLANG 0
+#endif // DOCTEST_CLANG
+#ifndef DOCTEST_GCC
+#define DOCTEST_GCC 0
+#endif // DOCTEST_GCC
+#ifndef DOCTEST_ICC
+#define DOCTEST_ICC 0
+#endif // DOCTEST_ICC
+
+// =================================================================================================
+// == COMPILER WARNINGS HELPERS ====================================================================
+// =================================================================================================
+
+#if DOCTEST_CLANG && !DOCTEST_ICC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#else // DOCTEST_CLANG
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_CLANG
+
+#if DOCTEST_GCC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
+#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w)
+#else // DOCTEST_GCC
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_GCC_SUPPRESS_WARNING(w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_GCC
+
+#if DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#else // DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_MSVC
+
+// =================================================================================================
+// == COMPILER WARNINGS ============================================================================
+// =================================================================================================
+
+// both the header and the implementation suppress all of these,
+// so it only makes sense to aggregate them like so
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
+ \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \
+ \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ /* these 4 also disabled globally via cmake: */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
+ /* common ones */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \
+ /* static analysis */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
+
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
+
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
+
+DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
+
+DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+// =================================================================================================
+// == FEATURE DETECTION ============================================================================
+// =================================================================================================
+
+// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support
+// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx
+// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
+// MSVC version table:
+// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
+// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
+// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
+// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
+// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
+// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
+// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
+// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
+// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
+// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
+
+// Universal Windows Platform support
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#define DOCTEST_CONFIG_NO_WINDOWS_SEH
+#endif // WINAPI_FAMILY
+#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#define DOCTEST_CONFIG_WINDOWS_SEH
+#endif // MSVC
+#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#undef DOCTEST_CONFIG_WINDOWS_SEH
+#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
+
+#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \
+ !defined(__EMSCRIPTEN__) && !defined(__wasi__)
+#define DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // _WIN32
+#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
+#undef DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \
+ || defined(__wasi__)
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // no exceptions
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
+#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#ifdef __wasi__
+#define DOCTEST_CONFIG_NO_MULTITHREADING
+#endif
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
+#define DOCTEST_CONFIG_IMPLEMENT
+#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#if DOCTEST_MSVC
+#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport)
+#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport)
+#else // MSVC
+#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport))
+#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport))
+#endif // MSVC
+#else // _WIN32
+#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default")))
+#define DOCTEST_SYMBOL_IMPORT
+#endif // _WIN32
+
+#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#ifdef DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT
+#else // DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT
+#endif // DOCTEST_CONFIG_IMPLEMENT
+#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#define DOCTEST_INTERFACE
+#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+
+// needed for extern template instantiations
+// see https://github.com/fmtlib/fmt/issues/2228
+#if DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL
+#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE
+#else // DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE
+#define DOCTEST_INTERFACE_DEF
+#endif // DOCTEST_MSVC
+
+#define DOCTEST_EMPTY
+
+#if DOCTEST_MSVC
+#define DOCTEST_NOINLINE __declspec(noinline)
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
+#define DOCTEST_NOINLINE
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#else
+#define DOCTEST_NOINLINE __attribute__((noinline))
+#define DOCTEST_UNUSED __attribute__((unused))
+#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
+#endif
+
+#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE
+#define DOCTEST_INLINE_NOINLINE inline
+#else
+#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE
+#endif
+
+#ifndef DOCTEST_NORETURN
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NORETURN
+#else // DOCTEST_MSVC
+#define DOCTEST_NORETURN [[noreturn]]
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_NORETURN
+
+#ifndef DOCTEST_NOEXCEPT
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NOEXCEPT
+#else // DOCTEST_MSVC
+#define DOCTEST_NOEXCEPT noexcept
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_NOEXCEPT
+
+#ifndef DOCTEST_CONSTEXPR
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_CONSTEXPR const
+#define DOCTEST_CONSTEXPR_FUNC inline
+#else // DOCTEST_MSVC
+#define DOCTEST_CONSTEXPR constexpr
+#define DOCTEST_CONSTEXPR_FUNC constexpr
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_CONSTEXPR
+
+#ifndef DOCTEST_NO_SANITIZE_INTEGER
+#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0)
+#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define DOCTEST_NO_SANITIZE_INTEGER
+#endif
+#endif // DOCTEST_NO_SANITIZE_INTEGER
+
+// =================================================================================================
+// == FEATURE DETECTION END ========================================================================
+// =================================================================================================
+
+#define DOCTEST_DECLARE_INTERFACE(name) \
+ virtual ~name(); \
+ name() = default; \
+ name(const name&) = delete; \
+ name(name&&) = delete; \
+ name& operator=(const name&) = delete; \
+ name& operator=(name&&) = delete;
+
+#define DOCTEST_DEFINE_INTERFACE(name) \
+ name::~name() = default;
+
+// internal macros for string concatenation and anonymous variable name generation
+#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
+#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
+#ifdef __COUNTER__ // not standard and may be missing for some compilers
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
+#else // __COUNTER__
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
+#endif // __COUNTER__
+
+#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x&
+#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x
+#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+
+// not using __APPLE__ because... this is how Catch does it
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+#define DOCTEST_PLATFORM_MAC
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#define DOCTEST_PLATFORM_IPHONE
+#elif defined(_WIN32)
+#define DOCTEST_PLATFORM_WINDOWS
+#elif defined(__wasi__)
+#define DOCTEST_PLATFORM_WASI
+#else // DOCTEST_PLATFORM
+#define DOCTEST_PLATFORM_LINUX
+#endif // DOCTEST_PLATFORM
+
+namespace doctest {
+ namespace detail {
+ static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; }
+ }
+}
+
+#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
+ static const int var = doctest::detail::consume(&var, __VA_ARGS__); \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#ifndef DOCTEST_BREAK_INTO_DEBUGGER
+// should probably take a look at https://github.com/scottt/debugbreak
+#ifdef DOCTEST_PLATFORM_LINUX
+#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+// Break at the location of the failing check if possible
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#else
+#include
+#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
+#endif
+#elif defined(DOCTEST_PLATFORM_MAC)
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#elif defined(__ppc__) || defined(__ppc64__)
+// https://www.cocoawithlove.com/2008/03/break-into-debugger.html
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler)
+#else
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler)
+#endif
+#elif DOCTEST_MSVC
+#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
+#elif defined(__MINGW32__)
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
+extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
+#else // linux
+#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0))
+#endif // linux
+#endif // DOCTEST_BREAK_INTO_DEBUGGER
+
+// this is kept here for backwards compatibility since the config option was changed
+#ifdef DOCTEST_CONFIG_USE_IOSFWD
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // DOCTEST_CONFIG_USE_IOSFWD
+
+// for clang - always include ciso646 (which drags some std stuff) because
+// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
+// which case we don't want to forward declare stuff from std - for reference:
+// https://github.com/doctest/doctest/issues/126
+// https://github.com/doctest/doctest/issues/356
+#if DOCTEST_CLANG
+#include
+#endif // clang
+
+#ifdef _LIBCPP_VERSION
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // _LIBCPP_VERSION
+
+#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
+#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
+#include
+#include
+#include
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
+#else // DOCTEST_CONFIG_USE_STD_HEADERS
+
+// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
+
+namespace std { // NOLINT(cert-dcl58-cpp)
+ typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using)
+ typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using)
+ template
+ struct char_traits;
+ template <>
+ struct char_traits;
+ template
+ class basic_ostream; // NOLINT(fuchsia-virtual-inheritance)
+ typedef basic_ostream> ostream; // NOLINT(modernize-use-using)
+ template
+ // NOLINTNEXTLINE
+ basic_ostream& operator<<(basic_ostream&, const char*);
+ template
+ class basic_istream;
+ typedef basic_istream> istream; // NOLINT(modernize-use-using)
+ template
+ class tuple;
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+ // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+ template
+ class allocator;
+ template
+ class basic_string;
+ using string = basic_string, allocator>;
+#endif // VS 2019
+} // namespace std
+
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_USE_STD_HEADERS
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#include
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+namespace doctest {
+
+ using std::size_t;
+
+ DOCTEST_INTERFACE extern bool is_running_in_test;
+
+#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE
+#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned
+#endif
+
+ // A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
+ // of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
+ // - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
+ // - if small - capacity left before going on the heap - using the lowest 5 bits
+ // - if small - 2 bits are left unused - the second and third highest ones
+ // - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator)
+ // and the "is small" bit remains "0" ("as well as the capacity left") so its OK
+ // Idea taken from this lecture about the string implementation of facebook/folly - fbstring
+ // https://www.youtube.com/watch?v=kPR8h4-qZdk
+ // TODO:
+ // - optimizations - like not deleting memory unnecessarily in operator= and etc.
+ // - resize/reserve/clear
+ // - replace
+ // - back/front
+ // - iterator stuff
+ // - find & friends
+ // - push_back/pop_back
+ // - assign/insert/erase
+ // - relational operators as free functions - taking const char* as one of the params
+ class DOCTEST_INTERFACE String
+ {
+ public:
+ using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE;
+
+ private:
+ static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members
+ static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members
+
+ struct view // len should be more than sizeof(view) - because of the final byte for flags
+ {
+ char* ptr;
+ size_type size;
+ size_type capacity;
+ };
+
+ union
+ {
+ char buf[len]; // NOLINT(*-avoid-c-arrays)
+ view data;
+ };
+
+ char* allocate(size_type sz);
+
+ bool isOnStack() const noexcept { return (buf[last] & 128) == 0; }
+ void setOnHeap() noexcept;
+ void setLast(size_type in = last) noexcept;
+ void setSize(size_type sz) noexcept;
+
+ void copy(const String& other);
+
+ public:
+ static DOCTEST_CONSTEXPR size_type npos = static_cast(-1);
+
+ String() noexcept;
+ ~String();
+
+ // cppcheck-suppress noExplicitConstructor
+ String(const char* in);
+ String(const char* in, size_type in_size);
+
+ String(std::istream& in, size_type in_size);
+
+ String(const String& other);
+ String& operator=(const String& other);
+
+ String& operator+=(const String& other);
+
+ String(String&& other) noexcept;
+ String& operator=(String&& other) noexcept;
+
+ char operator[](size_type i) const;
+ char& operator[](size_type i);
+
+ // the only functions I'm willing to leave in the interface - available for inlining
+ const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT
+ char* c_str() {
+ if (isOnStack()) {
+ return reinterpret_cast(buf);
+ }
+ return data.ptr;
+ }
+
+ size_type size() const;
+ size_type capacity() const;
+
+ String substr(size_type pos, size_type cnt = npos)&&;
+ String substr(size_type pos, size_type cnt = npos) const&;
+
+ size_type find(char ch, size_type pos = 0) const;
+ size_type rfind(char ch, size_type pos = npos) const;
+
+ int compare(const char* other, bool no_case = false) const;
+ int compare(const String& other, bool no_case = false) const;
+
+ friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
+ };
+
+ DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
+
+ DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
+
+ class DOCTEST_INTERFACE Contains {
+ public:
+ explicit Contains(const String& string);
+
+ bool checkWith(const String& other) const;
+
+ String string;
+ };
+
+ DOCTEST_INTERFACE String toString(const Contains& in);
+
+ DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs);
+ DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs);
+ DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs);
+
+ namespace Color {
+ enum Enum
+ {
+ None = 0,
+ White,
+ Red,
+ Green,
+ Blue,
+ Cyan,
+ Yellow,
+ Grey,
+
+ Bright = 0x10,
+
+ BrightRed = Bright | Red,
+ BrightGreen = Bright | Green,
+ LightGrey = Bright | Grey,
+ BrightWhite = Bright | White
+ };
+
+ DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code);
+ } // namespace Color
+
+ namespace assertType {
+ enum Enum
+ {
+ // macro traits
+
+ is_warn = 1,
+ is_check = 2 * is_warn,
+ is_require = 2 * is_check,
+
+ is_normal = 2 * is_require,
+ is_throws = 2 * is_normal,
+ is_throws_as = 2 * is_throws,
+ is_throws_with = 2 * is_throws_as,
+ is_nothrow = 2 * is_throws_with,
+
+ is_false = 2 * is_nothrow,
+ is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types
+
+ is_eq = 2 * is_unary,
+ is_ne = 2 * is_eq,
+
+ is_lt = 2 * is_ne,
+ is_gt = 2 * is_lt,
+
+ is_ge = 2 * is_gt,
+ is_le = 2 * is_ge,
+
+ // macro types
+
+ DT_WARN = is_normal | is_warn,
+ DT_CHECK = is_normal | is_check,
+ DT_REQUIRE = is_normal | is_require,
+
+ DT_WARN_FALSE = is_normal | is_false | is_warn,
+ DT_CHECK_FALSE = is_normal | is_false | is_check,
+ DT_REQUIRE_FALSE = is_normal | is_false | is_require,
+
+ DT_WARN_THROWS = is_throws | is_warn,
+ DT_CHECK_THROWS = is_throws | is_check,
+ DT_REQUIRE_THROWS = is_throws | is_require,
+
+ DT_WARN_THROWS_AS = is_throws_as | is_warn,
+ DT_CHECK_THROWS_AS = is_throws_as | is_check,
+ DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
+
+ DT_WARN_THROWS_WITH = is_throws_with | is_warn,
+ DT_CHECK_THROWS_WITH = is_throws_with | is_check,
+ DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
+
+ DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
+ DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
+ DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
+
+ DT_WARN_NOTHROW = is_nothrow | is_warn,
+ DT_CHECK_NOTHROW = is_nothrow | is_check,
+ DT_REQUIRE_NOTHROW = is_nothrow | is_require,
+
+ DT_WARN_EQ = is_normal | is_eq | is_warn,
+ DT_CHECK_EQ = is_normal | is_eq | is_check,
+ DT_REQUIRE_EQ = is_normal | is_eq | is_require,
+
+ DT_WARN_NE = is_normal | is_ne | is_warn,
+ DT_CHECK_NE = is_normal | is_ne | is_check,
+ DT_REQUIRE_NE = is_normal | is_ne | is_require,
+
+ DT_WARN_GT = is_normal | is_gt | is_warn,
+ DT_CHECK_GT = is_normal | is_gt | is_check,
+ DT_REQUIRE_GT = is_normal | is_gt | is_require,
+
+ DT_WARN_LT = is_normal | is_lt | is_warn,
+ DT_CHECK_LT = is_normal | is_lt | is_check,
+ DT_REQUIRE_LT = is_normal | is_lt | is_require,
+
+ DT_WARN_GE = is_normal | is_ge | is_warn,
+ DT_CHECK_GE = is_normal | is_ge | is_check,
+ DT_REQUIRE_GE = is_normal | is_ge | is_require,
+
+ DT_WARN_LE = is_normal | is_le | is_warn,
+ DT_CHECK_LE = is_normal | is_le | is_check,
+ DT_REQUIRE_LE = is_normal | is_le | is_require,
+
+ DT_WARN_UNARY = is_normal | is_unary | is_warn,
+ DT_CHECK_UNARY = is_normal | is_unary | is_check,
+ DT_REQUIRE_UNARY = is_normal | is_unary | is_require,
+
+ DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn,
+ DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check,
+ DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require,
+ };
+ } // namespace assertType
+
+ DOCTEST_INTERFACE const char* assertString(assertType::Enum at);
+ DOCTEST_INTERFACE const char* failureString(assertType::Enum at);
+ DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
+
+ struct DOCTEST_INTERFACE TestCaseData
+ {
+ String m_file; // the file in which the test was registered (using String - see #350)
+ unsigned m_line; // the line where the test was registered
+ const char* m_name; // name of the test case
+ const char* m_test_suite; // the test suite in which the test was added
+ const char* m_description;
+ bool m_skip;
+ bool m_no_breaks;
+ bool m_no_output;
+ bool m_may_fail;
+ bool m_should_fail;
+ int m_expected_failures;
+ double m_timeout;
+ };
+
+ struct DOCTEST_INTERFACE AssertData
+ {
+ // common - for all asserts
+ const TestCaseData* m_test_case;
+ assertType::Enum m_at;
+ const char* m_file;
+ int m_line;
+ const char* m_expr;
+ bool m_failed;
+
+ // exception-related - for all asserts
+ bool m_threw;
+ String m_exception;
+
+ // for normal asserts
+ String m_decomp;
+
+ // for specific exception-related asserts
+ bool m_threw_as;
+ const char* m_exception_type;
+
+ class DOCTEST_INTERFACE StringContains {
+ private:
+ Contains content;
+ bool isContains;
+
+ public:
+ StringContains(const String& str) : content(str), isContains(false) { }
+ StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { }
+
+ bool check(const String& str) { return isContains ? (content == str) : (content.string == str); }
+
+ operator const String& () const { return content.string; }
+
+ const char* c_str() const { return content.string.c_str(); }
+ } m_exception_string;
+
+ AssertData(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const StringContains& exception_string);
+ };
+
+ struct DOCTEST_INTERFACE MessageData
+ {
+ String m_string;
+ const char* m_file;
+ int m_line;
+ assertType::Enum m_severity;
+ };
+
+ struct DOCTEST_INTERFACE SubcaseSignature
+ {
+ String m_name;
+ const char* m_file;
+ int m_line;
+
+ bool operator==(const SubcaseSignature& other) const;
+ bool operator<(const SubcaseSignature& other) const;
+ };
+
+ struct DOCTEST_INTERFACE IContextScope
+ {
+ DOCTEST_DECLARE_INTERFACE(IContextScope)
+ virtual void stringify(std::ostream*) const = 0;
+ };
+
+ namespace detail {
+ struct DOCTEST_INTERFACE TestCase;
+ } // namespace detail
+
+ struct ContextOptions //!OCLINT too many fields
+ {
+ std::ostream* cout = nullptr; // stdout stream
+ String binary_name; // the test binary name
+
+ const detail::TestCase* currentTest = nullptr;
+
+ // == parameters from the command line
+ String out; // output filename
+ String order_by; // how tests should be ordered
+ unsigned rand_seed; // the seed for rand ordering
+
+ unsigned first; // the first (matching) test to be executed
+ unsigned last; // the last (matching) test to be executed
+
+ int abort_after; // stop tests after this many failed assertions
+ int subcase_filter_levels; // apply the subcase filters for the first N levels
+
+ bool success; // include successful assertions in output
+ bool case_sensitive; // if filtering should be case sensitive
+ bool exit; // if the program should be exited after the tests are ran/whatever
+ bool duration; // print the time duration of each test case
+ bool minimal; // minimal console output (only test failures)
+ bool quiet; // no console output
+ bool no_throw; // to skip exceptions-related assertion macros
+ bool no_exitcode; // if the framework should return 0 as the exitcode
+ bool no_run; // to not run the tests at all (can be done with an "*" exclude)
+ bool no_intro; // to not print the intro of the framework
+ bool no_version; // to not print the version of the framework
+ bool no_colors; // if output to the console should be colorized
+ bool force_colors; // forces the use of colors even when a tty cannot be detected
+ bool no_breaks; // to not break into the debugger
+ bool no_skip; // don't skip test cases which are marked to be skipped
+ bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x):
+ bool no_path_in_filenames; // if the path to files should be removed from the output
+ bool no_line_numbers; // if source code line numbers should be omitted from the output
+ bool no_debug_output; // no output in the debug console when a debugger is attached
+ bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
+ bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!!
+
+ bool help; // to print the help
+ bool version; // to print the version
+ bool count; // if only the count of matching tests is to be retrieved
+ bool list_test_cases; // to list all tests matching the filters
+ bool list_test_suites; // to list all suites matching the filters
+ bool list_reporters; // lists all registered reporters
+ };
+
+ namespace detail {
+ namespace types {
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ using namespace std;
+#else
+ template
+ struct enable_if { };
+
+ template
+ struct enable_if { using type = T; };
+
+ struct true_type { static DOCTEST_CONSTEXPR bool value = true; };
+ struct false_type { static DOCTEST_CONSTEXPR bool value = false; };
+
+ template struct remove_reference { using type = T; };
+ template struct remove_reference { using type = T; };
+ template struct remove_reference { using type = T; };
+
+ template struct is_rvalue_reference : false_type { };
+ template struct is_rvalue_reference : true_type { };
+
+ template struct remove_const { using type = T; };
+ template struct remove_const { using type = T; };
+
+ // Compiler intrinsics
+ template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); };
+ template struct underlying_type { using type = __underlying_type(T); };
+
+ template struct is_pointer : false_type { };
+ template struct is_pointer : true_type { };
+
+ template struct is_array : false_type { };
+ // NOLINTNEXTLINE(*-avoid-c-arrays)
+ template struct is_array : true_type { };
+#endif
+ }
+
+ //
+ template
+ T&& declval();
+
+ template
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT {
+ return static_cast(t);
+ }
+
+ template
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT {
+ return static_cast(t);
+ }
+
+ template
+ struct deferred_false : types::false_type { };
+
+ // MSVS 2015 :(
+#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900
+ template
+ struct has_global_insertion_operator : types::false_type { };
+
+ template
+ struct has_global_insertion_operator(), declval()), void())> : types::true_type { };
+
+ template
+ struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; };
+
+ template
+ struct insert_hack;
+
+ template
+ struct insert_hack {
+ static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); }
+ };
+
+ template
+ struct insert_hack {
+ static void insert(std::ostream& os, const T& t) { operator<<(os, t); }
+ };
+
+ template
+ using insert_hack_t = insert_hack::value>;
+#else
+ template
+ struct has_insertion_operator : types::false_type { };
+#endif
+
+ template
+ struct has_insertion_operator(), declval()), void())> : types::true_type { };
+
+ template
+ struct should_stringify_as_underlying_type {
+ static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value;
+ };
+
+ DOCTEST_INTERFACE std::ostream* tlssPush();
+ DOCTEST_INTERFACE String tlssPop();
+
+ template
+ struct StringMakerBase {
+ template
+ static String convert(const DOCTEST_REF_WRAP(T)) {
+#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES
+ static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual");
+#endif
+ return "{?}";
+ }
+ };
+
+ template
+ struct filldata;
+
+ template
+ void filloss(std::ostream* stream, const T& in) {
+ filldata::fill(stream, in);
+ }
+
+ template
+ void filloss(std::ostream* stream, const T(&in)[N]) { // NOLINT(*-avoid-c-arrays)
+ // T[N], T(&)[N], T(&&)[N] have same behaviour.
+ // Hence remove reference.
+ filloss::type>(stream, in);
+ }
+
+ template
+ String toStream(const T& in) {
+ std::ostream* stream = tlssPush();
+ filloss(stream, in);
+ return tlssPop();
+ }
+
+ template <>
+ struct StringMakerBase {
+ template
+ static String convert(const DOCTEST_REF_WRAP(T) in) {
+ return toStream(in);
+ }
+ };
+ } // namespace detail
+
+ template
+ struct StringMaker : public detail::StringMakerBase<
+ detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value>
+ {};
+
+#ifndef DOCTEST_STRINGIFY
+#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY
+#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__))
+#else
+#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__)
+#endif
+#endif
+
+ template
+ String toString() {
+#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0
+ String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void)
+ String::size_type beginPos = ret.find('<');
+ return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)")));
+#else
+ String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE]
+ String::size_type begin = ret.find('=') + 2;
+ return ret.substr(begin, ret.size() - begin - 1);
+#endif
+ }
+
+ template ::value, bool>::type = true>
+ String toString(const DOCTEST_REF_WRAP(T) value) {
+ return StringMaker::convert(value);
+ }
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE String toString(const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+ // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+ DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
+ DOCTEST_INTERFACE String toString(String in);
+
+ DOCTEST_INTERFACE String toString(std::nullptr_t);
+
+ DOCTEST_INTERFACE String toString(bool in);
+
+ DOCTEST_INTERFACE String toString(float in);
+ DOCTEST_INTERFACE String toString(double in);
+ DOCTEST_INTERFACE String toString(double long in);
+
+ DOCTEST_INTERFACE String toString(char in);
+ DOCTEST_INTERFACE String toString(char signed in);
+ DOCTEST_INTERFACE String toString(char unsigned in);
+ DOCTEST_INTERFACE String toString(short in);
+ DOCTEST_INTERFACE String toString(short unsigned in);
+ DOCTEST_INTERFACE String toString(signed in);
+ DOCTEST_INTERFACE String toString(unsigned in);
+ DOCTEST_INTERFACE String toString(long in);
+ DOCTEST_INTERFACE String toString(long unsigned in);
+ DOCTEST_INTERFACE String toString(long long in);
+ DOCTEST_INTERFACE String toString(long long unsigned in);
+
+ template ::value, bool>::type = true>
+ String toString(const DOCTEST_REF_WRAP(T) value) {
+ using UT = typename detail::types::underlying_type::type;
+ return (DOCTEST_STRINGIFY(static_cast(value)));
+ }
+
+ namespace detail {
+ template
+ struct filldata
+ {
+ static void fill(std::ostream* stream, const T& in) {
+#if defined(_MSC_VER) && _MSC_VER <= 1900
+ insert_hack_t::insert(*stream, in);
+#else
+ operator<<(*stream, in);
+#endif
+ }
+ };
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
+ // NOLINTBEGIN(*-avoid-c-arrays)
+ template
+ struct filldata {
+ static void fill(std::ostream* stream, const T(&in)[N]) {
+ *stream << "[";
+ for (size_t i = 0; i < N; i++) {
+ if (i != 0) { *stream << ", "; }
+ *stream << (DOCTEST_STRINGIFY(in[i]));
+ }
+ *stream << "]";
+ }
+ };
+ // NOLINTEND(*-avoid-c-arrays)
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ // Specialized since we don't want the terminating null byte!
+ // NOLINTBEGIN(*-avoid-c-arrays)
+ template
+ struct filldata {
+ static void fill(std::ostream* stream, const char(&in)[N]) {
+ *stream << String(in, in[N - 1] ? N : N - 1);
+ } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+ };
+ // NOLINTEND(*-avoid-c-arrays)
+
+ template <>
+ struct filldata {
+ static void fill(std::ostream* stream, const void* in);
+ };
+
+ template
+ struct filldata {
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180)
+ static void fill(std::ostream* stream, const T* in) {
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast")
+ filldata::fill(stream,
+#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+ reinterpret_cast(in)
+#else
+ * reinterpret_cast(&in)
+#endif
+ );
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ }
+ };
+ }
+
+ struct DOCTEST_INTERFACE Approx
+ {
+ Approx(double value);
+
+ Approx operator()(double value) const;
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template
+ explicit Approx(const T& value,
+ typename detail::types::enable_if::value>::type* =
+ static_cast(nullptr)) {
+ *this = static_cast(value);
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& epsilon(double newEpsilon);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template
+ typename std::enable_if::value, Approx&>::type epsilon(
+ const T& newEpsilon) {
+ m_epsilon = static_cast(newEpsilon);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& scale(double newScale);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template
+ typename std::enable_if::value, Approx&>::type scale(
+ const T& newScale) {
+ m_scale = static_cast(newScale);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format off
+ DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator==(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator!=(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator<=(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator>=(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator< (const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator> (const Approx& lhs, double rhs);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_APPROX_PREFIX \
+ template friend typename std::enable_if::value, bool>::type
+
+ DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); }
+ DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; }
+#undef DOCTEST_APPROX_PREFIX
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format on
+
+ double m_epsilon;
+ double m_scale;
+ double m_value;
+ };
+
+ DOCTEST_INTERFACE String toString(const Approx& in);
+
+ DOCTEST_INTERFACE const ContextOptions* getContextOptions();
+
+ template
+ struct DOCTEST_INTERFACE_DECL IsNaN
+ {
+ F value; bool flipped;
+ IsNaN(F f, bool flip = false) : value(f), flipped(flip) { }
+ IsNaN operator!() const { return { value, !flipped }; }
+ operator bool() const;
+ };
+#ifndef __MINGW32__
+ extern template struct DOCTEST_INTERFACE_DECL IsNaN;
+ extern template struct DOCTEST_INTERFACE_DECL IsNaN;
+ extern template struct DOCTEST_INTERFACE_DECL IsNaN;
+#endif
+ DOCTEST_INTERFACE String toString(IsNaN in);
+ DOCTEST_INTERFACE String toString(IsNaN in);
+ DOCTEST_INTERFACE String toString(IsNaN in);
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+ namespace detail {
+ // clang-format off
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ template struct decay_array { using type = T; };
+ template struct decay_array { using type = T*; };
+ template struct decay_array { using type = T*; };
+
+ template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; };
+ template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; };
+ template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; };
+
+ template struct can_use_op : public not_char_pointer::type> {};
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+ struct DOCTEST_INTERFACE TestFailureException
+ {
+ };
+
+ DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_NORETURN
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_INTERFACE void throwException();
+
+ struct DOCTEST_INTERFACE Subcase
+ {
+ SubcaseSignature m_signature;
+ bool m_entered = false;
+
+ Subcase(const String& name, const char* file, int line);
+ Subcase(const Subcase&) = delete;
+ Subcase(Subcase&&) = delete;
+ Subcase& operator=(const Subcase&) = delete;
+ Subcase& operator=(Subcase&&) = delete;
+ ~Subcase();
+
+ operator bool() const;
+
+ private:
+ bool checkFilters();
+ };
+
+ template
+ String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs));
+ }
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
+#endif
+
+ // This will check if there is any way it could find a operator like member or friend and uses it.
+ // If not it doesn't find the operator or if the operator at global scope is defined after
+ // this template, the template won't be instantiated due to SFINAE. Once the template is not
+ // instantiated it can look for global operator using normal conversions.
+#ifdef __NVCC__
+#define SFINAE_OP(ret,op) ret
+#else
+#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{})
+#endif
+
+#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
+ template \
+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
+ bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \
+ if(m_at & assertType::is_false) \
+ res = !res; \
+ if(!res || doctest::getContextOptions()->success) \
+ return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \
+ return Result(res); \
+ }
+
+ // more checks could be added - like in Catch:
+ // https://github.com/catchorg/Catch2/pull/1480/files
+ // https://github.com/catchorg/Catch2/pull/1481/files
+#define DOCTEST_FORBIT_EXPRESSION(rt, op) \
+ template \
+ rt& operator op(const R&) { \
+ static_assert(deferred_false::value, \
+ "Expression Too Complex Please Rewrite As Binary Comparison!"); \
+ return *this; \
+ }
+
+ struct DOCTEST_INTERFACE Result // NOLINT(*-member-init)
+ {
+ bool m_passed;
+ String m_decomp;
+
+ Result() = default; // TODO: Why do we need this? (To remove NOLINT)
+ Result(bool passed, const String& decomposition = String());
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Result, &)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^)
+ DOCTEST_FORBIT_EXPRESSION(Result, | )
+ DOCTEST_FORBIT_EXPRESSION(Result, &&)
+ DOCTEST_FORBIT_EXPRESSION(Result, || )
+ DOCTEST_FORBIT_EXPRESSION(Result, == )
+ DOCTEST_FORBIT_EXPRESSION(Result, != )
+ DOCTEST_FORBIT_EXPRESSION(Result, < )
+ DOCTEST_FORBIT_EXPRESSION(Result, > )
+ DOCTEST_FORBIT_EXPRESSION(Result, <= )
+ DOCTEST_FORBIT_EXPRESSION(Result, >= )
+ DOCTEST_FORBIT_EXPRESSION(Result, =)
+ DOCTEST_FORBIT_EXPRESSION(Result, +=)
+ DOCTEST_FORBIT_EXPRESSION(Result, -=)
+ DOCTEST_FORBIT_EXPRESSION(Result, *=)
+ DOCTEST_FORBIT_EXPRESSION(Result, /=)
+ DOCTEST_FORBIT_EXPRESSION(Result, %=)
+ DOCTEST_FORBIT_EXPRESSION(Result, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Result, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Result, &=)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Result, |=)
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+ // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
+ DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
+ //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ // clang-format off
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE bool
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type
+ inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
+ inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
+ inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
+ inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
+ inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
+ inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+#define DOCTEST_RELATIONAL_OP(name, op) \
+ template \
+ DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \
+ const DOCTEST_REF_WRAP(R) rhs) { \
+ return lhs op rhs; \
+ }
+
+ DOCTEST_RELATIONAL_OP(eq, == )
+ DOCTEST_RELATIONAL_OP(ne, != )
+ DOCTEST_RELATIONAL_OP(lt, < )
+ DOCTEST_RELATIONAL_OP(gt, > )
+ DOCTEST_RELATIONAL_OP(le, <= )
+ DOCTEST_RELATIONAL_OP(ge, >= )
+
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) l == r
+#define DOCTEST_CMP_NE(l, r) l != r
+#define DOCTEST_CMP_GT(l, r) l > r
+#define DOCTEST_CMP_LT(l, r) l < r
+#define DOCTEST_CMP_GE(l, r) l >= r
+#define DOCTEST_CMP_LE(l, r) l <= r
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) eq(l, r)
+#define DOCTEST_CMP_NE(l, r) ne(l, r)
+#define DOCTEST_CMP_GT(l, r) gt(l, r)
+#define DOCTEST_CMP_LT(l, r) lt(l, r)
+#define DOCTEST_CMP_GE(l, r) ge(l, r)
+#define DOCTEST_CMP_LE(l, r) le(l, r)
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+ template
+ // cppcheck-suppress copyCtorAndEqOperator
+ struct Expression_lhs
+ {
+ L lhs;
+ assertType::Enum m_at;
+
+ explicit Expression_lhs(L&& in, assertType::Enum at)
+ : lhs(static_cast(in))
+ , m_at(at) {}
+
+ DOCTEST_NOINLINE operator Result() {
+ // this is needed only for MSVC 2015
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
+ bool res = static_cast(lhs);
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
+ res = !res;
+ }
+
+ if (!res || getContextOptions()->success) {
+ return { res, (DOCTEST_STRINGIFY(lhs)) };
+ }
+ return { res };
+ }
+
+ /* This is required for user-defined conversions from Expression_lhs to L */
+ operator L() const { return lhs; }
+
+ // clang-format off
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(== , " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!= , " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(> , " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(< , " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>= , " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<= , " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
+ // clang-format on
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, | )
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, || )
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=)
+ // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
+ // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, << )
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >> )
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#endif
+
+ struct DOCTEST_INTERFACE ExpressionDecomposer
+ {
+ assertType::Enum m_at;
+
+ ExpressionDecomposer(assertType::Enum at);
+
+ // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
+ // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
+ // https://github.com/catchorg/Catch2/issues/870
+ // https://github.com/catchorg/Catch2/issues/565
+ template
+ Expression_lhs operator<<(L&& operand) {
+ return Expression_lhs(static_cast(operand), m_at);
+ }
+
+ template ::value, void >::type* = nullptr>
+ Expression_lhs operator<<(const L& operand) {
+ return Expression_lhs(operand, m_at);
+ }
+ };
+
+ struct DOCTEST_INTERFACE TestSuite
+ {
+ const char* m_test_suite = nullptr;
+ const char* m_description = nullptr;
+ bool m_skip = false;
+ bool m_no_breaks = false;
+ bool m_no_output = false;
+ bool m_may_fail = false;
+ bool m_should_fail = false;
+ int m_expected_failures = 0;
+ double m_timeout = 0;
+
+ TestSuite& operator*(const char* in);
+
+ template
+ TestSuite& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+ };
+
+ using funcType = void (*)();
+
+ struct DOCTEST_INTERFACE TestCase : public TestCaseData
+ {
+ funcType m_test; // a function pointer to the test case
+
+ String m_type; // for templated test cases - gets appended to the real name
+ int m_template_id; // an ID used to distinguish between the different versions of a templated test case
+ String m_full_name; // contains the name (only for templated test cases!) + the template type
+
+ TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
+ const String& type = String(), int template_id = -1);
+
+ TestCase(const TestCase& other);
+ TestCase(TestCase&&) = delete;
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
+ TestCase& operator=(const TestCase& other);
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ TestCase& operator=(TestCase&&) = delete;
+
+ TestCase& operator*(const char* in);
+
+ template
+ TestCase& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+
+ bool operator<(const TestCase& other) const;
+
+ ~TestCase() = default;
+ };
+
+ // forward declarations of functions used by the macros
+ DOCTEST_INTERFACE int regTest(const TestCase& tc);
+ DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
+ DOCTEST_INTERFACE bool isDebuggerActive();
+
+ template
+ int instantiationHelper(const T&) { return 0; }
+
+ namespace binaryAssertComparison {
+ enum Enum
+ {
+ eq = 0,
+ ne,
+ gt,
+ lt,
+ ge,
+ le
+ };
+ } // namespace binaryAssertComparison
+
+ // clang-format off
+ template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R)) const { return false; } };
+
+#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
+ template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
+ // clang-format on
+
+ DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
+ DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
+ DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
+ DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
+ DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
+ DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
+
+ struct DOCTEST_INTERFACE ResultBuilder : public AssertData
+ {
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type = "", const String& exception_string = "");
+
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const Contains& exception_string);
+
+ void setResult(const Result& res);
+
+ template
+ DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ m_failed = !RelationalComparator()(lhs, rhs);
+ if (m_failed || getContextOptions()->success) {
+ m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
+ }
+ return !m_failed;
+ }
+
+ template
+ DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) {
+ m_failed = !val;
+
+ if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_failed;
+ }
+
+ if (m_failed || getContextOptions()->success) {
+ m_decomp = (DOCTEST_STRINGIFY(val));
+ }
+
+ return !m_failed;
+ }
+
+ void translateException();
+
+ bool log();
+ void react() const;
+ };
+
+ namespace assertAction {
+ enum Enum
+ {
+ nothing = 0,
+ dbgbreak = 1,
+ shouldthrow = 2
+ };
+ } // namespace assertAction
+
+ DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
+
+ DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const Result& result);
+
+#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \
+ do { \
+ if(!is_running_in_test) { \
+ if(failed) { \
+ ResultBuilder rb(at, file, line, expr); \
+ rb.m_failed = failed; \
+ rb.m_decomp = decomp; \
+ failed_out_of_a_testing_context(rb); \
+ if(isDebuggerActive() && !getContextOptions()->no_breaks) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ if(checkIfShouldThrow(at)) \
+ throwException(); \
+ } \
+ return !failed; \
+ } \
+ } while(false)
+
+#define DOCTEST_ASSERT_IN_TESTS(decomp) \
+ ResultBuilder rb(at, file, line, expr); \
+ rb.m_failed = failed; \
+ if(rb.m_failed || getContextOptions()->success) \
+ rb.m_decomp = decomp; \
+ if(rb.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ if(rb.m_failed && checkIfShouldThrow(at)) \
+ throwException()
+
+ template
+ DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ bool failed = !RelationalComparator()(lhs, rhs);
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ return !failed;
+ }
+
+ template
+ DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const DOCTEST_REF_WRAP(L) val) {
+ bool failed = !val;
+
+ if (at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ failed = !failed;
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val)));
+ DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val)));
+ return !failed;
+ }
+
+ struct DOCTEST_INTERFACE IExceptionTranslator
+ {
+ DOCTEST_DECLARE_INTERFACE(IExceptionTranslator)
+ virtual bool translate(String&) const = 0;
+ };
+
+ template
+ class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class
+ {
+ public:
+ explicit ExceptionTranslator(String(*translateFunction)(T))
+ : m_translateFunction(translateFunction) {}
+
+ bool translate(String& res) const override {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ try {
+ throw; // lgtm [cpp/rethrow-no-exception]
+ // cppcheck-suppress catchExceptionByValue
+ }
+ catch (const T& ex) {
+ res = m_translateFunction(ex); //!OCLINT parameter reassignment
+ return true;
+ }
+ catch (...) {} //!OCLINT - empty catch statement
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ static_cast(res); // to silence -Wunused-parameter
+ return false;
+ }
+
+ private:
+ String(*m_translateFunction)(T);
+ };
+
+ DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
+
+ // ContextScope base class used to allow implementing methods of ContextScope
+ // that don't depend on the template parameter in doctest.cpp.
+ struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
+ ContextScopeBase(const ContextScopeBase&) = delete;
+
+ ContextScopeBase& operator=(const ContextScopeBase&) = delete;
+ ContextScopeBase& operator=(ContextScopeBase&&) = delete;
+
+ ~ContextScopeBase() override = default;
+
+ protected:
+ ContextScopeBase();
+ ContextScopeBase(ContextScopeBase&& other) noexcept;
+
+ void destroy();
+ bool need_to_destroy{ true };
+ };
+
+ template class ContextScope : public ContextScopeBase
+ {
+ L lambda_;
+
+ public:
+ explicit ContextScope(const L& lambda) : lambda_(lambda) {}
+ explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { }
+
+ ContextScope(const ContextScope&) = delete;
+ ContextScope(ContextScope&&) noexcept = default;
+
+ ContextScope& operator=(const ContextScope&) = delete;
+ ContextScope& operator=(ContextScope&&) = delete;
+
+ void stringify(std::ostream* s) const override { lambda_(s); }
+
+ ~ContextScope() override {
+ if (need_to_destroy) {
+ destroy();
+ }
+ }
+ };
+
+ struct DOCTEST_INTERFACE MessageBuilder : public MessageData
+ {
+ std::ostream* m_stream;
+ bool logged = false;
+
+ MessageBuilder(const char* file, int line, assertType::Enum severity);
+
+ MessageBuilder(const MessageBuilder&) = delete;
+ MessageBuilder(MessageBuilder&&) = delete;
+
+ MessageBuilder& operator=(const MessageBuilder&) = delete;
+ MessageBuilder& operator=(MessageBuilder&&) = delete;
+
+ ~MessageBuilder();
+
+ // the preferred way of chaining parameters for stringification
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
+ template
+ MessageBuilder& operator,(const T& in) {
+ *m_stream << (DOCTEST_STRINGIFY(in));
+ return *this;
+ }
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ // kept here just for backwards-compatibility - the comma operator should be preferred now
+ template
+ MessageBuilder& operator<<(const T& in) { return this->operator,(in); }
+
+ // the `,` operator has the lowest operator precedence - if `<<` is used by the user then
+ // the `,` operator will be called last which is not what we want and thus the `*` operator
+ // is used first (has higher operator precedence compared to `<<`) so that we guarantee that
+ // an operator of the MessageBuilder class is called first before the rest of the parameters
+ template
+ MessageBuilder& operator*(const T& in) { return this->operator,(in); }
+
+ bool log();
+ void react();
+ };
+
+ template
+ ContextScope MakeContextScope(const L& lambda) {
+ return ContextScope(lambda);
+ }
+ } // namespace detail
+
+#define DOCTEST_DEFINE_DECORATOR(name, type, def) \
+ struct name \
+ { \
+ type data; \
+ name(type in = def) \
+ : data(in) {} \
+ void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \
+ void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \
+ }
+
+ DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
+ DOCTEST_DEFINE_DECORATOR(description, const char*, "");
+ DOCTEST_DEFINE_DECORATOR(skip, bool, true);
+ DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
+ DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
+ DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
+ DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
+ DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
+ DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0);
+
+ template
+ int registerExceptionTranslator(String(*translateFunction)(T)) {
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors")
+ static detail::ExceptionTranslator exceptionTranslator(translateFunction);
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ detail::registerExceptionTranslatorImpl(&exceptionTranslator);
+ return 0;
+ }
+
+} // namespace doctest
+
+// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro
+// introduces an anonymous namespace in which getCurrentTestSuite gets overridden
+namespace doctest_detail_test_suite_ns {
+ DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite();
+} // namespace doctest_detail_test_suite_ns
+
+namespace doctest {
+#else // DOCTEST_CONFIG_DISABLE
+ template
+ int registerExceptionTranslator(String(*)(T)) {
+ return 0;
+ }
+#endif // DOCTEST_CONFIG_DISABLE
+
+ namespace detail {
+ using assert_handler = void (*)(const AssertData&);
+ struct ContextState;
+ } // namespace detail
+
+ class DOCTEST_INTERFACE Context
+ {
+ detail::ContextState* p;
+
+ void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
+
+ public:
+ explicit Context(int argc = 0, const char* const* argv = nullptr);
+
+ Context(const Context&) = delete;
+ Context(Context&&) = delete;
+
+ Context& operator=(const Context&) = delete;
+ Context& operator=(Context&&) = delete;
+
+ ~Context(); // NOLINT(performance-trivially-destructible)
+
+ void applyCommandLine(int argc, const char* const* argv);
+
+ void addFilter(const char* filter, const char* value);
+ void clearFilters();
+ void setOption(const char* option, bool value);
+ void setOption(const char* option, int value);
+ void setOption(const char* option, const char* value);
+
+ bool shouldExit();
+
+ void setAsDefaultForAssertsOutOfTestCases();
+
+ void setAssertHandler(detail::assert_handler ah);
+
+ void setCout(std::ostream* out);
+
+ int run();
+ };
+
+ namespace TestCaseFailureReason {
+ enum Enum
+ {
+ None = 0,
+ AssertFailure = 1, // an assertion has failed in the test case
+ Exception = 2, // test case threw an exception
+ Crash = 4, // a crash...
+ TooManyFailedAsserts = 8, // the abort-after option
+ Timeout = 16, // see the timeout decorator
+ ShouldHaveFailedButDidnt = 32, // see the should_fail decorator
+ ShouldHaveFailedAndDid = 64, // see the should_fail decorator
+ DidntFailExactlyNumTimes = 128, // see the expected_failures decorator
+ FailedExactlyNumTimes = 256, // see the expected_failures decorator
+ CouldHaveFailedAndDid = 512 // see the may_fail decorator
+ };
+ } // namespace TestCaseFailureReason
+
+ struct DOCTEST_INTERFACE CurrentTestCaseStats
+ {
+ int numAssertsCurrentTest;
+ int numAssertsFailedCurrentTest;
+ double seconds;
+ int failure_flags; // use TestCaseFailureReason::Enum
+ bool testCaseSuccess;
+ };
+
+ struct DOCTEST_INTERFACE TestCaseException
+ {
+ String error_string;
+ bool is_crash;
+ };
+
+ struct DOCTEST_INTERFACE TestRunStats
+ {
+ unsigned numTestCases;
+ unsigned numTestCasesPassingFilters;
+ unsigned numTestSuitesPassingFilters;
+ unsigned numTestCasesFailed;
+ int numAsserts;
+ int numAssertsFailed;
+ };
+
+ struct QueryData
+ {
+ const TestRunStats* run_stats = nullptr;
+ const TestCaseData** data = nullptr;
+ unsigned num_data = 0;
+ };
+
+ struct DOCTEST_INTERFACE IReporter
+ {
+ // The constructor has to accept "const ContextOptions&" as a single argument
+ // which has most of the options for the run + a pointer to the stdout stream
+ // Reporter(const ContextOptions& in)
+
+ // called when a query should be reported (listing test cases, printing the version, etc.)
+ virtual void report_query(const QueryData&) = 0;
+
+ // called when the whole test run starts
+ virtual void test_run_start() = 0;
+ // called when the whole test run ends (caching a pointer to the input doesn't make sense here)
+ virtual void test_run_end(const TestRunStats&) = 0;
+
+ // called when a test case is started (safe to cache a pointer to the input)
+ virtual void test_case_start(const TestCaseData&) = 0;
+ // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
+ virtual void test_case_reenter(const TestCaseData&) = 0;
+ // called when a test case has ended
+ virtual void test_case_end(const CurrentTestCaseStats&) = 0;
+
+ // called when an exception is thrown from the test case (or it crashes)
+ virtual void test_case_exception(const TestCaseException&) = 0;
+
+ // called whenever a subcase is entered (don't cache pointers to the input)
+ virtual void subcase_start(const SubcaseSignature&) = 0;
+ // called whenever a subcase is exited (don't cache pointers to the input)
+ virtual void subcase_end() = 0;
+
+ // called for each assert (don't cache pointers to the input)
+ virtual void log_assert(const AssertData&) = 0;
+ // called for each message (don't cache pointers to the input)
+ virtual void log_message(const MessageData&) = 0;
+
+ // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator
+ // or isn't in the execution range (between first and last) (safe to cache a pointer to the input)
+ virtual void test_case_skipped(const TestCaseData&) = 0;
+
+ DOCTEST_DECLARE_INTERFACE(IReporter)
+
+ // can obtain all currently active contexts and stringify them if one wishes to do so
+ static int get_num_active_contexts();
+ static const IContextScope* const* get_active_contexts();
+
+ // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown
+ static int get_num_stringified_contexts();
+ static const String* get_stringified_contexts();
+ };
+
+ namespace detail {
+ using reporterCreatorFunc = IReporter * (*)(const ContextOptions&);
+
+ DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
+
+ template
+ IReporter* reporterCreator(const ContextOptions& o) {
+ return new Reporter(o);
+ }
+ } // namespace detail
+
+ template