This repository was archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[url_launcher] Add native unit tests for Windows #4156
Merged
stuartmorgan-g
merged 12 commits into
flutter:master
from
stuartmorgan-g:windows-unit-test
Aug 17, 2021
Merged
Changes from 1 commit
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
6b6d723
Initial proof of concept
stuartmorgan-g 99b2ab1
Refactor file structure, plugin class, for testability
stuartmorgan-g bc94f32
Add real tests, and make them build.
stuartmorgan-g e239b3d
Tweaks
stuartmorgan-g ec3b3e2
Update changelog
stuartmorgan-g a6a1e8b
Improve the filename mess
stuartmorgan-g ce8bb54
Format
stuartmorgan-g eb432df
Merge branch 'master' into windows-unit-test
stuartmorgan-g 8542f52
Missing license
stuartmorgan-g 3032865
Merge branch 'master' into windows-unit-test
stuartmorgan-g cef2f07
Fix weird autoformat
stuartmorgan-g c5c0a8f
Fix weird autoformat
stuartmorgan-g File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add real tests, and make them build.
- Loading branch information
commit bc94f32468490275bab4165302be946ab27af8bc
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 167 additions & 3 deletions
170
packages/url_launcher/url_launcher_windows/windows/test/url_launcher_windows_test.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,170 @@ | ||
| #include <flutter/method_call.h> | ||
| #include <flutter/method_result_functions.h> | ||
| #include <flutter/standard_method_codec.h> | ||
| #include <gmock/gmock.h> | ||
| #include <gtest/gtest.h> | ||
| #include <windows.h> | ||
|
|
||
| TEST(TestMe, HelloTestWorld) { | ||
| EXPECT_STRNE("hello", "world"); | ||
| EXPECT_TRUE(false); | ||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include "url_launcher_plugin.h" | ||
|
|
||
| namespace url_launcher_plugin { | ||
| namespace test { | ||
|
|
||
| namespace { | ||
|
|
||
| using flutter::EncodableMap; | ||
| using flutter::EncodableValue; | ||
| using ::testing::DoAll; | ||
| using ::testing::Pointee; | ||
| using ::testing::Return; | ||
| using ::testing::SetArgPointee; | ||
|
|
||
| class MockSystemApis : public SystemApis { | ||
| public: | ||
| MOCK_METHOD(LSTATUS, RegCloseKey, (HKEY key), (override)); | ||
| MOCK_METHOD(LSTATUS, RegQueryValueExW, | ||
| (HKEY key, LPCWSTR value_name, LPDWORD type, LPBYTE data, | ||
| LPDWORD data_size), | ||
| (override)); | ||
| MOCK_METHOD(LSTATUS, RegOpenKeyExW, | ||
| (HKEY key, LPCWSTR sub_key, DWORD options, REGSAM desired, | ||
| PHKEY result), | ||
| (override)); | ||
| MOCK_METHOD(HINSTANCE, ShellExecuteW, | ||
| (HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR parameters, | ||
| LPCWSTR directory, int show_flags), | ||
| (override)); | ||
| }; | ||
|
|
||
| class MockMethodResult : public flutter::MethodResult<> { | ||
| public: | ||
| MOCK_METHOD(void, SuccessInternal, (const EncodableValue* result), | ||
| (override)); | ||
| MOCK_METHOD(void, ErrorInternal, | ||
| (const std::string& error_code, const std::string& error_message, | ||
| const EncodableValue* details), | ||
| (override)); | ||
| MOCK_METHOD(void, NotImplementedInternal, (), (override)); | ||
| }; | ||
|
|
||
| std::unique_ptr<EncodableValue> CreateArgumentsWithUrl(const std::string& url) { | ||
| EncodableMap args = { | ||
| {EncodableValue("url"), EncodableValue(url)}, | ||
| }; | ||
| return std::make_unique<EncodableValue>(args); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| TEST(UrlLauncherPlugin, CanLaunchSuccessTrue) { | ||
| std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>(); | ||
| std::unique_ptr<MockMethodResult> result = | ||
| std::make_unique<MockMethodResult>(); | ||
|
|
||
| // Return success values from the registery commands. | ||
| HKEY fake_key = reinterpret_cast<HKEY>(1); | ||
| EXPECT_CALL(*system, RegOpenKeyExW) | ||
| .WillOnce(DoAll(SetArgPointee<4>(fake_key), Return(ERROR_SUCCESS))); | ||
| EXPECT_CALL(*system, RegQueryValueExW).WillOnce(Return(ERROR_SUCCESS)); | ||
| EXPECT_CALL(*system, RegCloseKey(fake_key)).WillOnce(Return(ERROR_SUCCESS)); | ||
| // Expect a success response. | ||
| EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(true)))); | ||
|
|
||
| UrlLauncherPlugin plugin(std::move(system)); | ||
| plugin.HandleMethodCall( | ||
| flutter::MethodCall( | ||
| "canLaunch", CreateArgumentsWithUrl("https://some.url.com") | ||
|
|
||
| ), | ||
| std::move(result)); | ||
| } | ||
|
|
||
| TEST(UrlLauncherPlugin, CanLaunchQueryFailure) { | ||
| std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>(); | ||
| std::unique_ptr<MockMethodResult> result = | ||
| std::make_unique<MockMethodResult>(); | ||
|
|
||
| // Return success values from the registery commands, except for the query, | ||
| // to simulate a scheme that is in the registry, but has no URL handler. | ||
| HKEY fake_key = reinterpret_cast<HKEY>(1); | ||
| EXPECT_CALL(*system, RegOpenKeyExW) | ||
| .WillOnce(DoAll(SetArgPointee<4>(fake_key), Return(ERROR_SUCCESS))); | ||
| EXPECT_CALL(*system, RegQueryValueExW).WillOnce(Return(ERROR_FILE_NOT_FOUND)); | ||
| EXPECT_CALL(*system, RegCloseKey(fake_key)).WillOnce(Return(ERROR_SUCCESS)); | ||
| // Expect a success response. | ||
| EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(false)))); | ||
|
|
||
| UrlLauncherPlugin plugin(std::move(system)); | ||
| plugin.HandleMethodCall( | ||
| flutter::MethodCall( | ||
| "canLaunch", CreateArgumentsWithUrl("https://some.url.com") | ||
|
|
||
| ), | ||
| std::move(result)); | ||
| } | ||
|
|
||
| TEST(UrlLauncherPlugin, CanLaunchHandlesOpenFailure) { | ||
| std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>(); | ||
| std::unique_ptr<MockMethodResult> result = | ||
| std::make_unique<MockMethodResult>(); | ||
|
|
||
| // Return failure for opening. | ||
| EXPECT_CALL(*system, RegOpenKeyExW) | ||
| .WillOnce(Return(ERROR_BAD_PATHNAME)); | ||
| // Expect a success response. | ||
| EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(false)))); | ||
|
|
||
| UrlLauncherPlugin plugin(std::move(system)); | ||
| plugin.HandleMethodCall( | ||
| flutter::MethodCall( | ||
| "canLaunch", CreateArgumentsWithUrl("https://some.url.com") | ||
|
|
||
| ), | ||
| std::move(result)); | ||
| } | ||
|
|
||
| TEST(UrlLauncherPlugin, LaunchSuccess) { | ||
| std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>(); | ||
| std::unique_ptr<MockMethodResult> result = | ||
| std::make_unique<MockMethodResult>(); | ||
|
|
||
| // Return a success value (>32) from launching. | ||
| EXPECT_CALL(*system, ShellExecuteW) | ||
| .WillOnce(Return(reinterpret_cast<HINSTANCE>(33))); | ||
| // Expect a success response. | ||
| EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(true)))); | ||
|
|
||
| UrlLauncherPlugin plugin(std::move(system)); | ||
| plugin.HandleMethodCall( | ||
| flutter::MethodCall( | ||
| "launch", CreateArgumentsWithUrl("https://some.url.com") | ||
|
|
||
| ), | ||
| std::move(result)); | ||
| } | ||
|
|
||
| TEST(UrlLauncherPlugin, LaunchReportsFailure) { | ||
| std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>(); | ||
| std::unique_ptr<MockMethodResult> result = | ||
| std::make_unique<MockMethodResult>(); | ||
|
|
||
| // Return a faile value (<=32) from launching. | ||
| EXPECT_CALL(*system, ShellExecuteW) | ||
| .WillOnce(Return(reinterpret_cast<HINSTANCE>(32))); | ||
| // Expect an error response. | ||
| EXPECT_CALL(*result, ErrorInternal); | ||
|
|
||
| UrlLauncherPlugin plugin(std::move(system)); | ||
| plugin.HandleMethodCall( | ||
| flutter::MethodCall( | ||
| "launch", CreateArgumentsWithUrl("https://some.url.com") | ||
|
|
||
| ), | ||
| std::move(result)); | ||
| } | ||
|
|
||
| } // namespace test | ||
| } // namespace url_launcher_plugin | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
packages/url_launcher/url_launcher_windows/windows/url_launcher_plugin_registration.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
| #include <flutter/plugin_registrar_windows.h> | ||
|
|
||
| #include "include/url_launcher_windows/url_launcher_plugin.h" | ||
| #include "url_launcher_plugin.h" | ||
|
|
||
| void UrlLauncherPluginRegisterWithRegistrar( | ||
| FlutterDesktopPluginRegistrarRef registrar) { | ||
| url_launcher_plugin::UrlLauncherPlugin::RegisterWithRegistrar( | ||
| flutter::PluginRegistrarManager::GetInstance() | ||
| ->GetRegistrar<flutter::PluginRegistrarWindows>(registrar)); | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpicky and up to you -- I wonder if a simple fake here that returns hardcoded/deterministic values and maybe a bool for open/close state would be enough, and make the tests themselves a bit more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The results can't be hard-coded, because I wanted to do full failure path testing, which means I would need a variable and a setter for the return value of each method. By the time I did that, the helper would be a lot more complicated than the mock declaration, so I came down on the side of gmock. (This also lets me check a few arguments to the calls trivially, which is a nice bit of added test robustness.)