@@ -1738,9 +1738,9 @@ TEST(config, can_replace_scheduler)
1738
1738
1739
1739
mre.get ();
1740
1740
1741
- // http_client->send (negotiate), websocket_client->start, handshake timeout timer, websocket_client->send, websocket_client->send, websocket_client->stop
1741
+ // http_client->send (negotiate), websocket_client->start, handshake timeout timer, websocket_client->send, websocket_client->send, keep alive timer, websocket_client->send ping, websocket_client->stop
1742
1742
// handshake timeout timer can trigger more than once if test takes more than 1 second
1743
- ASSERT_GE (6 , scheduler->schedule_count );
1743
+ ASSERT_GE (scheduler->schedule_count , 8 );
1744
1744
}
1745
1745
1746
1746
class throw_hub_protocol : public hub_protocol
@@ -1814,3 +1814,135 @@ TEST(send, throws_if_protocol_fails)
1814
1814
1815
1815
ASSERT_EQ (connection_state::connected, hub_connection->get_connection_state ());
1816
1816
}
1817
+
1818
+ TEST (keepalive, sends_ping_messages)
1819
+ {
1820
+ signalr_client_config config;
1821
+ config.set_keepalive_interval (std::chrono::seconds (1 ));
1822
+ config.set_server_timeout (std::chrono::seconds (3 ));
1823
+ auto ping_mre = manual_reset_event<void >();
1824
+ auto messages = std::make_shared<std::deque<std::string>>();
1825
+ auto websocket_client = create_test_websocket_client (
1826
+ /* send function */ [messages, &ping_mre](const std::string& msg, std::function<void (std::exception_ptr)> callback)
1827
+ {
1828
+ if (messages->size () < 3 )
1829
+ {
1830
+ messages->push_back (msg);
1831
+ }
1832
+ if (messages->size () == 3 )
1833
+ {
1834
+ ping_mre.set ();
1835
+ }
1836
+ callback (nullptr );
1837
+ },
1838
+ [](const std::string&, std::function<void (std::exception_ptr)> callback) { callback (nullptr ); },
1839
+ [](std::function<void (std::exception_ptr)> callback) { callback (nullptr ); },
1840
+ false );
1841
+ auto hub_connection = create_hub_connection (websocket_client);
1842
+ hub_connection.set_client_config (config);
1843
+
1844
+ auto mre = manual_reset_event<void >();
1845
+ hub_connection.start ([&mre](std::exception_ptr exception)
1846
+ {
1847
+ mre.set (exception);
1848
+ });
1849
+
1850
+ ASSERT_FALSE (websocket_client->receive_loop_started .wait (5000 ));
1851
+ ASSERT_FALSE (websocket_client->handshake_sent .wait (5000 ));
1852
+ websocket_client->receive_message (" {}\x1e " );
1853
+
1854
+ mre.get ();
1855
+
1856
+ ping_mre.get ();
1857
+
1858
+ ASSERT_EQ (3 , messages->size ());
1859
+ ASSERT_EQ (" {\" protocol\" :\" json\" ,\" version\" :1}\x1e " , (*messages)[0 ]);
1860
+ ASSERT_EQ (" {\" type\" :6}\x1e " , (*messages)[1 ]);
1861
+ ASSERT_EQ (" {\" type\" :6}\x1e " , (*messages)[2 ]);
1862
+ ASSERT_EQ (connection_state::connected, hub_connection.get_connection_state ());
1863
+ }
1864
+
1865
+ TEST (keepalive, server_timeout_on_no_ping_from_server)
1866
+ {
1867
+ signalr_client_config config;
1868
+ config.set_keepalive_interval (std::chrono::seconds (1 ));
1869
+ config.set_server_timeout (std::chrono::seconds (1 ));
1870
+ auto websocket_client = create_test_websocket_client ();
1871
+ auto hub_connection = create_hub_connection (websocket_client);
1872
+ hub_connection.set_client_config (config);
1873
+
1874
+ auto disconnected_called = false ;
1875
+
1876
+ auto disconnect_mre = manual_reset_event<void >();
1877
+ hub_connection.set_disconnected ([&disconnected_called, &disconnect_mre](std::exception_ptr ex)
1878
+ {
1879
+ disconnect_mre.set (ex);
1880
+ });
1881
+
1882
+ auto mre = manual_reset_event<void >();
1883
+ hub_connection.start ([&mre](std::exception_ptr exception)
1884
+ {
1885
+ mre.set (exception);
1886
+ });
1887
+
1888
+ ASSERT_FALSE (websocket_client->receive_loop_started .wait (5000 ));
1889
+ ASSERT_FALSE (websocket_client->handshake_sent .wait (5000 ));
1890
+ websocket_client->receive_message (" {}\x1e " );
1891
+
1892
+ mre.get ();
1893
+
1894
+ try
1895
+ {
1896
+ disconnect_mre.get ();
1897
+ ASSERT_TRUE (false );
1898
+ }
1899
+ catch (const std::exception& ex)
1900
+ {
1901
+ ASSERT_STREQ (" server timeout (1000 ms) elapsed without receiving a message from the server." , ex.what ());
1902
+ }
1903
+ ASSERT_EQ (connection_state::disconnected, hub_connection.get_connection_state ());
1904
+ }
1905
+
1906
+ TEST (keepalive, resets_server_timeout_timer_on_any_message_from_server)
1907
+ {
1908
+ signalr_client_config config;
1909
+ config.set_keepalive_interval (std::chrono::seconds (1 ));
1910
+ config.set_server_timeout (std::chrono::seconds (1 ));
1911
+ auto websocket_client = create_test_websocket_client ();
1912
+ auto hub_connection = create_hub_connection (websocket_client);
1913
+ hub_connection.set_client_config (config);
1914
+
1915
+ auto disconnect_mre = manual_reset_event<void >();
1916
+ hub_connection.set_disconnected ([&disconnect_mre](std::exception_ptr ex)
1917
+ {
1918
+ disconnect_mre.set (ex);
1919
+ });
1920
+
1921
+ auto mre = manual_reset_event<void >();
1922
+ hub_connection.start ([&mre](std::exception_ptr exception)
1923
+ {
1924
+ mre.set (exception);
1925
+ });
1926
+
1927
+ ASSERT_FALSE (websocket_client->receive_loop_started .wait (5000 ));
1928
+ ASSERT_FALSE (websocket_client->handshake_sent .wait (5000 ));
1929
+ websocket_client->receive_message (" {}\x1e " );
1930
+
1931
+ mre.get ();
1932
+
1933
+ std::this_thread::sleep_for (config.get_server_timeout () - std::chrono::milliseconds (500 ));
1934
+ websocket_client->receive_message (" {\" type\" :6}\x1e " );
1935
+ std::this_thread::sleep_for (std::chrono::seconds (1 ));
1936
+ ASSERT_EQ (connection_state::connected, hub_connection.get_connection_state ());
1937
+
1938
+ try
1939
+ {
1940
+ disconnect_mre.get ();
1941
+ ASSERT_TRUE (false );
1942
+ }
1943
+ catch (const std::exception& ex)
1944
+ {
1945
+ ASSERT_STREQ (" server timeout (1000 ms) elapsed without receiving a message from the server." , ex.what ());
1946
+ }
1947
+ ASSERT_EQ (connection_state::disconnected, hub_connection.get_connection_state ());
1948
+ }
0 commit comments