Commit efbfaa7e authored by Giuseppe Carboni's avatar Giuseppe Carboni
Browse files

Updated SRTMinorServoSocket and tests

parent ad139635
Loading
Loading
Loading
Loading
+23 −10
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@

module MinorServo
{
    /**
     * Enumerator which indicates a Leonardo minor servo configuration
     */
    enum SRTMinorServoFocalConfiguration
    {
        CONFIGURATION_UNKNOWN,
@@ -33,35 +36,43 @@ module MinorServo
        CONFIGURATION_BWG3,
        CONFIGURATION_BWG4
    };

    ACS_ENUM(SRTMinorServoFocalConfiguration);

    /**
     * Enumerator which indicates the status of the control for the Leonardo minor servo system
     */
    enum SRTMinorServoControlStatus
    {
        CONTROL_DISCOS,
        CONTROL_VBRAIN
    };

    ACS_ENUM(SRTMinorServoControlStatus);

    /**
     * Enumerator which indicates the position of the gregorian cover
     */
    enum SRTMinorServoGregorianCoverStatus
    {
        COVER_STATUS_UNKNOWN,
        COVER_STATUS_OPEN,
        COVER_STATUS_CLOSED
    };

    ACS_ENUM(SRTMinorServoGregorianCoverStatus);

    /**
     * Enumerator which indicates the status of a servo drive cabinet
     */
    enum SRTMinorServoCabinetStatus
    {
        DRIVE_CABINET_OK,
        DRIVE_CABINET_WARNING,
        DRIVE_CABINET_ERROR
    };

    ACS_ENUM(SRTMinorServoCabinetStatus);

    /**
     * Enumerator which indicates the operating mode of a single servo
     */
    enum SRTMinorServoOperativeMode
    {
        OPERATIVE_MODE_UNKNOWN,
@@ -71,19 +82,21 @@ module MinorServo
        OPERATIVE_MODE_PRESET,
        OPERATIVE_MODE_PROGRAMTRACK
    };

    ACS_ENUM(SRTMinorServoOperativeMode);

    /**
     * Enumerator which indicates the type of movement made by the whole system (i.e.: performing setup, parking, tracking...)
     */
    enum SRTMinorServoMotionStatus
    {
        MOTION_STATUS_UNCONFIGURED,
        MOTION_STATUS_CONFIGURING,
        MOTION_STATUS_PARK,
        MOTION_STATUS_ERROR,
        MOTION_STATUS_STARTING,
        MOTION_STATUS_CONFIGURED,
        MOTION_STATUS_TRACKING
        MOTION_STATUS_TRACKING,
        MOTION_STATUS_PARKING,
        MOTION_STATUS_PARKED,
        MOTION_STATUS_ERROR
    };

    ACS_ENUM(SRTMinorServoMotionStatus);
};
#endif
+24 −28
Original line number Diff line number Diff line
@@ -14,51 +14,40 @@
#include <optional>
#include "SRTMinorServoCommandLibrary.h"


#define SOCKET_TIMEOUT 0.1
#define CONFIG_DOMAIN   "alma/"
#define CONFIG_DIRNAME  "/MINORSERVO/Socket"


class SRTMinorServoSocketTest;
class SRPProgramTrackTest;
class DerotatorProgramTrackTest;
class CombinedProgramTrackTest;
class ReadStatusOnlyTest;


namespace MinorServo
{
    /**
     * Testing class forward declaration.
     * The declaration of this class can be found in the SRTMinorServoTestingSocket.h header file.
     * Instructions on how to use this for testing purposes can be found there as well.
     */
    class SRTMinorServoTestingSocket;

    class SRTMinorServoSocket: public IRA::CSocket
    {
        /**
         * This class implements a singleton socket. The singleton pattern was necessary to provide each servo system component communication capabilities with the Leonardo system.
         * As long as all the said components run on the same container this will only be instanced once.
         */

        /**
         * Declare the testing classes as friend classes in order for them to have access to destroyInstance for testing purposes
         */
        friend class ::SRTMinorServoSocketTest;
        friend class ::SRPProgramTrackTest;
        friend class ::DerotatorProgramTrackTest;
        friend class ::CombinedProgramTrackTest;
        friend class ::ReadStatusOnlyTest;

    public:
        /**
         * Calls the constructor and returns the singleton socket instance
         * @param ip_address the IP address to which the socket will connect
         * @param port the port to which the socket will connect
         * @param timeout the timeout, in seconds, for the communication to be considered failed
         * @throw MinorServoErrors::CommunicationErrorExImpl when the user calls this method a second time with different IP address and port arguments
         * @throw MinorServoErrors::MinorServoErrorsEx when the user calls this method a second time with different IP address and port arguments (non testing mode)
         * @throw MinorServoErrors::CommunicationErrorExImpl (testing mode)
         * @return the singleton socket instance, eventually connected to the given IP address and port, by reference
         */
        static SRTMinorServoSocket& getInstance(std::string ip_address, int port, double timeout=SOCKET_TIMEOUT);

        /**
         * Returns the previously generated singleton socket instance
         * @throw MinorServoErrors::CommunicationErrorExImpl when the user calls this method when the instance has not been generated yet
         * @throw MinorServoErrors::MinorServoErrorsExImpl when the user calls this method when the instance has not been generated yet
         * @return the singleton socket instance, by reference
         */
        static SRTMinorServoSocket& getInstance();
@@ -67,7 +56,8 @@ namespace MinorServo
         * Sends a command on the socket and returns the received answer, if any
         * @param command the command to be sent over the socket
         * @param map, optional SRTMinorServoAnswerMap object. If provided, the 'map' argument content gets updated with the newly received answer
         * @throw MinorServoErrors::CommunicationErrorExImpl when the operation of sending or receiving fails unexpectedly
         * @throw MinorServoErrors::MinorServoErrorsEx when the operation of sending or receiving fails unexpectedly (non testing mode)
         * @throw MinorServoErrors::CommunicationErrorExImpl (testing mode)
         * @return the received answer to the given command
         */
        SRTMinorServoAnswerMap sendCommand(std::string command, std::optional<std::reference_wrapper<SRTMinorServoAnswerMap>> map = {});
@@ -89,6 +79,11 @@ namespace MinorServo
        const bool isConnected() const;

    private:
        /**
         * Declare the testing class as friend class in order for it to have access to private members for testing purposes
         */
        friend class SRTMinorServoTestingSocket;

        /**
         * Constructor method. Generates the singleton socket instance
         * @param ip_address the IP address to which the socket will connect
@@ -102,14 +97,10 @@ namespace MinorServo
         */
        ~SRTMinorServoSocket();

        /**
         * Force the destruction of the singleton socket object. Only used in tests
         */
        static void destroyInstance();

        /**
         * Connection function. It gets called every time the socket gets disconnected
         * throw MinorServoErrors::CommunicationErrorExImpl when the connection attempt fails
         * throw MinorServoErrors::MinorServoErrorsEx when the connection attempt fails (non testing mode)
         * throw MinorServoErrors::CommunicationErrorExImpl (testing mode)
         */
        void connect();

@@ -139,6 +130,11 @@ namespace MinorServo
         */
        static std::mutex c_mutex;

        /**
         * Boolean indicating whether we are testing the socket or not
         */
        inline static bool c_testing = false;

        /**
         * Socket status enumerator
         */
+65 −0
Original line number Diff line number Diff line
#include "SRTMinorServoSocket.h"

namespace MinorServo
{
    class SRTMinorServoTestingSocket: public SRTMinorServoSocket
    {
        /**
         * This class is a friend class of SRTMinorServoSocket. It can be used for testing purposes without altering the behavior of the original class.
         * Instructions on how to use this class inside tests:
         * 1) Declare the test class with a forward declaration
         * 2) Define the FRIEND_CLASS_DECLARATION macro
         * 3) Include this header file
         * 4) Finally implement the test class
         * Example:
         *
         * ...
         * class TestClass;
         * #define FRIEND_CLASS_DECLARATION friend class ::TestClass;
         * #include "SRTMinorServoTestingSocket.h"
         *
         * class TestClass : public ::testing::Test
         * {
         * ...
         */

        /**
         * This is a macro that each test file will have to define prior to including this header file.
         * It can be a single or multiple lines each one containing a friend class declaration.
         */
        FRIEND_CLASS_DECLARATION;
    public:
        /**
         * Ovverride of the original SRTMinorServoSocket getInstance methods. Before doing anything, they set the c_testing variable of the original class to true.
         * This changes how the exceptions are thrown.
         * In non testing purposes, exceptions are thrown as MinorServoErrorsEx
         * In testing purposes, exceptions are thrown as they are (ExImpl)
         * This change in behavior allow for better testing and debugging purposes, while still allowing the socket to throw the base MinorServoErrorsEx when not used in testing purposes.
         * This allow us to avoid catching exceptions in the component, since MinorServoErrorsEx are already captured by CORBA
         */
        static SRTMinorServoSocket& getInstance(std::string ip_address, int port, double timeout=SOCKET_TIMEOUT)
        {
            SRTMinorServoSocket::c_testing = true;
            return SRTMinorServoSocket::getInstance(ip_address, port, timeout);
        }
        static SRTMinorServoSocket& getInstance()
        {
            SRTMinorServoSocket::c_testing = true;
            return SRTMinorServoSocket::getInstance();
        }

        /**
         * This method explicitly destroys the singleton socket instance.
         * Each test in the same test file is executed under the same process, therefore a singleton instance that does not get destroyed will still exist in the next executed tests.
         * We want to test a new instance of the socket every time, therefore the existence of this method is critical.
         */
        static void destroyInstance()
        {
            if(SRTMinorServoSocket::m_instance != nullptr)
            {
                delete SRTMinorServoSocket::m_instance;
                SRTMinorServoSocket::m_instance = nullptr;
            }
        }
    };
}
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ xxxxx_LIBS =
#
# Includes (.h) files (public only)
# ---------------------------------
INCLUDES        = hexlib.h SRTMinorServoCommandLibrary.h SRTMinorServoAnswerMap.h SRTMinorServoSocket.h
INCLUDES        = SRTMinorServoCommandLibrary.h SRTMinorServoAnswerMap.h SRTMinorServoSocket.h SRTMinorServoTestingSocket.h #hexlib.h

#
# Libraries (public and local)
+19 −18
Original line number Diff line number Diff line
#include "SRTMinorServoSocket.h"

#define THROW \
if(c_testing) \
{ \
    throw impl; \
} \
else \
{ \
    throw impl.getMinorServoErrorsEx(); \
}

using namespace MinorServo;

std::mutex SRTMinorServoSocket::c_mutex;
@@ -14,7 +24,7 @@ SRTMinorServoSocket& SRTMinorServoSocket::getInstance(std::string ip_address, in
        {
            _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::getInstance(std::string, int)");
            impl.setReason(("Socket already open on '" + m_instance->m_ip_address + ":" + std::to_string(m_instance->m_port) + "' . Use getInstance() (no arguments) to retrieve the object.").c_str());
            throw impl;
            THROW;
        }
    }
    else
@@ -32,20 +42,11 @@ SRTMinorServoSocket& SRTMinorServoSocket::getInstance()
    {
        _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::getInstance()");
        impl.setReason("Socket not yet initialized. Use getInstance(std::string ip_address, int port) to initialize it and retrieve the object.");
        throw impl;
        THROW;
    }
    return *m_instance;
}

void SRTMinorServoSocket::destroyInstance()
{
    if(m_instance != nullptr)
    {
        delete m_instance;
        m_instance = nullptr;
    }
}

SRTMinorServoSocket::SRTMinorServoSocket(std::string ip_address, int port, double timeout) : m_ip_address(ip_address), m_port(port), m_timeout(timeout), m_socket_status(NOTREADY)
{
    try
@@ -80,7 +81,7 @@ void SRTMinorServoSocket::connect()
        Close(m_error);
        _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::SRTMinorServoSocket()");
        impl.setReason("Cannot create the socket.");
        throw impl;
        THROW;
    }

    if(Connect(m_error, m_ip_address.c_str(), m_port) == FAIL)
@@ -89,7 +90,7 @@ void SRTMinorServoSocket::connect()
        Close(m_error);
        _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::SRTMinorServoSocket()");
        impl.setReason("Cannot connect the socket.");
        throw impl;
        THROW;
    }

    if(setSockMode(m_error, NONBLOCKING) != SUCCESS)
@@ -98,7 +99,7 @@ void SRTMinorServoSocket::connect()
        Close(m_error);
        _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::SRTMinorServoSocket()");
        impl.setReason("Cannot set the socket to non-blocking.");
        throw impl;
        THROW;
    }

    m_socket_status = READY;
@@ -133,7 +134,7 @@ SRTMinorServoAnswerMap SRTMinorServoSocket::sendCommand(std::string command, std
            Close(m_error);
            _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocker::sendCommand()");
            impl.setReason("Something went wrong while sending some bytes.");
            throw impl;
            THROW;
        }

        if(sent_now > 0)
@@ -147,7 +148,7 @@ SRTMinorServoAnswerMap SRTMinorServoSocket::sendCommand(std::string command, std
            Close(m_error);
            _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::sendCommand()");
            impl.setReason("Timeout when sending command.");
            throw impl;
            THROW;
        }
    }

@@ -172,7 +173,7 @@ SRTMinorServoAnswerMap SRTMinorServoSocket::sendCommand(std::string command, std
                Close(m_error);
                _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocket::sendCommand()");
                impl.setReason("Timeout when receiving answer.");
                throw impl;
                THROW;
            }
        }
        catch(...)
@@ -181,7 +182,7 @@ SRTMinorServoAnswerMap SRTMinorServoSocket::sendCommand(std::string command, std
            Close(m_error);
            _EXCPT(MinorServoErrors::CommunicationErrorExImpl, impl, "SRTMinorServoSocker::sendCommand()");
            impl.setReason("Something went wrong while receiving some bytes.");
            throw impl;
            THROW;
        }
    }

Loading