TooSensitive - making comparison of hub and hub function names case insensitive
This commit is contained in:
Родитель
6ae3f6b52a
Коммит
bc71c05d73
|
@ -38,6 +38,7 @@
|
|||
<ClInclude Include="..\..\..\..\include\signalrclient\transport_type.h" />
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\web_exception.h" />
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\_exports.h" />
|
||||
<ClInclude Include="..\..\case_insensitive_comparison_utils.h" />
|
||||
<ClInclude Include="..\..\connection_impl.h" />
|
||||
<ClInclude Include="..\..\constants.h" />
|
||||
<ClInclude Include="..\..\default_websocket_client.h" />
|
||||
|
@ -49,7 +50,7 @@
|
|||
<ClInclude Include="..\..\negotiation_response.h" />
|
||||
<ClInclude Include="..\..\request_sender.h" />
|
||||
<ClInclude Include="..\..\stdafx.h" />
|
||||
<ClInclude Include="..\..\trace_log_writer.h" />
|
||||
<ClInclude Include="..\..\trace_log_writer.h" />
|
||||
<ClInclude Include="..\..\transport.h" />
|
||||
<ClInclude Include="..\..\transport_factory.h" />
|
||||
<ClInclude Include="..\..\url_builder.h" />
|
||||
|
|
|
@ -105,6 +105,9 @@
|
|||
<ClInclude Include="..\..\..\..\include\signalrclient\hub_proxy.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\case_insensitive_comparison_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\stdafx.cpp">
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include "cpprest\details\basic_types.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
// Note: These functions are not pretending to be all-purpose helpers for case insensitive string comparison. Rather
|
||||
// we use them to compare hub and hub method names which are expected to be almost exclusively ASCII and this is the
|
||||
// simplest thing that would work without having to take dependencies on third party libraries.
|
||||
struct case_insensitive_equals : std::binary_function<utility::string_t, utility::string_t, bool>
|
||||
{
|
||||
bool operator()(const utility::string_t& s1, const utility::string_t& s2) const
|
||||
{
|
||||
if (s1.length() != s2.length())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto s1_iterator = s1.begin(), s2_iterator = s2.begin(); s1_iterator != s1.end(); ++s1_iterator, ++s2_iterator)
|
||||
{
|
||||
if (std::toupper(*s1_iterator) != std::toupper(*s2_iterator))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct case_insensitive_hash : std::unary_function<utility::string_t, std::size_t>
|
||||
{
|
||||
std::size_t operator()(const utility::string_t& s) const
|
||||
{
|
||||
size_t hash = 0;
|
||||
std::hash<size_t> hasher;
|
||||
for (const utility::char_t& c : s)
|
||||
{
|
||||
hash ^= hasher(std::toupper(c)) + (hash << 5) + (hash >> 2);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
#include "connection_impl.h"
|
||||
#include "internal_hub_proxy.h"
|
||||
#include "callback_manager.h"
|
||||
#include "case_insensitive_comparison_utils.h"
|
||||
|
||||
namespace signalr
|
||||
{
|
||||
|
@ -54,7 +55,7 @@ namespace signalr
|
|||
logger m_logger;
|
||||
|
||||
std::shared_ptr<connection_impl> m_connection;
|
||||
std::unordered_map<utility::string_t, std::shared_ptr<internal_hub_proxy>> m_proxies;
|
||||
std::unordered_map<utility::string_t, std::shared_ptr<internal_hub_proxy>, case_insensitive_hash, case_insensitive_equals> m_proxies;
|
||||
callback_manager m_callback_manager;
|
||||
|
||||
void initialize();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "cpprest\details\basic_types.h"
|
||||
#include "cpprest\json.h"
|
||||
#include "logger.h"
|
||||
#include "case_insensitive_comparison_utils.h"
|
||||
|
||||
using namespace web;
|
||||
|
||||
|
@ -36,6 +37,6 @@ namespace signalr
|
|||
const utility::string_t m_hub_name;
|
||||
logger m_logger;
|
||||
|
||||
std::unordered_map<utility::string_t, std::function<void(const json::value &)>> m_subscriptions;
|
||||
std::unordered_map<utility::string_t, std::function<void(const json::value &)>, case_insensitive_hash, case_insensitive_equals> m_subscriptions;
|
||||
};
|
||||
}
|
|
@ -38,6 +38,7 @@
|
|||
<ClInclude Include="..\..\..\..\include\signalrclient\transport_type.h" />
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\web_exception.h" />
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\_exports.h" />
|
||||
<ClInclude Include="..\..\..\signalrclient\case_insensitive_comparison_utils.h" />
|
||||
<ClInclude Include="..\..\..\signalrclient\connection_impl.h" />
|
||||
<ClInclude Include="..\..\..\signalrclient\constants.h" />
|
||||
<ClInclude Include="..\..\..\signalrclient\default_websocket_client.h" />
|
||||
|
|
|
@ -45,9 +45,6 @@
|
|||
<ClInclude Include="..\..\..\signalrclient\request_sender.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\signalrclient\trace_level.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\signalrclient\transport.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -87,9 +84,6 @@
|
|||
<ClInclude Include="..\..\..\..\include\signalrclient\log_writer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\trace_log_writer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\transport_type.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -105,6 +99,15 @@
|
|||
<ClInclude Include="..\..\..\..\include\signalrclient\hub_proxy.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\include\signalrclient\trace_level.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\signalrclient\trace_log_writer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\signalrclient\case_insensitive_comparison_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\dllmain.cpp">
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\callback_manager_tests.cpp" />
|
||||
<ClCompile Include="..\..\case_insensitive_comparison_utils_tests.cpp" />
|
||||
<ClCompile Include="..\..\connection_impl_tests.cpp" />
|
||||
<ClCompile Include="..\..\http_sender_tests.cpp" />
|
||||
<ClCompile Include="..\..\hub_connection_impl_tests.cpp" />
|
||||
|
|
|
@ -98,6 +98,9 @@
|
|||
<ClCompile Include="..\..\hub_exception_tests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\case_insensitive_comparison_utils_tests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "case_insensitive_comparison_utils.h"
|
||||
|
||||
using namespace signalr;
|
||||
|
||||
TEST(case_insensitive_equals_functor, basic_comparison_tests)
|
||||
{
|
||||
case_insensitive_equals case_insensitive_compare;
|
||||
|
||||
ASSERT_TRUE(case_insensitive_compare(_XPLATSTR(""), _XPLATSTR("")));
|
||||
ASSERT_TRUE(case_insensitive_compare(_XPLATSTR("abc"), _XPLATSTR("ABC")));
|
||||
ASSERT_TRUE(case_insensitive_compare(_XPLATSTR("abc123!@"), _XPLATSTR("ABC123!@")));
|
||||
|
||||
ASSERT_FALSE(case_insensitive_compare(_XPLATSTR("abc"), _XPLATSTR("ABCD")));
|
||||
ASSERT_FALSE(case_insensitive_compare(_XPLATSTR("abce"), _XPLATSTR("ABCD")));
|
||||
}
|
||||
|
||||
TEST(case_insensitive_hash_functor, basic_hash_tests)
|
||||
{
|
||||
case_insensitive_hash case_insensitive_hasher;
|
||||
|
||||
ASSERT_EQ(0, case_insensitive_hasher(_XPLATSTR("")));
|
||||
|
||||
ASSERT_EQ(case_insensitive_hasher(_XPLATSTR("abc")), case_insensitive_hasher(_XPLATSTR("ABC")));
|
||||
ASSERT_EQ(case_insensitive_hasher(_XPLATSTR("abc123!@")), case_insensitive_hasher(_XPLATSTR("ABC123!@")));
|
||||
ASSERT_NE(case_insensitive_hasher(_XPLATSTR("abcd")), case_insensitive_hasher(_XPLATSTR("ABC")));
|
||||
}
|
|
@ -85,8 +85,10 @@ TEST(create_hub_proxy, create_hub_proxy_returns_existing_proxies_if_possible)
|
|||
auto hub_connection = create_hub_connection();
|
||||
auto hub_proxy_1 = hub_connection->create_hub_proxy(_XPLATSTR("my_hub_proxy"));
|
||||
auto hub_proxy_2 = hub_connection->create_hub_proxy(_XPLATSTR("my_hub_proxy"));
|
||||
auto hub_proxy_3 = hub_connection->create_hub_proxy(_XPLATSTR("My_Hub_Proxy"));
|
||||
|
||||
ASSERT_EQ(hub_proxy_1.get(), hub_proxy_2.get());
|
||||
ASSERT_EQ(hub_proxy_2.get(), hub_proxy_3.get());
|
||||
}
|
||||
|
||||
TEST(create_hub_proxy, cannot_create_proxy_with_empty_name)
|
||||
|
@ -319,7 +321,7 @@ TEST(hub_invocation, hub_connection_invokes_users_code_on_hub_invocations)
|
|||
std::string responses[]
|
||||
{
|
||||
"{ \"C\":\"x\", \"S\":1, \"M\":[] }",
|
||||
"{ \"C\":\"d- F430FB19\", \"M\" : [{\"H\":\"my_hub\", \"M\":\"broadcast\", \"A\" : [\"message\", 1]}] }",
|
||||
"{ \"C\":\"d- F430FB19\", \"M\" : [{\"H\":\"my_HUB\", \"M\":\"BROADcast\", \"A\" : [\"message\", 1]}] }",
|
||||
"{}"
|
||||
};
|
||||
|
||||
|
@ -329,11 +331,11 @@ TEST(hub_invocation, hub_connection_invokes_users_code_on_hub_invocations)
|
|||
});
|
||||
|
||||
auto hub_connection = create_hub_connection(websocket_client);
|
||||
auto hub_proxy = hub_connection->create_hub_proxy(_XPLATSTR("my_hub"));
|
||||
auto hub_proxy = hub_connection->create_hub_proxy(_XPLATSTR("MY_hub"));
|
||||
|
||||
auto payload = std::make_shared<utility::string_t>();
|
||||
auto on_broadcast_event = std::make_shared<pplx::event>();
|
||||
hub_proxy->on(_XPLATSTR("broadcast"), [on_broadcast_event, payload](const json::value& message)
|
||||
hub_proxy->on(_XPLATSTR("broadCAST"), [on_broadcast_event, payload](const json::value& message)
|
||||
{
|
||||
*payload = message.serialize();
|
||||
on_broadcast_event->set();
|
||||
|
|
|
@ -337,7 +337,7 @@ TEST(websocket_transport_disconnect, exceptions_from_outstanding_receive_task_ob
|
|||
receive_event->set();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<typename T>
|
||||
void receive_loop_logs_exception_runner(const T& e, const utility::string_t& expected_message, trace_level trace_level);
|
||||
|
||||
TEST(websocket_transport_receive_loop, receive_loop_logs_websocket_exceptions)
|
||||
|
@ -364,7 +364,7 @@ TEST(websocket_transport_receive_loop, receive_loop_logs_std_exception)
|
|||
trace_level::errors);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<typename T>
|
||||
void receive_loop_logs_exception_runner(const T& e, const utility::string_t& expected_message, trace_level trace_level)
|
||||
{
|
||||
pplx::event receive_event;
|
||||
|
|
Загрузка…
Ссылка в новой задаче