From 910685d157ec09a78df4499829aa2b4c7815a263 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 00:07:19 -0700 Subject: [PATCH 01/13] Prototype mockable MessageQueueThread and JSExecutor --- .../Desktop.UnitTests/WebSocketModuleTest.cpp | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index cced3d4ab59..2205b3eff69 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -4,12 +4,144 @@ #include #include +// TODO: Move out +#include +#include +#include +#include +#include +#include + using namespace facebook::react; using namespace facebook::xplat::module; using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace Microsoft::React::Test { +class MockMessageQueueThread : public MessageQueueThread { + public: +#pragma region MessageQueueThread overrides + + void runOnQueue(std::function &&) override; + + void runOnQueueSync(std::function &&) override; + + void quitSynchronous() override; + +#pragma endregion // MessageQueueThread overrides +}; + +class MockInstanceCallback : public InstanceCallback { + public: +#pragma region InstanceCallback overrides + + void onBatchComplete() override; + void incrementPendingJSCalls() override; + void decrementPendingJSCalls() override; + +#pragma endregion // InstanceCallback overrides +}; + +class MockJSExecutor : public JSExecutor { + public: +#pragma region JSExecutor overrides + + void loadApplicationScript(std::unique_ptr script, std::string sourceURL) override; + + void setBundleRegistry(std::unique_ptr bundleRegistry) override; + + void registerBundle(uint32_t bundleId, const std::string &bundlePath) override; + + void callFunction(const std::string &moduleId, const std::string &methodId, const folly::dynamic &arguments) override; + + void invokeCallback(const double callbackId, const folly::dynamic &arguments) override; + + void setGlobalVariable(std::string propName, std::unique_ptr jsonValue) override; + + void *getJavaScriptContext() override; + + bool isInspectable() override; + + std::string getDescription() override; + + void handleMemoryPressure(__unused int pressureLevel) override; + + void destroy() override; + + void flush() override; + +#pragma endregion // JSExecutor overrides +}; + +class MockJSExecutorFactory : public JSExecutorFactory { +#pragma region JSExecutorFactory overrides + public: + std::unique_ptr createJSExecutor( + std::shared_ptr delegate, + std::shared_ptr jsQueue) override; + +#pragma endregion // JSExecutorFactory overrides +}; + +#pragma region Move + +// MockMessageQueueThread +using std::function; + +void MockMessageQueueThread::runOnQueue(function &&) /*override*/ {} +void MockMessageQueueThread::runOnQueueSync(function &&work) /*override*/ +{ + work(); +} + +void MockMessageQueueThread::quitSynchronous() /*override*/ {} + +// MockInstanceCallback +void MockInstanceCallback::onBatchComplete() /*override*/ {} +void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {} +void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {} + +// MockJSExecutor +void MockJSExecutor::loadApplicationScript(std::unique_ptr script, std::string sourceURL) {} +void MockJSExecutor::setBundleRegistry(std::unique_ptr bundleRegistry) {} +void MockJSExecutor::registerBundle(uint32_t bundleId, const std::string &bundlePath) {} +void MockJSExecutor::callFunction( + const std::string &moduleId, + const std::string &methodId, + const folly::dynamic &arguments) {} +void MockJSExecutor::invokeCallback(const double callbackId, const folly::dynamic &arguments) {} +void MockJSExecutor::setGlobalVariable(std::string propName, std::unique_ptr jsonValue) {} +void *MockJSExecutor::getJavaScriptContext() { + return nullptr; +} + +bool MockJSExecutor::isInspectable() { + return false; +} +std::string MockJSExecutor::getDescription() { + return {}; +} +void MockJSExecutor::handleMemoryPressure(__unused int pressureLevel) {} +void MockJSExecutor::destroy() {} +void MockJSExecutor::flush() {} + +// MockJSExecutorFactory + +using std::make_shared; +using std::make_unique; +using std::shared_ptr; +using std::unique_ptr; + +unique_ptr MockJSExecutorFactory::createJSExecutor( + shared_ptr delegate, + shared_ptr jsQueue) /*override*/ +{ + std::vector> modules{}; + return make_unique(); +} + +#pragma endregion // Move + TEST_CLASS (WebSocketModuleTest) { enum class MethodId : size_t { Connect = 0, Close = 1, Send = 2, SendBinary = 3, Ping = 4, SIZE = 5 }; @@ -28,6 +160,24 @@ TEST_CLASS (WebSocketModuleTest) { Assert::AreEqual(static_cast(0), module->getConstants().size()); } + + TEST_METHOD(WebSocketModuleDummyRemove) { + auto instance = std::make_shared(); + auto callback = std::make_unique(); + auto jsef = std::make_shared(); + auto jsQueue = std::make_shared(); + auto moduleRegistry = std::make_shared( + std::vector>(), // modules + nullptr // moduleNotFoundCallback + ); + + instance->initializeBridge( + std::move(callback), // callback + jsef, // jsef + jsQueue, // jsQueue + moduleRegistry // moduleRegistry + ); + } }; } // namespace Microsoft::React::Test From 6c8f67005e17b5cf338192ad009f67e3102f6873 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 01:06:14 -0700 Subject: [PATCH 02/13] Declare MockJSExecutor::CallFunctionFunctor --- .../Desktop.UnitTests/WebSocketModuleTest.cpp | 88 +++++++++++++------ 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 2205b3eff69..18ef695b5a9 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -44,6 +44,8 @@ class MockInstanceCallback : public InstanceCallback { class MockJSExecutor : public JSExecutor { public: + std::function CallFunctionFunctor; + #pragma region JSExecutor overrides void loadApplicationScript(std::unique_ptr script, std::string sourceURL) override; @@ -74,8 +76,12 @@ class MockJSExecutor : public JSExecutor { }; class MockJSExecutorFactory : public JSExecutorFactory { -#pragma region JSExecutorFactory overrides public: + std::function(std::shared_ptr, std::shared_ptr)> + CreateJSExecutorFunction; + +#pragma region JSExecutorFactory overrides + std::unique_ptr createJSExecutor( std::shared_ptr delegate, std::shared_ptr jsQueue) override; @@ -86,7 +92,9 @@ class MockJSExecutorFactory : public JSExecutorFactory { #pragma region Move // MockMessageQueueThread +using folly::dynamic; using std::function; +using std::string; void MockMessageQueueThread::runOnQueue(function &&) /*override*/ {} void MockMessageQueueThread::runOnQueueSync(function &&work) /*override*/ @@ -102,15 +110,18 @@ void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {} void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {} // MockJSExecutor -void MockJSExecutor::loadApplicationScript(std::unique_ptr script, std::string sourceURL) {} -void MockJSExecutor::setBundleRegistry(std::unique_ptr bundleRegistry) {} -void MockJSExecutor::registerBundle(uint32_t bundleId, const std::string &bundlePath) {} -void MockJSExecutor::callFunction( - const std::string &moduleId, - const std::string &methodId, - const folly::dynamic &arguments) {} -void MockJSExecutor::invokeCallback(const double callbackId, const folly::dynamic &arguments) {} -void MockJSExecutor::setGlobalVariable(std::string propName, std::unique_ptr jsonValue) {} +void MockJSExecutor::loadApplicationScript(unique_ptr script, string sourceURL) {} +void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegistry) {} +void MockJSExecutor::registerBundle(uint32_t bundleId, const string &bundlePath) {} + +void MockJSExecutor::callFunction(const string &moduleId, const string &methodId, const dynamic &arguments) { + if (CallFunctionFunctor) { + CallFunctionFunctor(moduleId, methodId, arguments); + } +} + +void MockJSExecutor::invokeCallback(const double callbackId, const dynamic &arguments) {} +void MockJSExecutor::setGlobalVariable(string propName, unique_ptr jsonValue) {} void *MockJSExecutor::getJavaScriptContext() { return nullptr; } @@ -131,15 +142,35 @@ using std::make_shared; using std::make_unique; using std::shared_ptr; using std::unique_ptr; +using std::vector; unique_ptr MockJSExecutorFactory::createJSExecutor( shared_ptr delegate, shared_ptr jsQueue) /*override*/ { - std::vector> modules{}; + if (CreateJSExecutorFunction) { + return CreateJSExecutorFunction(delegate, jsQueue); + } + return make_unique(); } +// MockInstance.cpp ? + +shared_ptr CreateMockInstance(shared_ptr jsef) { + auto instance = make_shared(); + auto callback = make_unique(); + auto jsQueue = make_shared(); + auto moduleRegistry = make_shared( + vector>(), // modules + nullptr // moduleNotFoundCallback + ); + + instance->initializeBridge(std::move(callback), jsef, jsQueue, moduleRegistry); + + return instance; +} + #pragma endregion // Move TEST_CLASS (WebSocketModuleTest) { @@ -148,35 +179,34 @@ TEST_CLASS (WebSocketModuleTest) { const char *MethodName[static_cast(MethodId::SIZE)]{"connect", "close", "send", "sendBinary", "ping"}; TEST_METHOD(WebSocketModuleTest_CreateModule) { - auto module = std::make_unique(); + auto module = make_unique(); Assert::IsFalse(module == nullptr); - Assert::AreEqual(std::string("WebSocketModule"), module->getName()); + Assert::AreEqual(string("WebSocketModule"), module->getName()); auto methods = module->getMethods(); for (size_t i = 0; i < static_cast(MethodId::SIZE); i++) { - Assert::AreEqual(std::string(MethodName[i]), std::string(methods[i].name)); + Assert::AreEqual(string(MethodName[i]), string(methods[i].name)); } Assert::AreEqual(static_cast(0), module->getConstants().size()); } TEST_METHOD(WebSocketModuleDummyRemove) { - auto instance = std::make_shared(); - auto callback = std::make_unique(); - auto jsef = std::make_shared(); - auto jsQueue = std::make_shared(); - auto moduleRegistry = std::make_shared( - std::vector>(), // modules - nullptr // moduleNotFoundCallback - ); - - instance->initializeBridge( - std::move(callback), // callback - jsef, // jsef - jsQueue, // jsQueue - moduleRegistry // moduleRegistry - ); + auto jsef = make_shared(); + auto instance = CreateMockInstance(jsef); + + jsef->CreateJSExecutorFunction = [](shared_ptr, shared_ptr) { + auto jse = make_unique(); + jse->CallFunctionFunctor = [](const string &, const string &, const dynamic &) { + // TODO: Handle callFunction + }; + + return std::move(jse); + }; + + auto module = make_unique(); + // TODO: Mock member WebSocket resource. } }; From ec9052d94e8ede5a8cca769c6d91ef6d151cbb46 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 01:13:17 -0700 Subject: [PATCH 03/13] Add missing using std::unique_ptr --- vnext/Desktop.UnitTests/WebSocketModuleTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 18ef695b5a9..d6f894d4c1b 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -95,6 +95,7 @@ class MockJSExecutorFactory : public JSExecutorFactory { using folly::dynamic; using std::function; using std::string; +using std::unique_ptr; void MockMessageQueueThread::runOnQueue(function &&) /*override*/ {} void MockMessageQueueThread::runOnQueueSync(function &&work) /*override*/ From 53a9cf135449fed4e59f1c60c2ecb7e29da35844 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 01:19:22 -0700 Subject: [PATCH 04/13] Use WebSocketModule::MethodId --- vnext/Desktop.UnitTests/WebSocketModuleTest.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index d6f894d4c1b..d53d49c267b 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -175,10 +175,8 @@ shared_ptr CreateMockInstance(shared_ptr jsef) { #pragma endregion // Move TEST_CLASS (WebSocketModuleTest) { - enum class MethodId : size_t { Connect = 0, Close = 1, Send = 2, SendBinary = 3, Ping = 4, SIZE = 5 }; - - const char *MethodName[static_cast(MethodId::SIZE)]{"connect", "close", "send", "sendBinary", "ping"}; + const char *MethodName[static_cast(WebSocketModule::MethodId::SIZE)]{"connect", "close", "send", "sendBinary", "ping"}; TEST_METHOD(WebSocketModuleTest_CreateModule) { auto module = make_unique(); @@ -186,7 +184,7 @@ TEST_CLASS (WebSocketModuleTest) { Assert::AreEqual(string("WebSocketModule"), module->getName()); auto methods = module->getMethods(); - for (size_t i = 0; i < static_cast(MethodId::SIZE); i++) { + for (size_t i = 0; i < static_cast(WebSocketModule::MethodId::SIZE); i++) { Assert::AreEqual(string(MethodName[i]), string(methods[i].name)); } From 9bde51132879702b2ee1f3a35365ccf95166abcd Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 01:19:37 -0700 Subject: [PATCH 05/13] clang format --- vnext/Desktop.UnitTests/WebSocketModuleTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index d53d49c267b..543c5108d7f 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -175,8 +175,8 @@ shared_ptr CreateMockInstance(shared_ptr jsef) { #pragma endregion // Move TEST_CLASS (WebSocketModuleTest) { - - const char *MethodName[static_cast(WebSocketModule::MethodId::SIZE)]{"connect", "close", "send", "sendBinary", "ping"}; + const char *MethodName[static_cast(WebSocketModule::MethodId::SIZE)]{ + "connect", "close", "send", "sendBinary", "ping"}; TEST_METHOD(WebSocketModuleTest_CreateModule) { auto module = make_unique(); From 8cb4413142eac992278f90eee0b243ad589b12ad Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 14:09:03 -0700 Subject: [PATCH 06/13] Make WebSocketModule methods override instead of virtual. --- .../Desktop.UnitTests/WebSocketModuleTest.cpp | 20 +++++++++---------- .../Modules/WebSocketModule.h | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 543c5108d7f..6bae3ef5350 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -44,7 +44,7 @@ class MockInstanceCallback : public InstanceCallback { class MockJSExecutor : public JSExecutor { public: - std::function CallFunctionFunctor; + std::function CallFunctionImpl; #pragma region JSExecutor overrides @@ -78,7 +78,7 @@ class MockJSExecutor : public JSExecutor { class MockJSExecutorFactory : public JSExecutorFactory { public: std::function(std::shared_ptr, std::shared_ptr)> - CreateJSExecutorFunction; + CreateJSExecutorImpl; #pragma region JSExecutorFactory overrides @@ -116,8 +116,8 @@ void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegis void MockJSExecutor::registerBundle(uint32_t bundleId, const string &bundlePath) {} void MockJSExecutor::callFunction(const string &moduleId, const string &methodId, const dynamic &arguments) { - if (CallFunctionFunctor) { - CallFunctionFunctor(moduleId, methodId, arguments); + if (CallFunctionImpl) { + CallFunctionImpl(moduleId, methodId, arguments); } } @@ -149,8 +149,8 @@ unique_ptr MockJSExecutorFactory::createJSExecutor( shared_ptr delegate, shared_ptr jsQueue) /*override*/ { - if (CreateJSExecutorFunction) { - return CreateJSExecutorFunction(delegate, jsQueue); + if (CreateJSExecutorImpl) { + return CreateJSExecutorImpl(delegate, jsQueue); } return make_unique(); @@ -177,7 +177,7 @@ shared_ptr CreateMockInstance(shared_ptr jsef) { TEST_CLASS (WebSocketModuleTest) { const char *MethodName[static_cast(WebSocketModule::MethodId::SIZE)]{ "connect", "close", "send", "sendBinary", "ping"}; - TEST_METHOD(WebSocketModuleTest_CreateModule) { + TEST_METHOD(CreateModule) { auto module = make_unique(); Assert::IsFalse(module == nullptr); @@ -191,13 +191,13 @@ TEST_CLASS (WebSocketModuleTest) { Assert::AreEqual(static_cast(0), module->getConstants().size()); } - TEST_METHOD(WebSocketModuleDummyRemove) { + TEST_METHOD(ConnectSucceeds) { auto jsef = make_shared(); auto instance = CreateMockInstance(jsef); - jsef->CreateJSExecutorFunction = [](shared_ptr, shared_ptr) { + jsef->CreateJSExecutorImpl = [](shared_ptr, shared_ptr) { auto jse = make_unique(); - jse->CallFunctionFunctor = [](const string &, const string &, const dynamic &) { + jse->CallFunctionImpl = [](const string &, const string &, const dynamic &) { // TODO: Handle callFunction }; diff --git a/vnext/ReactWindowsCore/Modules/WebSocketModule.h b/vnext/ReactWindowsCore/Modules/WebSocketModule.h index bc2e4ca3fef..1f13d917324 100644 --- a/vnext/ReactWindowsCore/Modules/WebSocketModule.h +++ b/vnext/ReactWindowsCore/Modules/WebSocketModule.h @@ -21,18 +21,18 @@ class WebSocketModule : public facebook::xplat::module::CxxModule { /// /// /// - std::string getName(); + std::string getName() override; /// /// /// - virtual std::map getConstants(); + std::map getConstants() override; /// /// /// /// See See react-native/Libraries/WebSocket/WebSocket.js - virtual std::vector getMethods(); + std::vector getMethods() override; private: /// From aa9ddc5974c9ea509937ddc30935093314ebbc12 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 19:48:59 -0700 Subject: [PATCH 07/13] Allow WebSocketModule to use custom resource factory --- .../Desktop.UnitTests/WebSocketModuleTest.cpp | 75 +++++++++++++++++-- vnext/Desktop/Modules/WebSocketModule.cpp | 14 +++- .../Modules/WebSocketModule.h | 8 +- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 6bae3ef5350..cea89f23332 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -97,7 +97,11 @@ using std::function; using std::string; using std::unique_ptr; -void MockMessageQueueThread::runOnQueue(function &&) /*override*/ {} +void MockMessageQueueThread::runOnQueue(function &&work) /*override*/ +{ + work(); +} + void MockMessageQueueThread::runOnQueueSync(function &&work) /*override*/ { work(); @@ -177,6 +181,7 @@ shared_ptr CreateMockInstance(shared_ptr jsef) { TEST_CLASS (WebSocketModuleTest) { const char *MethodName[static_cast(WebSocketModule::MethodId::SIZE)]{ "connect", "close", "send", "sendBinary", "ping"}; + TEST_METHOD(CreateModule) { auto module = make_unique(); @@ -191,21 +196,75 @@ TEST_CLASS (WebSocketModuleTest) { Assert::AreEqual(static_cast(0), module->getConstants().size()); } - TEST_METHOD(ConnectSucceeds) { + TEST_METHOD(ConnectSendsEvent) { auto jsef = make_shared(); - auto instance = CreateMockInstance(jsef); - jsef->CreateJSExecutorImpl = [](shared_ptr, shared_ptr) { + string eventName; + string moduleName; + string methodName; + jsef->CreateJSExecutorImpl = [&eventName, &moduleName, &methodName]( + shared_ptr, shared_ptr) { auto jse = make_unique(); - jse->CallFunctionImpl = [](const string &, const string &, const dynamic &) { - // TODO: Handle callFunction + jse->CallFunctionImpl = [&eventName, &moduleName, &methodName]( + const string &module, const string &method, const dynamic &args) { + moduleName = module; + methodName = method; + eventName = args.at(0).asString(); }; return std::move(jse); }; + auto instance = CreateMockInstance(jsef); - auto module = make_unique(); - // TODO: Mock member WebSocket resource. + struct MockWebSocketResource : public IWebSocketResource { + void Connect(const Protocols &, const Options &) override { + m_onConnect(); + } + + void Ping() override {} + + void Send(const string &) override {} + + void SendBinary(const string &) override {} + + void Close(CloseCode, const string &) override {} + + ReadyState GetReadyState() const override { + return ReadyState::Open; + } + + void SetOnConnect(function &&onConnect) override { + m_onConnect = std::move(onConnect); + } + + void SetOnPing(function &&) override {} + + void SetOnSend(function &&) override {} + + void SetOnMessage(function &&) {} + + void SetOnClose(function &&) {} + + void SetOnError(function &&) {} + + private: + function m_onConnect; + }; + + auto module = + make_unique([](const string &, bool, bool) { return make_shared(); }); + module->setInstance(instance); + + // Execute module method + auto connect = module->getMethods().at(WebSocketModule::MethodId::Connect); + connect.func( + dynamic::array("ws://localhost:0", dynamic(), dynamic(), /*id*/ 0), + [](vector) {}, + [](vector) {}); + + Assert::AreEqual({"RCTDeviceEventEmitter"}, moduleName); + Assert::AreEqual({"emit"}, methodName); + Assert::AreEqual({"websocketOpen"}, eventName); } }; diff --git a/vnext/Desktop/Modules/WebSocketModule.cpp b/vnext/Desktop/Modules/WebSocketModule.cpp index ef20c0baa7e..e7e8a7c9ea8 100644 --- a/vnext/Desktop/Modules/WebSocketModule.cpp +++ b/vnext/Desktop/Modules/WebSocketModule.cpp @@ -15,6 +15,7 @@ using namespace folly; using Microsoft::Common::Unicode::Utf8ToUtf16; +using std::shared_ptr; using std::string; using std::weak_ptr; @@ -24,7 +25,16 @@ constexpr char moduleName[] = "WebSocketModule"; namespace Microsoft::React { -WebSocketModule::WebSocketModule() {} +WebSocketModule::WebSocketModule( + std::function(const string &, bool, bool)> &&resourceFactory) { + if (resourceFactory) { + m_resourceFactory = std::move(resourceFactory); + } else { + m_resourceFactory = [](const string &url, bool legacyImplementation, bool acceptSelfSigned) { + return IWebSocketResource::Make(url, legacyImplementation, acceptSelfSigned); + }; + } +} string WebSocketModule::getName() { return moduleName; @@ -146,7 +156,7 @@ std::shared_ptr WebSocketModule::GetOrCreateWebSocket(int64_ auto itr = m_webSockets.find(id); if (itr == m_webSockets.end()) { - auto ws = IWebSocketResource::Make(std::move(url)); + auto ws = m_resourceFactory(std::move(url), /*legacyImplementation*/ false, /*acceptSelfSigned*/ false); auto weakInstance = this->getInstance(); ws->SetOnError([this, id, weakInstance](const IWebSocketResource::Error& err) { diff --git a/vnext/ReactWindowsCore/Modules/WebSocketModule.h b/vnext/ReactWindowsCore/Modules/WebSocketModule.h index 1f13d917324..e0ff85d6fe6 100644 --- a/vnext/ReactWindowsCore/Modules/WebSocketModule.h +++ b/vnext/ReactWindowsCore/Modules/WebSocketModule.h @@ -16,7 +16,8 @@ class WebSocketModule : public facebook::xplat::module::CxxModule { public: enum MethodId { Connect = 0, Close = 1, Send = 2, SendBinary = 3, Ping = 4, SIZE = 5 }; - WebSocketModule(); + WebSocketModule( + std::function(const std::string &, bool, bool)> &&resourceFactory = nullptr); /// /// @@ -50,6 +51,11 @@ class WebSocketModule : public facebook::xplat::module::CxxModule { /// As defined in WebSocket.js. /// std::map> m_webSockets; + + /// + /// Generates IWebSocketResource instances, defaulting to IWebSocketResource::Make. + /// + std::function(const std::string &, bool, bool)> m_resourceFactory; }; } // namespace Microsoft::React From e1f3edf872c47db51ba34aa5ea579947b20d48b5 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 20:10:36 -0700 Subject: [PATCH 08/13] Rename *Impl to *Mock --- vnext/Desktop.UnitTests/WebSocketModuleTest.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index cea89f23332..70ee15f29a4 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -44,7 +44,7 @@ class MockInstanceCallback : public InstanceCallback { class MockJSExecutor : public JSExecutor { public: - std::function CallFunctionImpl; + std::function CallFunctionMock; #pragma region JSExecutor overrides @@ -78,7 +78,7 @@ class MockJSExecutor : public JSExecutor { class MockJSExecutorFactory : public JSExecutorFactory { public: std::function(std::shared_ptr, std::shared_ptr)> - CreateJSExecutorImpl; + CreateJSExecutorMock; #pragma region JSExecutorFactory overrides @@ -120,8 +120,8 @@ void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegis void MockJSExecutor::registerBundle(uint32_t bundleId, const string &bundlePath) {} void MockJSExecutor::callFunction(const string &moduleId, const string &methodId, const dynamic &arguments) { - if (CallFunctionImpl) { - CallFunctionImpl(moduleId, methodId, arguments); + if (CallFunctionMock) { + CallFunctionMock(moduleId, methodId, arguments); } } @@ -153,8 +153,8 @@ unique_ptr MockJSExecutorFactory::createJSExecutor( shared_ptr delegate, shared_ptr jsQueue) /*override*/ { - if (CreateJSExecutorImpl) { - return CreateJSExecutorImpl(delegate, jsQueue); + if (CreateJSExecutorMock) { + return CreateJSExecutorMock(delegate, jsQueue); } return make_unique(); @@ -202,10 +202,10 @@ TEST_CLASS (WebSocketModuleTest) { string eventName; string moduleName; string methodName; - jsef->CreateJSExecutorImpl = [&eventName, &moduleName, &methodName]( + jsef->CreateJSExecutorMock = [&eventName, &moduleName, &methodName]( shared_ptr, shared_ptr) { auto jse = make_unique(); - jse->CallFunctionImpl = [&eventName, &moduleName, &methodName]( + jse->CallFunctionMock = [&eventName, &moduleName, &methodName]( const string &module, const string &method, const dynamic &args) { moduleName = module; methodName = method; From 280135f2fd99296c852ea12e896c10030f7caab5 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 21:58:48 -0700 Subject: [PATCH 09/13] Move Instance mocks into separate source files --- .../React.Windows.Desktop.UnitTests.vcxproj | 4 + ....Windows.Desktop.UnitTests.vcxproj.filters | 12 + .../Desktop.UnitTests/WebSocketModuleTest.cpp | 205 +----------------- 3 files changed, 22 insertions(+), 199 deletions(-) diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index 25d21585994..548a182d84d 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -87,12 +87,14 @@ + + @@ -104,7 +106,9 @@ + + diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters index 7ef3ff227b3..b473de81f8b 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj.filters @@ -46,6 +46,12 @@ Source Files + + Source Files + + + Source Files + @@ -68,5 +74,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 70ee15f29a4..4055b5c35e7 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -3,180 +3,23 @@ #include #include - -// TODO: Move out -#include -#include -#include -#include -#include -#include +#include "InstanceMocks.h" +#include "WebSocketMocks.h" using namespace facebook::react; using namespace facebook::xplat::module; using namespace Microsoft::VisualStudio::CppUnitTestFramework; -namespace Microsoft::React::Test { - -class MockMessageQueueThread : public MessageQueueThread { - public: -#pragma region MessageQueueThread overrides - - void runOnQueue(std::function &&) override; - - void runOnQueueSync(std::function &&) override; - - void quitSynchronous() override; - -#pragma endregion // MessageQueueThread overrides -}; - -class MockInstanceCallback : public InstanceCallback { - public: -#pragma region InstanceCallback overrides - - void onBatchComplete() override; - void incrementPendingJSCalls() override; - void decrementPendingJSCalls() override; - -#pragma endregion // InstanceCallback overrides -}; - -class MockJSExecutor : public JSExecutor { - public: - std::function CallFunctionMock; - -#pragma region JSExecutor overrides - - void loadApplicationScript(std::unique_ptr script, std::string sourceURL) override; - - void setBundleRegistry(std::unique_ptr bundleRegistry) override; - - void registerBundle(uint32_t bundleId, const std::string &bundlePath) override; - - void callFunction(const std::string &moduleId, const std::string &methodId, const folly::dynamic &arguments) override; - - void invokeCallback(const double callbackId, const folly::dynamic &arguments) override; - - void setGlobalVariable(std::string propName, std::unique_ptr jsonValue) override; - - void *getJavaScriptContext() override; - - bool isInspectable() override; - - std::string getDescription() override; - - void handleMemoryPressure(__unused int pressureLevel) override; - - void destroy() override; - - void flush() override; - -#pragma endregion // JSExecutor overrides -}; - -class MockJSExecutorFactory : public JSExecutorFactory { - public: - std::function(std::shared_ptr, std::shared_ptr)> - CreateJSExecutorMock; - -#pragma region JSExecutorFactory overrides - - std::unique_ptr createJSExecutor( - std::shared_ptr delegate, - std::shared_ptr jsQueue) override; - -#pragma endregion // JSExecutorFactory overrides -}; - -#pragma region Move - -// MockMessageQueueThread using folly::dynamic; using std::function; -using std::string; -using std::unique_ptr; - -void MockMessageQueueThread::runOnQueue(function &&work) /*override*/ -{ - work(); -} - -void MockMessageQueueThread::runOnQueueSync(function &&work) /*override*/ -{ - work(); -} - -void MockMessageQueueThread::quitSynchronous() /*override*/ {} - -// MockInstanceCallback -void MockInstanceCallback::onBatchComplete() /*override*/ {} -void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {} -void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {} - -// MockJSExecutor -void MockJSExecutor::loadApplicationScript(unique_ptr script, string sourceURL) {} -void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegistry) {} -void MockJSExecutor::registerBundle(uint32_t bundleId, const string &bundlePath) {} - -void MockJSExecutor::callFunction(const string &moduleId, const string &methodId, const dynamic &arguments) { - if (CallFunctionMock) { - CallFunctionMock(moduleId, methodId, arguments); - } -} - -void MockJSExecutor::invokeCallback(const double callbackId, const dynamic &arguments) {} -void MockJSExecutor::setGlobalVariable(string propName, unique_ptr jsonValue) {} -void *MockJSExecutor::getJavaScriptContext() { - return nullptr; -} - -bool MockJSExecutor::isInspectable() { - return false; -} -std::string MockJSExecutor::getDescription() { - return {}; -} -void MockJSExecutor::handleMemoryPressure(__unused int pressureLevel) {} -void MockJSExecutor::destroy() {} -void MockJSExecutor::flush() {} - -// MockJSExecutorFactory - using std::make_shared; using std::make_unique; using std::shared_ptr; +using std::string; using std::unique_ptr; using std::vector; -unique_ptr MockJSExecutorFactory::createJSExecutor( - shared_ptr delegate, - shared_ptr jsQueue) /*override*/ -{ - if (CreateJSExecutorMock) { - return CreateJSExecutorMock(delegate, jsQueue); - } - - return make_unique(); -} - -// MockInstance.cpp ? - -shared_ptr CreateMockInstance(shared_ptr jsef) { - auto instance = make_shared(); - auto callback = make_unique(); - auto jsQueue = make_shared(); - auto moduleRegistry = make_shared( - vector>(), // modules - nullptr // moduleNotFoundCallback - ); - - instance->initializeBridge(std::move(callback), jsef, jsQueue, moduleRegistry); - - return instance; -} - -#pragma endregion // Move +namespace Microsoft::React::Test { TEST_CLASS (WebSocketModuleTest) { const char *MethodName[static_cast(WebSocketModule::MethodId::SIZE)]{ @@ -197,11 +40,10 @@ TEST_CLASS (WebSocketModuleTest) { } TEST_METHOD(ConnectSendsEvent) { - auto jsef = make_shared(); - string eventName; string moduleName; string methodName; + auto jsef = make_shared(); jsef->CreateJSExecutorMock = [&eventName, &moduleName, &methodName]( shared_ptr, shared_ptr) { auto jse = make_unique(); @@ -214,43 +56,8 @@ TEST_CLASS (WebSocketModuleTest) { return std::move(jse); }; - auto instance = CreateMockInstance(jsef); - - struct MockWebSocketResource : public IWebSocketResource { - void Connect(const Protocols &, const Options &) override { - m_onConnect(); - } - - void Ping() override {} - - void Send(const string &) override {} - - void SendBinary(const string &) override {} - - void Close(CloseCode, const string &) override {} - - ReadyState GetReadyState() const override { - return ReadyState::Open; - } - - void SetOnConnect(function &&onConnect) override { - m_onConnect = std::move(onConnect); - } - - void SetOnPing(function &&) override {} - - void SetOnSend(function &&) override {} - - void SetOnMessage(function &&) {} - - void SetOnClose(function &&) {} - - void SetOnError(function &&) {} - - private: - function m_onConnect; - }; + auto instance = CreateMockInstance(jsef); auto module = make_unique([](const string &, bool, bool) { return make_shared(); }); module->setInstance(instance); From 1122e1ff1ad247e792937cec3c3aed580bcd6d07 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 Apr 2020 21:59:08 -0700 Subject: [PATCH 10/13] Move Instance mocks into separate source files --- vnext/Desktop.UnitTests/InstanceMocks.cpp | 100 +++++++++++++++++++++ vnext/Desktop.UnitTests/InstanceMocks.h | 84 +++++++++++++++++ vnext/Desktop.UnitTests/WebSocketMocks.cpp | 44 +++++++++ vnext/Desktop.UnitTests/WebSocketMocks.h | 41 +++++++++ 4 files changed, 269 insertions(+) create mode 100644 vnext/Desktop.UnitTests/InstanceMocks.cpp create mode 100644 vnext/Desktop.UnitTests/InstanceMocks.h create mode 100644 vnext/Desktop.UnitTests/WebSocketMocks.cpp create mode 100644 vnext/Desktop.UnitTests/WebSocketMocks.h diff --git a/vnext/Desktop.UnitTests/InstanceMocks.cpp b/vnext/Desktop.UnitTests/InstanceMocks.cpp new file mode 100644 index 00000000000..4465e0d0f12 --- /dev/null +++ b/vnext/Desktop.UnitTests/InstanceMocks.cpp @@ -0,0 +1,100 @@ +#include "InstanceMocks.h" + +#include + +using namespace facebook::react; + +using folly::dynamic; +using std::function; +using std::make_unique; +using std::make_shared; +using std::shared_ptr; +using std::string; +using std::unique_ptr; +using std::vector; + +namespace Microsoft::React::Test +{ +#pragma region MockMessageQueueThread + void MockMessageQueueThread::runOnQueue(function&& work) /*override*/ + { + work(); + } + + void MockMessageQueueThread::runOnQueueSync(function&& work) /*override*/ + { + work(); + } + + void MockMessageQueueThread::quitSynchronous() /*override*/ {} +#pragma endregion // MockMessageQueueThread + +#pragma region MockInstanceCallback + + void MockInstanceCallback::onBatchComplete() /*override*/ {} + void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {} + void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {} + +#pragma endregion // MockInstanceCallback + +#pragma region MockJSExecutor + + void MockJSExecutor::loadApplicationScript(unique_ptr script, string sourceURL) {} + void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegistry) {} + void MockJSExecutor::registerBundle(uint32_t bundleId, const string& bundlePath) {} + + +void MockJSExecutor::callFunction(const string& moduleId, const string& methodId, const dynamic& arguments) { + if (CallFunctionMock) { + CallFunctionMock(moduleId, methodId, arguments); + } +} + +void MockJSExecutor::invokeCallback(const double callbackId, const dynamic& arguments) {} +void MockJSExecutor::setGlobalVariable(string propName, unique_ptr jsonValue) {} +void* MockJSExecutor::getJavaScriptContext() { + return nullptr; +} + +bool MockJSExecutor::isInspectable() { + return false; +} +std::string MockJSExecutor::getDescription() { + return {}; +} +void MockJSExecutor::handleMemoryPressure(__unused int pressureLevel) {} +void MockJSExecutor::destroy() {} +void MockJSExecutor::flush() {} + +#pragma endregion // MockJSExecutor + +#pragma region MockJSExecutorFactory + +unique_ptr MockJSExecutorFactory::createJSExecutor( + shared_ptr delegate, + shared_ptr jsQueue) /*override*/ +{ + if (CreateJSExecutorMock) { + return CreateJSExecutorMock(delegate, jsQueue); + } + + return make_unique(); +} + +#pragma endregion // MockJSExecutorFactory + +shared_ptr CreateMockInstance(shared_ptr jsef) { + auto instance = make_shared(); + auto callback = make_unique(); + auto jsQueue = make_shared(); + auto moduleRegistry = make_shared( + vector>(), // modules + nullptr // moduleNotFoundCallback + ); + + instance->initializeBridge(std::move(callback), jsef, jsQueue, moduleRegistry); + + return instance; +} + +} // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/InstanceMocks.h b/vnext/Desktop.UnitTests/InstanceMocks.h new file mode 100644 index 00000000000..c0f1f58fab2 --- /dev/null +++ b/vnext/Desktop.UnitTests/InstanceMocks.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace Microsoft::React::Test +{ +std::shared_ptr CreateMockInstance(std::shared_ptr jsef); + +class MockMessageQueueThread : public facebook::react::MessageQueueThread { +public: +#pragma region MessageQueueThread overrides + + void runOnQueue(std::function&&) override; + + void runOnQueueSync(std::function&&) override; + + void quitSynchronous() override; + +#pragma endregion // MessageQueueThread overrides +}; + +class MockInstanceCallback : public facebook::react::InstanceCallback { +public: +#pragma region InstanceCallback overrides + + void onBatchComplete() override; + void incrementPendingJSCalls() override; + void decrementPendingJSCalls() override; + +#pragma endregion // InstanceCallback overrides +}; + +class MockJSExecutor : public facebook::react::JSExecutor { +public: + std::function CallFunctionMock; + +#pragma region JSExecutor overrides + + void loadApplicationScript(std::unique_ptr script, std::string sourceURL) override; + + void setBundleRegistry(std::unique_ptr bundleRegistry) override; + + void registerBundle(uint32_t bundleId, const std::string& bundlePath) override; + + void callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) override; + + void invokeCallback(const double callbackId, const folly::dynamic& arguments) override; + + void setGlobalVariable(std::string propName, std::unique_ptr jsonValue) override; + + void* getJavaScriptContext() override; + + bool isInspectable() override; + + std::string getDescription() override; + + void handleMemoryPressure(__unused int pressureLevel) override; + + void destroy() override; + + void flush() override; + +#pragma endregion // JSExecutor overrides +}; + +class MockJSExecutorFactory : public facebook::react::JSExecutorFactory { +public: + std::function(std::shared_ptr, std::shared_ptr)> + CreateJSExecutorMock; + +#pragma region JSExecutorFactory overrides + + std::unique_ptr createJSExecutor( + std::shared_ptr delegate, + std::shared_ptr jsQueue) override; + +#pragma endregion // JSExecutorFactory overrides +}; + +} // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/WebSocketMocks.cpp b/vnext/Desktop.UnitTests/WebSocketMocks.cpp new file mode 100644 index 00000000000..df0d0b201c9 --- /dev/null +++ b/vnext/Desktop.UnitTests/WebSocketMocks.cpp @@ -0,0 +1,44 @@ +#include "WebSocketMocks.h" + +using std::function; +using std::string; + +namespace Microsoft::React::Test +{ +#pragma region IWebSocketResource overrides + +void MockWebSocketResource::Connect(const Protocols&, const Options&) /*override*/ +{ + m_onConnect(); +} + +void MockWebSocketResource::Ping() /*override*/ {} + +void MockWebSocketResource::Send(const string&) /*override*/ {} + +void MockWebSocketResource::SendBinary(const string&) /*override*/ {} + +void MockWebSocketResource::Close(CloseCode, const string&) /*override*/ {} + +IWebSocketResource::ReadyState MockWebSocketResource::GetReadyState() const /*override*/ +{ + return ReadyState::Open; +} + +void MockWebSocketResource::SetOnConnect(function&& onConnect) /*override*/ +{ + m_onConnect = std::move(onConnect); +} + +void MockWebSocketResource::SetOnPing(function&&) /*override*/ {} + +void MockWebSocketResource::SetOnSend(function&&) /*override*/ {} + +void MockWebSocketResource::SetOnMessage(function&&) /*override*/ {} + +void MockWebSocketResource::SetOnClose(function&&) /*override*/ {} + +void MockWebSocketResource::SetOnError(function&&) /*override*/ {} + +#pragma endregion IWebSocketResource overrides +} diff --git a/vnext/Desktop.UnitTests/WebSocketMocks.h b/vnext/Desktop.UnitTests/WebSocketMocks.h new file mode 100644 index 00000000000..7a7de40eed4 --- /dev/null +++ b/vnext/Desktop.UnitTests/WebSocketMocks.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace Microsoft::React::Test +{ +struct MockWebSocketResource : public IWebSocketResource { + +#pragma region IWebSocketResource overrides + + void Connect(const Protocols&, const Options&) override; + + void Ping() override; + + void Send(const std::string&) override; + + void SendBinary(const std::string&) override; + + void Close(CloseCode, const std::string&) override; + + ReadyState GetReadyState() const override; + + void SetOnConnect(std::function&& onConnect) override; + + void SetOnPing(std::function&&) override; + + void SetOnSend(std::function&&) override; + + void SetOnMessage(std::function&&) override; + + void SetOnClose(std::function&&) override; + + void SetOnError(std::function&&) override; + +#pragma endregion IWebSocketResource overrides + +private: + std::function m_onConnect; +}; + +} // namespace Microsoft::React::Test From 4306ceb7b80632490e9e9caa35eca51800838dd2 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 9 Apr 2020 16:51:56 -0700 Subject: [PATCH 11/13] Change files --- ...ve-windows-2020-04-09-16-51-25-wsmodule_unittests.json | 7 +++++++ ...ve-windows-2020-04-09-16-51-56-wsmodule_unittests.json | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 change/react-native-windows-2020-04-09-16-51-25-wsmodule_unittests.json create mode 100644 change/react-native-windows-2020-04-09-16-51-56-wsmodule_unittests.json diff --git a/change/react-native-windows-2020-04-09-16-51-25-wsmodule_unittests.json b/change/react-native-windows-2020-04-09-16-51-25-wsmodule_unittests.json new file mode 100644 index 00000000000..c5e9d9c9e0d --- /dev/null +++ b/change/react-native-windows-2020-04-09-16-51-25-wsmodule_unittests.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "packageName": "react-native-windows", + "email": "julio@rochsquadron.net", + "dependentChangeType": "none", + "date": "2020-04-09T23:51:25.594Z" +} \ No newline at end of file diff --git a/change/react-native-windows-2020-04-09-16-51-56-wsmodule_unittests.json b/change/react-native-windows-2020-04-09-16-51-56-wsmodule_unittests.json new file mode 100644 index 00000000000..a09e3a1389d --- /dev/null +++ b/change/react-native-windows-2020-04-09-16-51-56-wsmodule_unittests.json @@ -0,0 +1,8 @@ +{ + "type": "none", + "comment": "Allow WebSocketModule to use custom resource factory", + "packageName": "react-native-windows", + "email": "julio@rochsquadron.net", + "dependentChangeType": "none", + "date": "2020-04-09T23:51:56.846Z" +} \ No newline at end of file From 14fa2dfb58695048b016e53334c158fa5214aab7 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 9 Apr 2020 16:53:36 -0700 Subject: [PATCH 12/13] clang format --- vnext/Desktop.UnitTests/InstanceMocks.cpp | 52 +++++++++++----------- vnext/Desktop.UnitTests/InstanceMocks.h | 38 ++++++++-------- vnext/Desktop.UnitTests/WebSocketMocks.cpp | 25 +++++------ vnext/Desktop.UnitTests/WebSocketMocks.h | 26 +++++------ 4 files changed, 69 insertions(+), 72 deletions(-) diff --git a/vnext/Desktop.UnitTests/InstanceMocks.cpp b/vnext/Desktop.UnitTests/InstanceMocks.cpp index 4465e0d0f12..1eb48c50fb1 100644 --- a/vnext/Desktop.UnitTests/InstanceMocks.cpp +++ b/vnext/Desktop.UnitTests/InstanceMocks.cpp @@ -6,53 +6,51 @@ using namespace facebook::react; using folly::dynamic; using std::function; -using std::make_unique; using std::make_shared; +using std::make_unique; using std::shared_ptr; using std::string; using std::unique_ptr; using std::vector; -namespace Microsoft::React::Test -{ +namespace Microsoft::React::Test { #pragma region MockMessageQueueThread - void MockMessageQueueThread::runOnQueue(function&& work) /*override*/ - { - work(); - } +void MockMessageQueueThread::runOnQueue(function &&work) /*override*/ +{ + work(); +} - void MockMessageQueueThread::runOnQueueSync(function&& work) /*override*/ - { - work(); - } +void MockMessageQueueThread::runOnQueueSync(function &&work) /*override*/ +{ + work(); +} - void MockMessageQueueThread::quitSynchronous() /*override*/ {} +void MockMessageQueueThread::quitSynchronous() /*override*/ {} #pragma endregion // MockMessageQueueThread #pragma region MockInstanceCallback - void MockInstanceCallback::onBatchComplete() /*override*/ {} - void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {} - void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {} +void MockInstanceCallback::onBatchComplete() /*override*/ {} +void MockInstanceCallback::incrementPendingJSCalls() /*override*/ {} +void MockInstanceCallback::decrementPendingJSCalls() /*override*/ {} #pragma endregion // MockInstanceCallback #pragma region MockJSExecutor - void MockJSExecutor::loadApplicationScript(unique_ptr script, string sourceURL) {} - void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegistry) {} - void MockJSExecutor::registerBundle(uint32_t bundleId, const string& bundlePath) {} - +void MockJSExecutor::loadApplicationScript(unique_ptr script, string sourceURL) {} +void MockJSExecutor::setBundleRegistry(unique_ptr bundleRegistry) {} +void MockJSExecutor::registerBundle(uint32_t bundleId, const string &bundlePath) {} -void MockJSExecutor::callFunction(const string& moduleId, const string& methodId, const dynamic& arguments) { +void MockJSExecutor::callFunction(const string &moduleId, const string &methodId, const dynamic &arguments) { if (CallFunctionMock) { CallFunctionMock(moduleId, methodId, arguments); } } -void MockJSExecutor::invokeCallback(const double callbackId, const dynamic& arguments) {} +void MockJSExecutor::invokeCallback(const double callbackId, const dynamic &arguments) {} void MockJSExecutor::setGlobalVariable(string propName, unique_ptr jsonValue) {} -void* MockJSExecutor::getJavaScriptContext() { +void *MockJSExecutor::getJavaScriptContext() { return nullptr; } @@ -71,8 +69,8 @@ void MockJSExecutor::flush() {} #pragma region MockJSExecutorFactory unique_ptr MockJSExecutorFactory::createJSExecutor( - shared_ptr delegate, - shared_ptr jsQueue) /*override*/ + shared_ptr delegate, + shared_ptr jsQueue) /*override*/ { if (CreateJSExecutorMock) { return CreateJSExecutorMock(delegate, jsQueue); @@ -88,9 +86,9 @@ shared_ptr CreateMockInstance(shared_ptr jsef) { auto callback = make_unique(); auto jsQueue = make_shared(); auto moduleRegistry = make_shared( - vector>(), // modules - nullptr // moduleNotFoundCallback - ); + vector>(), // modules + nullptr // moduleNotFoundCallback + ); instance->initializeBridge(std::move(callback), jsef, jsQueue, moduleRegistry); diff --git a/vnext/Desktop.UnitTests/InstanceMocks.h b/vnext/Desktop.UnitTests/InstanceMocks.h index c0f1f58fab2..bb535c79ece 100644 --- a/vnext/Desktop.UnitTests/InstanceMocks.h +++ b/vnext/Desktop.UnitTests/InstanceMocks.h @@ -6,17 +6,16 @@ #include #include -namespace Microsoft::React::Test -{ +namespace Microsoft::React::Test { std::shared_ptr CreateMockInstance(std::shared_ptr jsef); class MockMessageQueueThread : public facebook::react::MessageQueueThread { -public: + public: #pragma region MessageQueueThread overrides - void runOnQueue(std::function&&) override; + void runOnQueue(std::function &&) override; - void runOnQueueSync(std::function&&) override; + void runOnQueueSync(std::function &&) override; void quitSynchronous() override; @@ -24,7 +23,7 @@ class MockMessageQueueThread : public facebook::react::MessageQueueThread { }; class MockInstanceCallback : public facebook::react::InstanceCallback { -public: + public: #pragma region InstanceCallback overrides void onBatchComplete() override; @@ -35,24 +34,25 @@ class MockInstanceCallback : public facebook::react::InstanceCallback { }; class MockJSExecutor : public facebook::react::JSExecutor { -public: - std::function CallFunctionMock; + public: + std::function CallFunctionMock; #pragma region JSExecutor overrides - void loadApplicationScript(std::unique_ptr script, std::string sourceURL) override; + void loadApplicationScript(std::unique_ptr script, std::string sourceURL) + override; void setBundleRegistry(std::unique_ptr bundleRegistry) override; - void registerBundle(uint32_t bundleId, const std::string& bundlePath) override; + void registerBundle(uint32_t bundleId, const std::string &bundlePath) override; - void callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) override; + void callFunction(const std::string &moduleId, const std::string &methodId, const folly::dynamic &arguments) override; - void invokeCallback(const double callbackId, const folly::dynamic& arguments) override; + void invokeCallback(const double callbackId, const folly::dynamic &arguments) override; void setGlobalVariable(std::string propName, std::unique_ptr jsonValue) override; - void* getJavaScriptContext() override; + void *getJavaScriptContext() override; bool isInspectable() override; @@ -68,15 +68,17 @@ class MockJSExecutor : public facebook::react::JSExecutor { }; class MockJSExecutorFactory : public facebook::react::JSExecutorFactory { -public: - std::function(std::shared_ptr, std::shared_ptr)> - CreateJSExecutorMock; + public: + std::function( + std::shared_ptr, + std::shared_ptr)> + CreateJSExecutorMock; #pragma region JSExecutorFactory overrides std::unique_ptr createJSExecutor( - std::shared_ptr delegate, - std::shared_ptr jsQueue) override; + std::shared_ptr delegate, + std::shared_ptr jsQueue) override; #pragma endregion // JSExecutorFactory overrides }; diff --git a/vnext/Desktop.UnitTests/WebSocketMocks.cpp b/vnext/Desktop.UnitTests/WebSocketMocks.cpp index df0d0b201c9..a57365cff9d 100644 --- a/vnext/Desktop.UnitTests/WebSocketMocks.cpp +++ b/vnext/Desktop.UnitTests/WebSocketMocks.cpp @@ -3,42 +3,41 @@ using std::function; using std::string; -namespace Microsoft::React::Test -{ +namespace Microsoft::React::Test { #pragma region IWebSocketResource overrides -void MockWebSocketResource::Connect(const Protocols&, const Options&) /*override*/ +void MockWebSocketResource::Connect(const Protocols &, const Options &) /*override*/ { m_onConnect(); } void MockWebSocketResource::Ping() /*override*/ {} -void MockWebSocketResource::Send(const string&) /*override*/ {} +void MockWebSocketResource::Send(const string &) /*override*/ {} -void MockWebSocketResource::SendBinary(const string&) /*override*/ {} +void MockWebSocketResource::SendBinary(const string &) /*override*/ {} -void MockWebSocketResource::Close(CloseCode, const string&) /*override*/ {} +void MockWebSocketResource::Close(CloseCode, const string &) /*override*/ {} IWebSocketResource::ReadyState MockWebSocketResource::GetReadyState() const /*override*/ { return ReadyState::Open; } -void MockWebSocketResource::SetOnConnect(function&& onConnect) /*override*/ +void MockWebSocketResource::SetOnConnect(function &&onConnect) /*override*/ { m_onConnect = std::move(onConnect); } -void MockWebSocketResource::SetOnPing(function&&) /*override*/ {} +void MockWebSocketResource::SetOnPing(function &&) /*override*/ {} -void MockWebSocketResource::SetOnSend(function&&) /*override*/ {} +void MockWebSocketResource::SetOnSend(function &&) /*override*/ {} -void MockWebSocketResource::SetOnMessage(function&&) /*override*/ {} +void MockWebSocketResource::SetOnMessage(function &&) /*override*/ {} -void MockWebSocketResource::SetOnClose(function&&) /*override*/ {} +void MockWebSocketResource::SetOnClose(function &&) /*override*/ {} -void MockWebSocketResource::SetOnError(function&&) /*override*/ {} +void MockWebSocketResource::SetOnError(function &&) /*override*/ {} #pragma endregion IWebSocketResource overrides -} +} // namespace Microsoft::React::Test diff --git a/vnext/Desktop.UnitTests/WebSocketMocks.h b/vnext/Desktop.UnitTests/WebSocketMocks.h index 7a7de40eed4..beeceac830b 100644 --- a/vnext/Desktop.UnitTests/WebSocketMocks.h +++ b/vnext/Desktop.UnitTests/WebSocketMocks.h @@ -2,39 +2,37 @@ #include -namespace Microsoft::React::Test -{ +namespace Microsoft::React::Test { struct MockWebSocketResource : public IWebSocketResource { - #pragma region IWebSocketResource overrides - void Connect(const Protocols&, const Options&) override; + void Connect(const Protocols &, const Options &) override; void Ping() override; - void Send(const std::string&) override; + void Send(const std::string &) override; - void SendBinary(const std::string&) override; + void SendBinary(const std::string &) override; - void Close(CloseCode, const std::string&) override; + void Close(CloseCode, const std::string &) override; ReadyState GetReadyState() const override; - void SetOnConnect(std::function&& onConnect) override; + void SetOnConnect(std::function &&onConnect) override; - void SetOnPing(std::function&&) override; + void SetOnPing(std::function &&) override; - void SetOnSend(std::function&&) override; + void SetOnSend(std::function &&) override; - void SetOnMessage(std::function&&) override; + void SetOnMessage(std::function &&) override; - void SetOnClose(std::function&&) override; + void SetOnClose(std::function &&) override; - void SetOnError(std::function&&) override; + void SetOnError(std::function &&) override; #pragma endregion IWebSocketResource overrides -private: + private: std::function m_onConnect; }; From 3400f6d62cfd390eef7c5f76546d11d0ff8e75c6 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 9 Apr 2020 17:36:05 -0700 Subject: [PATCH 13/13] Define WebSocketModule::SetResourceFactory --- vnext/Desktop.UnitTests/WebSocketModuleTest.cpp | 4 ++-- vnext/Desktop/Modules/WebSocketModule.cpp | 15 +++++++-------- vnext/ReactWindowsCore/Modules/WebSocketModule.h | 10 ++++++++-- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp index 4055b5c35e7..0aa7d57dba3 100644 --- a/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp +++ b/vnext/Desktop.UnitTests/WebSocketModuleTest.cpp @@ -58,9 +58,9 @@ TEST_CLASS (WebSocketModuleTest) { }; auto instance = CreateMockInstance(jsef); - auto module = - make_unique([](const string &, bool, bool) { return make_shared(); }); + auto module = make_unique(); module->setInstance(instance); + module->SetResourceFactory([](const string &, bool, bool) { return make_shared(); }); // Execute module method auto connect = module->getMethods().at(WebSocketModule::MethodId::Connect); diff --git a/vnext/Desktop/Modules/WebSocketModule.cpp b/vnext/Desktop/Modules/WebSocketModule.cpp index e7e8a7c9ea8..6ac369f22f0 100644 --- a/vnext/Desktop/Modules/WebSocketModule.cpp +++ b/vnext/Desktop/Modules/WebSocketModule.cpp @@ -25,15 +25,14 @@ constexpr char moduleName[] = "WebSocketModule"; namespace Microsoft::React { -WebSocketModule::WebSocketModule( +WebSocketModule::WebSocketModule() + : m_resourceFactory{[](const string &url, bool legacyImplementation, bool acceptSelfSigned) { + return IWebSocketResource::Make(url, legacyImplementation, acceptSelfSigned); + }} {} + +void WebSocketModule::SetResourceFactory( std::function(const string &, bool, bool)> &&resourceFactory) { - if (resourceFactory) { - m_resourceFactory = std::move(resourceFactory); - } else { - m_resourceFactory = [](const string &url, bool legacyImplementation, bool acceptSelfSigned) { - return IWebSocketResource::Make(url, legacyImplementation, acceptSelfSigned); - }; - } + m_resourceFactory = std::move(resourceFactory); } string WebSocketModule::getName() { diff --git a/vnext/ReactWindowsCore/Modules/WebSocketModule.h b/vnext/ReactWindowsCore/Modules/WebSocketModule.h index e0ff85d6fe6..2b4dbaf5a86 100644 --- a/vnext/ReactWindowsCore/Modules/WebSocketModule.h +++ b/vnext/ReactWindowsCore/Modules/WebSocketModule.h @@ -16,8 +16,9 @@ class WebSocketModule : public facebook::xplat::module::CxxModule { public: enum MethodId { Connect = 0, Close = 1, Send = 2, SendBinary = 3, Ping = 4, SIZE = 5 }; - WebSocketModule( - std::function(const std::string &, bool, bool)> &&resourceFactory = nullptr); + WebSocketModule(); + +#pragma region CxxModule overrides /// /// @@ -35,6 +36,11 @@ class WebSocketModule : public facebook::xplat::module::CxxModule { /// See See react-native/Libraries/WebSocket/WebSocket.js std::vector getMethods() override; +#pragma endregion CxxModule overrides + + void SetResourceFactory( + std::function(const std::string &, bool, bool)> &&resourceFactory = nullptr); + private: /// /// Notifies an event to the current React Instance.