Commit 77109ca5 authored by Hoch Hochkeppel's avatar Hoch Hochkeppel Committed by Commit Bot

WebShare: Add fake DataTransferManager for testing

Adding a class to represent the Windows DataTransferManager APIs within
tests, as well as basic unit tests to validate the test class behaviors.

Bug: 1035527
Change-Id: Id0fcc1c1f98abfa74648e459dc420ca9aad4fecf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2392443Reviewed-by: default avatarEric Willigers <ericwilligers@chromium.org>
Commit-Queue: Hoch Hochkeppel <mhochk@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#804588}
parent fc7d53f1
This diff is collapsed.
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_WEBSHARE_WIN_FAKE_DATA_TRANSFER_MANAGER_H_
#define CHROME_BROWSER_WEBSHARE_WIN_FAKE_DATA_TRANSFER_MANAGER_H_
#include <windows.applicationmodel.datatransfer.h>
#include <wrl/implements.h>
#include <vector>
#include "base/callback_forward.h"
namespace webshare {
// Provides an implementation of IDataTransferManager for use in GTests.
class FakeDataTransferManager
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager> {
public:
FakeDataTransferManager();
FakeDataTransferManager(const FakeDataTransferManager&) = delete;
FakeDataTransferManager& operator=(const FakeDataTransferManager&) = delete;
~FakeDataTransferManager() override;
// ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager:
IFACEMETHODIMP add_DataRequested(
__FITypedEventHandler_2_Windows__CApplicationModel__CDataTransfer__CDataTransferManager_Windows__CApplicationModel__CDataTransfer__CDataRequestedEventArgs*
event_handler,
EventRegistrationToken* event_cookie) override;
IFACEMETHODIMP
remove_DataRequested(EventRegistrationToken event_cookie) override;
IFACEMETHODIMP add_TargetApplicationChosen(
__FITypedEventHandler_2_Windows__CApplicationModel__CDataTransfer__CDataTransferManager_Windows__CApplicationModel__CDataTransfer__CTargetApplicationChosenEventArgs*
eventHandler,
EventRegistrationToken* event_cookie) override;
IFACEMETHODIMP
remove_TargetApplicationChosen(EventRegistrationToken event_cookie) override;
// Returns a callback that captures a reference to the current DataRequested
// event handler and, when invoked, triggers that handler.
//
// If the registered handler changes after this method is called the callback
// will still trigger the previous event handler, not a newly registered one.
base::OnceClosure GetDataRequestedInvoker();
bool HasDataRequestedListener();
private:
struct DataRequestedHandlerEntry {
DataRequestedHandlerEntry();
DataRequestedHandlerEntry(DataRequestedHandlerEntry const& other);
~DataRequestedHandlerEntry();
Microsoft::WRL::ComPtr<
__FITypedEventHandler_2_Windows__CApplicationModel__CDataTransfer__CDataTransferManager_Windows__CApplicationModel__CDataTransfer__CDataRequestedEventArgs>
event_handler_;
int64_t token_value_;
};
std::vector<DataRequestedHandlerEntry> data_requested_event_handlers_;
int64_t latest_token_value_ = 0;
};
} // namespace webshare
#endif // CHROME_BROWSER_WEBSHARE_WIN_FAKE_DATA_TRANSFER_MANAGER_H_
// Copyright 2020 The Chromium 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 "chrome/browser/webshare/win/fake_data_transfer_manager.h"
#include <wrl/event.h>
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/win/core_winrt_util.h"
#include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/gtest/include/gtest/gtest.h"
using ABI::Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs;
using ABI::Windows::ApplicationModel::DataTransfer::DataTransferManager;
using ABI::Windows::ApplicationModel::DataTransfer::IDataRequestedEventArgs;
using ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager;
using ABI::Windows::Foundation::ITypedEventHandler;
using Microsoft::WRL::Callback;
using Microsoft::WRL::ComPtr;
namespace webshare {
// Provides a DataRequested callback and records the number of times it is
// invoked
class DataRequestedTestCallback {
public:
DataRequestedTestCallback() {
auto weak_ptr = weak_factory_.GetWeakPtr();
callback_ = Callback<
ITypedEventHandler<DataTransferManager*, DataRequestedEventArgs*>>(
[weak_ptr](IDataTransferManager* data_transfer_manager,
IDataRequestedEventArgs* event_args) -> HRESULT {
if (weak_ptr.get())
weak_ptr->invocation_count_++;
return S_OK;
});
}
int invocation_count_ = 0;
ComPtr<ITypedEventHandler<DataTransferManager*, DataRequestedEventArgs*>>
callback_;
private:
base::WeakPtrFactory<DataRequestedTestCallback> weak_factory_{this};
};
class FakeDataTransferManagerTest : public ::testing::Test {
protected:
bool IsSupportedEnvironment() {
return base::win::ResolveCoreWinRTDelayload() &&
base::win::ScopedHString::ResolveCoreWinRTStringDelayload();
}
void SetUp() override {
if (!IsSupportedEnvironment())
return;
ASSERT_HRESULT_SUCCEEDED(
base::win::RoInitialize(RO_INIT_TYPE::RO_INIT_MULTITHREADED));
fake_data_transfer_manager_ =
Microsoft::WRL::Make<FakeDataTransferManager>();
}
void TearDown() override {
if (!IsSupportedEnvironment())
return;
base::win::RoUninitialize();
}
ComPtr<FakeDataTransferManager> fake_data_transfer_manager_;
};
TEST_F(FakeDataTransferManagerTest, RemovingHandlerForInvalidToken) {
if (!IsSupportedEnvironment())
return;
// Validate removing an invalid token both fails and creates a test failure
// when there is no listener
EventRegistrationToken invalid_token;
EXPECT_NONFATAL_FAILURE(
ASSERT_HRESULT_FAILED(
fake_data_transfer_manager_->remove_DataRequested(invalid_token)),
"remove_DataRequested");
invalid_token.value = 123;
EXPECT_NONFATAL_FAILURE(
ASSERT_HRESULT_FAILED(
fake_data_transfer_manager_->remove_DataRequested(invalid_token)),
"remove_DataRequested");
// Validate removing an invalid token both fails and creates a test failure
// when there is a listener
EventRegistrationToken valid_token;
DataRequestedTestCallback test_callback;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
test_callback.callback_.Get(), &valid_token));
EXPECT_NONFATAL_FAILURE(
ASSERT_HRESULT_FAILED(
fake_data_transfer_manager_->remove_DataRequested(invalid_token)),
"remove_DataRequested");
// Validate removing a valid token is successful only once, failing and
// creating a test failure on repeated uses
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(valid_token));
EXPECT_NONFATAL_FAILURE(
ASSERT_HRESULT_FAILED(
fake_data_transfer_manager_->remove_DataRequested(valid_token)),
"remove_DataRequested");
}
TEST_F(FakeDataTransferManagerTest, OutOfOrderEventUnsubscribing) {
if (!IsSupportedEnvironment())
return;
ASSERT_FALSE(fake_data_transfer_manager_->HasDataRequestedListener());
DataRequestedTestCallback callback_1;
EventRegistrationToken token_1;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
callback_1.callback_.Get(), &token_1));
ASSERT_TRUE(fake_data_transfer_manager_->HasDataRequestedListener());
DataRequestedTestCallback callback_2;
EventRegistrationToken token_2;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
callback_2.callback_.Get(), &token_2));
ASSERT_TRUE(fake_data_transfer_manager_->HasDataRequestedListener());
DataRequestedTestCallback callback_3;
EventRegistrationToken token_3;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
callback_3.callback_.Get(), &token_3));
ASSERT_TRUE(fake_data_transfer_manager_->HasDataRequestedListener());
ASSERT_EQ(callback_1.invocation_count_, 0);
ASSERT_EQ(callback_2.invocation_count_, 0);
ASSERT_EQ(callback_3.invocation_count_, 0);
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token_2));
ASSERT_TRUE(fake_data_transfer_manager_->HasDataRequestedListener());
std::move(fake_data_transfer_manager_->GetDataRequestedInvoker()).Run();
ASSERT_EQ(callback_1.invocation_count_, 0);
ASSERT_EQ(callback_2.invocation_count_, 0);
ASSERT_EQ(callback_3.invocation_count_, 1);
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token_3));
ASSERT_TRUE(fake_data_transfer_manager_->HasDataRequestedListener());
std::move(fake_data_transfer_manager_->GetDataRequestedInvoker()).Run();
ASSERT_EQ(callback_1.invocation_count_, 1);
ASSERT_EQ(callback_2.invocation_count_, 0);
ASSERT_EQ(callback_3.invocation_count_, 1);
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token_1));
ASSERT_FALSE(fake_data_transfer_manager_->HasDataRequestedListener());
EXPECT_NONFATAL_FAILURE(
fake_data_transfer_manager_->GetDataRequestedInvoker(),
"GetDataRequestedInvoker");
}
TEST_F(FakeDataTransferManagerTest, OutOfOrderEventInvocation) {
if (!IsSupportedEnvironment())
return;
DataRequestedTestCallback callback_1;
EventRegistrationToken token_1;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
callback_1.callback_.Get(), &token_1));
auto callback_1_invoker =
fake_data_transfer_manager_->GetDataRequestedInvoker();
DataRequestedTestCallback callback_2;
EventRegistrationToken token_2;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
callback_2.callback_.Get(), &token_2));
auto callback_2_invoker =
fake_data_transfer_manager_->GetDataRequestedInvoker();
DataRequestedTestCallback callback_3;
EventRegistrationToken token_3;
ASSERT_HRESULT_SUCCEEDED(fake_data_transfer_manager_->add_DataRequested(
callback_3.callback_.Get(), &token_3));
auto callback_3_invoker =
fake_data_transfer_manager_->GetDataRequestedInvoker();
ASSERT_EQ(callback_1.invocation_count_, 0);
ASSERT_EQ(callback_2.invocation_count_, 0);
ASSERT_EQ(callback_3.invocation_count_, 0);
std::move(callback_2_invoker).Run();
ASSERT_EQ(callback_1.invocation_count_, 0);
ASSERT_EQ(callback_2.invocation_count_, 1);
ASSERT_EQ(callback_3.invocation_count_, 0);
std::move(callback_3_invoker).Run();
ASSERT_EQ(callback_1.invocation_count_, 0);
ASSERT_EQ(callback_2.invocation_count_, 1);
ASSERT_EQ(callback_3.invocation_count_, 1);
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token_1));
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token_2));
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token_3));
std::move(callback_1_invoker).Run();
ASSERT_EQ(callback_1.invocation_count_, 1);
ASSERT_EQ(callback_2.invocation_count_, 1);
ASSERT_EQ(callback_3.invocation_count_, 1);
}
} // namespace webshare
...@@ -296,7 +296,11 @@ static_library("test_support") { ...@@ -296,7 +296,11 @@ static_library("test_support") {
} }
if (is_win) { if (is_win) {
sources += [ "//chrome/app/chrome_crash_reporter_client_win.cc" ] sources += [
"../browser/webshare/win/fake_data_transfer_manager.cc",
"../browser/webshare/win/fake_data_transfer_manager.h",
"//chrome/app/chrome_crash_reporter_client_win.cc",
]
public_deps += [ public_deps += [
"//chrome/install_static/test:test_support", "//chrome/install_static/test:test_support",
"//components/crash/core/app", "//components/crash/core/app",
...@@ -5544,6 +5548,7 @@ test("unit_tests") { ...@@ -5544,6 +5548,7 @@ test("unit_tests") {
"../browser/notifications/win/notification_image_retainer_unittest.cc", "../browser/notifications/win/notification_image_retainer_unittest.cc",
"../browser/notifications/win/notification_template_builder_unittest.cc", "../browser/notifications/win/notification_template_builder_unittest.cc",
"../browser/ui/views/uninstall_view_unittest.cc", "../browser/ui/views/uninstall_view_unittest.cc",
"../browser/webshare/win/fake_data_transfer_manager_unittest.cc",
] ]
deps += [ deps += [
"//chrome:other_version", "//chrome:other_version",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment