UIA Operation Abstraction library: resolve any results alredy available before a remote unhandled exception (#94)

In pr #91, new exceptions were raised by scope.Resolve such as InstructionLimitExceeded and UnhandledException. In the case of InstructionLimitExceeded, any result variables already calculated before the limit was hit will be still resolved, making them available locally. 
This pr now resolves any possible variables for UnhandledException as well.
This now means that it is possible to track the progress of a remote operation either via remote logging for example, and even if an UnhandledException is raised from a COM call, or deliberately through a call to AbortOperationWithHresult, the variable/s holding the remote logging will still be available.
This then enables the pattern of failing fast in a remote operation much nicer, as you can just abort at any point but still have access to previous variables.
Tests for unhandledException have been added/updated to ensure result variables are resolved.
This commit is contained in:
Michael Curran 2022-05-27 09:08:23 +10:00 коммит произвёл GitHub
Родитель 2ce5d73eb4
Коммит d8c87fae21
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 51 добавлений и 3 удалений

Просмотреть файл

@ -2803,7 +2803,7 @@ namespace UiaOperationAbstractionTests
}
// Test that a runtime error within a remote operation causes an UnhandledRemoteException in resolve.
TEST_METHOD(ResolveThrowsUnhandledRemoteException)
TEST_METHOD(ResolveThrowsUnhandledRemoteExceptionForRuntimeError)
{
auto guard = InitializeUiaOperationAbstraction(true);
@ -2816,8 +2816,12 @@ namespace UiaOperationAbstractionTests
UiaElement element = calc;
UiaArray<UiaInt> a;
// Accessing an element of an empty array should cause an E_BOUNDS error
a.Append(42);
auto x = a.GetAt(0);
// Accessing an out of bounds index of an array should raise E_BOUNDS
auto y = a.GetAt(1);
scope.BindResult(x);
Assert::ExpectException<UnhandledRemoteException>([&]()
{
@ -2831,6 +2835,49 @@ namespace UiaOperationAbstractionTests
throw;
}
});
// Verify that we still can access the result of a variable calculated before the exception
Assert::AreEqual(static_cast<int>(x), 42);
}
// Test that aborting an operation causes an UnhandledRemoteException in resolve,
// and that calculated results before the abort are still available.
TEST_METHOD(ResolveThrowsUnhandledRemoteExceptionOnAboart)
{
auto guard = InitializeUiaOperationAbstraction(true);
ModernApp app(L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App");
app.Activate();
auto calc = WaitForElementFocus(L"Display is 0");
auto scope = UiaOperationScope::StartNew();
UiaElement element = calc;
UiaArray<UiaInt> a;
a.Append(42);
auto x = a.GetAt(0);
// Aborting a remote operation should result in an Unhandled exception
const HRESULT myError = -1234;
scope.AbortOperationWithHresult(myError);
scope.BindResult(x);
Assert::ExpectException<UnhandledRemoteException>([&]()
{
try
{
scope.Resolve();
}
catch(winrt::hresult_error& e)
{
Assert::AreEqual(myError, static_cast<HRESULT>(e.code()));
throw;
}
});
// Verify that we still can access the result of a variable calculated before the exception
Assert::AreEqual(static_cast<int>(x), 42);
}
// Test that an execution failure within a remote operation causes an ExecutionFailureException in resolve.

Просмотреть файл

@ -2370,11 +2370,12 @@ namespace UiaOperationAbstraction
}
// Fetch bound results on success, but also
// instruction limit exceeded,
// instruction limit exceeded and UnhandledException,
// As we know certainly some of the remote operation did execute.
if (
status == winrt::Windows::UI::UIAutomation::Core::AutomationRemoteOperationStatus::Success
|| status == winrt::Windows::UI::UIAutomation::Core::AutomationRemoteOperationStatus::InstructionLimitExceeded
|| status == winrt::Windows::UI::UIAutomation::Core::AutomationRemoteOperationStatus::UnhandledException
)
{
for (auto& resolver : remoteOperationResolvers)