Remove pplx::task from public API (#8747)
This commit is contained in:
parent
61b3504dbe
commit
9d8990a710
|
|
@ -6,7 +6,6 @@
|
|||
#include "_exports.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "connection_state.h"
|
||||
#include "trace_level.h"
|
||||
#include "log_writer.h"
|
||||
|
|
@ -29,16 +28,16 @@ namespace signalr
|
|||
|
||||
connection& operator=(const connection&) = delete;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl start();
|
||||
SIGNALRCLIENT_API void __cdecl start(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl send(const std::string& data);
|
||||
SIGNALRCLIENT_API void __cdecl send(const std::string& data, std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl set_message_received(const message_received_handler& message_received_callback);
|
||||
SIGNALRCLIENT_API void __cdecl set_disconnected(const std::function<void __cdecl()>& disconnected_callback);
|
||||
|
||||
SIGNALRCLIENT_API void __cdecl set_client_config(const signalr_client_config& config);
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl stop();
|
||||
SIGNALRCLIENT_API void __cdecl stop(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
SIGNALRCLIENT_API connection_state __cdecl get_connection_state() const noexcept;
|
||||
SIGNALRCLIENT_API std::string __cdecl get_connection_id() const;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include "_exports.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "connection_state.h"
|
||||
#include "trace_level.h"
|
||||
|
|
@ -31,8 +30,8 @@ namespace signalr
|
|||
|
||||
hub_connection& operator=(const hub_connection&) = delete;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl start();
|
||||
SIGNALRCLIENT_API pplx::task<void> __cdecl stop();
|
||||
SIGNALRCLIENT_API void __cdecl start(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
SIGNALRCLIENT_API void __cdecl stop(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
SIGNALRCLIENT_API connection_state __cdecl get_connection_state() const;
|
||||
SIGNALRCLIENT_API std::string __cdecl get_connection_id() const;
|
||||
|
|
@ -43,9 +42,9 @@ namespace signalr
|
|||
|
||||
SIGNALRCLIENT_API void __cdecl on(const std::string& event_name, const method_invoked_handler& handler);
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<web::json::value> invoke(const std::string& method_name, const web::json::value& arguments = web::json::value::array());
|
||||
SIGNALRCLIENT_API void invoke(const std::string& method_name, const web::json::value& arguments = web::json::value::array(), std::function<void(const web::json::value&, std::exception_ptr)> callback = [](const web::json::value&, std::exception_ptr) {}) noexcept;
|
||||
|
||||
SIGNALRCLIENT_API pplx::task<void> send(const std::string& method_name, const web::json::value& arguments = web::json::value::array());
|
||||
SIGNALRCLIENT_API void send(const std::string& method_name, const web::json::value& arguments = web::json::value::array(), std::function<void(std::exception_ptr)> callback = [](std::exception_ptr) {}) noexcept;
|
||||
|
||||
private:
|
||||
std::shared_ptr<hub_connection_impl> m_pImpl;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <sstream>
|
||||
#include "hub_connection.h"
|
||||
#include "log_writer.h"
|
||||
#include <future>
|
||||
|
||||
class logger : public signalr::log_writer
|
||||
{
|
||||
|
|
@ -23,13 +24,16 @@ void send_message(signalr::hub_connection& connection, const std::string& messag
|
|||
args[0] = web::json::value(utility::conversions::to_string_t(message));
|
||||
|
||||
// if you get an internal compiler error uncomment the lambda below or install VS Update 4
|
||||
connection.invoke("Send", args)
|
||||
.then([](pplx::task<web::json::value> invoke_task) // fire and forget but we need to observe exceptions
|
||||
connection.invoke("Send", args, [](const web::json::value& value, std::exception_ptr exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto val = invoke_task.get();
|
||||
ucout << U("Received: ") << val.serialize() << std::endl;
|
||||
if (exception)
|
||||
{
|
||||
std::rethrow_exception(exception);
|
||||
}
|
||||
|
||||
ucout << U("Received: ") << value.serialize() << std::endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
|
@ -41,44 +45,63 @@ void send_message(signalr::hub_connection& connection, const std::string& messag
|
|||
void chat()
|
||||
{
|
||||
signalr::hub_connection connection("http://localhost:5000/default", signalr::trace_level::all, std::make_shared<logger>());
|
||||
connection.on("Send", [](const web::json::value& m)
|
||||
connection.on("Send", [](const web::json::value & m)
|
||||
{
|
||||
ucout << std::endl << m.at(0).as_string() << /*U(" wrote:") << m.at(1).as_string() <<*/ std::endl << U("Enter your message: ");
|
||||
});
|
||||
|
||||
connection.start()
|
||||
.then([&connection]()
|
||||
{
|
||||
ucout << U("Enter your message:");
|
||||
for (;;)
|
||||
{
|
||||
std::string message;
|
||||
std::getline(std::cin, message);
|
||||
|
||||
if (message == ":q")
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
send_message(connection, message);
|
||||
}
|
||||
})
|
||||
.then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
|
||||
{
|
||||
return connection.stop();
|
||||
})
|
||||
.then([](pplx::task<void> stop_task)
|
||||
std::promise<void> task;
|
||||
connection.start([&connection, &task](std::exception_ptr exception)
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
stop_task.get();
|
||||
std::rethrow_exception(exception);
|
||||
}
|
||||
catch (const std::exception & ex)
|
||||
{
|
||||
ucout << U("exception when starting connection: ") << ex.what() << std::endl;
|
||||
}
|
||||
task.set_value();
|
||||
return;
|
||||
}
|
||||
|
||||
ucout << U("Enter your message:");
|
||||
for (;;)
|
||||
{
|
||||
std::string message;
|
||||
std::getline(std::cin, message);
|
||||
|
||||
if (message == ":q")
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
send_message(connection, message);
|
||||
}
|
||||
|
||||
connection.stop([&task](std::exception_ptr exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
std::rethrow_exception(exception);
|
||||
}
|
||||
|
||||
ucout << U("connection stopped successfully") << std::endl;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
|
||||
ucout << U("exception when stopping connection: ") << e.what() << std::endl;
|
||||
}
|
||||
}).get();
|
||||
|
||||
task.set_value();
|
||||
});
|
||||
});
|
||||
|
||||
task.get_future().get();
|
||||
}
|
||||
|
||||
int main()
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ namespace signalr
|
|||
// undefinded behavior since we are using an incomplete type. More details here: http://herbsutter.com/gotw/_100/
|
||||
connection::~connection() = default;
|
||||
|
||||
pplx::task<void> connection::start()
|
||||
void connection::start(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
return m_pImpl->start();
|
||||
m_pImpl->start(callback);
|
||||
}
|
||||
|
||||
pplx::task<void> connection::send(const std::string& data)
|
||||
void connection::send(const std::string& data, std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
return m_pImpl->send(data);
|
||||
m_pImpl->send(data, callback);
|
||||
}
|
||||
|
||||
void connection::set_message_received(const message_received_handler& message_received_callback)
|
||||
|
|
@ -41,9 +41,9 @@ namespace signalr
|
|||
m_pImpl->set_client_config(config);
|
||||
}
|
||||
|
||||
pplx::task<void> connection::stop()
|
||||
void connection::stop(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
return m_pImpl->stop();
|
||||
m_pImpl->stop(callback);
|
||||
}
|
||||
|
||||
connection_state connection::get_connection_state() const noexcept
|
||||
|
|
|
|||
|
|
@ -74,14 +74,14 @@ namespace signalr
|
|||
change_state(connection_state::disconnected);
|
||||
}
|
||||
|
||||
pplx::task<void> connection_impl::start()
|
||||
void connection_impl::start(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_stop_lock);
|
||||
if (!change_state(connection_state::disconnected, connection_state::connecting))
|
||||
{
|
||||
return pplx::task_from_exception<void>(
|
||||
signalr_exception("cannot start a connection that is not in the disconnected state"));
|
||||
callback(std::make_exception_ptr(signalr_exception("cannot start a connection that is not in the disconnected state")));
|
||||
return;
|
||||
}
|
||||
|
||||
// there should not be any active transport at this point
|
||||
|
|
@ -92,7 +92,19 @@ namespace signalr
|
|||
m_connection_id = "";
|
||||
}
|
||||
|
||||
return start_negotiate(m_base_url, 0);
|
||||
start_negotiate(m_base_url, 0)
|
||||
.then([callback](pplx::task<void> prev_task)
|
||||
{
|
||||
try
|
||||
{
|
||||
prev_task.get();
|
||||
callback(nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
callback(std::current_exception());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pplx::task<void> connection_impl::start_negotiate(const std::string& url, int redirect_count)
|
||||
|
|
@ -362,7 +374,7 @@ namespace signalr
|
|||
}
|
||||
}
|
||||
|
||||
pplx::task<void> connection_impl::send(const std::string& data)
|
||||
void connection_impl::send(const std::string& data, std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
// To prevent an (unlikely) condition where the transport is nulled out after we checked the connection_state
|
||||
// and before sending data we store the pointer in the local variable. In this case `send()` will throw but
|
||||
|
|
@ -372,17 +384,17 @@ namespace signalr
|
|||
const auto connection_state = get_connection_state();
|
||||
if (connection_state != signalr::connection_state::connected || !transport)
|
||||
{
|
||||
return pplx::task_from_exception<void>(signalr_exception(
|
||||
callback(std::make_exception_ptr(signalr_exception(
|
||||
std::string("cannot send data when the connection is not in the connected state. current connection state: ")
|
||||
.append(translate_connection_state(connection_state))));
|
||||
.append(translate_connection_state(connection_state)))));
|
||||
return;
|
||||
}
|
||||
|
||||
auto logger = m_logger;
|
||||
|
||||
logger.log(trace_level::info, std::string("sending data: ").append(data));
|
||||
|
||||
pplx::task_completion_event<void> event;
|
||||
transport->send(data, [logger, event](std::exception_ptr exception)
|
||||
transport->send(data, [logger, callback](std::exception_ptr exception)
|
||||
mutable {
|
||||
try
|
||||
{
|
||||
|
|
@ -390,7 +402,7 @@ namespace signalr
|
|||
{
|
||||
std::rethrow_exception(exception);
|
||||
}
|
||||
event.set();
|
||||
callback(nullptr);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
|
@ -399,21 +411,29 @@ namespace signalr
|
|||
std::string("error sending data: ")
|
||||
.append(e.what()));
|
||||
|
||||
event.set_exception(exception);
|
||||
callback(exception);
|
||||
}
|
||||
});
|
||||
|
||||
return pplx::create_task(event);
|
||||
}
|
||||
|
||||
pplx::task<void> connection_impl::stop()
|
||||
void connection_impl::stop(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
m_logger.log(trace_level::info, "stopping connection");
|
||||
|
||||
auto connection = shared_from_this();
|
||||
return shutdown()
|
||||
.then([connection]()
|
||||
shutdown()
|
||||
.then([connection, callback](pplx::task<void> prev_task)
|
||||
{
|
||||
try
|
||||
{
|
||||
prev_task.get();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
callback(std::current_exception());
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
// the lock prevents a race where the user calls `stop` on a disconnected connection and calls `start`
|
||||
// on a different thread at the same time. In this case we must not null out the transport if we are
|
||||
|
|
@ -443,6 +463,8 @@ namespace signalr
|
|||
trace_level::errors,
|
||||
std::string("disconnected callback threw an unknown exception"));
|
||||
}
|
||||
|
||||
callback(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include "cpprest/http_client.h"
|
||||
#include "signalrclient/http_client.h"
|
||||
#include "signalrclient/trace_level.h"
|
||||
#include "signalrclient/connection_state.h"
|
||||
|
|
@ -37,9 +36,9 @@ namespace signalr
|
|||
|
||||
~connection_impl();
|
||||
|
||||
pplx::task<void> start();
|
||||
pplx::task<void> send(const std::string &data);
|
||||
pplx::task<void> stop();
|
||||
void start(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
void send(const std::string &data, std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
void stop(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
connection_state get_connection_state() const noexcept;
|
||||
std::string get_connection_id() const noexcept;
|
||||
|
|
|
|||
|
|
@ -17,63 +17,95 @@ namespace signalr
|
|||
// undefinded behavior since we are using an incomplete type. More details here: http://herbsutter.com/gotw/_100/
|
||||
hub_connection::~hub_connection() = default;
|
||||
|
||||
pplx::task<void> hub_connection::start()
|
||||
void hub_connection::start(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
return m_pImpl->start();
|
||||
if (!m_pImpl)
|
||||
{
|
||||
callback(std::make_exception_ptr(signalr_exception("start() cannot be called on destructed hub_connection instance")));
|
||||
}
|
||||
|
||||
m_pImpl->start(callback);
|
||||
}
|
||||
|
||||
pplx::task<void> hub_connection::stop()
|
||||
void hub_connection::stop(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
return m_pImpl->stop();
|
||||
if (!m_pImpl)
|
||||
{
|
||||
callback(std::make_exception_ptr(signalr_exception("stop() cannot be called on destructed hub_connection instance")));
|
||||
}
|
||||
|
||||
m_pImpl->stop(callback);
|
||||
}
|
||||
|
||||
void hub_connection::on(const std::string& event_name, const method_invoked_handler& handler)
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("on() cannot be called on uninitialized hub_connection instance");
|
||||
throw signalr_exception("on() cannot be called on destructed hub_connection instance");
|
||||
}
|
||||
|
||||
return m_pImpl->on(event_name, handler);
|
||||
}
|
||||
|
||||
pplx::task<web::json::value> hub_connection::invoke(const std::string& method_name, const web::json::value& arguments)
|
||||
void hub_connection::invoke(const std::string& method_name, const web::json::value& arguments, std::function<void(const web::json::value&, std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("invoke() cannot be called on uninitialized hub_connection instance");
|
||||
callback(web::json::value(), std::make_exception_ptr(signalr_exception("invoke() cannot be called on destructed hub_connection instance")));
|
||||
return;
|
||||
}
|
||||
|
||||
return m_pImpl->invoke(method_name, arguments);
|
||||
return m_pImpl->invoke(method_name, arguments, callback);
|
||||
}
|
||||
|
||||
pplx::task<void> hub_connection::send(const std::string& method_name, const web::json::value& arguments)
|
||||
void hub_connection::send(const std::string& method_name, const web::json::value& arguments, std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("send() cannot be called on uninitialized hub_connection instance");
|
||||
callback(std::make_exception_ptr(signalr_exception("send() cannot be called on destructed hub_connection instance")));
|
||||
return;
|
||||
}
|
||||
|
||||
return m_pImpl->send(method_name, arguments);
|
||||
m_pImpl->send(method_name, arguments, callback);
|
||||
}
|
||||
|
||||
connection_state hub_connection::get_connection_state() const
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("get_connection_state() cannot be called on destructed hub_connection instance");
|
||||
}
|
||||
|
||||
return m_pImpl->get_connection_state();
|
||||
}
|
||||
|
||||
std::string hub_connection::get_connection_id() const
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("get_connection_id() cannot be called on destructed hub_connection instance");
|
||||
}
|
||||
|
||||
return m_pImpl->get_connection_id();
|
||||
}
|
||||
|
||||
void hub_connection::set_disconnected(const std::function<void()>& disconnected_callback)
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("set_disconnected() cannot be called on destructed hub_connection instance");
|
||||
}
|
||||
|
||||
m_pImpl->set_disconnected(disconnected_callback);
|
||||
}
|
||||
|
||||
void hub_connection::set_client_config(const signalr_client_config& config)
|
||||
{
|
||||
if (!m_pImpl)
|
||||
{
|
||||
throw signalr_exception("set_client_config() cannot be called on destructed hub_connection instance");
|
||||
}
|
||||
|
||||
m_pImpl->set_client_config(config);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,67 +96,89 @@ namespace signalr
|
|||
m_subscriptions.insert(std::pair<std::string, std::function<void(const json::value &)>> {event_name, handler});
|
||||
}
|
||||
|
||||
pplx::task<void> hub_connection_impl::start()
|
||||
void hub_connection_impl::start(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
if (m_connection->get_connection_state() != connection_state::disconnected)
|
||||
{
|
||||
throw signalr_exception(
|
||||
"the connection can only be started if it is in the disconnected state");
|
||||
callback(std::make_exception_ptr(signalr_exception(
|
||||
"the connection can only be started if it is in the disconnected state")));
|
||||
return;
|
||||
}
|
||||
|
||||
m_connection->set_client_config(m_signalr_client_config);
|
||||
m_handshakeTask = pplx::task_completion_event<void>();
|
||||
m_handshakeReceived = false;
|
||||
std::weak_ptr<hub_connection_impl> weak_connection = shared_from_this();
|
||||
return m_connection->start()
|
||||
.then([weak_connection](pplx::task<void> startTask)
|
||||
m_connection->start([weak_connection, callback](std::exception_ptr start_exception)
|
||||
{
|
||||
startTask.get();
|
||||
auto connection = weak_connection.lock();
|
||||
if (!connection)
|
||||
{
|
||||
// The connection has been destructed
|
||||
return pplx::task_from_exception<void>(signalr_exception("the hub connection has been deconstructed"));
|
||||
callback(std::make_exception_ptr(signalr_exception("the hub connection has been deconstructed")));
|
||||
return;
|
||||
}
|
||||
return connection->m_connection->send("{\"protocol\":\"json\",\"version\":1}\x1e")
|
||||
.then([weak_connection](pplx::task<void> previous_task)
|
||||
{
|
||||
auto connection = weak_connection.lock();
|
||||
if (!connection)
|
||||
{
|
||||
// The connection has been destructed
|
||||
return pplx::task_from_exception<void>(signalr_exception("the hub connection has been deconstructed"));
|
||||
}
|
||||
previous_task.get();
|
||||
return pplx::task<void>(connection->m_handshakeTask);
|
||||
})
|
||||
.then([weak_connection](pplx::task<void> previous_task)
|
||||
|
||||
if (start_exception)
|
||||
{
|
||||
connection->m_connection->stop([start_exception, callback, weak_connection](std::exception_ptr)
|
||||
{
|
||||
try
|
||||
{
|
||||
previous_task.get();
|
||||
return previous_task;
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
auto connection = weak_connection.lock();
|
||||
if (connection)
|
||||
if (!connection)
|
||||
{
|
||||
return connection->m_connection->stop()
|
||||
.then([e]() {
|
||||
throw e;
|
||||
});
|
||||
callback(std::make_exception_ptr(signalr_exception("the hub connection has been deconstructed")));
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
pplx::task<void>(connection->m_handshakeTask).get();
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
callback(start_exception);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Generate this later when we have the protocol abstraction
|
||||
auto handshake_request = "{\"protocol\":\"json\",\"version\":1}\x1e";
|
||||
connection->m_connection->send(handshake_request, [weak_connection, callback](std::exception_ptr exception)
|
||||
{
|
||||
auto connection = weak_connection.lock();
|
||||
if (!connection)
|
||||
{
|
||||
// The connection has been destructed
|
||||
callback(std::make_exception_ptr(signalr_exception("the hub connection has been deconstructed")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (exception)
|
||||
{
|
||||
callback(exception);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
pplx::task<void>(connection->m_handshakeTask).get();
|
||||
callback(nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
auto handshake_exception = std::current_exception();
|
||||
connection->m_connection->stop([callback, handshake_exception](std::exception_ptr)
|
||||
{
|
||||
callback(handshake_exception);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pplx::task<void> hub_connection_impl::stop()
|
||||
void hub_connection_impl::stop(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
m_callback_manager.clear(json::value::parse(_XPLATSTR("{ \"error\" : \"connection was stopped before invocation result was received\"}")));
|
||||
return m_connection->stop();
|
||||
m_connection->stop(callback);
|
||||
}
|
||||
|
||||
enum MessageType
|
||||
|
|
@ -275,37 +297,29 @@ namespace signalr
|
|||
return true;
|
||||
}
|
||||
|
||||
pplx::task<json::value> hub_connection_impl::invoke(const std::string& method_name, const json::value& arguments)
|
||||
void hub_connection_impl::invoke(const std::string& method_name, const json::value& arguments, std::function<void(const web::json::value&, std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
_ASSERTE(arguments.is_array());
|
||||
|
||||
pplx::task_completion_event<json::value> tce;
|
||||
|
||||
const auto callback_id = m_callback_manager.register_callback(
|
||||
create_hub_invocation_callback(m_logger, [tce](const json::value& result) { tce.set(result); },
|
||||
[tce](const std::exception_ptr e) { tce.set_exception(e); }));
|
||||
create_hub_invocation_callback(m_logger, [callback](const json::value& result) { callback(result, nullptr); },
|
||||
[callback](const std::exception_ptr e) { callback(json::value(), e); }));
|
||||
|
||||
invoke_hub_method(method_name, arguments, callback_id, nullptr,
|
||||
[tce](const std::exception_ptr e){ tce.set_exception(e); });
|
||||
|
||||
return pplx::create_task(tce);
|
||||
[callback](const std::exception_ptr e){ callback(json::value(), e); });
|
||||
}
|
||||
|
||||
pplx::task<void> hub_connection_impl::send(const std::string& method_name, const json::value& arguments)
|
||||
void hub_connection_impl::send(const std::string& method_name, const json::value& arguments, std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
_ASSERTE(arguments.is_array());
|
||||
|
||||
pplx::task_completion_event<void> tce;
|
||||
|
||||
invoke_hub_method(method_name, arguments, "",
|
||||
[tce]() { tce.set(); },
|
||||
[tce](const std::exception_ptr e){ tce.set_exception(e); });
|
||||
|
||||
return pplx::create_task(tce);
|
||||
[callback]() { callback(nullptr); },
|
||||
[callback](const std::exception_ptr e){ callback(e); });
|
||||
}
|
||||
|
||||
void hub_connection_impl::invoke_hub_method(const std::string& method_name, const json::value& arguments,
|
||||
const std::string& callback_id, std::function<void()> set_completion, std::function<void(const std::exception_ptr)> set_exception)
|
||||
const std::string& callback_id, std::function<void()> set_completion, std::function<void(const std::exception_ptr)> set_exception) noexcept
|
||||
{
|
||||
json::value request;
|
||||
request[_XPLATSTR("type")] = json::value(1);
|
||||
|
|
@ -319,28 +333,26 @@ namespace signalr
|
|||
// weak_ptr prevents a circular dependency leading to memory leak and other problems
|
||||
auto weak_hub_connection = std::weak_ptr<hub_connection_impl>(shared_from_this());
|
||||
|
||||
m_connection->send(utility::conversions::to_utf8string(request.serialize() + _XPLATSTR('\x1e')))
|
||||
.then([set_completion, set_exception, weak_hub_connection, callback_id](pplx::task<void> send_task)
|
||||
m_connection->send(utility::conversions::to_utf8string(request.serialize() + _XPLATSTR('\x1e')), [set_completion, set_exception, weak_hub_connection, callback_id](std::exception_ptr exception)
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
try
|
||||
set_exception(exception);
|
||||
auto hub_connection = weak_hub_connection.lock();
|
||||
if (hub_connection)
|
||||
{
|
||||
send_task.get();
|
||||
if (callback_id.empty())
|
||||
{
|
||||
// complete nonBlocking call
|
||||
set_completion();
|
||||
}
|
||||
hub_connection->m_callback_manager.remove_callback(callback_id);
|
||||
}
|
||||
catch (const std::exception&)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (callback_id.empty())
|
||||
{
|
||||
set_exception(std::current_exception());
|
||||
auto hub_connection = weak_hub_connection.lock();
|
||||
if (hub_connection)
|
||||
{
|
||||
hub_connection->m_callback_manager.remove_callback(callback_id);
|
||||
}
|
||||
// complete nonBlocking call
|
||||
set_completion();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
connection_state hub_connection_impl::get_connection_state() const noexcept
|
||||
|
|
@ -383,8 +395,10 @@ namespace signalr
|
|||
std::make_exception_ptr(
|
||||
hub_exception(utility::conversions::to_utf8string(message.at(_XPLATSTR("error")).serialize()))));
|
||||
}
|
||||
|
||||
set_result(json::value::null());
|
||||
else
|
||||
{
|
||||
set_result(json::value::value());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ namespace signalr
|
|||
|
||||
void on(const std::string& event_name, const std::function<void(const json::value &)>& handler);
|
||||
|
||||
pplx::task<json::value> invoke(const std::string& method_name, const json::value& arguments);
|
||||
pplx::task<void> send(const std::string& method_name, const json::value& arguments);
|
||||
void invoke(const std::string& method_name, const json::value& arguments, std::function<void(const json::value&, std::exception_ptr)> callback) noexcept;
|
||||
void send(const std::string& method_name, const json::value& arguments, std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
pplx::task<void> start();
|
||||
pplx::task<void> stop();
|
||||
void start(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
void stop(std::function<void(std::exception_ptr)> callback) noexcept;
|
||||
|
||||
connection_state get_connection_state() const noexcept;
|
||||
std::string get_connection_id() const;
|
||||
|
|
@ -62,7 +62,7 @@ namespace signalr
|
|||
void process_message(const std::string& message);
|
||||
|
||||
void invoke_hub_method(const std::string& method_name, const json::value& arguments, const std::string& callback_id,
|
||||
std::function<void()> set_completion, std::function<void(const std::exception_ptr)> set_exception);
|
||||
std::function<void()> set_completion, std::function<void(const std::exception_ptr)> set_exception) noexcept;
|
||||
bool invoke_callback(const web::json::value& message);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ namespace signalr
|
|||
|
||||
virtual ~transport();
|
||||
|
||||
virtual void start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback) = 0;
|
||||
virtual void stop(std::function<void(std::exception_ptr)> callback) = 0;
|
||||
virtual void start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback) noexcept = 0;
|
||||
virtual void stop(std::function<void(std::exception_ptr)> callback) noexcept = 0;
|
||||
virtual void on_close(std::function<void(std::exception_ptr)> callback) = 0;
|
||||
|
||||
virtual void send(std::string payload, std::function<void(std::exception_ptr)> callback) = 0;
|
||||
virtual void send(std::string payload, std::function<void(std::exception_ptr)> callback) noexcept = 0;
|
||||
|
||||
virtual void on_receive(std::function<void(std::string, std::exception_ptr)> callback) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ namespace signalr
|
|||
}
|
||||
}
|
||||
|
||||
void websocket_transport::start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback)
|
||||
void websocket_transport::start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
web::uri uri(utility::conversions::to_string_t(url));
|
||||
_ASSERTE(uri.scheme() == _XPLATSTR("ws") || uri.scheme() == _XPLATSTR("wss"));
|
||||
|
|
@ -152,7 +152,8 @@ namespace signalr
|
|||
|
||||
if (!m_receive_loop_cts.get_token().is_canceled())
|
||||
{
|
||||
throw signalr_exception("transport already connected");
|
||||
callback(std::make_exception_ptr(signalr_exception("transport already connected")));
|
||||
return;
|
||||
}
|
||||
|
||||
m_logger.log(trace_level::info,
|
||||
|
|
@ -197,7 +198,7 @@ namespace signalr
|
|||
}
|
||||
}
|
||||
|
||||
void websocket_transport::stop(std::function<void(std::exception_ptr)> callback)
|
||||
void websocket_transport::stop(std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
std::shared_ptr<websocket_client> websocket_client = nullptr;
|
||||
|
||||
|
|
@ -252,7 +253,7 @@ namespace signalr
|
|||
m_process_response_callback = callback;
|
||||
}
|
||||
|
||||
void websocket_transport::send(std::string payload, std::function<void(std::exception_ptr)> callback)
|
||||
void websocket_transport::send(std::string payload, std::function<void(std::exception_ptr)> callback) noexcept
|
||||
{
|
||||
safe_get_websocket_client()->send(payload, [callback](std::exception_ptr exception)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ namespace signalr
|
|||
|
||||
transport_type get_transport_type() const noexcept override;
|
||||
|
||||
void start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback) override;
|
||||
void stop(std::function<void(std::exception_ptr)> callback) override;
|
||||
void start(const std::string& url, transfer_format format, std::function<void(std::exception_ptr)> callback) noexcept override;
|
||||
void stop(std::function<void(std::exception_ptr)> callback) noexcept override;
|
||||
void on_close(std::function<void(std::exception_ptr)> callback) override;
|
||||
|
||||
void send(std::string payload, std::function<void(std::exception_ptr)> callback) override;
|
||||
void send(std::string payload, std::function<void(std::exception_ptr)> callback) noexcept override;
|
||||
|
||||
void on_receive(std::function<void(std::string, std::exception_ptr)>) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(GoogleTestSubmoduleRoot)googletest\include;..\..\..\..\include\signalrclient;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(GoogleTestSubmoduleRoot)googletest\include;..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
@ -75,4 +75,4 @@
|
|||
<Target Name="AfterBuild">
|
||||
<Exec Command="copy /y "$(SolutionDir)bin\Desktop\$(Platform)\$(Configuration)\dll\$(SignalrClientTargetName).dll" "$(SolutionDir)bin\Desktop\$(Platform)\$(Configuration)\$(SignalrClientTargetName).dll"" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -39,7 +39,4 @@
|
|||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -7,8 +7,9 @@
|
|||
#include <string>
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "connection.h"
|
||||
#include "hub_connection.h"
|
||||
#include "signalrclient/connection.h"
|
||||
#include "signalrclient/hub_connection.h"
|
||||
#include "../signalrclienttests/test_utils.h"
|
||||
|
||||
extern std::string url;
|
||||
|
||||
|
|
@ -16,13 +17,29 @@ TEST(connection_tests, connection_status_start_stop)
|
|||
{
|
||||
auto conn = std::make_shared<signalr::connection>(url + "raw-connection");
|
||||
|
||||
conn->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(conn->get_connection_state(), signalr::connection_state::connected);
|
||||
|
||||
conn->stop().get();
|
||||
conn->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(conn->get_connection_state(), signalr::connection_state::disconnected);
|
||||
|
||||
conn->start().get();
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(conn->get_connection_state(), signalr::connection_state::connected);
|
||||
}
|
||||
|
||||
|
|
@ -38,14 +55,23 @@ TEST(connection_tests, send_message)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
conn->start().then([conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj;
|
||||
obj[U("type")] = web::json::value::number(0);
|
||||
obj[U("value")] = web::json::value::string(U("test"));
|
||||
return conn->send(utility::conversions::to_utf8string(obj.serialize()));
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
}).get();
|
||||
mre.get();
|
||||
|
||||
web::json::value obj;
|
||||
obj[U("type")] = web::json::value::number(0);
|
||||
obj[U("value")] = web::json::value::string(U("test"));
|
||||
conn->send(utility::conversions::to_utf8string(obj.serialize()), [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
|
|
@ -64,18 +90,37 @@ TEST(connection_tests, send_message_after_connection_restart)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
conn->start().get();
|
||||
|
||||
conn->stop().get();
|
||||
|
||||
conn->start().then([conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj;
|
||||
obj[U("type")] = web::json::value::number(0);
|
||||
obj[U("value")] = web::json::value::string(U("test"));
|
||||
return conn->send(utility::conversions::to_utf8string(obj.serialize()));
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
}).get();
|
||||
mre.get();
|
||||
|
||||
conn->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
web::json::value obj;
|
||||
obj[U("type")] = web::json::value::number(0);
|
||||
obj[U("value")] = web::json::value::string(U("test"));
|
||||
conn->send(utility::conversions::to_utf8string(obj.serialize()), [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
|
|
@ -88,14 +133,30 @@ TEST(connection_tests, connection_id_start_stop)
|
|||
|
||||
ASSERT_EQ("", conn->get_connection_id());
|
||||
|
||||
conn->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
auto connection_id = conn->get_connection_id();
|
||||
ASSERT_NE(connection_id, "");
|
||||
|
||||
conn->stop().get();
|
||||
conn->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(conn->get_connection_id(), connection_id);
|
||||
|
||||
conn->start().get();
|
||||
conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_NE(conn->get_connection_id(), "");
|
||||
ASSERT_NE(conn->get_connection_id(), connection_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@
|
|||
#include <string>
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "connection.h"
|
||||
#include "hub_connection.h"
|
||||
#include "signalr_exception.h"
|
||||
#include "signalrclient/connection.h"
|
||||
#include "signalrclient/hub_connection.h"
|
||||
#include "signalrclient/signalr_exception.h"
|
||||
#include "../signalrclienttests/test_utils.h"
|
||||
|
||||
extern std::string url;
|
||||
|
||||
|
|
@ -18,13 +19,29 @@ TEST(hub_connection_tests, connection_status_start_stop_start)
|
|||
auto hub_conn = std::make_shared<signalr::hub_connection>(url);
|
||||
auto weak_hub_conn = std::weak_ptr<signalr::hub_connection>(hub_conn);
|
||||
|
||||
hub_conn->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(hub_conn->get_connection_state(), signalr::connection_state::connected);
|
||||
|
||||
hub_conn->stop().get();
|
||||
hub_conn->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(hub_conn->get_connection_state(), signalr::connection_state::disconnected);
|
||||
|
||||
hub_conn->start().get();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(hub_conn->get_connection_state(), signalr::connection_state::connected);
|
||||
}
|
||||
|
||||
|
|
@ -40,14 +57,23 @@ TEST(hub_connection_tests, send_message)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(U("test"));
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
return hub_conn->send("invokeWithString", obj);
|
||||
mre.get();
|
||||
|
||||
}).get();
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(U("test"));
|
||||
|
||||
hub_conn->send("invokeWithString", obj, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
|
|
@ -58,14 +84,30 @@ TEST(hub_connection_tests, send_message_return)
|
|||
{
|
||||
auto hub_conn = std::make_shared<signalr::hub_connection>(url);
|
||||
|
||||
auto test = hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<web::json::value>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(U("test"));
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
return hub_conn->invoke("returnString", obj);
|
||||
mre.get();
|
||||
|
||||
}).get();
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(U("test"));
|
||||
|
||||
hub_conn->invoke("returnString", obj, [&mre](const web::json::value & value, std::exception_ptr exception)
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
mre.set(value);
|
||||
}
|
||||
});
|
||||
|
||||
auto test = mre.get();
|
||||
|
||||
ASSERT_EQ(test.serialize(), U("\"test\""));
|
||||
}
|
||||
|
|
@ -82,18 +124,37 @@ TEST(hub_connection_tests, send_message_after_connection_restart)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
hub_conn->start().get();
|
||||
|
||||
hub_conn->stop().get();
|
||||
|
||||
hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(U("test"));
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
return hub_conn->send("invokeWithString", obj);
|
||||
mre.get();
|
||||
|
||||
}).get();
|
||||
hub_conn->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(U("test"));
|
||||
|
||||
hub_conn->send("invokeWithString", obj, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
|
|
@ -112,11 +173,21 @@ TEST(hub_connection_tests, send_message_empty_param)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
return hub_conn->invoke("invokeWithEmptyParam");
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
}).get();
|
||||
mre.get();
|
||||
|
||||
|
||||
hub_conn->invoke("invokeWithEmptyParam", web::json::value::array(), [&mre](const web::json::value &, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
|
|
@ -135,21 +206,29 @@ TEST(hub_connection_tests, send_message_primitive_params)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(5);
|
||||
obj[1] = web::json::value(21.05);
|
||||
obj[2] = web::json::value(8.999999999);
|
||||
obj[3] = web::json::value(true);
|
||||
obj[4] = web::json::value('a');
|
||||
return hub_conn->send("invokeWithPrimitiveParams", obj);
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
}).get();
|
||||
mre.get();
|
||||
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(5);
|
||||
obj[1] = web::json::value(21.05);
|
||||
obj[2] = web::json::value(8.999999999);
|
||||
obj[3] = web::json::value(true);
|
||||
obj[4] = web::json::value('a');
|
||||
hub_conn->send("invokeWithPrimitiveParams", obj, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
web::json::value obj{};
|
||||
obj[0] = web::json::value(6);
|
||||
obj[1] = web::json::value(22.05);
|
||||
obj[2] = web::json::value(9.999999999);
|
||||
|
|
@ -171,21 +250,30 @@ TEST(hub_connection_tests, send_message_complex_type)
|
|||
received_event->set();
|
||||
});
|
||||
|
||||
hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj{};
|
||||
web::json::value person;
|
||||
web::json::value address;
|
||||
address[U("street")] = web::json::value::string(U("main st"));
|
||||
address[U("zip")] = web::json::value::string(U("98052"));
|
||||
person[U("address")] = address;
|
||||
person[U("name")] = web::json::value::string(U("test"));
|
||||
person[U("age")] = web::json::value::number(15);
|
||||
obj[0] = person;
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
return hub_conn->send("invokeWithComplexType", obj);
|
||||
mre.get();
|
||||
|
||||
}).get();
|
||||
web::json::value obj{};
|
||||
web::json::value person;
|
||||
web::json::value address;
|
||||
address[U("street")] = web::json::value::string(U("main st"));
|
||||
address[U("zip")] = web::json::value::string(U("98052"));
|
||||
person[U("address")] = address;
|
||||
person[U("name")] = web::json::value::string(U("test"));
|
||||
person[U("age")] = web::json::value::number(15);
|
||||
obj[0] = person;
|
||||
|
||||
hub_conn->send("invokeWithComplexType", obj, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(received_event->wait(2000));
|
||||
|
||||
|
|
@ -196,21 +284,37 @@ TEST(hub_connection_tests, send_message_complex_type_return)
|
|||
{
|
||||
auto hub_conn = std::make_shared<signalr::hub_connection>(url);
|
||||
|
||||
auto test = hub_conn->start().then([&hub_conn]()
|
||||
auto mre = manual_reset_event<web::json::value>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
web::json::value obj{};
|
||||
web::json::value person;
|
||||
web::json::value address;
|
||||
address[U("street")] = web::json::value::string(U("main st"));
|
||||
address[U("zip")] = web::json::value::string(U("98052"));
|
||||
person[U("address")] = address;
|
||||
person[U("name")] = web::json::value::string(U("test"));
|
||||
person[U("age")] = web::json::value::number(15);
|
||||
obj[0] = person;
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
return hub_conn->invoke("returnComplexType", obj);
|
||||
mre.get();
|
||||
|
||||
}).get();
|
||||
web::json::value obj{};
|
||||
web::json::value person;
|
||||
web::json::value address;
|
||||
address[U("street")] = web::json::value::string(U("main st"));
|
||||
address[U("zip")] = web::json::value::string(U("98052"));
|
||||
person[U("address")] = address;
|
||||
person[U("name")] = web::json::value::string(U("test"));
|
||||
person[U("age")] = web::json::value::number(15);
|
||||
obj[0] = person;
|
||||
|
||||
hub_conn->invoke("returnComplexType", obj, [&mre](const web::json::value & value, std::exception_ptr exception)
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
mre.set(value);
|
||||
}
|
||||
});
|
||||
|
||||
auto test = mre.get();
|
||||
|
||||
ASSERT_EQ(test.serialize(), U("{\"Address\":{\"Street\":\"main st\",\"Zip\":\"98052\"},\"Age\":15,\"Name\":\"test\"}"));
|
||||
}
|
||||
|
|
@ -224,14 +328,31 @@ TEST(hub_connection_tests, connection_id_start_stop_start)
|
|||
|
||||
ASSERT_EQ(u8"", hub_conn->get_connection_id());
|
||||
|
||||
hub_conn->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
connection_id = hub_conn->get_connection_id();
|
||||
ASSERT_NE(connection_id, u8"");
|
||||
|
||||
hub_conn->stop().get();
|
||||
hub_conn->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_EQ(hub_conn->get_connection_id(), connection_id);
|
||||
|
||||
hub_conn->start().get();
|
||||
hub_conn->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_NE(hub_conn->get_connection_id(), u8"");
|
||||
ASSERT_NE(hub_conn->get_connection_id(), connection_id);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -37,9 +37,16 @@ TEST(url, negotiate_appended_to_url)
|
|||
std::make_shared<trace_log_writer>(), std::move(http_client),
|
||||
std::make_unique<test_transport_factory>(create_test_websocket_client()));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->start().get();
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
catch (const std::exception&) {}
|
||||
|
||||
|
|
@ -53,7 +60,13 @@ TEST(start, start_starts_connection)
|
|||
/* receive function */ [](std::function<void(std::string, std::exception_ptr)> callback) { callback("{ }\x1e", nullptr); });
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_EQ(connection_state::connected, hub_connection->get_connection_state());
|
||||
}
|
||||
|
|
@ -66,7 +79,13 @@ TEST(start, start_sends_handshake)
|
|||
/* send function */ [message](const std::string& msg, std::function<void(std::exception_ptr)> callback) { *message = msg; callback(nullptr); });
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_EQ("{\"protocol\":\"json\",\"version\":1}\x1e", *message);
|
||||
|
||||
|
|
@ -86,11 +105,18 @@ TEST(start, start_waits_for_handshake_response)
|
|||
});
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
auto startTask = hub_connection->start();
|
||||
auto mre = manual_reset_event<void>();
|
||||
auto done = false;
|
||||
hub_connection->start([&mre, &done](std::exception_ptr exception)
|
||||
{
|
||||
done = true;
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
pplx::task<void>(tceWaitForSend).get();
|
||||
ASSERT_FALSE(startTask.is_done());
|
||||
ASSERT_FALSE(done);
|
||||
tce.set();
|
||||
startTask.get();
|
||||
mre.get();
|
||||
|
||||
ASSERT_EQ(connection_state::connected, hub_connection->get_connection_state());
|
||||
}
|
||||
|
|
@ -101,12 +127,18 @@ TEST(start, start_fails_for_handshake_response_with_error)
|
|||
/* receive function */ [](std::function<void(std::string, std::exception_ptr)> callback) { callback("{\"error\":\"bad things\"}\x1e", nullptr); });
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->start().get();
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
catch (std::exception ex)
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
ASSERT_STREQ("Received an error during handshake: bad things", ex.what());
|
||||
}
|
||||
|
|
@ -131,13 +163,18 @@ TEST(start, start_fails_if_stop_called_before_handshake_response)
|
|||
});
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
auto startTask = hub_connection->start();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
pplx::task<void>(tceWaitForSend).get();
|
||||
hub_connection->stop();
|
||||
hub_connection->stop([](std::exception_ptr) {});
|
||||
|
||||
try
|
||||
{
|
||||
startTask.get();
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
catch (std::exception ex)
|
||||
|
|
@ -154,8 +191,20 @@ TEST(stop, stop_stops_connection)
|
|||
/* receive function */ [](std::function<void(std::string, std::exception_ptr)> callback) { callback("{ }\x1e", nullptr); });
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
hub_connection->start().get();
|
||||
hub_connection->stop().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_EQ(connection_state::disconnected, hub_connection->get_connection_state());
|
||||
}
|
||||
|
|
@ -169,8 +218,20 @@ TEST(stop, disconnected_callback_called_when_hub_connection_stops)
|
|||
auto disconnected_invoked = false;
|
||||
hub_connection->set_disconnected([&disconnected_invoked]() { disconnected_invoked = true; });
|
||||
|
||||
hub_connection->start().get();
|
||||
hub_connection->stop().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_TRUE(disconnected_invoked);
|
||||
}
|
||||
|
|
@ -184,7 +245,13 @@ TEST(stop, connection_stopped_when_going_out_of_scope)
|
|||
/* receive function */ [](std::function<void(std::string, std::exception_ptr)> callback) { callback("{ }\x1e", nullptr); });
|
||||
auto hub_connection = create_hub_connection(websocket_client, writer, trace_level::state_changes);
|
||||
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
}
|
||||
|
||||
auto memory_writer = std::dynamic_pointer_cast<memory_log_writer>(writer);
|
||||
|
|
@ -226,13 +293,30 @@ TEST(stop, stop_cancels_pending_callbacks)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start().get();
|
||||
auto t = hub_connection->invoke("method", json::value::array());
|
||||
hub_connection->stop();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
auto invoke_mre = manual_reset_event<void>();
|
||||
hub_connection->invoke("method", json::value::array(), [&invoke_mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
invoke_mre.set(exception);
|
||||
});
|
||||
|
||||
hub_connection->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
try
|
||||
{
|
||||
t.get();
|
||||
invoke_mre.get();
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
catch (const signalr_exception& e)
|
||||
|
|
@ -261,17 +345,27 @@ TEST(stop, pending_callbacks_finished_if_hub_connections_goes_out_of_scope)
|
|||
callback(responses[call_number], nullptr);
|
||||
});
|
||||
|
||||
pplx::task<web::json::value> t;
|
||||
auto invoke_mre = manual_reset_event<void>();
|
||||
|
||||
{
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start().get();
|
||||
t = hub_connection->invoke("method", json::value::array());
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->invoke("method", json::value::array(), [&invoke_mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
invoke_mre.set(exception);
|
||||
});
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
t.get();
|
||||
invoke_mre.get();
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
catch (const signalr_exception& e)
|
||||
|
|
@ -307,7 +401,13 @@ TEST(hub_invocation, hub_connection_invokes_users_code_on_hub_invocations)
|
|||
on_broadcast_event->set();
|
||||
});
|
||||
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
ASSERT_FALSE(on_broadcast_event->wait(5000));
|
||||
|
||||
ASSERT_EQ("[\"message\",1]", *payload);
|
||||
|
|
@ -333,9 +433,20 @@ TEST(send, creates_correct_payload)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
hub_connection->send("method", json::value::array()).get();
|
||||
mre.get();
|
||||
|
||||
hub_connection->send("method", json::value::array(), [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_EQ("{\"arguments\":[],\"target\":\"method\",\"type\":1}\x1e", payload);
|
||||
}
|
||||
|
|
@ -365,10 +476,21 @@ TEST(send, does_not_wait_for_server_response)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start().get();
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
// wont block waiting for server response
|
||||
hub_connection->send("method", json::value::array()).get();
|
||||
hub_connection->send("method", json::value::array(), [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
waitForSend.set();
|
||||
}
|
||||
|
||||
|
|
@ -392,11 +514,23 @@ TEST(invoke, creates_correct_payload)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->invoke("method", json::value::array()).get();
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
@ -423,11 +557,22 @@ TEST(invoke, callback_not_called_if_send_throws)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->invoke("method", json::value::array()).get();
|
||||
mre.get();
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
|
|
@ -438,7 +583,12 @@ TEST(invoke, callback_not_called_if_send_throws)
|
|||
// stop completes all outstanding callbacks so if we did not remove a callback when `invoke_void` failed an
|
||||
// unobserved exception exception would be thrown. Note that this would happen on a different thread and would
|
||||
// crash the process
|
||||
hub_connection->stop().get();
|
||||
hub_connection->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
}
|
||||
|
||||
TEST(invoke, invoke_returns_value_returned_from_the_server)
|
||||
|
|
@ -466,13 +616,31 @@ TEST(invoke, invoke_returns_value_returned_from_the_server)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
auto result = hub_connection->start()
|
||||
.then([hub_connection, callback_registered_event]()
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
auto invoke_mre = manual_reset_event<json::value>();
|
||||
hub_connection->invoke("method", json::value::array(), [&invoke_mre](const json::value& message, std::exception_ptr exception)
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
auto t = hub_connection->invoke("method", json::value::array());
|
||||
callback_registered_event->set();
|
||||
return t;
|
||||
}).get();
|
||||
invoke_mre.set(exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
invoke_mre.set(message);
|
||||
}
|
||||
});
|
||||
|
||||
callback_registered_event->set();
|
||||
|
||||
auto result = invoke_mre.get();
|
||||
|
||||
ASSERT_EQ(_XPLATSTR("\"abc\""), result.serialize());
|
||||
}
|
||||
|
|
@ -502,15 +670,25 @@ TEST(invoke, invoke_propagates_errors_from_server_as_hub_exceptions)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
callback_registered_event->set();
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->start()
|
||||
.then([hub_connection, callback_registered_event]()
|
||||
{
|
||||
auto t = hub_connection->invoke("method", json::value::array());
|
||||
callback_registered_event->set();
|
||||
return t;
|
||||
}).get();
|
||||
mre.get();
|
||||
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
|
|
@ -545,13 +723,23 @@ TEST(invoke, unblocks_task_when_server_completes_call)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
hub_connection->start()
|
||||
.then([hub_connection, callback_registered_event]()
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
auto t = hub_connection->invoke("method", json::value::array());
|
||||
callback_registered_event->set();
|
||||
return t;
|
||||
}).get();
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
callback_registered_event->set();
|
||||
|
||||
mre.get();
|
||||
|
||||
// should not block
|
||||
ASSERT_TRUE(true);
|
||||
|
|
@ -592,7 +780,14 @@ TEST(receive, logs_if_callback_for_given_id_not_found)
|
|||
|
||||
std::shared_ptr<log_writer> writer(std::make_shared<memory_log_writer>());
|
||||
auto hub_connection = create_hub_connection(websocket_client, writer, trace_level::info);
|
||||
hub_connection->start().get();
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_FALSE(message_received_event->wait(5000));
|
||||
|
||||
|
|
@ -628,15 +823,25 @@ TEST(invoke_void, invoke_creates_runtime_error)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
callback_registered_event->set();
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->start()
|
||||
.then([hub_connection, callback_registered_event]()
|
||||
{
|
||||
auto t = hub_connection->invoke("method", json::value::array());
|
||||
callback_registered_event->set();
|
||||
return t;
|
||||
}).get();
|
||||
mre.get();
|
||||
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
|
|
@ -655,9 +860,21 @@ TEST(connection_id, can_get_connection_id)
|
|||
|
||||
ASSERT_EQ("", hub_connection->get_connection_id());
|
||||
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
auto connection_id = hub_connection->get_connection_id();
|
||||
hub_connection->stop().get();
|
||||
|
||||
hub_connection->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
ASSERT_EQ("f7707523-307d-4cba-9abf-3eef701241e8", connection_id);
|
||||
ASSERT_EQ("f7707523-307d-4cba-9abf-3eef701241e8", hub_connection->get_connection_id());
|
||||
|
|
@ -702,7 +919,13 @@ TEST(on, cannot_register_handler_if_connection_not_in_disconnected_state)
|
|||
/* receive function */ [](std::function<void(std::string, std::exception_ptr)> callback) { callback("{ }\x1e", nullptr); });
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
|
||||
hub_connection->start().get();
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->start([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
||||
hub_connection->on("myfunc", [](const web::json::value&) {});
|
||||
|
||||
|
|
@ -718,10 +941,16 @@ TEST(invoke, invoke_throws_when_the_underlying_connection_is_not_valid)
|
|||
{
|
||||
auto hub_connection = create_hub_connection();
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->invoke("method", json::value::array()).get();
|
||||
ASSERT_TRUE(true); // exception expected but not thrown
|
||||
mre.get();
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
catch (const signalr_exception& e)
|
||||
{
|
||||
|
|
@ -733,10 +962,16 @@ TEST(invoke, send_throws_when_the_underlying_connection_is_not_valid)
|
|||
{
|
||||
auto hub_connection = create_hub_connection();
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
hub_connection->invoke("method", json::value::array(), [&mre](const json::value&, std::exception_ptr exception)
|
||||
{
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
hub_connection->invoke("method", json::value::array()).get();
|
||||
ASSERT_TRUE(true); // exception expected but not thrown
|
||||
mre.get();
|
||||
ASSERT_TRUE(false); // exception expected but not thrown
|
||||
}
|
||||
catch (const signalr_exception& e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "signalrclient/websocket_client.h"
|
||||
#include "web_request_factory.h"
|
||||
#include "signalrclient/http_client.h"
|
||||
#include <future>
|
||||
|
||||
|
|
@ -17,7 +16,6 @@ std::shared_ptr<signalr::websocket_client> create_test_websocket_client(
|
|||
std::function<void(const std::string&, std::function<void(std::exception_ptr)>)> connect_function = [](const std::string&, std::function<void(std::exception_ptr)> callback) { callback(nullptr); },
|
||||
std::function<void(std::function<void(std::exception_ptr)>)> close_function = [](std::function<void(std::exception_ptr)> callback) { callback(nullptr); });
|
||||
|
||||
std::unique_ptr<signalr::web_request_factory> create_test_web_request_factory();
|
||||
std::unique_ptr<signalr::http_client> create_test_http_client();
|
||||
std::string create_uri();
|
||||
std::string create_uri(const std::string& query_string);
|
||||
|
|
@ -33,12 +31,12 @@ public:
|
|||
m_promise.set_value(value);
|
||||
}
|
||||
|
||||
void set_exception(std::exception exception)
|
||||
void set(const std::exception& exception)
|
||||
{
|
||||
m_promise.set_exception(std::make_exception_ptr(exception));
|
||||
}
|
||||
|
||||
void set_exception(std::exception_ptr exception)
|
||||
void set(std::exception_ptr exception)
|
||||
{
|
||||
m_promise.set_exception(exception);
|
||||
}
|
||||
|
|
@ -71,14 +69,21 @@ public:
|
|||
m_promise.set_value();
|
||||
}
|
||||
|
||||
void set_exception(std::exception exception)
|
||||
void set(const std::exception& exception)
|
||||
{
|
||||
m_promise.set_exception(std::make_exception_ptr(exception));
|
||||
}
|
||||
|
||||
void set_exception(std::exception_ptr exception)
|
||||
void set(std::exception_ptr exception)
|
||||
{
|
||||
m_promise.set_exception(exception);
|
||||
if (exception != nullptr)
|
||||
{
|
||||
m_promise.set_exception(exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_promise.set_value();
|
||||
}
|
||||
}
|
||||
|
||||
void get()
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ TEST(websocket_transport_connect, connect_connects_and_starts_receive_loop)
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(writer, trace_level::info));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org/connect?param=42", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org/connect?param=42", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
|
||||
mre.get();
|
||||
|
|
@ -66,7 +66,7 @@ TEST(websocket_transport_connect, connect_propagates_exceptions)
|
|||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set_exception(exception);
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
|
|
@ -91,7 +91,7 @@ TEST(websocket_transport_connect, connect_logs_exceptions)
|
|||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set_exception(exception);
|
||||
mre.set(exception);
|
||||
});
|
||||
try
|
||||
{
|
||||
|
|
@ -116,9 +116,9 @@ TEST(websocket_transport_connect, cannot_call_connect_on_already_connected_trans
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ TEST(websocket_transport_connect, cannot_call_connect_on_already_connected_trans
|
|||
{
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set_exception(exception);
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
|
|
@ -143,21 +143,21 @@ TEST(websocket_transport_connect, can_connect_after_disconnecting)
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
}
|
||||
|
|
@ -177,15 +177,15 @@ TEST(websocket_transport_send, send_creates_and_sends_websocket_messages)
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->send("ABC", [&mre](std::exception_ptr)
|
||||
ws_transport->send("ABC", [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -207,15 +207,15 @@ TEST(websocket_transport_disconnect, disconnect_closes_websocket)
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -236,22 +236,15 @@ TEST(websocket_transport_stop, propogates_exception_from_close)
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
if (exception)
|
||||
{
|
||||
mre.set_exception(exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
mre.set();
|
||||
}
|
||||
mre.set(exception);
|
||||
});
|
||||
try
|
||||
{
|
||||
|
|
@ -276,17 +269,23 @@ TEST(websocket_transport_disconnect, disconnect_logs_exceptions)
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(writer, trace_level::errors));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
try
|
||||
{
|
||||
mre.get();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
auto log_entries = std::dynamic_pointer_cast<memory_log_writer>(writer)->get_log_entries();
|
||||
|
||||
|
|
@ -344,26 +343,26 @@ TEST(websocket_transport_disconnect, receive_not_called_after_disconnect)
|
|||
|
||||
pplx::create_task(receive_task_started_tce).get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
receive_task_tce = pplx::task_completion_event<std::string>();
|
||||
receive_task_started_tce = pplx::task_completion_event<void>();
|
||||
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
pplx::create_task(receive_task_started_tce).get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -385,9 +384,9 @@ TEST(websocket_transport_disconnect, disconnect_is_no_op_if_transport_not_starte
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -411,15 +410,15 @@ TEST(websocket_transport_disconnect, exceptions_from_outstanding_receive_task_ob
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
ws_transport->stop([&mre](std::exception_ptr)
|
||||
ws_transport->stop([&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -472,9 +471,9 @@ void receive_loop_logs_exception_runner(const T& e, const std::string& expected_
|
|||
auto ws_transport = websocket_transport::create([&](){ return client; }, logger(writer, trace_level));
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://url", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -512,9 +511,9 @@ TEST(websocket_transport_receive_loop, process_response_callback_called_when_mes
|
|||
ws_transport->on_receive(process_response);
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
@ -558,9 +557,9 @@ TEST(websocket_transport_receive_loop, error_callback_called_when_exception_thro
|
|||
ws_transport->on_close(error_callback);
|
||||
|
||||
auto mre = manual_reset_event<void>();
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr)
|
||||
ws_transport->start("ws://fakeuri.org", transfer_format::text, [&mre](std::exception_ptr exception)
|
||||
{
|
||||
mre.set();
|
||||
mre.set(exception);
|
||||
});
|
||||
mre.get();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue