| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/test/fake_iasync_operation_win.h" |
| |
| #include <asyncinfo.h> |
| #include <wrl/event.h> |
| #include <wrl/implements.h> |
| |
| #include "base/test/async_results_test_values_win.h" |
| #include "testing/gtest/include/gtest/gtest-spi.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using ABI::Windows::Foundation::IAsyncOperation; |
| using ABI::Windows::Foundation::IAsyncOperationCompletedHandler; |
| using Microsoft::WRL::Callback; |
| using Microsoft::WRL::Make; |
| |
| namespace base { |
| namespace win { |
| namespace { |
| constexpr HRESULT kTestError = 0x87654321; |
| } |
| |
| template <typename T> |
| class FakeIAsyncOperationTest : public ::testing::Test {}; |
| |
| TYPED_TEST_SUITE_P(FakeIAsyncOperationTest); |
| |
| TYPED_TEST_P(FakeIAsyncOperationTest, MultipleCompletedHandlers) { |
| auto operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| auto handler = Callback<IAsyncOperationCompletedHandler<TypeParam>>( |
| [](auto async_operation, AsyncStatus async_status) { return S_OK; }); |
| ASSERT_HRESULT_SUCCEEDED(operation->put_Completed(handler.Get())); |
| EXPECT_NONFATAL_FAILURE( |
| ASSERT_HRESULT_SUCCEEDED(operation->put_Completed(handler.Get())); |
| , "put_Completed"); |
| } |
| |
| TYPED_TEST_P(FakeIAsyncOperationTest, MultipleCompletions) { |
| auto operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| base::test::AsyncResultsTestValues<TypeParam> test_values; |
| ASSERT_NO_FATAL_FAILURE( |
| operation->CompleteWithResults(test_values.GetTestValue_T())); |
| // EXPECT_FATAL_FAILURE() can only reference globals and statics. |
| // https://github.com/google/googletest/blob/main/docs/advanced.md#catching-failures |
| static auto test_value_t = test_values.GetTestValue_T(); |
| static auto& static_operation = operation; |
| EXPECT_FATAL_FAILURE(static_operation->CompleteWithResults(test_value_t), |
| "already completed"); |
| |
| operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| static_operation = operation; |
| ASSERT_NO_FATAL_FAILURE(operation->CompleteWithError(E_FAIL)); |
| EXPECT_FATAL_FAILURE(static_operation->CompleteWithError(E_FAIL), |
| "already completed"); |
| |
| operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| static_operation = operation; |
| ASSERT_NO_FATAL_FAILURE(operation->CompleteWithError(E_FAIL)); |
| EXPECT_FATAL_FAILURE(static_operation->CompleteWithResults(test_value_t), |
| "already completed"); |
| |
| operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| static_operation = operation; |
| ASSERT_NO_FATAL_FAILURE( |
| operation->CompleteWithResults(test_values.GetTestValue_T())); |
| EXPECT_FATAL_FAILURE(static_operation->CompleteWithError(E_FAIL), |
| "already completed"); |
| } |
| |
| TYPED_TEST_P(FakeIAsyncOperationTest, CompleteWithResults_WithHandler) { |
| auto operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| |
| bool completed_handler_called = false; |
| ASSERT_HRESULT_SUCCEEDED(operation->put_Completed( |
| Callback<IAsyncOperationCompletedHandler<TypeParam>>( |
| [operation, &completed_handler_called](auto async_operation, |
| AsyncStatus async_status) { |
| completed_handler_called = true; |
| EXPECT_EQ(operation.Get(), async_operation); |
| EXPECT_EQ(async_status, AsyncStatus::Completed); |
| return S_OK; |
| }) |
| .Get())); |
| ASSERT_FALSE(completed_handler_called); |
| AsyncStatus async_status; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Started); |
| HRESULT error_code; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, S_OK); |
| base::test::AsyncResultsTestValues<TypeParam> test_values; |
| auto results = test_values.GetDefaultValue_AsyncResultsT(); |
| EXPECT_NONFATAL_FAILURE( |
| ASSERT_HRESULT_FAILED(operation->GetResults(&results)), "GetResults"); |
| |
| operation->CompleteWithResults(test_values.GetTestValue_AsyncResultsT()); |
| ASSERT_TRUE(completed_handler_called); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Completed); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, S_OK); |
| ASSERT_HRESULT_SUCCEEDED(operation->GetResults(&results)); |
| ASSERT_EQ(results, test_values.GetTestValue_AsyncResultsT()); |
| } |
| |
| TYPED_TEST_P(FakeIAsyncOperationTest, CompleteWithResults_WithoutHandler) { |
| auto operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| |
| AsyncStatus async_status; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Started); |
| HRESULT error_code; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, S_OK); |
| base::test::AsyncResultsTestValues<TypeParam> test_values; |
| auto results = test_values.GetDefaultValue_AsyncResultsT(); |
| EXPECT_NONFATAL_FAILURE( |
| ASSERT_HRESULT_FAILED(operation->GetResults(&results)), "GetResults"); |
| |
| operation->CompleteWithResults(test_values.GetTestValue_AsyncResultsT()); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Completed); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, S_OK); |
| ASSERT_HRESULT_SUCCEEDED(operation->GetResults(&results)); |
| ASSERT_EQ(results, test_values.GetTestValue_AsyncResultsT()); |
| } |
| |
| TYPED_TEST_P(FakeIAsyncOperationTest, CompleteWithError_WithHandler) { |
| auto operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| |
| bool completed_handler_called = false; |
| ASSERT_HRESULT_SUCCEEDED(operation->put_Completed( |
| Callback<IAsyncOperationCompletedHandler<TypeParam>>( |
| [operation, &completed_handler_called](auto async_operation, |
| AsyncStatus async_status) { |
| completed_handler_called = true; |
| EXPECT_EQ(operation.Get(), async_operation); |
| EXPECT_EQ(async_status, AsyncStatus::Error); |
| return S_OK; |
| }) |
| .Get())); |
| ASSERT_FALSE(completed_handler_called); |
| AsyncStatus async_status; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Started); |
| HRESULT error_code; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, S_OK); |
| base::test::AsyncResultsTestValues<TypeParam> test_values; |
| auto results = test_values.GetDefaultValue_AsyncResultsT(); |
| EXPECT_NONFATAL_FAILURE( |
| ASSERT_HRESULT_FAILED(operation->GetResults(&results)), "GetResults"); |
| |
| operation->CompleteWithError(kTestError); |
| ASSERT_TRUE(completed_handler_called); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Error); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, kTestError); |
| ASSERT_HRESULT_FAILED(operation->GetResults(&results)); |
| } |
| |
| TYPED_TEST_P(FakeIAsyncOperationTest, CompleteWithError_WithoutHandler) { |
| auto operation = Make<FakeIAsyncOperation<TypeParam>>(); |
| |
| AsyncStatus async_status; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Started); |
| HRESULT error_code; |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, S_OK); |
| base::test::AsyncResultsTestValues<TypeParam> test_values; |
| auto results = test_values.GetDefaultValue_AsyncResultsT(); |
| EXPECT_NONFATAL_FAILURE( |
| ASSERT_HRESULT_FAILED(operation->GetResults(&results)), "GetResults"); |
| |
| operation->CompleteWithError(kTestError); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_Status(&async_status)); |
| ASSERT_EQ(async_status, AsyncStatus::Error); |
| ASSERT_HRESULT_SUCCEEDED(operation->get_ErrorCode(&error_code)); |
| ASSERT_EQ(error_code, kTestError); |
| ASSERT_HRESULT_FAILED(operation->GetResults(&results)); |
| } |
| |
| REGISTER_TYPED_TEST_SUITE_P(FakeIAsyncOperationTest, |
| MultipleCompletedHandlers, |
| MultipleCompletions, |
| CompleteWithResults_WithHandler, |
| CompleteWithResults_WithoutHandler, |
| CompleteWithError_WithHandler, |
| CompleteWithError_WithoutHandler); |
| |
| INSTANTIATE_TYPED_TEST_SUITE_P(Win, |
| FakeIAsyncOperationTest, |
| base::test::AsyncResultsTestValuesTypes); |
| |
| } // namespace win |
| } // namespace base |