mirror of
https://github.com/nasa/trick.git
synced 2024-12-18 20:57:55 +00:00
Expand SIM_test_varserver (#1459)
* Add tests for alternate ways to open VS port * Don't connect to varserv when quiet=true in trickops * Add print to try to help debug hanging trickops test * Handle multicast connect failures gracefully * Multicast is disabled by default on mac * Forgot an important return value * Take away retries * Fix issue with restart test * Revert trickops debugging changes * Remove debugging accidentally left in [no ci] * whoops * Allow retries * Update trickops.py * sim test adjustments * Add docs [no ci] * wording [no ci] * Cleanup * Remove large messages, test that one in unit tests
This commit is contained in:
parent
29fb20c2eb
commit
5f6a5de070
@ -63,6 +63,16 @@ trick.var_server_get_hostname()
|
||||
trick.var_server_get_port()
|
||||
```
|
||||
|
||||
Additional TCP or UDP sockets can be opened as well. Additional TCP sockets operate the same way as the original variable server socket. A UDP socket will only host 1 variable server session, and the responses will be sent to the latest address that sends commands to it.
|
||||
|
||||
Note that this is not necessary to allow multiple variable server clients - any number of clients can connect to the original variable server port.
|
||||
|
||||
```python
|
||||
trick.var_server_create_udp_socket( const char * source_address, unsigned short port )
|
||||
trick.var_server_create_tcp_socket( const char * source_address, unsigned short port )
|
||||
```
|
||||
|
||||
|
||||
### Commands
|
||||
|
||||
The variable server accepts commands in the form of strings. The variable server parses
|
||||
@ -510,6 +520,8 @@ on your network sends it's information to this address and port so there may be
|
||||
messages with variable server information available here. Here is some
|
||||
C code that reads all messages on the variable server channel.
|
||||
|
||||
Note that the multicast protocol is disabled by default in MacOS.
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <exception>
|
||||
|
||||
#include "trick/parameter_types.h"
|
||||
@ -54,6 +55,22 @@ typedef union Number {
|
||||
double double_val;
|
||||
} Number;
|
||||
|
||||
const static std::map<TRICK_TYPE, unsigned int> type_size_map = {{TRICK_CHARACTER, sizeof(char)},
|
||||
{TRICK_UNSIGNED_CHARACTER, sizeof(unsigned char)},
|
||||
{TRICK_SHORT, sizeof(short)},
|
||||
{TRICK_UNSIGNED_SHORT, sizeof(unsigned short)},
|
||||
{TRICK_INTEGER, sizeof(int)},
|
||||
{TRICK_UNSIGNED_INTEGER, sizeof(unsigned int)},
|
||||
{TRICK_LONG, sizeof(long)},
|
||||
{TRICK_UNSIGNED_LONG, sizeof(unsigned long)},
|
||||
{TRICK_LONG_LONG, sizeof(long long)},
|
||||
{TRICK_UNSIGNED_LONG_LONG, sizeof(unsigned long)},
|
||||
{TRICK_FLOAT, sizeof (float)},
|
||||
{TRICK_DOUBLE, sizeof (double)},
|
||||
{TRICK_BOOLEAN, sizeof (bool)},
|
||||
{TRICK_WCHAR, sizeof (wchar_t)}
|
||||
};
|
||||
|
||||
|
||||
class Var {
|
||||
public:
|
||||
@ -65,10 +82,13 @@ class Var {
|
||||
// There won't be a general case
|
||||
template <typename T>
|
||||
T getValue() const;
|
||||
|
||||
std::vector<unsigned char> getRawBytes() const;
|
||||
|
||||
int getArraySize() const;
|
||||
std::string getName() const;
|
||||
TRICK_TYPE getType() const;
|
||||
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> value_bytes;
|
||||
Number getInterpreter () const;
|
||||
@ -81,16 +101,18 @@ class Var {
|
||||
|
||||
TRICK_TYPE _trick_type;
|
||||
unsigned int _var_size;
|
||||
unsigned int _arr_length;
|
||||
};
|
||||
|
||||
class ParsedBinaryMessage {
|
||||
public:
|
||||
ParsedBinaryMessage() : _byteswap(false), _nonames(false) {}
|
||||
ParsedBinaryMessage (bool byteswap, bool nonames) : _byteswap(byteswap), _nonames(nonames) {}
|
||||
ParsedBinaryMessage() : ParsedBinaryMessage(false, false) {}
|
||||
ParsedBinaryMessage (bool byteswap, bool nonames) : _message_type(0), _message_size(0), _num_vars(0), _byteswap(byteswap), _nonames(nonames) {}
|
||||
|
||||
void combine (const ParsedBinaryMessage& message);
|
||||
|
||||
int parse (const std::vector<unsigned char>& bytes);
|
||||
int parse (char * raw_bytes);
|
||||
|
||||
int getMessageType() const;
|
||||
unsigned int getMessageSize() const;
|
||||
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
@ -25,3 +25,4 @@ trick.zip
|
||||
jitlib
|
||||
build
|
||||
S_sie.json
|
||||
*.ckpnt
|
31
test/SIM_test_varserv/RUN_test/manual_test.py
Normal file
31
test/SIM_test_varserv/RUN_test/manual_test.py
Normal file
@ -0,0 +1,31 @@
|
||||
import trick
|
||||
import socket
|
||||
|
||||
from trick.unit_test import *
|
||||
|
||||
def main():
|
||||
|
||||
trick.var_server_set_port(4000)
|
||||
trick.var_ascii()
|
||||
trick.real_time_enable()
|
||||
trick.exec_set_software_frame(0.01)
|
||||
# trick.set_var_server_info_msg_on()
|
||||
|
||||
trick.var_server_create_tcp_socket('localhost', 49000)
|
||||
trick.var_server_create_udp_socket('', 48000)
|
||||
# trick.var_server_create_multicast_socket('224.10.10.10','', 47000)
|
||||
|
||||
# trick.exec_set_terminate_time(100000.0)
|
||||
|
||||
varServerPort = trick.var_server_get_port()
|
||||
test_output = ( os.getenv("TRICK_HOME") + "/trick_test/SIM_test_varserv.xml" )
|
||||
# command = 'os.system("./models/test_client/test_client ' + str(varServerPort) + ' --gtest_output=xml:' + test_output + ' &")'
|
||||
|
||||
# Start the test client after everything has been initialized (hopefully)
|
||||
# trick.add_read(1.0, command)
|
||||
trick.sim_control_panel_set_enabled(True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -11,7 +11,11 @@ def main():
|
||||
trick.exec_set_software_frame(0.01)
|
||||
# trick.set_var_server_info_msg_on()
|
||||
|
||||
trick.exec_set_terminate_time(100.0)
|
||||
trick.var_server_create_tcp_socket('localhost', 49000)
|
||||
trick.var_server_create_udp_socket('', 48000)
|
||||
# trick.var_server_create_multicast_socket('224.10.10.10','', 47000)
|
||||
|
||||
trick.exec_set_terminate_time(1000.0)
|
||||
|
||||
varServerPort = trick.var_server_get_port()
|
||||
test_output = ( os.getenv("TRICK_HOME") + "/trick_test/SIM_test_varserv.xml" )
|
||||
|
@ -8,7 +8,8 @@ clean: clean_test_client
|
||||
TEST_CLIENT_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread -L${TRICK_LIB_DIR} -ltrick_var_binary_parser
|
||||
|
||||
test_client: models/test_client/test_client.cpp
|
||||
cd models/test_client; $(TRICK_CXX) test_client.cpp -o test_client $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_TEST_FLAGS) -I$(TRICK_HOME)/include $(TEST_CLIENT_LIBS)
|
||||
cd models/test_client; $(TRICK_CXX) test_client.cpp -o test_client $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_TEST_FLAGS) -Wno-write-strings -Wno-sign-compare -I$(TRICK_HOME)/include $(TEST_CLIENT_LIBS)
|
||||
|
||||
clean_test_client:
|
||||
rm -f models/test_client/test_client
|
||||
rm -f models/test_client/test_client
|
||||
|
@ -10,14 +10,15 @@
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "trick/var_binary_parser.hh"
|
||||
|
||||
#define SOCKET_BUF_SIZE 20480
|
||||
|
||||
#define DOUBLE_TOL 1e-5
|
||||
#define SOCKET_BUF_SIZE 204800
|
||||
|
||||
// Pretend that gtest was kind enough to provide an EXPECT_FEQ operator with a tolerance
|
||||
#define EXPECT_FEQ(a,b) EXPECT_LE(fabs(a - b), DOUBLE_TOL)
|
||||
@ -29,12 +30,14 @@ class Socket {
|
||||
int max_retries = 10;
|
||||
|
||||
Socket() : _initialized(false) {}
|
||||
int init(std::string hostname, int port) {
|
||||
int init(std::string hostname, int port, int mode = SOCK_STREAM) {
|
||||
_multicast_socket = false;
|
||||
|
||||
_hostname = hostname;
|
||||
_port = port;
|
||||
int tries = 0;
|
||||
|
||||
while ((_socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 && tries < max_retries) tries++;
|
||||
while ((_socket_fd = socket(AF_INET, mode, 0)) < 0 && tries < max_retries) tries++;
|
||||
|
||||
if (_socket_fd < 0) {
|
||||
std::cout << "Socket connection failed" << std::endl;
|
||||
@ -65,12 +68,60 @@ class Socket {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
int init_multicast (std::string hostname, int port) {
|
||||
_multicast_socket = true;
|
||||
_hostname = hostname;
|
||||
_port = port;
|
||||
int tries = 0;
|
||||
|
||||
while ((_socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 && tries < max_retries) tries++;
|
||||
|
||||
if (_socket_fd < 0) {
|
||||
std::cout << "init_multicast: Socket open failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int value = 1;
|
||||
if (setsockopt(_socket_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &value, (socklen_t) sizeof(value)) < 0) {
|
||||
std::cout << "init_multicast: Socket option failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ip_mreq mreq;
|
||||
// Use setsockopt() to request that the kernel join a multicast group
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(_hostname.c_str());
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
if (setsockopt(_socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, (socklen_t) sizeof(mreq)) < 0) {
|
||||
std::cout << "init_multicast: setsockopt: ip_add_membership failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct sockaddr_in sockin ;
|
||||
|
||||
// Set up destination address
|
||||
sockin.sin_family = AF_INET;
|
||||
sockin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
sockin.sin_port = htons(_port);
|
||||
|
||||
if ( bind(_socket_fd, (struct sockaddr *) &sockin, (socklen_t) sizeof(sockin)) < 0 ) {
|
||||
std::cout << "init_multicast: bind failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int send (std::string message) {
|
||||
// weird syntax I've never used before - since the send syscall that i'm trying to use is overloaded in this class,
|
||||
// I have to append :: to the front of it so that the compiler knows to look in the global namespace
|
||||
int success = ::send(_socket_fd, message.c_str(), message.size(), 0);
|
||||
if (success < message.size()) {
|
||||
std::cout << "Failed to send message" << std::endl;
|
||||
std::cout << "init_multicast: Failed to send message" << std::endl;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@ -98,7 +149,7 @@ class Socket {
|
||||
unsigned char buffer[SOCKET_BUF_SIZE];
|
||||
int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0);
|
||||
if (numBytes < 0) {
|
||||
std::cout << "Failed to read from socket" << std::endl;
|
||||
std::cout << "init_multicast: Failed to read from socket" << std::endl;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> bytes;
|
||||
@ -139,9 +190,97 @@ class Socket {
|
||||
std::string _hostname;
|
||||
int _socket_fd;
|
||||
bool _initialized;
|
||||
bool _multicast_socket;
|
||||
|
||||
};
|
||||
|
||||
class VariableServerTest : public ::testing::Test {
|
||||
protected:
|
||||
VariableServerTest() {
|
||||
socket_status = socket.init("localhost", 40000);
|
||||
if (socket_status == 0) {
|
||||
std::stringstream request;
|
||||
request << "trick.var_set_client_tag(\"VSTest";
|
||||
request << numSession++;
|
||||
request << "\") \n";
|
||||
|
||||
socket << request.str();
|
||||
}
|
||||
}
|
||||
~VariableServerTest() {
|
||||
socket << "trick.var_exit()\n";
|
||||
socket.close();
|
||||
}
|
||||
|
||||
Socket socket;
|
||||
int socket_status;
|
||||
|
||||
static int numSession;
|
||||
};
|
||||
|
||||
class VariableServerUDPTest : public ::testing::Test {
|
||||
protected:
|
||||
VariableServerUDPTest() {
|
||||
socket_status = socket.init("localhost", 48000, SOCK_DGRAM);
|
||||
|
||||
if (socket_status == 0) {
|
||||
std::stringstream request;
|
||||
request << "trick.var_set_client_tag(\"UDP_VSTest";
|
||||
request << numSession++;
|
||||
request << "\") \n";
|
||||
|
||||
socket << request.str();
|
||||
}
|
||||
}
|
||||
~VariableServerUDPTest() {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
Socket socket;
|
||||
int socket_status;
|
||||
|
||||
static int numSession;
|
||||
};
|
||||
|
||||
class VariableServerTestAltListener : public ::testing::Test {
|
||||
protected:
|
||||
VariableServerTestAltListener() {
|
||||
socket_status = socket.init("localhost", 49000);
|
||||
|
||||
if (socket_status == 0) {
|
||||
std::stringstream request;
|
||||
request << "trick.var_set_client_tag(\"altListener_VSTest";
|
||||
request << numSession++;
|
||||
request << "\") \n";
|
||||
|
||||
socket << request.str();
|
||||
}
|
||||
}
|
||||
~VariableServerTestAltListener() {
|
||||
socket << "trick.var_exit()\n";
|
||||
socket.close();
|
||||
}
|
||||
|
||||
Socket socket;
|
||||
int socket_status;
|
||||
|
||||
static int numSession;
|
||||
};
|
||||
|
||||
int VariableServerTest::numSession = 0;
|
||||
int VariableServerUDPTest::numSession = 0;
|
||||
int VariableServerTestAltListener::numSession = 0;
|
||||
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* Helpful constants and functions */
|
||||
/**********************************************************/
|
||||
|
||||
|
||||
const int MODE_RUN = 5;
|
||||
const int MODE_FREEZE = 1;
|
||||
|
||||
int strcmp_IgnoringWhiteSpace(std::string s1_str, std::string s2_str) {
|
||||
const char * s1 = s1_str.c_str();
|
||||
const char * s2 = s2_str.c_str();
|
||||
@ -164,32 +303,212 @@ int strcmp_IgnoringWhiteSpace(std::string s1_str, std::string s2_str) {
|
||||
}
|
||||
}
|
||||
|
||||
class VariableServerTest : public ::testing::Test {
|
||||
protected:
|
||||
VariableServerTest() {
|
||||
socket_status = socket.init("localhost", 40000);
|
||||
void spin (Socket& socket, int wait_cycles = 5) {
|
||||
for (int i = 0; i < wait_cycles; i++)
|
||||
socket.receive();
|
||||
}
|
||||
|
||||
if (socket_status == 0) {
|
||||
std::stringstream request;
|
||||
request << "trick.var_set_client_tag(\"VSTest";
|
||||
request << numSession++;
|
||||
request << "\") \n";
|
||||
void wait_for_mode_change (Socket& socket, int expected_mode, int max_wait_iterations = 10) {
|
||||
int iteration = 0;
|
||||
std::string mode_reply;
|
||||
std::string expected_reply = "5\t" + std::to_string(expected_mode) + "\n";
|
||||
while (iteration++ < max_wait_iterations) {
|
||||
socket << "trick.var_send_once(\"trick_sys.sched.mode\")\n";
|
||||
socket >> mode_reply;
|
||||
if (mode_reply == expected_reply)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
socket << request.str();
|
||||
}
|
||||
}
|
||||
~VariableServerTest() {
|
||||
socket << "trick.var_exit()\n";
|
||||
socket.close();
|
||||
}
|
||||
void dump_checkpoint (Socket& socket, const std::string& checkpoint_name) {
|
||||
socket << "trick.var_pause()\ntrick.exec_freeze()\n";
|
||||
wait_for_mode_change(socket, MODE_FREEZE);
|
||||
|
||||
Socket socket;
|
||||
int socket_status;
|
||||
|
||||
static int numSession;
|
||||
};
|
||||
std::string checkpoint_cmd = "trick.checkpoint(\"" + checkpoint_name + "\")\n";
|
||||
socket << checkpoint_cmd;
|
||||
|
||||
int VariableServerTest::numSession = 0;
|
||||
socket << "trick.exec_run()\n";
|
||||
wait_for_mode_change(socket, MODE_RUN);
|
||||
socket << "trick.var_unpause()\n";
|
||||
}
|
||||
|
||||
void load_checkpoint (Socket& socket, const std::string& checkpoint_name) {
|
||||
socket << "trick.var_pause()\ntrick.exec_freeze()\n";
|
||||
wait_for_mode_change(socket, MODE_FREEZE);
|
||||
|
||||
std::string checkpoint_cmd = "trick.load_checkpoint(\"" + checkpoint_name + "\")\n";
|
||||
socket << checkpoint_cmd;
|
||||
sleep(5);
|
||||
|
||||
socket << "trick.exec_run()\n";
|
||||
wait_for_mode_change(socket, MODE_RUN);
|
||||
socket << "trick.var_unpause()\n";
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/* UDP Tests */
|
||||
/************************************/
|
||||
|
||||
|
||||
TEST_F (VariableServerUDPTest, Strings) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
socket << "trick.var_send_once(\"vsx.vst.o\")\n";
|
||||
socket >> reply;
|
||||
std::string expected("5\tYou will rejoice to hear that no disaster has accompanied the commencement of an enterprise which you have regarded with such evil forebodings. I arrived here yesterday, and my first task is to assure my dear sister of my welfare and increasing confidence in the success of my undertaking.");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
|
||||
expected = std::string("5\tI am already far north of London, and as I walk in the streets of Petersburgh, I feel a cold northern breeze play upon my cheeks, which braces my nerves and fills me with delight. Do you understand this feeling?");
|
||||
socket << "trick.var_send_once(\"vsx.vst.p\")\n";
|
||||
|
||||
socket >> reply;
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_F (VariableServerUDPTest, AddRemove) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
std::string expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.c\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket >> reply;
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234 1");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_remove(\"vsx.vst.m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.n\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234 0,1,2,3,4");
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_exit()\n";
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Alt Listener Tests */
|
||||
/*********************************************/
|
||||
|
||||
TEST_F (VariableServerTestAltListener, Strings) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
socket << "trick.var_send_once(\"vsx.vst.o\")\n";
|
||||
socket >> reply;
|
||||
std::string expected("5\tYou will rejoice to hear that no disaster has accompanied the commencement of an enterprise which you have regarded with such evil forebodings. I arrived here yesterday, and my first task is to assure my dear sister of my welfare and increasing confidence in the success of my undertaking.");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
|
||||
expected = std::string("5\tI am already far north of London, and as I walk in the streets of Petersburgh, I feel a cold northern breeze play upon my cheeks, which braces my nerves and fills me with delight. Do you understand this feeling?");
|
||||
socket << "trick.var_send_once(\"vsx.vst.p\")\n";
|
||||
|
||||
socket >> reply;
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTestAltListener, AddRemove) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
std::string expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.c\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket >> reply;
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234 1");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_remove(\"vsx.vst.m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234");
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.n\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234 0,1,2,3,4");
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_F (VariableServerTestAltListener, RestartAndSet) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
std::string expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.c\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\n");
|
||||
|
||||
EXPECT_EQ(reply, expected);
|
||||
|
||||
dump_checkpoint(socket, "reload_file.ckpnt");
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.e\",\"m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\t-123456 {m}\n");
|
||||
|
||||
socket << "trick.var_set(\"vsx.vst.c\", 5)\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t5\t-123456 {m}\n");
|
||||
|
||||
EXPECT_EQ(reply, expected);
|
||||
|
||||
load_checkpoint(socket, "RUN_test/reload_file.ckpnt");
|
||||
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\t-123456\n");
|
||||
|
||||
EXPECT_EQ(reply, expected);
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Normal case tests */
|
||||
/*********************************************/
|
||||
|
||||
TEST_F (VariableServerTest, Strings) {
|
||||
if (socket_status != 0) {
|
||||
@ -222,6 +541,41 @@ TEST_F (VariableServerTest, Strings) {
|
||||
// EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, NoExtraTab) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
std::string expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.c\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\n");
|
||||
|
||||
EXPECT_STREQ(reply.c_str(), expected.c_str());
|
||||
|
||||
socket >> reply;
|
||||
|
||||
EXPECT_STREQ(reply.c_str(), expected.c_str());
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\t1\n");
|
||||
|
||||
EXPECT_STREQ(reply.c_str(), expected.c_str());
|
||||
|
||||
socket << "trick.var_remove(\"vsx.vst.m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\n");
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.n\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\t0,1,2,3,4\n");
|
||||
|
||||
EXPECT_STREQ(reply.c_str(), expected.c_str());
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, AddRemove) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
@ -256,7 +610,6 @@ TEST_F (VariableServerTest, AddRemove) {
|
||||
socket >> reply;
|
||||
expected = std::string("0 -1234 0,1,2,3,4");
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, BadRefResponse) {
|
||||
@ -356,8 +709,94 @@ TEST_F (VariableServerTest, Exists) {
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
|
||||
socket << "trick.var_binary()\n";
|
||||
|
||||
std::vector<unsigned char> actual_bytes;
|
||||
std::vector<unsigned char> expected_bytes;
|
||||
socket << "trick.var_exists(\"vsx.vst.e\")\n";
|
||||
actual_bytes = socket.receive_bytes();
|
||||
expected_bytes = {0x01, 0x00, 0x00, 0x00, 0x01};
|
||||
|
||||
EXPECT_EQ(expected_bytes, actual_bytes);
|
||||
|
||||
|
||||
socket << "trick.var_exists(\"vsx.vst.z\")\n";
|
||||
actual_bytes = socket.receive_bytes();
|
||||
expected_bytes = {0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
EXPECT_EQ(expected_bytes, actual_bytes);
|
||||
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, ListSize) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
std::string expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.a\")\ntrick.var_add(\"vsx.vst.b\")\ntrick.var_add(\"vsx.vst.c\")\ntrick.var_add(\"vsx.vst.d\")\ntrick.var_pause()\n";
|
||||
socket << "trick.var_send_list_size()\n";
|
||||
|
||||
socket >> reply;
|
||||
expected = "3 4";
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Reply: " << reply << "\tExpected: " << expected;
|
||||
|
||||
// Adding a variable to the list more than once is allowed
|
||||
socket << "trick.var_add(\"vsx.vst.a\")\n";
|
||||
socket << "trick.var_send_list_size()\n";
|
||||
|
||||
socket >> reply;
|
||||
expected = "3 5";
|
||||
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Reply: " << reply << "\tExpected: " << expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.e\")\ntrick.var_binary()\ntrick.var_send_list_size()\n";
|
||||
|
||||
std::vector<unsigned char> actual_bytes;
|
||||
std::vector<unsigned char> expected_bytes;
|
||||
actual_bytes = socket.receive_bytes();
|
||||
expected_bytes = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00};
|
||||
|
||||
EXPECT_EQ(expected_bytes, actual_bytes);
|
||||
}
|
||||
|
||||
|
||||
TEST_F (VariableServerTest, RestartAndSet) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
std::string reply;
|
||||
std::string expected;
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.c\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\n");
|
||||
|
||||
EXPECT_EQ(reply, expected);
|
||||
|
||||
dump_checkpoint(socket, "reload_file.ckpnt");
|
||||
|
||||
socket << "trick.var_add(\"vsx.vst.e\",\"m\")\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\t-123456 {m}\n");
|
||||
|
||||
socket << "trick.var_set(\"vsx.vst.c\", 5)\n";
|
||||
socket >> reply;
|
||||
expected = std::string("0\t5\t-123456 {m}\n");
|
||||
|
||||
EXPECT_EQ(reply, expected);
|
||||
|
||||
load_checkpoint(socket, "RUN_test/reload_file.ckpnt");
|
||||
|
||||
socket >> reply;
|
||||
expected = std::string("0\t-1234\t-123456\n");
|
||||
|
||||
EXPECT_EQ(reply, expected);
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, Cycle) {
|
||||
if (socket_status != 0) {
|
||||
@ -365,7 +804,6 @@ TEST_F (VariableServerTest, Cycle) {
|
||||
}
|
||||
|
||||
double cycle = 1.0;
|
||||
double tolerance = 1e-5;
|
||||
int num_cycles = 5;
|
||||
|
||||
// Challenge: no loops allowed
|
||||
@ -408,7 +846,7 @@ TEST_F (VariableServerTest, Cycle) {
|
||||
|
||||
std::string command = "trick.var_set_copy_mode(1)\ntrick.var_set_write_mode(1)\ntrick.var_add(\"time\")\n";
|
||||
socket << command;
|
||||
|
||||
|
||||
cycle = 0.1;
|
||||
num_cycles = 5;
|
||||
run_cycle_test();
|
||||
@ -451,6 +889,84 @@ TEST_F (VariableServerTest, Pause) {
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
TEST_F (VariableServerTest, Multicast) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
socket << "trick.var_server_set_user_tag(\"VSTestServer\")\n";
|
||||
|
||||
Socket multicast_socket;
|
||||
if (multicast_socket.init_multicast("224.3.14.15", 9265) != 0) {
|
||||
FAIL() << "Multicast Socket failed to initialize.";
|
||||
}
|
||||
|
||||
int max_multicast_tries = 100;
|
||||
int tries = 0;
|
||||
bool found = false;
|
||||
|
||||
char expected_hostname[80];
|
||||
gethostname(expected_hostname, 80);
|
||||
int expected_port = 40000;
|
||||
|
||||
// get expected username
|
||||
struct passwd *passp = getpwuid(getuid()) ;
|
||||
char * expected_username;
|
||||
if ( passp == NULL ) {
|
||||
expected_username = strdup("unknown") ;
|
||||
} else {
|
||||
expected_username = strdup(passp->pw_name) ;
|
||||
}
|
||||
|
||||
// Don't care about PID, just check that it's > 0
|
||||
char * expected_sim_dir = "trick/test/SIM_test_varserv"; // Compare against the end of the string for this one
|
||||
// Don't care about cmdline name
|
||||
char * expected_input_file = "RUN_test/unit_test.py";
|
||||
// Don't care about trick_version
|
||||
char * expected_tag = "VSTestServer";
|
||||
|
||||
// Variables to be populated by the multicast message
|
||||
char actual_hostname[80];
|
||||
unsigned short actual_port = 0;
|
||||
char actual_username[80];
|
||||
int actual_pid = 0;
|
||||
char actual_sim_dir[80];
|
||||
char actual_cmdline_name[80];
|
||||
char actual_input_file[80];
|
||||
char actual_trick_version[80];
|
||||
char actual_tag[80];
|
||||
unsigned short actual_duplicate_port = 0;
|
||||
|
||||
while (!found && tries++ < max_multicast_tries) {
|
||||
std::string broadcast_data = multicast_socket.receive();
|
||||
sscanf(broadcast_data.c_str(), "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , actual_hostname, &actual_port ,
|
||||
actual_username , &actual_pid , actual_sim_dir , actual_cmdline_name ,
|
||||
actual_input_file , actual_trick_version , actual_tag, &actual_duplicate_port) ;
|
||||
|
||||
if (strcmp(actual_hostname, expected_hostname) == 0 && strcmp(expected_tag, actual_tag) == 0) {
|
||||
found = true;
|
||||
EXPECT_STREQ(actual_hostname, expected_hostname);
|
||||
EXPECT_EQ(actual_port, expected_port);
|
||||
EXPECT_STREQ(actual_username, expected_username);
|
||||
EXPECT_GT(actual_pid, 0);
|
||||
std::string expected_sim_dir_str(expected_sim_dir);
|
||||
std::string actual_sim_dir_str(actual_sim_dir);
|
||||
std::string end_of_actual = actual_sim_dir_str.substr(actual_sim_dir_str.length() - expected_sim_dir_str.length(), actual_sim_dir_str.length());
|
||||
EXPECT_EQ(expected_sim_dir_str, end_of_actual);
|
||||
EXPECT_STREQ(actual_input_file, expected_input_file);
|
||||
EXPECT_STREQ(actual_tag, expected_tag);
|
||||
EXPECT_EQ(actual_duplicate_port, expected_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
FAIL() << "Multicast message never received";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_F (VariableServerTest, Freeze) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
@ -461,10 +977,6 @@ TEST_F (VariableServerTest, Freeze) {
|
||||
int mode;
|
||||
long long frame_count;
|
||||
long long freeze_frame_count;
|
||||
|
||||
// Constants for clarity
|
||||
const int MODE_RUN = 5;
|
||||
const int MODE_FREEZE = 1;
|
||||
|
||||
// lambda capture by refence is neat
|
||||
auto parse_message_for_sim_mode_and_frames = [&](const std::string& message) {
|
||||
@ -539,7 +1051,6 @@ TEST_F (VariableServerTest, Freeze) {
|
||||
ASSERT_EQ(mode, MODE_RUN);
|
||||
}
|
||||
|
||||
|
||||
TEST_F (VariableServerTest, CopyAndWriteModes) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
@ -575,10 +1086,6 @@ TEST_F (VariableServerTest, CopyAndWriteModes) {
|
||||
vars = token;
|
||||
};
|
||||
|
||||
auto spin = [&](int wait_cycles = 5) {
|
||||
socket.receive();
|
||||
};
|
||||
|
||||
// Check that every combination of modes is functional
|
||||
// Check that reasonable times and frames are returned as well
|
||||
// Default is VS_COPY_ASYNC=0 and VS_WRITE_ASYNC=0
|
||||
@ -602,7 +1109,7 @@ TEST_F (VariableServerTest, CopyAndWriteModes) {
|
||||
|
||||
// With copy mode VS_COPY_SCHEDULED and write mode VS_WRITE_ASYNC, the first reply will be all 0 since the main time to copy has not occurred yet.
|
||||
// Is this what we want? Maybe we should have more strict communication on whether the data has been staged so the first message isn't incorrect
|
||||
spin();
|
||||
// spin();
|
||||
|
||||
expected = "-1234 1234";
|
||||
parse_message(socket.receive());
|
||||
@ -654,11 +1161,7 @@ TEST_F (VariableServerTest, CopyAndWriteModes) {
|
||||
socket << command;
|
||||
|
||||
// Same issue as copy mode 1 write mode 0
|
||||
spin();
|
||||
// expected = "0 -1234567 123456789";
|
||||
// EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
|
||||
// std::cout << "\tExpected: " << expected << "\n\tActual: " << reply << std::endl;
|
||||
|
||||
// spin();
|
||||
parse_message(socket.receive());
|
||||
expected = "-1234567 123456789";
|
||||
EXPECT_EQ(strcmp_IgnoringWhiteSpace(vars, expected), 0) << "Received: " << vars << " Expected: " << expected;
|
||||
@ -703,7 +1206,7 @@ TEST_F (VariableServerTest, CopyAndWriteModes) {
|
||||
socket.clear_buffered_data();
|
||||
}
|
||||
|
||||
bool getCompleteBinaryMessage(ParsedBinaryMessage& message, Socket& socket) {
|
||||
bool getCompleteBinaryMessage(ParsedBinaryMessage& message, Socket& socket, bool print = false) {
|
||||
static const int max_retries = 5;
|
||||
|
||||
int tries = 0;
|
||||
@ -722,15 +1225,162 @@ bool getCompleteBinaryMessage(ParsedBinaryMessage& message, Socket& socket) {
|
||||
}
|
||||
}
|
||||
|
||||
if (print) {
|
||||
std::cout << "Message: ";
|
||||
for (unsigned char byte : reply) {
|
||||
std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return parse_success;
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, send_stdio) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
socket << "trick.var_set_send_stdio(True)\n";
|
||||
socket << "sys.stdout.write(\"This message should redirect to varserver\")\n";
|
||||
|
||||
std::string message;
|
||||
socket >> message;
|
||||
|
||||
std::stringstream message_stream(message);
|
||||
std::string token;
|
||||
|
||||
int message_type;
|
||||
int stream_num;
|
||||
int text_size;
|
||||
std::string text;
|
||||
|
||||
message_stream >> message_type;
|
||||
message_stream >> stream_num;
|
||||
std::getline(message_stream, token, '\n');
|
||||
text_size = stoi(token);
|
||||
std::getline(message_stream, text);
|
||||
|
||||
if (text.size() != text_size) {
|
||||
socket >> text;
|
||||
}
|
||||
|
||||
EXPECT_EQ (message_type, 4);
|
||||
EXPECT_EQ (stream_num, 1);
|
||||
EXPECT_EQ (text_size, 41);
|
||||
|
||||
EXPECT_EQ(text, std::string("This message should redirect to varserver"));
|
||||
}
|
||||
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
TEST_F (VariableServerTest, MulticastAfterRestart) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
socket << "trick.var_server_set_user_tag(\"VSTestServer\")\n";
|
||||
|
||||
Socket multicast_socket;
|
||||
if (multicast_socket.init_multicast("224.3.14.15", 9265) != 0) {
|
||||
FAIL() << "Multicast Socket failed to initialize.";
|
||||
}
|
||||
|
||||
int max_multicast_tries = 100;
|
||||
int tries = 0;
|
||||
bool found = false;
|
||||
|
||||
char expected_hostname[80];
|
||||
gethostname(expected_hostname, 80);
|
||||
int expected_port = 40000;
|
||||
|
||||
// get expected username
|
||||
struct passwd *passp = getpwuid(getuid()) ;
|
||||
char * expected_username;
|
||||
if ( passp == NULL ) {
|
||||
expected_username = strdup("unknown") ;
|
||||
} else {
|
||||
expected_username = strdup(passp->pw_name) ;
|
||||
}
|
||||
|
||||
// Don't care about PID, just check that it's > 0
|
||||
char * expected_sim_dir = "trick/test/SIM_test_varserv"; // Compare against the end of the string for this one
|
||||
// Don't care about cmdline name
|
||||
char * expected_input_file = "RUN_test/unit_test.py";
|
||||
// Don't care about trick_version
|
||||
char * expected_tag = "VSTestServer";
|
||||
|
||||
// Variables to be populated by the multicast message
|
||||
char actual_hostname[80];
|
||||
unsigned short actual_port = 0;
|
||||
char actual_username[80];
|
||||
int actual_pid = 0;
|
||||
char actual_sim_dir[80];
|
||||
char actual_cmdline_name[80];
|
||||
char actual_input_file[80];
|
||||
char actual_trick_version[80];
|
||||
char actual_tag[80];
|
||||
unsigned short actual_duplicate_port = 0;
|
||||
|
||||
while (!found && tries++ < max_multicast_tries) {
|
||||
std::string broadcast_data = multicast_socket.receive();
|
||||
sscanf(broadcast_data.c_str(), "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , actual_hostname, &actual_port ,
|
||||
actual_username , &actual_pid , actual_sim_dir , actual_cmdline_name ,
|
||||
actual_input_file , actual_trick_version , actual_tag, &actual_duplicate_port) ;
|
||||
|
||||
if (strcmp(actual_hostname, expected_hostname) == 0 && strcmp(expected_tag, actual_tag) == 0) {
|
||||
found = true;
|
||||
EXPECT_STREQ(actual_hostname, expected_hostname);
|
||||
EXPECT_EQ(actual_port, expected_port);
|
||||
EXPECT_STREQ(actual_username, expected_username);
|
||||
EXPECT_GT(actual_pid, 0);
|
||||
std::string expected_sim_dir_str(expected_sim_dir);
|
||||
std::string actual_sim_dir_str(actual_sim_dir);
|
||||
std::string end_of_actual = actual_sim_dir_str.substr(actual_sim_dir_str.length() - expected_sim_dir_str.length(), actual_sim_dir_str.length());
|
||||
EXPECT_EQ(expected_sim_dir_str, end_of_actual);
|
||||
EXPECT_STREQ(actual_input_file, expected_input_file);
|
||||
EXPECT_STREQ(actual_tag, expected_tag);
|
||||
EXPECT_EQ(actual_duplicate_port, expected_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
FAIL() << "Multicast message never received";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_F (VariableServerTest, Binary) {
|
||||
if (socket_status != 0) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
socket << "trick.var_binary()\ntrick.var_add(\"vsx.vst.n\")\n";
|
||||
ParsedBinaryMessage message_n;
|
||||
|
||||
if (!getCompleteBinaryMessage(message_n, socket)) {
|
||||
FAIL() << "Parser was not able to interpret the message.";
|
||||
}
|
||||
|
||||
Var arr_var = message_n.getVariable("vsx.vst.n");
|
||||
EXPECT_EQ(arr_var.getArraySize(), 5);
|
||||
std::vector<unsigned char> raw_arr = arr_var.getRawBytes();
|
||||
std::vector<int> values;
|
||||
for (unsigned int i = 0; i < raw_arr.size(); i += 4) {
|
||||
int val = 0;
|
||||
for (unsigned int j = i; j < i+4; j++) {
|
||||
val |= raw_arr[j] << j*8;
|
||||
}
|
||||
values.push_back(val);
|
||||
}
|
||||
|
||||
std::vector<int> expected_arr = {0, 1, 2, 3, 4};
|
||||
EXPECT_EQ(values, expected_arr);
|
||||
|
||||
|
||||
std::vector<unsigned char> reply;
|
||||
socket << "trick.var_binary()\ntrick.var_add(\"vsx.vst.c\")\ntrick.var_add(\"vsx.vst.k\")\ntrick.var_add(\"vsx.vst.o\")\ntrick.var_add(\"vsx.vst.m\")\n";
|
||||
socket << "trick.var_clear()\ntrick.var_add(\"vsx.vst.c\")\ntrick.var_add(\"vsx.vst.k\")\ntrick.var_add(\"vsx.vst.o\")\ntrick.var_add(\"vsx.vst.m\")\n";
|
||||
|
||||
ParsedBinaryMessage message;
|
||||
|
||||
@ -792,7 +1442,6 @@ TEST_F (VariableServerTest, Binary) {
|
||||
}
|
||||
|
||||
TEST_F (VariableServerTest, DISABLED_BinaryByteswap) {
|
||||
// TODO: VAR_BYTESWAP DOES NOT APPEAR TO WORK CORRECTLY
|
||||
|
||||
std::vector<unsigned char> reply;
|
||||
socket << "trick.var_binary()\ntrick.var_byteswap(False)\ntrick.var_add(\"vsx.vst.f\")\ntrick.var_add(\"vsx.vst.j\")\n";
|
||||
@ -802,11 +1451,11 @@ TEST_F (VariableServerTest, DISABLED_BinaryByteswap) {
|
||||
|
||||
// Test byteswap
|
||||
|
||||
std::cout << "Message: ";
|
||||
for (unsigned char byte : reply) {
|
||||
std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// std::cout << "Message: ";
|
||||
// for (unsigned char byte : reply) {
|
||||
// std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
ParsedBinaryMessage message;
|
||||
|
||||
@ -832,11 +1481,11 @@ TEST_F (VariableServerTest, DISABLED_BinaryByteswap) {
|
||||
socket.receive_bytes();
|
||||
reply = socket.receive_bytes();
|
||||
|
||||
std::cout << "Message: ";
|
||||
for (unsigned char byte : reply) {
|
||||
std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// std::cout << "Message: ";
|
||||
// for (unsigned char byte : reply) {
|
||||
// std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
ParsedBinaryMessage byteswap_message(true, false);
|
||||
|
||||
@ -852,7 +1501,6 @@ TEST_F (VariableServerTest, DISABLED_BinaryByteswap) {
|
||||
EXPECT_EQ(strcmp(byteswap_message.variables[0].getName().c_str(), "vsx.vst.f"), 0);
|
||||
EXPECT_EQ(byteswap_message.variables[0].getType(), TRICK_UNSIGNED_INTEGER);
|
||||
EXPECT_EQ(byteswap_message.variables[0].getValue<unsigned int>(), 123456);
|
||||
std::cout << "Byteswap value: " << byteswap_message.variables[0].getValue<unsigned int>() << std::endl;
|
||||
|
||||
EXPECT_EQ(strcmp(byteswap_message.variables[1].getName().c_str(), "vsx.vst.j"), 0);
|
||||
EXPECT_EQ(byteswap_message.variables[1].getType(), TRICK_DOUBLE);
|
||||
|
@ -31,7 +31,9 @@ class VSTest {
|
||||
int n[5];
|
||||
std::string o;
|
||||
char * p;
|
||||
wchar_t * q;
|
||||
wchar_t * q; /**< trick_chkpnt_io(**) */
|
||||
|
||||
int large_arr[4000];
|
||||
|
||||
int status;
|
||||
|
||||
|
@ -4,7 +4,8 @@ REFERENCE: ( None )
|
||||
ASSUMPTIONS AND LIMITATIONS: ( None )
|
||||
CLASS: ( scheduled )
|
||||
LIBRARY DEPENDENCY: ( VS.o )
|
||||
PROGRAMMERS: ( (Lindsay Landry) (L3) (9-12-2013) (Jackie Deans) (CACI) (11-30-2022) )
|
||||
PROGRAMMERS: ( (Lindsay Landry) (L3) (9-12-2013)
|
||||
(Jackie Deans) (CACI) (11-30-2022) )
|
||||
*******************************************************************************/
|
||||
#include <iostream>
|
||||
#include "../include/VS.hh"
|
||||
@ -35,6 +36,10 @@ int VSTest::default_vars() {
|
||||
o = std::string("You will rejoice to hear that no disaster has accompanied the commencement of an enterprise which you have regarded with such evil forebodings. I arrived here yesterday, and my first task is to assure my dear sister of my welfare and increasing confidence in the success of my undertaking.");
|
||||
p = "I am already far north of London, and as I walk in the streets of Petersburgh, I feel a cold northern breeze play upon my cheeks, which braces my nerves and fills me with delight. Do you understand this feeling?";
|
||||
q = L"This breeze, which has travelled from the regions towards which I am advancing, gives me a foretaste of those icy climes. Inspirited by this wind of promise, my daydreams become more fervent and vivid.";
|
||||
|
||||
for (int i = 0; i < 4000; i++) {
|
||||
large_arr[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int VSTest::init() {
|
||||
@ -44,10 +49,12 @@ int VSTest::init() {
|
||||
|
||||
int VSTest::fail() {
|
||||
status = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VSTest::success() {
|
||||
status = 0;
|
||||
status = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VSTest::shutdown() {
|
||||
|
@ -106,7 +106,10 @@ int Trick::VariableServerListenThread::check_and_move_listen_device() {
|
||||
}
|
||||
|
||||
void Trick::VariableServerListenThread::create_tcp_socket(const char * address, unsigned short in_port ) {
|
||||
tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, address, in_port) ;
|
||||
int result = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, address, in_port) ;
|
||||
if (result != 0) {
|
||||
message_publish(MSG_ERROR, "ERROR: Could not establish additional listen port at address %s and port %d for Variable Server.\n", address, in_port);
|
||||
}
|
||||
}
|
||||
|
||||
void * Trick::VariableServerListenThread::thread_body() {
|
||||
|
@ -5,168 +5,6 @@
|
||||
#include <sstream>
|
||||
|
||||
|
||||
// Utility method
|
||||
uint64_t bytesToInt(const std::vector<unsigned char>& bytes, bool byteswap) {
|
||||
uint64_t result = 0;
|
||||
|
||||
if (byteswap) {
|
||||
for (unsigned int i = 0; i < bytes.size(); i++) {
|
||||
result |= bytes[bytes.size() - 1 - i] << i*8;
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 0; i < bytes.size(); i++) {
|
||||
result |= bytes[i] << i*8;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
class MessageIterator {
|
||||
public:
|
||||
MessageIterator(const std::vector<unsigned char>& container) : _container(container), _index(0) {}
|
||||
|
||||
std::vector<unsigned char> slice(unsigned int length) {
|
||||
unsigned int slice_end = _index + length;
|
||||
if (_index > _container.size() || slice_end > _container.size()) {
|
||||
throw MalformedMessageException("Message ends unexpectedly");
|
||||
}
|
||||
|
||||
return std::vector<unsigned char>(_container.begin() + _index, _container.begin() + slice_end);
|
||||
}
|
||||
|
||||
void operator+= (int n) {
|
||||
_index += n;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> _container;
|
||||
unsigned int _index;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* Var implementation
|
||||
**************************************************************************/
|
||||
|
||||
const size_t ParsedBinaryMessage::header_size = 12;
|
||||
const size_t ParsedBinaryMessage::message_indicator_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_num_size = 4;
|
||||
const size_t ParsedBinaryMessage::message_size_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_name_length_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_type_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_size_size = 4;
|
||||
|
||||
int ParsedBinaryMessage::parse (const std::vector<unsigned char>& bytes){
|
||||
if (bytes.size() < header_size) {
|
||||
throw MalformedMessageException(std::string("Not enough bytes in message to contain header: expected at least 12, got " + std::to_string(bytes.size())));
|
||||
}
|
||||
|
||||
MessageIterator messageIterator (bytes);
|
||||
|
||||
// First 4 bytes is message type
|
||||
_message_type = bytesToInt(messageIterator.slice(message_indicator_size), _byteswap);
|
||||
if (!validateMessageType(_message_type)) {
|
||||
throw MalformedMessageException(std::string("Received unknown message type: " + std::to_string(_message_type)));
|
||||
}
|
||||
|
||||
messageIterator += message_indicator_size;
|
||||
|
||||
// Next 4 bytes is message size
|
||||
_message_size = bytesToInt(messageIterator.slice(message_size_size), _byteswap);
|
||||
if (bytes.size() - message_indicator_size != _message_size) {
|
||||
std::string error_message = "Message size in header (" + std::to_string(_message_size) + ") does not match size of message received (" + std::to_string(bytes.size() - message_indicator_size) + ")";
|
||||
throw MalformedMessageException(error_message);
|
||||
}
|
||||
|
||||
messageIterator += message_size_size;
|
||||
|
||||
// Next 4 bytes is number of variables
|
||||
_num_vars = bytesToInt(messageIterator.slice(variable_num_size), _byteswap);
|
||||
messageIterator += variable_num_size;
|
||||
|
||||
// Pull out all of the variables
|
||||
for (unsigned int i = 0; i < _num_vars; i++) {
|
||||
Var variable;
|
||||
|
||||
if (!_nonames) {
|
||||
// Get the name
|
||||
size_t name_length = bytesToInt(messageIterator.slice(variable_name_length_size), _byteswap);
|
||||
messageIterator += variable_name_length_size;
|
||||
|
||||
variable.setName(name_length, messageIterator.slice(name_length));
|
||||
messageIterator += name_length;
|
||||
}
|
||||
|
||||
// Parse the type first
|
||||
int var_type = bytesToInt(messageIterator.slice(variable_type_size), _byteswap);
|
||||
messageIterator += variable_type_size;
|
||||
|
||||
size_t var_size = bytesToInt(messageIterator.slice(variable_size_size), _byteswap);
|
||||
messageIterator += variable_size_size;
|
||||
|
||||
variable.setValue(messageIterator.slice(var_size), var_size, static_cast<TRICK_TYPE>(var_type), _byteswap);
|
||||
messageIterator += var_size;
|
||||
|
||||
variables.emplace_back(variable);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ParsedBinaryMessage::combine (const ParsedBinaryMessage& other) {
|
||||
if (_message_type != other._message_type) {
|
||||
std::string error_message = "Trying to combine two messages with different message indicators (" + std::to_string(_message_type) + " and " + std::to_string(other._message_type) + ")";
|
||||
throw MalformedMessageException(error_message);
|
||||
}
|
||||
|
||||
// Combined size - subtract the header size from other message size
|
||||
_message_size += other._message_size - message_size_size - variable_num_size;
|
||||
|
||||
// Combine variables
|
||||
_num_vars += other._num_vars;
|
||||
variables.insert(variables.end(), other.variables.begin(), other.variables.end());
|
||||
|
||||
// Other error checking - duplicate variables?
|
||||
}
|
||||
|
||||
Var ParsedBinaryMessage::getVariable(const std::string& name) {
|
||||
if (_nonames)
|
||||
throw IncorrectUsageException("Cannot fetch variables by name in noname message");
|
||||
|
||||
for (auto variable : variables) {
|
||||
if (variable.getName() == name)
|
||||
return variable;
|
||||
}
|
||||
|
||||
throw IncorrectUsageException("Variable " + name + " does not exist in this message.");
|
||||
}
|
||||
|
||||
Var ParsedBinaryMessage::getVariable(unsigned int index) {
|
||||
if (index >= variables.size()) {
|
||||
throw IncorrectUsageException("Variable index " + std::to_string(index) + " does not exist in this message.");
|
||||
}
|
||||
|
||||
return variables[index];
|
||||
}
|
||||
|
||||
int ParsedBinaryMessage::getMessageType() const {
|
||||
return _message_type;
|
||||
}
|
||||
|
||||
unsigned int ParsedBinaryMessage::getMessageSize() const {
|
||||
return _message_size;
|
||||
}
|
||||
|
||||
unsigned int ParsedBinaryMessage::getNumVars() const {
|
||||
return _num_vars;
|
||||
}
|
||||
|
||||
// Static methods
|
||||
|
||||
bool ParsedBinaryMessage::validateMessageType(int message_type) {
|
||||
return message_type >= VS_MIN_CODE && message_type <= VS_MAX_CODE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Var implementation
|
||||
**************************************************************************/
|
||||
@ -221,6 +59,24 @@ TRICK_TYPE Var::getType() const {
|
||||
return _trick_type;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> Var::getRawBytes() const {
|
||||
return value_bytes;
|
||||
}
|
||||
|
||||
int Var::getArraySize() const {
|
||||
auto val_size_pair = type_size_map.find(_trick_type);
|
||||
if (val_size_pair == type_size_map.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int val_size = val_size_pair->second;
|
||||
if (_var_size % val_size != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _var_size / val_size;
|
||||
}
|
||||
|
||||
|
||||
// Template specialization for each supported type
|
||||
template<>
|
||||
@ -362,3 +218,185 @@ wchar_t Var::getValue<wchar_t> () const {
|
||||
|
||||
return getInterpreter().wchar_val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Utility method
|
||||
uint64_t bytesToInt(const std::vector<unsigned char>& bytes, bool byteswap) {
|
||||
uint64_t result = 0;
|
||||
|
||||
if (byteswap) {
|
||||
for (unsigned int i = 0; i < bytes.size(); i++) {
|
||||
result |= bytes[bytes.size() - 1 - i] << i*8;
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 0; i < bytes.size(); i++) {
|
||||
result |= bytes[i] << i*8;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
class MessageIterator {
|
||||
public:
|
||||
MessageIterator(const std::vector<unsigned char>& container) : _container(container), _index(0) {}
|
||||
|
||||
std::vector<unsigned char> slice(unsigned int length) {
|
||||
unsigned int slice_end = _index + length;
|
||||
if (_index > _container.size() || slice_end > _container.size()) {
|
||||
throw MalformedMessageException("Message ends unexpectedly");
|
||||
}
|
||||
|
||||
return std::vector<unsigned char>(_container.begin() + _index, _container.begin() + slice_end);
|
||||
}
|
||||
|
||||
void operator+= (int n) {
|
||||
_index += n;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> _container;
|
||||
unsigned int _index;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* Var implementation
|
||||
**************************************************************************/
|
||||
|
||||
const size_t ParsedBinaryMessage::header_size = 12;
|
||||
const size_t ParsedBinaryMessage::message_indicator_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_num_size = 4;
|
||||
const size_t ParsedBinaryMessage::message_size_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_name_length_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_type_size = 4;
|
||||
const size_t ParsedBinaryMessage::variable_size_size = 4;
|
||||
|
||||
// Sometimes, we need to reconstruct the size from the message.
|
||||
// Risk of segfaulting here if the bytes are not correctly formed
|
||||
int ParsedBinaryMessage::parse (char * raw_bytes) {
|
||||
std::vector<unsigned char> bytes;
|
||||
unsigned int i = 0;
|
||||
for ( ; i < message_indicator_size + message_size_size; i++) {
|
||||
bytes.push_back(raw_bytes[i]);
|
||||
}
|
||||
|
||||
unsigned int message_size = bytesToInt(std::vector<unsigned char> (bytes.begin() + message_indicator_size, bytes.begin() + message_indicator_size + message_size_size), _byteswap);
|
||||
for ( ; i < message_size + message_indicator_size; i++) {
|
||||
bytes.push_back(raw_bytes[i]);
|
||||
}
|
||||
|
||||
return parse(bytes);
|
||||
}
|
||||
|
||||
|
||||
int ParsedBinaryMessage::parse (const std::vector<unsigned char>& bytes) {
|
||||
if (bytes.size() < header_size) {
|
||||
throw MalformedMessageException(std::string("Not enough bytes in message to contain header: expected at least 12, got " + std::to_string(bytes.size())));
|
||||
}
|
||||
|
||||
MessageIterator messageIterator (bytes);
|
||||
|
||||
// First 4 bytes is message type
|
||||
_message_type = bytesToInt(messageIterator.slice(message_indicator_size), _byteswap);
|
||||
if (!validateMessageType(_message_type)) {
|
||||
throw MalformedMessageException(std::string("Received unknown message type: " + std::to_string(_message_type)));
|
||||
}
|
||||
|
||||
messageIterator += message_indicator_size;
|
||||
|
||||
// Next 4 bytes is message size
|
||||
_message_size = bytesToInt(messageIterator.slice(message_size_size), _byteswap);
|
||||
if (bytes.size() - message_indicator_size != _message_size) {
|
||||
std::string error_message = "Message size in header (" + std::to_string(_message_size) + ") does not match size of message received (" + std::to_string(bytes.size() - message_indicator_size) + ")";
|
||||
throw MalformedMessageException(error_message);
|
||||
}
|
||||
|
||||
messageIterator += message_size_size;
|
||||
|
||||
// Next 4 bytes is number of variables
|
||||
_num_vars = bytesToInt(messageIterator.slice(variable_num_size), _byteswap);
|
||||
messageIterator += variable_num_size;
|
||||
|
||||
// Pull out all of the variables
|
||||
for (unsigned int i = 0; i < _num_vars; i++) {
|
||||
Var variable;
|
||||
|
||||
if (!_nonames) {
|
||||
// Get the name
|
||||
size_t name_length = bytesToInt(messageIterator.slice(variable_name_length_size), _byteswap);
|
||||
messageIterator += variable_name_length_size;
|
||||
|
||||
variable.setName(name_length, messageIterator.slice(name_length));
|
||||
messageIterator += name_length;
|
||||
}
|
||||
|
||||
// Parse the type first
|
||||
int var_type = bytesToInt(messageIterator.slice(variable_type_size), _byteswap);
|
||||
messageIterator += variable_type_size;
|
||||
|
||||
size_t var_size = bytesToInt(messageIterator.slice(variable_size_size), _byteswap);
|
||||
messageIterator += variable_size_size;
|
||||
|
||||
variable.setValue(messageIterator.slice(var_size), var_size, static_cast<TRICK_TYPE>(var_type), _byteswap);
|
||||
messageIterator += var_size;
|
||||
|
||||
variables.emplace_back(variable);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ParsedBinaryMessage::combine (const ParsedBinaryMessage& other) {
|
||||
if (_message_type != other._message_type) {
|
||||
std::string error_message = "Trying to combine two messages with different message indicators (" + std::to_string(_message_type) + " and " + std::to_string(other._message_type) + ")";
|
||||
throw MalformedMessageException(error_message);
|
||||
}
|
||||
|
||||
// Combined size - subtract the header size from other message size
|
||||
_message_size += other._message_size - message_size_size - variable_num_size;
|
||||
|
||||
// Combine variables
|
||||
_num_vars += other._num_vars;
|
||||
variables.insert(variables.end(), other.variables.begin(), other.variables.end());
|
||||
|
||||
// Other error checking - duplicate variables?
|
||||
}
|
||||
|
||||
Var ParsedBinaryMessage::getVariable(const std::string& name) {
|
||||
if (_nonames)
|
||||
throw IncorrectUsageException("Cannot fetch variables by name in noname message");
|
||||
|
||||
for (auto variable : variables) {
|
||||
if (variable.getName() == name)
|
||||
return variable;
|
||||
}
|
||||
|
||||
throw IncorrectUsageException("Variable " + name + " does not exist in this message.");
|
||||
}
|
||||
|
||||
Var ParsedBinaryMessage::getVariable(unsigned int index) {
|
||||
if (index >= variables.size()) {
|
||||
throw IncorrectUsageException("Variable index " + std::to_string(index) + " does not exist in this message.");
|
||||
}
|
||||
|
||||
return variables[index];
|
||||
}
|
||||
|
||||
int ParsedBinaryMessage::getMessageType() const {
|
||||
return _message_type;
|
||||
}
|
||||
|
||||
unsigned int ParsedBinaryMessage::getMessageSize() const {
|
||||
return _message_size;
|
||||
}
|
||||
|
||||
unsigned int ParsedBinaryMessage::getNumVars() const {
|
||||
return _num_vars;
|
||||
}
|
||||
|
||||
// Static methods
|
||||
|
||||
bool ParsedBinaryMessage::validateMessageType(int message_type) {
|
||||
return message_type >= VS_MIN_CODE && message_type <= VS_MAX_CODE;
|
||||
}
|
||||
|
@ -616,6 +616,35 @@ TEST (BinaryParserTest, GetVarByIndexWrong) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST (BinaryParserTest, ArrayTest) {
|
||||
// Message: vst.vsx.n
|
||||
std::vector<unsigned char> bytes = {0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00};
|
||||
ParsedBinaryMessage message(false, true);
|
||||
|
||||
try {
|
||||
message.parse(bytes);
|
||||
} catch (const std::exception& ex) {
|
||||
FAIL() << "Exception thrown: " << ex.what();
|
||||
}
|
||||
|
||||
ASSERT_EQ(message.getNumVars(), 1);
|
||||
Var arr_var = message.getVariable(0);
|
||||
EXPECT_EQ(arr_var.getArraySize(), 5);
|
||||
std::vector<unsigned char> raw_arr = arr_var.getRawBytes();
|
||||
std::vector<int> values;
|
||||
for (unsigned int i = 0; i < raw_arr.size(); i += 4) {
|
||||
int val = 0;
|
||||
for (unsigned int j = i; j < i+4; j++) {
|
||||
val |= raw_arr[j] << j*8;
|
||||
}
|
||||
values.push_back(val);
|
||||
}
|
||||
|
||||
std::vector<int> expected = {0, 1, 2, 3, 4};
|
||||
EXPECT_EQ(values, expected);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Var parsing type tests
|
||||
**************************************************************************/
|
||||
|
19
trickops.py
19
trickops.py
@ -28,17 +28,20 @@ class SimTestWorkflow(TrickWorkflow):
|
||||
# This job in SIM_stls dumps a checkpoint that is then read in and checked by RUN_test/unit_test.py in the same sim
|
||||
# This is a workaround to ensure that this run goes first.
|
||||
first_phase_jobs = []
|
||||
stl_dump_job = self.get_sim('SIM_stls').get_run(input='RUN_test/setup.py').get_run_job()
|
||||
first_phase_jobs.append(stl_dump_job)
|
||||
run_jobs.remove(stl_dump_job)
|
||||
stl_sim = self.get_sim('SIM_stls')
|
||||
if stl_sim is not None:
|
||||
stl_dump_job = stl_sim.get_run(input='RUN_test/setup.py').get_run_job()
|
||||
first_phase_jobs.append(stl_dump_job)
|
||||
run_jobs.remove(stl_dump_job)
|
||||
|
||||
# Same with SIM_checkpoint_data_recording - half the runs dump checkpoints, the others read and verify.
|
||||
# Make sure that the dump checkpoint runs go first.
|
||||
num_dump_runs = int(len(self.get_sim('SIM_checkpoint_data_recording').get_runs())/2)
|
||||
for i in range(num_dump_runs):
|
||||
job = self.get_sim('SIM_checkpoint_data_recording').get_run(input=('RUN_test' + str(i+1) + '/dump.py')).get_run_job()
|
||||
first_phase_jobs.append(job)
|
||||
run_jobs.remove(job)
|
||||
if self.get_sim('SIM_checkpoint_data_recording') is not None:
|
||||
num_dump_runs = int(len(self.get_sim('SIM_checkpoint_data_recording').get_runs())/2)
|
||||
for i in range(num_dump_runs):
|
||||
job = self.get_sim('SIM_checkpoint_data_recording').get_run(input=('RUN_test' + str(i+1) + '/dump.py')).get_run_job()
|
||||
first_phase_jobs.append(job)
|
||||
run_jobs.remove(job)
|
||||
|
||||
# Some tests fail intermittently for reasons not related to the tests themselves, mostly network weirdness.
|
||||
# Allow retries so that we can still cover some network-adjacent code
|
||||
|
Loading…
Reference in New Issue
Block a user