// 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 #include #include #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 class FakeIAsyncOperationTest : public ::testing::Test {}; TYPED_TEST_SUITE_P(FakeIAsyncOperationTest); TYPED_TEST_P(FakeIAsyncOperationTest, MultipleCompletedHandlers) { auto operation = Make>(); auto handler = Callback>( [](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>(); base::test::AsyncResultsTestValues 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>(); static_operation = operation; ASSERT_NO_FATAL_FAILURE(operation->CompleteWithError(E_FAIL)); EXPECT_FATAL_FAILURE(static_operation->CompleteWithError(E_FAIL), "already completed"); operation = Make>(); static_operation = operation; ASSERT_NO_FATAL_FAILURE(operation->CompleteWithError(E_FAIL)); EXPECT_FATAL_FAILURE(static_operation->CompleteWithResults(test_value_t), "already completed"); operation = Make>(); 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>(); bool completed_handler_called = false; ASSERT_HRESULT_SUCCEEDED(operation->put_Completed( Callback>( [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 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>(); 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 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>(); bool completed_handler_called = false; ASSERT_HRESULT_SUCCEEDED(operation->put_Completed( Callback>( [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 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>(); 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 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