/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file TraCITestClient.h14/// @author Friedemann Wesner15/// @author Daniel Krajzewicz16/// @author Axel Wegener17/// @author Michael Behrisch18/// @date 2008/04/0719///20// A test execution class21/****************************************************************************/22#pragma once23#include <config.h>24#include <string>25#include <sstream>26#include <vector>2728#include <foreign/tcpip/socket.h>29#include <utils/traci/TraCIAPI.h>303132// ===========================================================================33// class definitions34// ===========================================================================35/**36* @class TraCITestClient37* @brief A test execution class38*39* Reads a program file and executes the actions stored within it40*/41class TraCITestClient : public TraCIAPI {42public:43/** @brief Constructor44* @param[in] outputFileName The name of the file the outputs will be written into45*/46TraCITestClient(std::string outputFileName = "testclient_result.out");474849/// @brief Destructor50~TraCITestClient();515253/** @brief Runs a test54* @param[in] fileName The name of the file containing the test script55* @param[in] port The server port to connect to56* @param[in] host The server name to connect to57*/58int run(std::string fileName, int port, std::string host = "localhost");596061protected:62/// @name Commands handling63/// @{6465/** @brief Sends and validates a simulation step command66* @param[in] time The time step to send67*/68void commandSimulationStep(double time);697071/** @brief Sends and validates a Close command72*/73void commandClose();747576/** @brief Sends and validates a SetOrder command77*/78void commandSetOrder(int order);798081/** @brief Sends and validates a GetVariable command82* @param[in] domID The ID of the domain the addressed object belongs to83* @param[in] varID The ID of the variable one asks for84* @param[in] objID The ID of the object a variable shall be retrieved from85* @param[in] addData Storage to read additional data from, if needed86*/87void commandGetVariable(int domID, int varID, const std::string& objID, tcpip::Storage* addData = 0);888990/** @brief Sends and validates a SetVariable command91* @param[in] domID The ID of the domain the addressed object belongs to92* @param[in] varID The ID of the variable to set93* @param[in] objID The ID of the object which shall be changed94* @param[in] defFile Storage to read additional data from95*/96void commandSetValue(int domID, int varID, const std::string& objID, std::ifstream& defFile);979899/** @brief Sends and validates a SubscribeVariable command100* @param[in] domID The ID of the domain the addressed object belongs to101* @param[in] objID The ID of the object a variable shall be subscribed from102* @param[in] beginTime The time the subscription shall begin at103* @param[in] endTime The time the subscription shall end at104* @param[in] varNo The number of subscribed variables105* @param[in] defFile The stream to read variable values from106*/107void commandSubscribeObjectVariable(int domID, const std::string& objID, double beginTime, double endTime, int varNo, std::ifstream& defFile);108109110/** @brief Sends and validates a SubscribeContext command111* @param[in] domID The ID of the domain the addressed object belongs to112* @param[in] objID The ID of the object a variable shall be subscribed from113* @param[in] beginTime The time the subscription shall begin at114* @param[in] endTime The time the subscription shall end at115* @param[in] domain The domain of the objects which shall be reported116* @param[in] range The range within which objects shall be for being reported117* @param[in] varNo The number of subscribed variables118* @param[in] defFile The stream to read variable values from119*/120void commandSubscribeContextVariable(int domID, const std::string& objID, double beginTime, double endTime, int domain, double range, int varNo, std::ifstream& defFile);121/// @}122123124125private:126/// @name Report helper127/// @{128129/** @brief Writes the results file130*/131void writeResult();132133134/** @brief Writes an error message135* @param[in] msg The message to write136*/137void errorMsg(std::stringstream& msg);138/// @}139140141142/// @name Results validation methods143/// @{144145/** @brief Validates whether the given message is a valid answer to CMD_SIMSTEP146* @param[in] inMsg The storage contain the message to validate147* @return Whether the message is valid148*/149bool validateSimulationStep2(tcpip::Storage& inMsg);150151152/** @brief Validates whether the given message is a valid subscription return message153* @param[in] inMsg The storage contain the message to validate154* @return Whether the message is valid155*/156bool validateSubscription(tcpip::Storage& inMsg);157/// @}158159160161/// @name Conversion helper162/// @{163164/** @brief Parses the next value type / value pair from the stream and inserts it into the storage165*166* @param[out] into The storage to add the value type and the value into167* @param[in] defFile The file to read the values from168* @param[out] msg If any error occurs, this should be filled169* @return The number of written bytes170*/171int setValueTypeDependant(tcpip::Storage& into, std::ifstream& defFile, std::stringstream& msg);172173174/** @brief Reads a value of the given type from the given storage and reports it175* @param[in] inMsg The storage to read the value from176* @param[in] valueDataType The type of the expected value177*/178void readAndReportTypeDependent(tcpip::Storage& inMsg, int valueDataType);179/// @}180181182/// @brief call all API methods once183void testAPI();184185inline std::string joinToString(const std::vector<std::string>& s, const std::string& between) {186std::ostringstream oss;187bool connect = false;188for (const std::string& it : s) {189if (connect) {190oss << between;191} else {192connect = true;193}194oss << it;195}196return oss.str();197}198199inline std::string joinToString(const std::map<std::string, std::string>& m) {200std::ostringstream oss;201bool connect = false;202for (const auto& it : m) {203if (connect) {204oss << " ";205} else {206connect = true;207}208oss << it.first << ":" << it.second;209}210return oss.str();211}212213inline std::string joinToString(const std::vector<double>& v, const std::string& between) {214std::ostringstream oss;215bool connect = false;216for (double it : v) {217if (connect) {218oss << between;219} else {220connect = true;221}222oss << it;223}224return oss.str();225}226227private:228/// @brief The name of the file to write the results log into229std::string outputFileName;230231/// @brief Stream containing the log232std::stringstream answerLog;233234};235236237