mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 16:26:10 +03:00
188 lines
5.5 KiB
C++
188 lines
5.5 KiB
C++
|
// Copyright 2018 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 "base/win/async_operation.h"
|
||
|
|
||
|
#include <utility>
|
||
|
|
||
|
#include "base/test/gtest_util.h"
|
||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||
|
|
||
|
namespace WRL = Microsoft::WRL;
|
||
|
|
||
|
using ABI::Windows::Foundation::IAsyncOperation;
|
||
|
using ABI::Windows::Foundation::IAsyncOperationCompletedHandler;
|
||
|
|
||
|
// In order to exercise the interface logic of AsyncOperation we define an empty
|
||
|
// dummy interface, its implementation, and the necessary boilerplate to hook it
|
||
|
// up with IAsyncOperation and IAsyncOperationCompletedHandler.
|
||
|
namespace {
|
||
|
|
||
|
// Chosen by fair `uuidgen` invocation. Also applies to the UUIDs below.
|
||
|
MIDL_INTERFACE("756358C7-8083-4D78-9D27-9278B76096d4")
|
||
|
IFooBar : public IInspectable{};
|
||
|
|
||
|
class FooBar
|
||
|
: public WRL::RuntimeClass<
|
||
|
WRL::RuntimeClassFlags<WRL::WinRt | WRL::InhibitRoOriginateError>,
|
||
|
IFooBar> {};
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
namespace ABI {
|
||
|
namespace Windows {
|
||
|
namespace Foundation {
|
||
|
|
||
|
// Provide the required template specializations to register
|
||
|
// IAsyncOperation<Foobar*> as an AggregateType. This is similar to how it is
|
||
|
// done for UWP classes.
|
||
|
template <>
|
||
|
struct DECLSPEC_UUID("124858e4-f97e-409c-86ae-418c4781144c")
|
||
|
IAsyncOperation<FooBar*>
|
||
|
: IAsyncOperation_impl<Internal::AggregateType<FooBar*, IFooBar*>> {
|
||
|
static const wchar_t* z_get_rc_name_impl() {
|
||
|
return L"Windows.Foundation.IAsyncOperation<FooBar>";
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <>
|
||
|
struct DECLSPEC_UUID("9e49373c-200c-4715-abd7-4214ba669c81")
|
||
|
IAsyncOperationCompletedHandler<FooBar*>
|
||
|
: IAsyncOperationCompletedHandler_impl<
|
||
|
Internal::AggregateType<FooBar*, IFooBar*>> {
|
||
|
static const wchar_t* z_get_rc_name_impl() {
|
||
|
return L"Windows.Foundation.AsyncOperationCompletedHandler<FooBar>";
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#ifdef NTDDI_WIN10_VB // Windows 10.0.19041
|
||
|
// Specialization templates that used to be in windows.foundation.h, removed in
|
||
|
// the 10.0.19041.0 SDK, so placed here instead.
|
||
|
template <>
|
||
|
struct __declspec(uuid("968b9665-06ed-5774-8f53-8edeabd5f7b5"))
|
||
|
IAsyncOperation<int> : IAsyncOperation_impl<int> {};
|
||
|
|
||
|
template <>
|
||
|
struct __declspec(uuid("d60cae9d-88cb-59f1-8576-3fba44796be8"))
|
||
|
IAsyncOperationCompletedHandler<int>
|
||
|
: IAsyncOperationCompletedHandler_impl<int> {};
|
||
|
#endif
|
||
|
|
||
|
} // namespace Foundation
|
||
|
} // namespace Windows
|
||
|
} // namespace ABI
|
||
|
|
||
|
namespace base {
|
||
|
namespace win {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
// Utility method to add a completion callback to |async_op|. |*called_cb| will
|
||
|
// be set to true once the callback is invoked.
|
||
|
template <typename T>
|
||
|
void PutCallback(AsyncOperation<T>* async_op, bool* called_cb) {
|
||
|
async_op->put_Completed(
|
||
|
WRL::Callback<IAsyncOperationCompletedHandler<T>>(
|
||
|
[=](IAsyncOperation<T>* iasync_op, AsyncStatus status) {
|
||
|
EXPECT_EQ(async_op, iasync_op);
|
||
|
*called_cb = true;
|
||
|
return S_OK;
|
||
|
})
|
||
|
.Get());
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
TEST(AsyncOperationTest, TestInt) {
|
||
|
bool called_cb = false;
|
||
|
|
||
|
auto int_op = WRL::Make<AsyncOperation<int>>();
|
||
|
PutCallback(int_op.Get(), &called_cb);
|
||
|
|
||
|
int results;
|
||
|
EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
|
||
|
EXPECT_FALSE(called_cb);
|
||
|
int_op->callback().Run(123);
|
||
|
|
||
|
EXPECT_TRUE(called_cb);
|
||
|
EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
|
||
|
EXPECT_EQ(123, results);
|
||
|
|
||
|
// GetResults should be idempotent.
|
||
|
EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
|
||
|
EXPECT_EQ(123, results);
|
||
|
}
|
||
|
|
||
|
TEST(AsyncOperationTest, TestBool) {
|
||
|
bool called_cb = false;
|
||
|
|
||
|
auto bool_op = WRL::Make<AsyncOperation<bool>>();
|
||
|
PutCallback(bool_op.Get(), &called_cb);
|
||
|
|
||
|
// AsyncOperation<bool> is an aggregate of bool and boolean, and requires a
|
||
|
// pointer to the latter to get the results.
|
||
|
boolean results;
|
||
|
EXPECT_TRUE(FAILED(bool_op->GetResults(&results)));
|
||
|
EXPECT_FALSE(called_cb);
|
||
|
bool_op->callback().Run(true);
|
||
|
|
||
|
EXPECT_TRUE(called_cb);
|
||
|
EXPECT_TRUE(SUCCEEDED(bool_op->GetResults(&results)));
|
||
|
EXPECT_TRUE(results);
|
||
|
}
|
||
|
|
||
|
TEST(AsyncOperationTest, TestInterface) {
|
||
|
bool called_cb = false;
|
||
|
|
||
|
auto foobar_op = WRL::Make<AsyncOperation<FooBar*>>();
|
||
|
PutCallback(foobar_op.Get(), &called_cb);
|
||
|
|
||
|
// AsyncOperation<FooBar*> is an aggregate of FooBar* and IFooBar*.
|
||
|
WRL::ComPtr<IFooBar> results;
|
||
|
EXPECT_TRUE(FAILED(foobar_op->GetResults(&results)));
|
||
|
EXPECT_FALSE(called_cb);
|
||
|
|
||
|
auto foobar = WRL::Make<FooBar>();
|
||
|
IFooBar* foobar_ptr = foobar.Get();
|
||
|
foobar_op->callback().Run(std::move(foobar));
|
||
|
|
||
|
EXPECT_TRUE(called_cb);
|
||
|
EXPECT_TRUE(SUCCEEDED(foobar_op->GetResults(&results)));
|
||
|
EXPECT_EQ(foobar_ptr, results.Get());
|
||
|
}
|
||
|
|
||
|
TEST(AsyncOperationTest, TestIdempotence) {
|
||
|
bool called_cb = false;
|
||
|
|
||
|
auto int_op = WRL::Make<AsyncOperation<int>>();
|
||
|
PutCallback(int_op.Get(), &called_cb);
|
||
|
|
||
|
int results;
|
||
|
EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
|
||
|
EXPECT_FALSE(called_cb);
|
||
|
// Calling GetResults twice shouldn't change the result.
|
||
|
EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
|
||
|
EXPECT_FALSE(called_cb);
|
||
|
|
||
|
int_op->callback().Run(42);
|
||
|
|
||
|
EXPECT_TRUE(called_cb);
|
||
|
EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
|
||
|
EXPECT_EQ(42, results);
|
||
|
// Calling GetResults twice shouldn't change the result.
|
||
|
EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
|
||
|
EXPECT_EQ(42, results);
|
||
|
}
|
||
|
|
||
|
TEST(AsyncOperationTest, DoubleCallbackFails) {
|
||
|
auto int_op = WRL::Make<AsyncOperation<int>>();
|
||
|
auto cb = int_op->callback();
|
||
|
|
||
|
// Obtaining another callback should result in a DCHECK failure.
|
||
|
EXPECT_DCHECK_DEATH(int_op->callback());
|
||
|
}
|
||
|
|
||
|
} // namespace win
|
||
|
} // namespace base
|