1 #include "tests/test.hpp"
2 #include "tests/unit/connector/certs.hpp"
3 #include "tests/unit/connector/mock_server.hpp"
4 #include "tests/unit/connector/connector_utils.hpp"
5 
6 #include <cpp-pcp-client/connector/errors.hpp>
7 #include <cpp-pcp-client/connector/v1/connector.hpp>
8 
9 #include <memory>
10 #include <atomic>
11 #include <functional>
12 
13 using namespace PCPClient;
14 using namespace v1;
15 
16 TEST_CASE("v1::Connector::Connector", "[connector]") {
17     SECTION("can instantiate") {
18         REQUIRE_NOTHROW(Connector("wss://localhost:8142/pcp", "test_client",
19                                   getCaPath(), getCertPath(), getKeyPath(), getEmptyCrlPath(), "",
20                                   WS_TIMEOUT_MS,
21                                   ASSOCIATION_TIMEOUT_S, ASSOCIATION_REQUEST_TTL_S,
22                                   PONG_TIMEOUTS_BEFORE_RETRY, PONG_TIMEOUT));
23     }
24 }
25 
26 TEST_CASE("v1::Connector::getAssociationTimings", "[connector]") {
27     Connector c { "wss://localhost:8142/pcp",
28                   "test_client",
29                   getCaPath(), getCertPath(), getKeyPath(), getEmptyCrlPath(), "",
30                   WS_TIMEOUT_MS, ASSOCIATION_TIMEOUT_S,
31                   ASSOCIATION_REQUEST_TTL_S,
32                   PONG_TIMEOUTS_BEFORE_RETRY, PONG_TIMEOUT };
33 
34     SECTION("can get PCP Association timings") {
35         REQUIRE_NOTHROW(c.getAssociationTimings());
36     }
37 
38     SECTION("timings will say if the session was not associated") {
39         auto ass_timings = c.getAssociationTimings();
40 
41         REQUIRE_FALSE(ass_timings.completed);
42     }
43 }
44 
45 TEST_CASE("v1::Connector::connect", "[connector]") {
46     SECTION("successfully connects and update WebSocket and Association timings") {
47         std::unique_ptr<Connector> c_ptr;
48         {
49             MockServer mock_server(0, getCertPath(), getKeyPath(), MockServer::Version::v1);
50             bool connected = false;
51             mock_server.set_open_handler(
__anon60342b290102(websocketpp::connection_hdl hdl) 52                 [&connected](websocketpp::connection_hdl hdl) {
53                     connected = true;
54                 });
55             mock_server.go();
56             auto port = mock_server.port();
57 
58             c_ptr.reset(new Connector { "wss://localhost:" + std::to_string(port) + "/pcp",
59                                         "test_client",
60                                         getCaPath(), getCertPath(), getKeyPath(), getEmptyCrlPath(), "",
61                                         WS_TIMEOUT_MS, ASSOCIATION_TIMEOUT_S,
62                                         ASSOCIATION_REQUEST_TTL_S,
63                                         PONG_TIMEOUTS_BEFORE_RETRY, PONG_TIMEOUT });
64             REQUIRE_FALSE(connected);
65             REQUIRE_NOTHROW(c_ptr->connect(1));
66 
67             // NB: ConnectorBase::connect is blocking, but the onOpen handler isn't
__anon60342b290202()68             wait_for([&](){return connected;});
69             REQUIRE(c_ptr->isConnected());
70             REQUIRE(connected);
71 
__anon60342b290302()72             wait_for([&c_ptr](){return c_ptr->isAssociated();});
73             auto ws_timings  = c_ptr->getConnectionTimings();
74             auto ass_timings = c_ptr->getAssociationTimings();
75             auto us_zero     = ConnectionTimings::Duration_us::zero();
76             auto min_zero    = ConnectionTimings::Duration_min::zero();
77 
78             REQUIRE(c_ptr->isAssociated());
79             REQUIRE(ass_timings.completed);
80             REQUIRE(ass_timings.success);
81             REQUIRE(ass_timings.start < ass_timings.association);
82             REQUIRE(us_zero   < ws_timings.getOpeningHandshakeInterval());
83             REQUIRE(us_zero   < ws_timings.getWebSocketInterval());
84             REQUIRE(us_zero   < ws_timings.getOverallConnectionInterval_us());
85             REQUIRE(min_zero == ws_timings.getOverallConnectionInterval_min());
86             REQUIRE(us_zero  == ws_timings.getClosingHandshakeInterval());
87         }
88 
89         // The broker does not exist anymore (RAII)
__anon60342b290402()90         wait_for([&c_ptr](){return !c_ptr->isConnected();});
91         auto ass_timings = c_ptr->getAssociationTimings();
92 
93         REQUIRE_FALSE(c_ptr->isConnected());
94         REQUIRE(ass_timings.closed);
95         // NB: using timepoints directly as getOverallSessionInterval_min
96         //     returns minutes
97         REQUIRE(ass_timings.close > ass_timings.start);
98     }
99     SECTION("When pcp-broker cert is included in CRL connection is not established") {
100         std::unique_ptr<Connector> c_ptr;
101         {
102             MockServer mock_server(0, getBadCertPath(), getBadKeyPath(), MockServer::Version::v1);
103             bool connected = false;
104             mock_server.set_open_handler(
__anon60342b290502(websocketpp::connection_hdl hdl) 105                 [&connected](websocketpp::connection_hdl hdl) {
106                     connected = true;
107                 });
108             mock_server.go();
109             auto port = mock_server.port();
110 
111             c_ptr.reset(new Connector { "wss://localhost:" + std::to_string(port) + "/pcp",
112                                         "test_client",
113                                         getCaPath(), getCertPath(), getKeyPath(), getRevokedCrlPath(), "",
114                                         WS_TIMEOUT_MS, ASSOCIATION_TIMEOUT_S,
115                                         ASSOCIATION_REQUEST_TTL_S,
116                                         PONG_TIMEOUTS_BEFORE_RETRY, PONG_TIMEOUT });
117             REQUIRE_FALSE(connected);
118             REQUIRE_THROWS_AS(c_ptr->connect(1), connection_fatal_error);
119         }
120     }
121 }
122