Просмотр исходного кода

Remove web::uri usage from public API (#7834)

BrennanConroy 7 лет назад
Родитель
Сommit
f8368097a9
27 измененных файлов с 110 добавлено и 293 удалено
  1. 6 6
      src/SignalR/clients/cpp/src/signalrclient/connection_impl.cpp
  2. 6 9
      src/SignalR/clients/cpp/src/signalrclient/connection_impl.h
  3. 0 3
      src/SignalR/clients/cpp/src/signalrclient/constants.h
  4. 3 3
      src/SignalR/clients/cpp/src/signalrclient/http_sender.cpp
  5. 3 3
      src/SignalR/clients/cpp/src/signalrclient/http_sender.h
  6. 1 1
      src/SignalR/clients/cpp/src/signalrclient/hub_connection_impl.cpp
  7. 1 1
      src/SignalR/clients/cpp/src/signalrclient/request_sender.cpp
  8. 1 1
      src/SignalR/clients/cpp/src/signalrclient/request_sender.h
  9. 2 2
      src/SignalR/clients/cpp/src/signalrclient/transport.h
  10. 6 58
      src/SignalR/clients/cpp/src/signalrclient/url_builder.cpp
  11. 3 3
      src/SignalR/clients/cpp/src/signalrclient/url_builder.h
  12. 2 2
      src/SignalR/clients/cpp/src/signalrclient/web_request.cpp
  13. 3 3
      src/SignalR/clients/cpp/src/signalrclient/web_request.h
  14. 1 1
      src/SignalR/clients/cpp/src/signalrclient/web_request_factory.cpp
  15. 2 2
      src/SignalR/clients/cpp/src/signalrclient/web_request_factory.h
  16. 4 3
      src/SignalR/clients/cpp/src/signalrclient/websocket_transport.cpp
  17. 1 1
      src/SignalR/clients/cpp/src/signalrclient/websocket_transport.h
  18. 0 3
      src/SignalR/clients/cpp/test/signalrclienttests/Build/VS/signalrclienttests.vcxproj
  19. 23 110
      src/SignalR/clients/cpp/test/signalrclienttests/connection_impl_tests.cpp
  20. 5 51
      src/SignalR/clients/cpp/test/signalrclienttests/hub_connection_impl_tests.cpp
  21. 14 8
      src/SignalR/clients/cpp/test/signalrclienttests/request_sender_tests.cpp
  22. 2 2
      src/SignalR/clients/cpp/test/signalrclienttests/test_web_request_factory.cpp
  23. 3 3
      src/SignalR/clients/cpp/test/signalrclienttests/test_web_request_factory.h
  24. 6 6
      src/SignalR/clients/cpp/test/signalrclienttests/url_builder_tests.cpp
  25. 2 2
      src/SignalR/clients/cpp/test/signalrclienttests/web_request_stub.cpp
  26. 2 2
      src/SignalR/clients/cpp/test/signalrclienttests/web_request_tests.cpp
  27. 8 4
      src/SignalR/clients/cpp/test/signalrclienttests/websocket_transport_tests.cpp

+ 6 - 6
src/SignalR/clients/cpp/src/signalrclient/connection_impl.cpp

@@ -80,13 +80,13 @@ namespace signalr
 
 
             m_disconnect_cts = pplx::cancellation_token_source();
             m_disconnect_cts = pplx::cancellation_token_source();
             m_start_completed_event.reset();
             m_start_completed_event.reset();
-            m_message_id = m_groups_token = m_connection_id = _XPLATSTR("");
+            m_connection_id = _XPLATSTR("");
         }
         }
 
 
         return start_negotiate(m_base_url, 0);
         return start_negotiate(m_base_url, 0);
     }
     }
 
 
-    pplx::task<void> connection_impl::start_negotiate(const web::uri& url, int redirect_count)
+    pplx::task<void> connection_impl::start_negotiate(const utility::string_t& url, int redirect_count)
     {
     {
         if (redirect_count >= MAX_NEGOTIATE_REDIRECTS)
         if (redirect_count >= MAX_NEGOTIATE_REDIRECTS)
         {
         {
@@ -214,7 +214,7 @@ namespace signalr
         return pplx::create_task(start_tce);
         return pplx::create_task(start_tce);
     }
     }
 
 
-    pplx::task<std::shared_ptr<transport>> connection_impl::start_transport(const web::uri& url)
+    pplx::task<std::shared_ptr<transport>> connection_impl::start_transport(const utility::string_t& url)
     {
     {
         auto connection = shared_from_this();
         auto connection = shared_from_this();
 
 
@@ -294,7 +294,7 @@ namespace signalr
             .then([transport](){ return pplx::task_from_result(transport); });
             .then([transport](){ return pplx::task_from_result(transport); });
     }
     }
 
 
-    pplx::task<void> connection_impl::send_connect_request(const std::shared_ptr<transport>& transport, const web::uri& url, const pplx::task_completion_event<void>& connect_request_tce)
+    pplx::task<void> connection_impl::send_connect_request(const std::shared_ptr<transport>& transport, const utility::string_t& url, const pplx::task_completion_event<void>& connect_request_tce)
     {
     {
         auto logger = m_logger;
         auto logger = m_logger;
         auto query_string = _XPLATSTR("id=" + m_connection_id);
         auto query_string = _XPLATSTR("id=" + m_connection_id);
@@ -479,7 +479,7 @@ namespace signalr
         return m_connection_state.load();
         return m_connection_state.load();
     }
     }
 
 
-    utility::string_t connection_impl::get_connection_id() const
+    utility::string_t connection_impl::get_connection_id() const noexcept
     {
     {
         if (m_connection_state.load() == connection_state::connecting)
         if (m_connection_state.load() == connection_state::connecting)
         {
         {
@@ -507,7 +507,7 @@ namespace signalr
         m_disconnected = disconnected;
         m_disconnected = disconnected;
     }
     }
 
 
-    void connection_impl::ensure_disconnected(const utility::string_t& error_message)
+    void connection_impl::ensure_disconnected(const utility::string_t& error_message) const
     {
     {
         const auto state = get_connection_state();
         const auto state = get_connection_state();
         if (state != connection_state::disconnected)
         if (state != connection_state::disconnected)

+ 6 - 9
src/SignalR/clients/cpp/src/signalrclient/connection_impl.h

@@ -41,14 +41,14 @@ namespace signalr
         pplx::task<void> stop();
         pplx::task<void> stop();
 
 
         connection_state get_connection_state() const noexcept;
         connection_state get_connection_state() const noexcept;
-        utility::string_t get_connection_id() const;
+        utility::string_t get_connection_id() const noexcept;
 
 
         void set_message_received(const std::function<void(const utility::string_t&)>& message_received);
         void set_message_received(const std::function<void(const utility::string_t&)>& message_received);
         void set_disconnected(const std::function<void()>& disconnected);
         void set_disconnected(const std::function<void()>& disconnected);
         void set_client_config(const signalr_client_config& config);
         void set_client_config(const signalr_client_config& config);
 
 
     private:
     private:
-        web::uri m_base_url;
+        utility::string_t m_base_url;
         std::atomic<connection_state> m_connection_state;
         std::atomic<connection_state> m_connection_state;
         logger m_logger;
         logger m_logger;
         std::shared_ptr<transport> m_transport;
         std::shared_ptr<transport> m_transport;
@@ -63,17 +63,14 @@ namespace signalr
         std::mutex m_stop_lock;
         std::mutex m_stop_lock;
         event m_start_completed_event;
         event m_start_completed_event;
         utility::string_t m_connection_id;
         utility::string_t m_connection_id;
-        utility::string_t m_connection_data;
-        utility::string_t m_message_id;
-        utility::string_t m_groups_token;
 
 
         connection_impl(const utility::string_t& url, trace_level trace_level, const std::shared_ptr<log_writer>& log_writer,
         connection_impl(const utility::string_t& url, trace_level trace_level, const std::shared_ptr<log_writer>& log_writer,
             std::unique_ptr<web_request_factory> web_request_factory, std::unique_ptr<transport_factory> transport_factory);
             std::unique_ptr<web_request_factory> web_request_factory, std::unique_ptr<transport_factory> transport_factory);
 
 
-        pplx::task<std::shared_ptr<transport>> start_transport(const web::uri& url);
+        pplx::task<std::shared_ptr<transport>> start_transport(const utility::string_t& url);
         pplx::task<void> send_connect_request(const std::shared_ptr<transport>& transport,
         pplx::task<void> send_connect_request(const std::shared_ptr<transport>& transport,
-            const web::uri& url, const pplx::task_completion_event<void>& connect_request_tce);
-        pplx::task<void> start_negotiate(const web::uri& url, int redirect_count);
+            const utility::string_t& url, const pplx::task_completion_event<void>& connect_request_tce);
+        pplx::task<void> start_negotiate(const utility::string_t& url, int redirect_count);
 
 
         void process_response(const utility::string_t& response);
         void process_response(const utility::string_t& response);
 
 
@@ -85,6 +82,6 @@ namespace signalr
         void invoke_message_received(const utility::string_t& message);
         void invoke_message_received(const utility::string_t& message);
 
 
         static utility::string_t translate_connection_state(connection_state state);
         static utility::string_t translate_connection_state(connection_state state);
-        void ensure_disconnected(const utility::string_t& error_message);
+        void ensure_disconnected(const utility::string_t& error_message) const;
     };
     };
 }
 }

+ 0 - 3
src/SignalR/clients/cpp/src/signalrclient/constants.h

@@ -3,9 +3,6 @@
 
 
 #pragma once
 #pragma once
 
 
-#include "cpprest/details/basic_types.h"
-
 #define SIGNALR_VERSION _XPLATSTR("0.1.0-alpha0")
 #define SIGNALR_VERSION _XPLATSTR("0.1.0-alpha0")
-#define PROTOCOL _XPLATSTR("1.4")
 #define USER_AGENT _XPLATSTR("SignalR.Client.Cpp/") SIGNALR_VERSION
 #define USER_AGENT _XPLATSTR("SignalR.Client.Cpp/") SIGNALR_VERSION
 #define MAX_NEGOTIATE_REDIRECTS 100
 #define MAX_NEGOTIATE_REDIRECTS 100

+ 3 - 3
src/SignalR/clients/cpp/src/signalrclient/http_sender.cpp

@@ -10,7 +10,7 @@ namespace signalr
 {
 {
     namespace http_sender
     namespace http_sender
     {
     {
-        pplx::task<utility::string_t> get(web_request_factory& request_factory, const web::uri& url,
+        pplx::task<utility::string_t> get(web_request_factory& request_factory, const utility::string_t& url,
             const signalr_client_config& signalr_client_config)
             const signalr_client_config& signalr_client_config)
         {
         {
             auto request = request_factory.create_web_request(url);
             auto request = request_factory.create_web_request(url);
@@ -32,7 +32,7 @@ namespace signalr
             });
             });
         }
         }
 
 
-        pplx::task<utility::string_t> post(web_request_factory& request_factory, const web::uri& url,
+        pplx::task<utility::string_t> post(web_request_factory& request_factory, const utility::string_t& url,
             const signalr_client_config& signalr_client_config)
             const signalr_client_config& signalr_client_config)
         {
         {
             auto request = request_factory.create_web_request(url);
             auto request = request_factory.create_web_request(url);
@@ -54,4 +54,4 @@ namespace signalr
             });
             });
         }
         }
     }
     }
-}
+}

+ 3 - 3
src/SignalR/clients/cpp/src/signalrclient/http_sender.h

@@ -12,10 +12,10 @@ namespace signalr
 {
 {
     namespace http_sender
     namespace http_sender
     {
     {
-        pplx::task<utility::string_t> get(web_request_factory& request_factory, const web::uri& url,
+        pplx::task<utility::string_t> get(web_request_factory& request_factory, const utility::string_t& url,
             const signalr_client_config& client_config = signalr_client_config{});
             const signalr_client_config& client_config = signalr_client_config{});
 
 
-        pplx::task<utility::string_t> post(web_request_factory& request_factory, const web::uri& url,
+        pplx::task<utility::string_t> post(web_request_factory& request_factory, const utility::string_t& url,
             const signalr_client_config& client_config = signalr_client_config{});
             const signalr_client_config& client_config = signalr_client_config{});
     }
     }
-}
+}

+ 1 - 1
src/SignalR/clients/cpp/src/signalrclient/hub_connection_impl.cpp

@@ -43,7 +43,7 @@ namespace signalr
         const std::shared_ptr<log_writer>& log_writer, std::unique_ptr<web_request_factory> web_request_factory,
         const std::shared_ptr<log_writer>& log_writer, std::unique_ptr<web_request_factory> web_request_factory,
         std::unique_ptr<transport_factory> transport_factory)
         std::unique_ptr<transport_factory> transport_factory)
         : m_connection(connection_impl::create(url, trace_level, log_writer,
         : m_connection(connection_impl::create(url, trace_level, log_writer,
-        std::move(web_request_factory), std::move(transport_factory))),m_logger(log_writer, trace_level),
+        std::move(web_request_factory), std::move(transport_factory))), m_logger(log_writer, trace_level),
         m_callback_manager(json::value::parse(_XPLATSTR("{ \"error\" : \"connection went out of scope before invocation result was received\"}"))),
         m_callback_manager(json::value::parse(_XPLATSTR("{ \"error\" : \"connection went out of scope before invocation result was received\"}"))),
         m_disconnected([]() noexcept {}), m_handshakeReceived(false)
         m_disconnected([]() noexcept {}), m_handshakeReceived(false)
     { }
     { }

+ 1 - 1
src/SignalR/clients/cpp/src/signalrclient/request_sender.cpp

@@ -11,7 +11,7 @@ namespace signalr
 {
 {
     namespace request_sender
     namespace request_sender
     {
     {
-        pplx::task<negotiation_response> negotiate(web_request_factory& request_factory, const web::uri& base_url,
+        pplx::task<negotiation_response> negotiate(web_request_factory& request_factory, const utility::string_t& base_url,
             const signalr_client_config& signalr_client_config)
             const signalr_client_config& signalr_client_config)
         {
         {
             auto negotiate_url = url_builder::build_negotiate(base_url);
             auto negotiate_url = url_builder::build_negotiate(base_url);

+ 1 - 1
src/SignalR/clients/cpp/src/signalrclient/request_sender.h

@@ -14,7 +14,7 @@ namespace signalr
 {
 {
     namespace request_sender
     namespace request_sender
     {
     {
-        pplx::task<negotiation_response> negotiate(web_request_factory& request_factory, const web::uri &base_url,
+        pplx::task<negotiation_response> negotiate(web_request_factory& request_factory, const utility::string_t& base_url,
             const signalr_client_config& signalr_client_config = signalr::signalr_client_config{});
             const signalr_client_config& signalr_client_config = signalr::signalr_client_config{});
     }
     }
 }
 }

+ 2 - 2
src/SignalR/clients/cpp/src/signalrclient/transport.h

@@ -13,7 +13,7 @@ namespace signalr
     class transport
     class transport
     {
     {
     public:
     public:
-        virtual pplx::task<void> connect(const web::uri &url) = 0;
+        virtual pplx::task<void> connect(const utility::string_t &url) = 0;
 
 
         virtual pplx::task<void> send(const utility::string_t &data) = 0;
         virtual pplx::task<void> send(const utility::string_t &data) = 0;
 
 
@@ -37,4 +37,4 @@ namespace signalr
 
 
         std::function<void(const std::exception&)> m_error_callback;
         std::function<void(const std::exception&)> m_error_callback;
     };
     };
-}
+}

+ 6 - 58
src/SignalR/clients/cpp/src/signalrclient/url_builder.cpp

@@ -2,7 +2,6 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 
 #include "stdafx.h"
 #include "stdafx.h"
-#include "constants.h"
 #include "cpprest/http_client.h"
 #include "cpprest/http_client.h"
 #include "signalrclient/transport_type.h"
 #include "signalrclient/transport_type.h"
 
 
@@ -10,55 +9,6 @@ namespace signalr
 {
 {
     namespace url_builder
     namespace url_builder
     {
     {
-        utility::string_t get_transport_name(transport_type transport)
-        {
-            _ASSERTE(transport == transport_type::websockets || transport == transport_type::long_polling);
-
-            return transport == transport_type::websockets
-                ? utility::string_t(_XPLATSTR("webSockets"))
-                : utility::string_t(_XPLATSTR("longPolling"));
-        }
-
-        void append_transport(web::uri_builder &builder, transport_type transport)
-        {
-            if (transport > static_cast<transport_type>(-1))
-            {
-                builder.append_query(_XPLATSTR("transport"), get_transport_name(transport));
-            }
-        }
-
-        void append_connection_token(web::uri_builder &builder, const utility::string_t &connection_token)
-        {
-            if (connection_token.length() > 0)
-            {
-                builder.append_query(_XPLATSTR("connectionToken"), connection_token, /* do_encoding */ true);
-            }
-        }
-
-        void append_connection_data(web::uri_builder& builder, const utility::string_t& connection_data)
-        {
-            if (connection_data.length() > 0)
-            {
-                builder.append_query(_XPLATSTR("connectionData"), connection_data, /* do_encoding */ true);
-            }
-        }
-
-        void append_message_id(web::uri_builder& builder, const utility::string_t& message_id)
-        {
-            if (message_id.length() > 0)
-            {
-                builder.append_query(_XPLATSTR("messageId"), message_id, /* do_encoding */ true);
-            }
-        }
-
-        void append_groups_token(web::uri_builder& builder, const utility::string_t& groups_token)
-        {
-            if (groups_token.length() > 0)
-            {
-                builder.append_query(_XPLATSTR("groupsToken"), groups_token, /* do_encoding */ true);
-            }
-        }
-
         web::uri_builder &convert_to_websocket_url(web::uri_builder &builder, transport_type transport)
         web::uri_builder &convert_to_websocket_url(web::uri_builder &builder, transport_type transport)
         {
         {
             if (transport == transport_type::websockets)
             if (transport == transport_type::websockets)
@@ -89,22 +39,20 @@ namespace signalr
             return builder.append_path(command);
             return builder.append_path(command);
         }
         }
 
 
-        web::uri build_negotiate(const web::uri& base_url)
+        utility::string_t build_negotiate(const utility::string_t& base_url)
         {
         {
-            return build_uri(base_url, _XPLATSTR("negotiate")).to_uri();
+            return build_uri(base_url, _XPLATSTR("negotiate")).to_string();
         }
         }
 
 
-        web::uri build_connect(const web::uri& base_url, transport_type transport, const utility::string_t& query_string)
+        utility::string_t build_connect(const utility::string_t& base_url, transport_type transport, const utility::string_t& query_string)
         {
         {
             auto builder = build_uri(base_url, _XPLATSTR(""), query_string);
             auto builder = build_uri(base_url, _XPLATSTR(""), query_string);
-            return convert_to_websocket_url(builder, transport).to_uri();
-            //auto builder = build_uri(base_url, _XPLATSTR("connect"), transport, connection_data, query_string);
-            //return convert_to_websocket_url(builder, transport).to_uri();
+            return convert_to_websocket_url(builder, transport).to_string();
         }
         }
 
 
-        web::uri build_start(const web::uri &base_url, const utility::string_t &query_string)
+        utility::string_t build_start(const utility::string_t& base_url, const utility::string_t &query_string)
         {
         {
-            return build_uri(base_url, _XPLATSTR(""), query_string).to_uri();
+            return build_uri(base_url, _XPLATSTR(""), query_string).to_string();
         }
         }
     }
     }
 }
 }

+ 3 - 3
src/SignalR/clients/cpp/src/signalrclient/url_builder.h

@@ -10,8 +10,8 @@ namespace signalr
 {
 {
     namespace url_builder
     namespace url_builder
     {
     {
-        web::uri build_negotiate(const web::uri& base_url);
-        web::uri build_connect(const web::uri& base_url, transport_type transport, const utility::string_t& query_string);
-        web::uri build_start(const web::uri& base_url, const utility::string_t& query_string);
+        utility::string_t build_negotiate(const utility::string_t& base_url);
+        utility::string_t build_connect(const utility::string_t& base_url, transport_type transport, const utility::string_t& query_string);
+        utility::string_t build_start(const utility::string_t& base_url, const utility::string_t& query_string);
     }
     }
 }
 }

+ 2 - 2
src/SignalR/clients/cpp/src/signalrclient/web_request.cpp

@@ -7,7 +7,7 @@
 
 
 namespace signalr
 namespace signalr
 {
 {
-    web_request::web_request(const web::uri &url)
+    web_request::web_request(const utility::string_t& url)
         : m_url(url)
         : m_url(url)
     { }
     { }
 
 
@@ -49,4 +49,4 @@ namespace signalr
     }
     }
 
 
     web_request::~web_request() = default;
     web_request::~web_request() = default;
-}
+}

+ 3 - 3
src/SignalR/clients/cpp/src/signalrclient/web_request.h

@@ -11,7 +11,7 @@ namespace signalr
     class web_request
     class web_request
     {
     {
     public:
     public:
-        explicit web_request(const web::uri &url);
+        explicit web_request(const utility::string_t& url);
 
 
         virtual void set_method(const utility::string_t &method);
         virtual void set_method(const utility::string_t &method);
         virtual void set_user_agent(const utility::string_t &user_agent_string);
         virtual void set_user_agent(const utility::string_t &user_agent_string);
@@ -24,9 +24,9 @@ namespace signalr
         virtual ~web_request();
         virtual ~web_request();
 
 
     private:
     private:
-        const web::uri m_url;
+        const utility::string_t m_url;
         web::http::http_request m_request;
         web::http::http_request m_request;
         utility::string_t m_user_agent_string;
         utility::string_t m_user_agent_string;
         signalr_client_config m_signalr_client_config;
         signalr_client_config m_signalr_client_config;
     };
     };
-}
+}

+ 1 - 1
src/SignalR/clients/cpp/src/signalrclient/web_request_factory.cpp

@@ -7,7 +7,7 @@
 
 
 namespace signalr
 namespace signalr
 {
 {
-    std::unique_ptr<web_request> web_request_factory::create_web_request(const web::uri &url)
+    std::unique_ptr<web_request> web_request_factory::create_web_request(const utility::string_t& url)
     {
     {
         return std::make_unique<web_request>(url);
         return std::make_unique<web_request>(url);
     }
     }

+ 2 - 2
src/SignalR/clients/cpp/src/signalrclient/web_request_factory.h

@@ -11,8 +11,8 @@ namespace signalr
     class web_request_factory
     class web_request_factory
     {
     {
     public:
     public:
-        virtual std::unique_ptr<web_request> create_web_request(const web::uri &url);
+        virtual std::unique_ptr<web_request> create_web_request(const utility::string_t& url);
 
 
         virtual ~web_request_factory();
         virtual ~web_request_factory();
     };
     };
-}
+}

+ 4 - 3
src/SignalR/clients/cpp/src/signalrclient/websocket_transport.cpp

@@ -41,9 +41,10 @@ namespace signalr
         return transport_type::websockets;
         return transport_type::websockets;
     }
     }
 
 
-    pplx::task<void> websocket_transport::connect(const web::uri &url)
+    pplx::task<void> websocket_transport::connect(const utility::string_t& url)
     {
     {
-        _ASSERTE(url.scheme() == _XPLATSTR("ws") || url.scheme() == _XPLATSTR("wss"));
+        web::uri uri(url);
+        _ASSERTE(uri.scheme() == _XPLATSTR("ws") || uri.scheme() == _XPLATSTR("wss"));
 
 
         {
         {
             std::lock_guard<std::mutex> stop_lock(m_start_stop_lock);
             std::lock_guard<std::mutex> stop_lock(m_start_stop_lock);
@@ -55,7 +56,7 @@ namespace signalr
 
 
             m_logger.log(trace_level::info,
             m_logger.log(trace_level::info,
                 utility::string_t(_XPLATSTR("[websocket transport] connecting to: "))
                 utility::string_t(_XPLATSTR("[websocket transport] connecting to: "))
-                .append(url.to_string()));
+                .append(url));
 
 
             auto websocket_client = m_websocket_client_factory();
             auto websocket_client = m_websocket_client_factory();
 
 

+ 1 - 1
src/SignalR/clients/cpp/src/signalrclient/websocket_transport.h

@@ -25,7 +25,7 @@ namespace signalr
 
 
         websocket_transport& operator=(const websocket_transport&) = delete;
         websocket_transport& operator=(const websocket_transport&) = delete;
 
 
-        pplx::task<void> connect(const web::uri &url) override;
+        pplx::task<void> connect(const utility::string_t& url) override;
 
 
         pplx::task<void> send(const utility::string_t &data) override;
         pplx::task<void> send(const utility::string_t &data) override;
 
 

+ 0 - 3
src/SignalR/clients/cpp/test/signalrclienttests/Build/VS/signalrclienttests.vcxproj

@@ -93,9 +93,6 @@
     <PackageReference Include="cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn" Version="2.9.1" />
     <PackageReference Include="cpprestsdk.v140.windesktop.msvcstl.dyn.rt-dyn" Version="2.9.1" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <Target Name="AfterBuild">
-    <Exec Command="copy /y &quot;$(SolutionDir)bin\Desktop\$(Platform)\$(Configuration)\dll\$(SignalrClientTargetName).dll&quot; &quot;$(SolutionDir)bin\Desktop\$(Platform)\$(Configuration)\$(SignalrClientTargetName).dll&quot;" />
-  </Target>
   <PropertyGroup>
   <PropertyGroup>
     <IsTestProject>true</IsTestProject>
     <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   </PropertyGroup>

+ 23 - 110
src/SignalR/clients/cpp/test/signalrclienttests/connection_impl_tests.cpp

@@ -111,6 +111,28 @@ TEST(connection_impl_start, connection_state_is_disconnected_when_connection_can
     ASSERT_EQ(connection->get_connection_state(), connection_state::disconnected);
     ASSERT_EQ(connection->get_connection_state(), connection_state::disconnected);
 }
 }
 
 
+TEST(connection_impl_start, throws_for_invalid_uri)
+{
+    std::shared_ptr<log_writer> writer(std::make_shared<memory_log_writer>());
+
+    auto websocket_client = create_test_websocket_client(
+        /* receive function */ []() { return pplx::task_from_result(std::string("{ }\x1e")); });
+
+    auto connection = connection_impl::create(_XPLATSTR(":1\t ä bad_uri&a=b"), trace_level::errors, writer, create_test_web_request_factory(), std::make_unique<test_transport_factory>(websocket_client));
+
+    try
+    {
+        connection->start().get();
+        ASSERT_TRUE(false);
+    }
+    catch (const std::exception&)
+    {
+        // We shouldn't check the exact exception as it would be specific to the http library being used
+    }
+
+    ASSERT_EQ(connection->get_connection_state(), connection_state::disconnected);
+}
+
 TEST(connection_impl_start, start_sets_id_query_string)
 TEST(connection_impl_start, start_sets_id_query_string)
 {
 {
     std::shared_ptr<log_writer> writer(std::make_shared<memory_log_writer>());
     std::shared_ptr<log_writer> writer(std::make_shared<memory_log_writer>());
@@ -246,35 +268,6 @@ TEST(connection_impl_start, start_fails_if_transport_connect_throws)
     ASSERT_EQ(_XPLATSTR("[error       ] transport could not connect due to: connecting failed\n"), entry);
     ASSERT_EQ(_XPLATSTR("[error       ] transport could not connect due to: connecting failed\n"), entry);
 }
 }
 
 
-// TODO
-TEST(connection_impl_start, DISABLED_start_fails_if_no_available_transports)
-{
-   auto web_request_factory = std::make_unique<test_web_request_factory>([](const web::uri &) -> std::unique_ptr<web_request>
-   {
-       auto response_body =
-           _XPLATSTR("{ \"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
-           _XPLATSTR("\"availableTransports\" : [] }");
-
-       return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));
-   });
-
-   auto websocket_client = std::make_shared<test_websocket_client>();
-   auto connection =
-       connection_impl::create(create_uri(), trace_level::errors, std::make_shared<trace_log_writer>(),
-       std::move(web_request_factory), std::make_unique<test_transport_factory>(websocket_client));
-
-   try
-   {
-       connection->start().get();
-       ASSERT_TRUE(false); // exception not thrown
-   }
-   catch (const std::exception &e)
-   {
-       ASSERT_EQ(_XPLATSTR("websockets not supported on the server and there is no fallback transport"),
-           utility::conversions::to_string_t(e.what()));
-   }
-}
-
 #if defined(_WIN32)   //  https://github.com/aspnet/SignalR-Client-Cpp/issues/131
 #if defined(_WIN32)   //  https://github.com/aspnet/SignalR-Client-Cpp/issues/131
 
 
 TEST(connection_impl_send, send_fails_if_transport_fails_when_receiving_messages)
 TEST(connection_impl_send, send_fails_if_transport_fails_when_receiving_messages)
@@ -984,86 +977,6 @@ TEST(connection_impl_set_message_received, non_std_exception_from_callback_caugh
     ASSERT_EQ(_XPLATSTR("[error       ] message_received callback threw an unknown exception\n"), entry);
     ASSERT_EQ(_XPLATSTR("[error       ] message_received callback threw an unknown exception\n"), entry);
 }
 }
 
 
-TEST(connection_impl_set_message_received, DISABLED_error_logged_for_malformed_payload)
-{
-    int call_number = -1;
-    auto websocket_client = create_test_websocket_client(
-        /* receive function */ [call_number]()
-        mutable {
-        std::string responses[]
-        {
-            "{ }\x1e",
-            "{ 42\x1e",
-            "{ \"type\": 1, \"target\": \"something\", \"arguments\" : [\"release\"] }\x1e",
-            "{}"
-        };
-
-        call_number = std::min(call_number + 1, 3);
-
-        return pplx::task_from_result(responses[call_number]);
-    });
-
-    std::shared_ptr<log_writer> writer(std::make_shared<memory_log_writer>());
-    auto connection = create_connection(websocket_client, writer, trace_level::errors);
-
-    auto message_received_event = std::make_shared<event>();
-    connection->set_message_received([message_received_event](const utility::string_t&)
-    {
-        // this is called only once because we have just one response with a message
-        message_received_event->set();
-    });
-
-    connection->start().get();
-
-    ASSERT_FALSE(message_received_event->wait(5000));
-
-    auto log_entries = std::dynamic_pointer_cast<memory_log_writer>(writer)->get_log_entries();
-    ASSERT_FALSE(log_entries.empty());
-
-    auto entry = remove_date_from_log_entry(log_entries[0]);
-    ASSERT_EQ(_XPLATSTR("[error       ] error occured when parsing response: * Line 1, Column 4 Syntax error: Malformed object literal. response: { 42\x1e\n"), entry);
-}
-
-TEST(connection_impl_set_message_received, DISABLED_unexpected_responses_logged)
-{
-    int call_number = -1;
-    auto websocket_client = create_test_websocket_client(
-        /* receive function */ [call_number]()
-        mutable {
-        std::string responses[]
-        {
-            "{ }\x1e",
-            "42\x1e",
-            "{ \"type\": 1, \"target\": \"something\", \"arguments\" : [\"release\"] }\x1e",
-            "{}"
-        };
-
-        call_number = std::min(call_number + 1, 3);
-
-        return pplx::task_from_result(responses[call_number]);
-    });
-
-    std::shared_ptr<log_writer> writer(std::make_shared<memory_log_writer>());
-    auto connection = create_connection(websocket_client, writer, trace_level::info);
-
-    auto message_received_event = std::make_shared<event>();
-    connection->set_message_received([message_received_event](const utility::string_t&)
-    {
-        // this is called only once because we have just one response with a message
-        message_received_event->set();
-    });
-
-    connection->start().get();
-
-    ASSERT_FALSE(message_received_event->wait(5000));
-
-    auto log_entries = std::dynamic_pointer_cast<memory_log_writer>(writer)->get_log_entries();
-    ASSERT_TRUE(log_entries.size() >= 1);
-
-    auto entry = remove_date_from_log_entry(log_entries[1]);
-    ASSERT_EQ(_XPLATSTR("[info        ] unexpected response received from the server: 42\n"), entry);
-}
-
 void can_be_set_only_in_disconnected_state(std::function<void(connection_impl *)> callback, const char* expected_exception_message)
 void can_be_set_only_in_disconnected_state(std::function<void(connection_impl *)> callback, const char* expected_exception_message)
 {
 {
     auto websocket_client = create_test_websocket_client(
     auto websocket_client = create_test_websocket_client(
@@ -1299,7 +1212,7 @@ TEST(connection_impl_stop, ongoing_start_request_canceled_if_connection_stopped_
         auto response_body =
         auto response_body =
             url.path() == _XPLATSTR("/negotiate")
             url.path() == _XPLATSTR("/negotiate")
             ? _XPLATSTR("{ \"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
             ? _XPLATSTR("{ \"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
-              _XPLATSTR("\"availableTransports\" : [] }")
+              _XPLATSTR("\"availableTransports\" : [ { \"transport\": \"WebSockets\", \"transferFormats\": [ \"Text\", \"Binary\" ] } ] }")
             : _XPLATSTR("");
             : _XPLATSTR("");
 
 
         return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));
         return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));

+ 5 - 51
src/SignalR/clients/cpp/test/signalrclienttests/hub_connection_impl_tests.cpp

@@ -470,7 +470,7 @@ TEST(invoke, invoke_returns_value_returned_from_the_server)
     ASSERT_EQ(_XPLATSTR("\"abc\""), result.serialize());
     ASSERT_EQ(_XPLATSTR("\"abc\""), result.serialize());
 }
 }
 
 
-TEST(invoke, invoke_propagates_hub_errors_from_server_as_hub_exceptions)
+TEST(invoke, invoke_propagates_errors_from_server_as_hub_exceptions)
 {
 {
     auto callback_registered_event = std::make_shared<event>();
     auto callback_registered_event = std::make_shared<event>();
 
 
@@ -562,7 +562,7 @@ TEST(receive, logs_if_callback_for_given_id_not_found)
         std::string responses[]
         std::string responses[]
         {
         {
             "{ }\x1e",
             "{ }\x1e",
-            "{ \"type\": 3, \"invocationId\": \"0\" }\x1e"
+            "{ \"type\": 3, \"invocationId\": \"0\" }\x1e",
             "{}"
             "{}"
         };
         };
 
 
@@ -596,53 +596,7 @@ TEST(receive, logs_if_callback_for_given_id_not_found)
     ASSERT_EQ(_XPLATSTR("[info        ] no callback found for id: 0\n"), entry) << dump_vector(log_entries);
     ASSERT_EQ(_XPLATSTR("[info        ] no callback found for id: 0\n"), entry) << dump_vector(log_entries);
 }
 }
 
 
-// TODO Flaky until hub_connection.start waits for handshake response
-TEST(invoke, DISABLED_invoke_propagates_errors_from_server_as_exceptions)
-{
-   auto callback_registered_event = std::make_shared<event>();
-
-   int call_number = -1;
-   auto websocket_client = create_test_websocket_client(
-       /* receive function */ [call_number, callback_registered_event]()
-       mutable {
-       std::string responses[]
-       {
-           "{ }\x1e",
-           "{ \"type\": 3, \"invocationId\": \"0\", \"error\": \"Ooops\" }\x1e"
-           "{}"
-       };
-
-       call_number = std::min(call_number + 1, 2);
-
-       if (call_number > 0)
-       {
-           callback_registered_event->wait();
-       }
-
-       return pplx::task_from_result(responses[call_number]);
-   });
-
-   auto hub_connection = create_hub_connection(websocket_client);
-   try
-   {
-       hub_connection->start()
-           .then([hub_connection, callback_registered_event]()
-       {
-           auto t = hub_connection->invoke(_XPLATSTR("method"), json::value::array());
-           callback_registered_event->set();
-           return t;
-       }).get();
-
-       ASSERT_TRUE(false); // exception expected but not thrown
-   }
-   catch (const std::runtime_error& e)
-   {
-       ASSERT_STREQ("\"Ooops\"", e.what());
-   }
-}
-
-// TODO Flaky until hub_connection.start waits for handshake response
-TEST(invoke_void, DISABLED_invoke_creates_runtime_error)
+TEST(invoke_void, invoke_creates_runtime_error)
 {
 {
    auto callback_registered_event = std::make_shared<event>();
    auto callback_registered_event = std::make_shared<event>();
 
 
@@ -679,10 +633,10 @@ TEST(invoke_void, DISABLED_invoke_creates_runtime_error)
 
 
        ASSERT_TRUE(false); // exception expected but not thrown
        ASSERT_TRUE(false); // exception expected but not thrown
    }
    }
-   catch (const signalr_exception& e)
+   catch (const hub_exception & e)
    {
    {
        ASSERT_STREQ("\"Ooops\"", e.what());
        ASSERT_STREQ("\"Ooops\"", e.what());
-       ASSERT_TRUE(dynamic_cast<const hub_exception *>(&e) == nullptr);
+       ASSERT_FALSE(callback_registered_event->wait(0));
    }
    }
 }
 }
 
 

+ 14 - 8
src/SignalR/clients/cpp/test/signalrclienttests/request_sender_tests.cpp

@@ -13,8 +13,8 @@ using namespace signalr;
 
 
 TEST(request_sender_negotiate, request_created_with_correct_url)
 TEST(request_sender_negotiate, request_created_with_correct_url)
 {
 {
-    web::uri requested_url;
-    auto request_factory = test_web_request_factory([&requested_url](const web::uri &url) -> std::unique_ptr<web_request>
+    utility::string_t requested_url;
+    auto request_factory = test_web_request_factory([&requested_url](const utility::string_t& url) -> std::unique_ptr<web_request>
     {
     {
         utility::string_t response_body(
         utility::string_t response_body(
             _XPLATSTR("{ \"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
             _XPLATSTR("{ \"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
@@ -24,24 +24,30 @@ TEST(request_sender_negotiate, request_created_with_correct_url)
         return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));
         return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));
     });
     });
 
 
-    request_sender::negotiate(request_factory, web::uri{ _XPLATSTR("http://fake/signalr") }).get();
+    request_sender::negotiate(request_factory, _XPLATSTR("http://fake/signalr")).get();
 
 
-    ASSERT_EQ(web::uri(_XPLATSTR("http://fake/signalr/negotiate")), requested_url);
+    ASSERT_EQ(_XPLATSTR("http://fake/signalr/negotiate"), requested_url);
 }
 }
 
 
 TEST(request_sender_negotiate, negotiation_request_sent_and_response_serialized)
 TEST(request_sender_negotiate, negotiation_request_sent_and_response_serialized)
 {
 {
-    auto request_factory = test_web_request_factory([](const web::uri&) -> std::unique_ptr<web_request>
+    auto request_factory = test_web_request_factory([](const utility::string_t&) -> std::unique_ptr<web_request>
     {
     {
         utility::string_t response_body(
         utility::string_t response_body(
             _XPLATSTR("{\"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
             _XPLATSTR("{\"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", ")
-            _XPLATSTR("\"availableTransports\" : [] }"));
+            _XPLATSTR("\"availableTransports\" : [ { \"transport\": \"WebSockets\", \"transferFormats\": [ \"Text\", \"Binary\" ] },")
+            _XPLATSTR("{ \"transport\": \"ServerSentEvents\", \"transferFormats\": [ \"Text\" ] } ] }"));
 
 
         return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));
         return std::unique_ptr<web_request>(new web_request_stub((unsigned short)200, _XPLATSTR("OK"), response_body));
     });
     });
 
 
-    auto response = request_sender::negotiate(request_factory, web::uri{ _XPLATSTR("http://fake/signalr") }).get();
+    auto response = request_sender::negotiate(request_factory, _XPLATSTR("http://fake/signalr")).get();
 
 
     ASSERT_EQ(_XPLATSTR("f7707523-307d-4cba-9abf-3eef701241e8"), response.connectionId);
     ASSERT_EQ(_XPLATSTR("f7707523-307d-4cba-9abf-3eef701241e8"), response.connectionId);
-    // TODO: response.availableTransports
+    ASSERT_EQ(2u, response.availableTransports.size());
+    ASSERT_EQ(2u, response.availableTransports[0].transfer_formats.size());
+    ASSERT_EQ(_XPLATSTR("Text"), response.availableTransports[0].transfer_formats[0]);
+    ASSERT_EQ(_XPLATSTR("Binary"), response.availableTransports[0].transfer_formats[1]);
+    ASSERT_EQ(1u, response.availableTransports[1].transfer_formats.size());
+    ASSERT_EQ(_XPLATSTR("Text"), response.availableTransports[1].transfer_formats[0]);
 }
 }

+ 2 - 2
src/SignalR/clients/cpp/test/signalrclienttests/test_web_request_factory.cpp

@@ -6,11 +6,11 @@
 
 
 using namespace signalr;
 using namespace signalr;
 
 
-test_web_request_factory::test_web_request_factory(std::function<std::unique_ptr<web_request>(const web::uri &url)> create_web_request_fn)
+test_web_request_factory::test_web_request_factory(std::function<std::unique_ptr<web_request>(const utility::string_t& url)> create_web_request_fn)
     : m_create_web_request_fn(create_web_request_fn)
     : m_create_web_request_fn(create_web_request_fn)
 { }
 { }
 
 
-std::unique_ptr<web_request> test_web_request_factory::create_web_request(const web::uri &url)
+std::unique_ptr<web_request> test_web_request_factory::create_web_request(const utility::string_t& url)
 {
 {
     return m_create_web_request_fn(url);
     return m_create_web_request_fn(url);
 }
 }

+ 3 - 3
src/SignalR/clients/cpp/test/signalrclienttests/test_web_request_factory.h

@@ -11,10 +11,10 @@ using namespace signalr;
 class test_web_request_factory : public web_request_factory
 class test_web_request_factory : public web_request_factory
 {
 {
 public:
 public:
-    explicit test_web_request_factory(std::function<std::unique_ptr<web_request>(const web::uri &url)> create_web_request_fn);
+    explicit test_web_request_factory(std::function<std::unique_ptr<web_request>(const utility::string_t& url)> create_web_request_fn);
 
 
-    virtual std::unique_ptr<web_request> create_web_request(const web::uri &url) override;
+    virtual std::unique_ptr<web_request> create_web_request(const utility::string_t& url) override;
 
 
 private:
 private:
-    std::function<std::unique_ptr<web_request>(const web::uri &url)> m_create_web_request_fn;
+    std::function<std::unique_ptr<web_request>(const utility::string_t& url)> m_create_web_request_fn;
 };
 };

+ 6 - 6
src/SignalR/clients/cpp/test/signalrclienttests/url_builder_tests.cpp

@@ -9,20 +9,20 @@ using namespace signalr;
 TEST(url_builder_negotiate, url_correct_if_query_string_empty)
 TEST(url_builder_negotiate, url_correct_if_query_string_empty)
 {
 {
     ASSERT_EQ(
     ASSERT_EQ(
-        web::uri(_XPLATSTR("http://fake/negotiate")),
-        url_builder::build_negotiate(web::uri{ _XPLATSTR("http://fake/") }));
+        _XPLATSTR("http://fake/negotiate"),
+        url_builder::build_negotiate(_XPLATSTR("http://fake/")));
 }
 }
 
 
 TEST(url_builder_negotiate, url_correct_if_query_string_not_empty)
 TEST(url_builder_negotiate, url_correct_if_query_string_not_empty)
 {
 {
     ASSERT_EQ(
     ASSERT_EQ(
-        web::uri(_XPLATSTR("http://fake/negotiate?q1=1&q2=2")),
-        url_builder::build_negotiate(web::uri{ _XPLATSTR("http://fake/?q1=1&q2=2") }));
+        _XPLATSTR("http://fake/negotiate?q1=1&q2=2"),
+        url_builder::build_negotiate(_XPLATSTR("http://fake/?q1=1&q2=2")));
 }
 }
 
 
 TEST(url_builder_connect_webSockets, url_correct_if_query_string_not_empty)
 TEST(url_builder_connect_webSockets, url_correct_if_query_string_not_empty)
 {
 {
     ASSERT_EQ(
     ASSERT_EQ(
-        web::uri(_XPLATSTR("ws://fake/?q1=1&q2=2")),
-        url_builder::build_connect(web::uri{ _XPLATSTR("http://fake/") }, transport_type::websockets, _XPLATSTR("q1=1&q2=2")));
+        _XPLATSTR("ws://fake/?q1=1&q2=2"),
+        url_builder::build_connect(_XPLATSTR("http://fake/"), transport_type::websockets, _XPLATSTR("q1=1&q2=2")));
 }
 }

+ 2 - 2
src/SignalR/clients/cpp/test/signalrclienttests/web_request_stub.cpp

@@ -5,7 +5,7 @@
 #include "web_request_stub.h"
 #include "web_request_stub.h"
 
 
 web_request_stub::web_request_stub(unsigned short status_code, const utility::string_t& reason_phrase, const utility::string_t& response_body)
 web_request_stub::web_request_stub(unsigned short status_code, const utility::string_t& reason_phrase, const utility::string_t& response_body)
-    : web_request(web::uri(_XPLATSTR(""))), m_status_code(status_code), m_reason_phrase(reason_phrase), m_response_body(response_body)
+    : web_request(_XPLATSTR("")), m_status_code(status_code), m_reason_phrase(reason_phrase), m_response_body(response_body)
 { }
 { }
 
 
 void web_request_stub::set_method(const utility::string_t &method)
 void web_request_stub::set_method(const utility::string_t &method)
@@ -29,4 +29,4 @@ pplx::task<web_response> web_request_stub::get_response()
 
 
     return pplx::task_from_result<web_response>(
     return pplx::task_from_result<web_response>(
         web_response{ m_status_code, m_reason_phrase, pplx::task_from_result<utility::string_t>(m_response_body) });
         web_response{ m_status_code, m_reason_phrase, pplx::task_from_result<utility::string_t>(m_response_body) });
-}
+}

+ 2 - 2
src/SignalR/clients/cpp/test/signalrclienttests/web_request_tests.cpp

@@ -10,7 +10,7 @@ using namespace signalr;
 
 
 TEST(web_request_get_response, DISABLED_sends_request_receives_response)
 TEST(web_request_get_response, DISABLED_sends_request_receives_response)
 {
 {
-    web::uri url(_XPLATSTR("http://localhost:56000/web_request_test"));
+    utility::string_t url(_XPLATSTR("http://localhost:56000/web_request_test"));
     auto request_received = false;
     auto request_received = false;
     utility::string_t user_agent_string;
     utility::string_t user_agent_string;
 
 
@@ -41,4 +41,4 @@ TEST(web_request_get_response, DISABLED_sends_request_receives_response)
 
 
     ASSERT_TRUE(request_received);
     ASSERT_TRUE(request_received);
     ASSERT_EQ(_XPLATSTR("007"), user_agent_string);
     ASSERT_EQ(_XPLATSTR("007"), user_agent_string);
-}
+}

+ 8 - 4
src/SignalR/clients/cpp/test/signalrclienttests/websocket_transport_tests.cpp

@@ -97,8 +97,7 @@ TEST(websocket_transport_connect, connect_logs_exceptions)
         entry);
         entry);
 }
 }
 
 
-// Flaky test: crashes test process
-TEST(websocket_transport_connect, DISABLED_cannot_call_connect_on_already_connected_transport)
+TEST(websocket_transport_connect, cannot_call_connect_on_already_connected_transport)
 {
 {
     auto client = std::make_shared<test_websocket_client>();
     auto client = std::make_shared<test_websocket_client>();
     auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none),
     auto ws_transport = websocket_transport::create([&](){ return client; }, logger(std::make_shared<trace_log_writer>(), trace_level::none),
@@ -237,9 +236,10 @@ TEST(websocket_transport_disconnect, receive_not_called_after_disconnect)
     auto client = std::make_shared<test_websocket_client>();
     auto client = std::make_shared<test_websocket_client>();
 
 
     pplx::task_completion_event<std::string> receive_task_tce;
     pplx::task_completion_event<std::string> receive_task_tce;
+    pplx::task_completion_event<void> receive_task_started_tce;
 
 
     // receive_task_tce is captured by reference since we assign it a new value after the first disconnect. This is
     // receive_task_tce is captured by reference since we assign it a new value after the first disconnect. This is
-    // safe here because we are blocking on disconnect and therefore we won't get into a state were we would be using
+    // safe here because we are blocking on disconnect and therefore we won't get into a state where we would be using
     // an invalid reference because the tce went out of scope and was destroyed.
     // an invalid reference because the tce went out of scope and was destroyed.
     client->set_close_function([&receive_task_tce]()
     client->set_close_function([&receive_task_tce]()
     {
     {
@@ -250,9 +250,10 @@ TEST(websocket_transport_disconnect, receive_not_called_after_disconnect)
 
 
     int num_called = 0;
     int num_called = 0;
 
 
-    client->set_receive_function([&receive_task_tce, &num_called]() -> pplx::task<std::string>
+    client->set_receive_function([&receive_task_tce, &receive_task_started_tce, &num_called]() -> pplx::task<std::string>
     {
     {
         num_called++;
         num_called++;
+        receive_task_started_tce.set();
         return pplx::create_task(receive_task_tce);
         return pplx::create_task(receive_task_tce);
     });
     });
 
 
@@ -260,10 +261,13 @@ TEST(websocket_transport_disconnect, receive_not_called_after_disconnect)
         [](const utility::string_t&){}, [](const std::exception&){});
         [](const utility::string_t&){}, [](const std::exception&){});
 
 
     ws_transport->connect(_XPLATSTR("ws://fakeuri.org")).get();
     ws_transport->connect(_XPLATSTR("ws://fakeuri.org")).get();
+    pplx::create_task(receive_task_started_tce).get();
     ws_transport->disconnect().get();
     ws_transport->disconnect().get();
 
 
     receive_task_tce = pplx::task_completion_event<std::string>();
     receive_task_tce = pplx::task_completion_event<std::string>();
+    receive_task_started_tce = pplx::task_completion_event<void>();
     ws_transport->connect(_XPLATSTR("ws://fakeuri.org")).get();
     ws_transport->connect(_XPLATSTR("ws://fakeuri.org")).get();
+    pplx::create_task(receive_task_started_tce).get();
     ws_transport->disconnect().get();
     ws_transport->disconnect().get();
 
 
     ASSERT_EQ(2, num_called);
     ASSERT_EQ(2, num_called);