Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others. 4 : // This program and the accompanying materials are made available under the 5 : // terms of the Eclipse Public License 2.0 which is available at 6 : // https://www.eclipse.org/legal/epl-2.0/ 7 : // This Source Code may also be made available under the following Secondary 8 : // Licenses when the conditions for such availability set forth in the Eclipse 9 : // Public License 2.0 are satisfied: GNU General Public License, version 2 10 : // or later which is available at 11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 13 : /****************************************************************************/ 14 : /// @file TraCITestClient.h 15 : /// @author Friedemann Wesner 16 : /// @author Daniel Krajzewicz 17 : /// @author Axel Wegener 18 : /// @author Michael Behrisch 19 : /// @date 2008/04/07 20 : /// 21 : // A test execution class 22 : /****************************************************************************/ 23 : #pragma once 24 : #include <config.h> 25 : #include <string> 26 : #include <sstream> 27 : #include <vector> 28 : 29 : #include <foreign/tcpip/socket.h> 30 : #include <utils/traci/TraCIAPI.h> 31 : 32 : 33 : // =========================================================================== 34 : // class definitions 35 : // =========================================================================== 36 : /** 37 : * @class TraCITestClient 38 : * @brief A test execution class 39 : * 40 : * Reads a program file and executes the actions stored within it 41 : */ 42 : class TraCITestClient : public TraCIAPI { 43 : public: 44 : /** @brief Constructor 45 : * @param[in] outputFileName The name of the file the outputs will be written into 46 : */ 47 : TraCITestClient(std::string outputFileName = "testclient_result.out"); 48 : 49 : 50 : /// @brief Destructor 51 : ~TraCITestClient(); 52 : 53 : 54 : /** @brief Runs a test 55 : * @param[in] fileName The name of the file containing the test script 56 : * @param[in] port The server port to connect to 57 : * @param[in] host The server name to connect to 58 : */ 59 : int run(std::string fileName, int port, std::string host = "localhost"); 60 : 61 : 62 : protected: 63 : /// @name Commands handling 64 : /// @{ 65 : 66 : /** @brief Sends and validates a simulation step command 67 : * @param[in] time The time step to send 68 : */ 69 : void commandSimulationStep(double time); 70 : 71 : 72 : /** @brief Sends and validates a Close command 73 : */ 74 : void commandClose(); 75 : 76 : 77 : /** @brief Sends and validates a SetOrder command 78 : */ 79 : void commandSetOrder(int order); 80 : 81 : 82 : /** @brief Sends and validates a GetVariable command 83 : * @param[in] domID The ID of the domain the addressed object belongs to 84 : * @param[in] varID The ID of the variable one asks for 85 : * @param[in] objID The ID of the object a variable shall be retrieved from 86 : * @param[in] addData Storage to read additional data from, if needed 87 : */ 88 : void commandGetVariable(int domID, int varID, const std::string& objID, tcpip::Storage* addData = 0); 89 : 90 : 91 : /** @brief Sends and validates a SetVariable command 92 : * @param[in] domID The ID of the domain the addressed object belongs to 93 : * @param[in] varID The ID of the variable to set 94 : * @param[in] objID The ID of the object which shall be changed 95 : * @param[in] defFile Storage to read additional data from 96 : */ 97 : void commandSetValue(int domID, int varID, const std::string& objID, std::ifstream& defFile); 98 : 99 : 100 : /** @brief Sends and validates a SubscribeVariable command 101 : * @param[in] domID The ID of the domain the addressed object belongs to 102 : * @param[in] objID The ID of the object a variable shall be subscribed from 103 : * @param[in] beginTime The time the subscription shall begin at 104 : * @param[in] endTime The time the subscription shall end at 105 : * @param[in] varNo The number of subscribed variables 106 : * @param[in] defFile The stream to read variable values from 107 : */ 108 : void commandSubscribeObjectVariable(int domID, const std::string& objID, double beginTime, double endTime, int varNo, std::ifstream& defFile); 109 : 110 : 111 : /** @brief Sends and validates a SubscribeContext command 112 : * @param[in] domID The ID of the domain the addressed object belongs to 113 : * @param[in] objID The ID of the object a variable shall be subscribed from 114 : * @param[in] beginTime The time the subscription shall begin at 115 : * @param[in] endTime The time the subscription shall end at 116 : * @param[in] domain The domain of the objects which shall be reported 117 : * @param[in] range The range within which objects shall be for being reported 118 : * @param[in] varNo The number of subscribed variables 119 : * @param[in] defFile The stream to read variable values from 120 : */ 121 : void commandSubscribeContextVariable(int domID, const std::string& objID, double beginTime, double endTime, int domain, double range, int varNo, std::ifstream& defFile); 122 : /// @} 123 : 124 : 125 : 126 : private: 127 : /// @name Report helper 128 : /// @{ 129 : 130 : /** @brief Writes the results file 131 : */ 132 : void writeResult(); 133 : 134 : 135 : /** @brief Writes an error message 136 : * @param[in] msg The message to write 137 : */ 138 : void errorMsg(std::stringstream& msg); 139 : /// @} 140 : 141 : 142 : 143 : /// @name Results validation methods 144 : /// @{ 145 : 146 : /** @brief Validates whether the given message is a valid answer to CMD_SIMSTEP 147 : * @param[in] inMsg The storage contain the message to validate 148 : * @return Whether the message is valid 149 : */ 150 : bool validateSimulationStep2(tcpip::Storage& inMsg); 151 : 152 : 153 : /** @brief Validates whether the given message is a valid subscription return message 154 : * @param[in] inMsg The storage contain the message to validate 155 : * @return Whether the message is valid 156 : */ 157 : bool validateSubscription(tcpip::Storage& inMsg); 158 : /// @} 159 : 160 : 161 : 162 : /// @name Conversion helper 163 : /// @{ 164 : 165 : /** @brief Parses the next value type / value pair from the stream and inserts it into the storage 166 : * 167 : * @param[out] into The storage to add the value type and the value into 168 : * @param[in] defFile The file to read the values from 169 : * @param[out] msg If any error occurs, this should be filled 170 : * @return The number of written bytes 171 : */ 172 : int setValueTypeDependant(tcpip::Storage& into, std::ifstream& defFile, std::stringstream& msg); 173 : 174 : 175 : /** @brief Reads a value of the given type from the given storage and reports it 176 : * @param[in] inMsg The storage to read the value from 177 : * @param[in] valueDataType The type of the expected value 178 : */ 179 : void readAndReportTypeDependent(tcpip::Storage& inMsg, int valueDataType); 180 : /// @} 181 : 182 : 183 : /// @brief call all API methods once 184 : void testAPI(); 185 : 186 24 : inline std::string joinToString(const std::vector<std::string>& s, const std::string& between) { 187 24 : std::ostringstream oss; 188 : bool connect = false; 189 290 : for (const std::string& it : s) { 190 266 : if (connect) { 191 : oss << between; 192 : } else { 193 : connect = true; 194 : } 195 : oss << it; 196 : } 197 24 : return oss.str(); 198 24 : } 199 : 200 2 : inline std::string joinToString(const std::map<std::string, std::string>& m) { 201 2 : std::ostringstream oss; 202 : bool connect = false; 203 2 : for (const auto& it : m) { 204 0 : if (connect) { 205 0 : oss << " "; 206 : } else { 207 : connect = true; 208 : } 209 : oss << it.first << ":" << it.second; 210 : } 211 2 : return oss.str(); 212 2 : } 213 : 214 : inline std::string joinToString(const std::vector<double>& v, const std::string& between) { 215 : std::ostringstream oss; 216 : bool connect = false; 217 : for (double it : v) { 218 : if (connect) { 219 : oss << between; 220 : } else { 221 : connect = true; 222 : } 223 : oss << it; 224 : } 225 : return oss.str(); 226 : } 227 : 228 : private: 229 : /// @brief The name of the file to write the results log into 230 : std::string outputFileName; 231 : 232 : /// @brief Stream containing the log 233 : std::stringstream answerLog; 234 : 235 : };