-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Quick prototype to test out an app service on top of #3552. Working locally with MSTest, though some oddities when trying to shore-up timing guards, unknown unhandled exception... Went back to looser code and working well. Not sure if this resolves the TAEF error we're seeing in #3552 yet, but wanted to see if this provided different info. Lots to do here to clean this work up, as I just hacked things together to see if it would work, but looking very promising. This should allow us to optimize the start-up performance of the app more easily as well as have a bi-directional communication pipe between our two processes for logging messages from the host within the harness/CI logs. 🎉 FYI @RosarioPulella
- Loading branch information
Showing
27 changed files
with
889 additions
and
174 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using Microsoft.Toolkit.Mvvm.Messaging; | ||
using UITests.App.Pages; | ||
using Windows.ApplicationModel.Activation; | ||
using Windows.ApplicationModel.AppService; | ||
using Windows.ApplicationModel.Background; | ||
using Windows.Foundation.Collections; | ||
using Windows.UI.Xaml; | ||
using Windows.UI.Xaml.Controls; | ||
|
||
namespace UITests.App | ||
{ | ||
/// <summary> | ||
/// This file contains part of the app related to the AppService for communication between this test host and the test harness processes. | ||
/// </summary> | ||
public sealed partial class App | ||
{ | ||
private AppServiceConnection _appServiceConnection; | ||
private BackgroundTaskDeferral _appServiceDeferral; | ||
|
||
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args) | ||
{ | ||
base.OnBackgroundActivated(args); | ||
IBackgroundTaskInstance taskInstance = args.TaskInstance; | ||
AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails; | ||
_appServiceDeferral = taskInstance.GetDeferral(); | ||
taskInstance.Canceled += OnAppServicesCanceled; | ||
_appServiceConnection = appService.AppServiceConnection; | ||
_appServiceConnection.RequestReceived += OnAppServiceRequestReceived; | ||
_appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed; | ||
} | ||
|
||
private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) | ||
{ | ||
AppServiceDeferral messageDeferral = args.GetDeferral(); | ||
ValueSet message = args.Request.Message; | ||
string cmd = message["Command"] as string; | ||
|
||
try | ||
{ | ||
// Return the data to the caller. | ||
if (cmd == "Start") | ||
{ | ||
var pageName = message["Page"] as string; | ||
|
||
Log.Comment("Received request for Page: {0}", pageName); | ||
|
||
ValueSet returnMessage = new ValueSet(); | ||
|
||
// We await the OpenPage method to ensure the navigation has finished. | ||
if (await WeakReferenceMessenger.Default.Send(new RequestPageMessage(pageName))) | ||
{ | ||
returnMessage.Add("Status", "OK"); | ||
} | ||
else | ||
{ | ||
returnMessage.Add("Status", "BAD"); | ||
} | ||
|
||
await args.Request.SendResponseAsync(returnMessage); | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
// Your exception handling code here. | ||
Log.Error("Exception processing request: {0}", e.Message); | ||
} | ||
finally | ||
{ | ||
// Complete the deferral so that the platform knows that we're done responding to the app service call. | ||
// Note: for error handling: this must be called even if SendResponseAsync() throws an exception. | ||
messageDeferral.Complete(); | ||
} | ||
} | ||
|
||
private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) | ||
{ | ||
_appServiceDeferral.Complete(); | ||
} | ||
|
||
private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args) | ||
{ | ||
_appServiceDeferral.Complete(); | ||
} | ||
|
||
public async void SendLogMessage(string level, string msg) | ||
{ | ||
var message = new ValueSet(); | ||
message.Add("Command", "Log"); | ||
message.Add("Level", level); | ||
message.Add("Message", msg); | ||
|
||
await _appServiceConnection.SendMessageAsync(message); | ||
|
||
// TODO: do we care if we have a problem here? | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,4 @@ | ||
<Application | ||
x:Class="UITests.App.App" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="using:UITests.App"> | ||
|
||
</Application> | ||
<Application x:Class="UITests.App.App" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="using:UITests.App" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Page x:Class="UITests.App.MainTestHost" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
xmlns:testhelpers="using:AppTestAutomationHelpers" | ||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" | ||
mc:Ignorable="d"> | ||
|
||
<Grid> | ||
<testhelpers:TestAutomationHelpersPanel /> | ||
|
||
<Frame x:Name="navigationFrame" | ||
Navigated="NavigationFrame_Navigated" | ||
NavigationFailed="NavigationFrame_NavigationFailed" /> | ||
</Grid> | ||
</Page> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Reflection; | ||
using System.Threading.Tasks; | ||
using Microsoft.Toolkit.Mvvm.Messaging; | ||
using Microsoft.Toolkit.Uwp.Extensions; | ||
using UITests.App.Pages; | ||
using Windows.System; | ||
using Windows.UI.Xaml; | ||
using Windows.UI.Xaml.Controls; | ||
using Windows.UI.Xaml.Media.Animation; | ||
|
||
namespace UITests.App | ||
{ | ||
/// <summary> | ||
/// MainPage hosting all other test pages. | ||
/// </summary> | ||
public sealed partial class MainTestHost : IRecipient<RequestPageMessage> | ||
{ | ||
private DispatcherQueue _queue; | ||
|
||
private Assembly _executingAssembly = Assembly.GetExecutingAssembly(); | ||
|
||
private TaskCompletionSource<bool> _loadingStateTask; | ||
|
||
public MainTestHost() | ||
{ | ||
InitializeComponent(); | ||
|
||
WeakReferenceMessenger.Default.Register<RequestPageMessage>(this); | ||
|
||
_queue = DispatcherQueue.GetForCurrentThread(); | ||
} | ||
|
||
public void Receive(RequestPageMessage message) | ||
{ | ||
// Reply with task back to so it can be properly awaited link:App.AppService.xaml.cs#L56 | ||
message.Reply(OpenPage(message.PageName)); | ||
} | ||
|
||
private async Task<bool> OpenPage(string pageName) | ||
{ | ||
try | ||
{ | ||
Log.Comment("Trying to Load Page: " + pageName); | ||
|
||
_loadingStateTask = new TaskCompletionSource<bool>(); | ||
|
||
// Ensure we're on the UI thread as we'll be called from the AppService now. | ||
_ = _queue.EnqueueAsync(() => | ||
{ | ||
// Navigate without extra animations | ||
navigationFrame.Navigate(FindPageType(pageName), new SuppressNavigationTransitionInfo()); | ||
}); | ||
|
||
// Wait for load to complete | ||
await _loadingStateTask.Task; | ||
} | ||
catch (Exception e) | ||
{ | ||
Log.Error("Exception Loading Page {0}: {1} ", pageName, e.Message); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private Type FindPageType(string pageName) | ||
{ | ||
try | ||
{ | ||
return _executingAssembly.GetType("UITests.App.Pages." + pageName); | ||
} | ||
catch (Exception e) | ||
{ | ||
Log.Error("Exception Finding Page {0}: {1} ", pageName, e.Message); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private void NavigationFrame_Navigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e) | ||
{ | ||
Log.Comment("Navigated to Page {0}", e.SourcePageType.FullName); | ||
if (e.Content is Page page) | ||
{ | ||
if (page.IsLoaded) | ||
{ | ||
Log.Comment("Loaded Page {0}", e.SourcePageType.FullName); | ||
_loadingStateTask.SetResult(true); | ||
} | ||
else | ||
{ | ||
page.Loaded += this.Page_Loaded; | ||
} | ||
} | ||
} | ||
|
||
private void Page_Loaded(object sender, RoutedEventArgs e) | ||
{ | ||
var page = sender as Page; | ||
|
||
page.Loaded -= Page_Loaded; | ||
|
||
Log.Comment("Loaded Page (E) {0}", page.GetType().FullName); | ||
_loadingStateTask.SetResult(true); | ||
} | ||
|
||
private void NavigationFrame_NavigationFailed(object sender, Windows.UI.Xaml.Navigation.NavigationFailedEventArgs e) | ||
{ | ||
Log.Error("Failed to navigate to page {0}", e.SourcePageType.FullName); | ||
_loadingStateTask.SetResult(false); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using Microsoft.Toolkit.Mvvm.Messaging.Messages; | ||
|
||
namespace UITests.App | ||
{ | ||
public sealed class RequestPageMessage : AsyncRequestMessage<bool> | ||
{ | ||
public RequestPageMessage(string name) | ||
{ | ||
PageName = name; | ||
} | ||
|
||
public string PageName { get; } | ||
} | ||
} |
Oops, something went wrong.