ChimeraTK-DeviceAccess 03.31.00
Loading...
Searching...
No Matches
testRebotConnectionCloseOnReset.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#define BOOST_TEST_DYN_LINK
5#define BOOST_TEST_MODULE RebotConnectionCloseOnResetTest
6
7#include <boost/test/unit_test.hpp>
8using namespace boost::unit_test_framework;
9
10#include "Device.h"
11#include "RebotDummyServer.h"
12
13#include <chrono>
14#include <thread>
15
16using namespace ChimeraTK;
17
18// Test fixture for setup and teardown.
19struct F {
20 F()
21 : rebotServer{0 /*use random port*/, "./mtcadummy_rebot.map", 1 /*protocol version*/},
22 serverThread([&]() { rebotServer.start(); }) {
23 while(not rebotServer.is_running()) {
24 std::this_thread::sleep_for(std::chrono::milliseconds(1));
25 }
26 }
27
28 ~F() {
30 serverThread.join();
31 }
32
34 boost::thread serverThread;
35
36 std::string uri(std::string ip) {
37 return "(rebot?ip=" + ip + "&port=" + std::to_string(rebotServer.port()) + "&map=mtcadummy_rebot.map&timeout=1)";
38 }
39};
40
41/********************************************************************************************************************/
42
43BOOST_FIXTURE_TEST_CASE(testSecondConnectionReset, F) {
44 // First device occupies the mock server's single session.
45 Device d1(uri("localhost"));
46 d1.open();
47 BOOST_CHECK(d1.isFunctional());
48
49 // A second device (a different URI on the same server port) connects while the
50 // session is occupied. The server accepts and then closes the second
51 // connection, which the client sees as a connection reset. Depending on timing
52 // the error surfaces at open() or at the first IO, so assert both only raise
53 // ChimeraTK::runtime_error, and that closing afterwards does not throw.
54 Device d2(uri("127.0.0.1"));
55 bool opened = false;
56 try {
57 d2.open();
58 opened = true;
59 }
60 catch(const ChimeraTK::runtime_error&) {
61 // acceptable: the reset surfaced at open()
62 }
63
64 if(opened) {
65 // The first read must fail with ChimeraTK::runtime_error, never a
66 // boost::system::system_error.
67 BOOST_CHECK_THROW([[maybe_unused]] auto result = d2.read<int>("BOARD.WORD_USER"), ChimeraTK::runtime_error);
68 }
69
70 // Closing a device whose connection was reset must not throw.
71 BOOST_CHECK_NO_THROW(d2.close());
72 BOOST_CHECK_NO_THROW(d1.close());
73}
74
75/********************************************************************************************************************/
76
77BOOST_FIXTURE_TEST_CASE(testCloseAfterServerReset, F) {
78 Device d(uri("localhost"));
79 d.open();
80 BOOST_CHECK(d.isFunctional());
81
82 // Reset the connection from the server side. The session socket is owned by
83 // the server io thread, so resetConnection() posts the close onto the server
84 // io loop.
85 rebotServer.resetConnection();
86
87 // The lost connection must surface at the next IO as ChimeraTK::runtime_error,
88 // never a boost::system::system_error.
89 BOOST_CHECK_THROW([[maybe_unused]] auto result = d.read<int>("BOARD.WORD_USER"), ChimeraTK::runtime_error);
90
91 // Closing a device whose connection was reset mid-operation must not throw.
92 BOOST_CHECK_NO_THROW(d.close());
93}
Class allows to read/write registers from device.
Definition Device.h:39
void close()
Close the device.
Definition Device.cc:66
bool isFunctional() const
Return wether a device is working as intended, usually this means it is opened and does not have any ...
Definition Device.cc:82
UserType read(const RegisterPath &registerPathName, const AccessModeFlags &flags=AccessModeFlags({})) const
Inefficient convenience function to read a single-word register without obtaining an accessor.
Definition Device.h:296
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition Device.cc:58
unsigned int port() const
Exception thrown when a runtime error has occured.
Definition Exception.h:18
This header collects some conversion routines which should be useful both for ApplicationCore Python ...
std::string to_string(const std::string &v)
RebotDummyServer rebotServer
boost::thread serverThread
std::string uri(std::string ip)
BOOST_FIXTURE_TEST_CASE(testSecondConnectionReset, F)