Skip to content

Commit

Permalink
Maui win UI startup testing (#2393)
Browse files Browse the repository at this point in the history
* First iteration of maui desktop changes/support

Add platform.

Add the WinUI Parser and WinUI Metric type.

Change WinUI test to use the WinUI startup metric and removed self contained from pre.py. Still need to figure out the exact way that the WindowsAppSDK will be installed/supported with the app.

Add the installation of the newer windowsappsdk.

Cleaned up pre.py command code.

Add maui desktop scenario to scenarios for testing while figuring out final format.

Only run winui on windows.

* Add Maui Blazor Desktop (#2526)

* Add `mauiblazordesktop` scenario
* Add WinUIBlazor startup parser
* Update release/6.0 to use dotnet version 6.0.4xx

* Reformat mauidesktop test.py to more closely match release/6.0 and remove comment from pre.py.

* Update blazor to use net7 rollback file.

* Update desktop blazor maui scenario to use PERFLAB_Framework instead of just _Framework for the target framework.

* Move the windows condition up to minimize duplicate places that it is and move the Maui blazor desktop work items into the same group as the default windows desktop ones.
  • Loading branch information
LoopedBard3 authored Aug 19, 2022
1 parent 80a42ee commit 89e9ed2
Show file tree
Hide file tree
Showing 13 changed files with 439 additions and 8 deletions.
26 changes: 26 additions & 0 deletions eng/performance/scenarios.proj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,32 @@
</HelixWorkItem>
</ItemGroup>

<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<!-- SOD & Device Startup for Windows Desktop MAUI -->
<HelixWorkItem Include="SOD - Desktop Maui Unpackaged">
<PayloadDirectory>$(ScenariosDir)mauidesktop</PayloadDirectory>
<PreCommands>$(Python) pre.py publish -c Release -f $(PERFLAB_Framework)-windows10.0.19041.0</PreCommands>
<Command>$(Python) test.py sod --scenario-name &quot;%(Identity)&quot;</Command>
</HelixWorkItem>
<HelixWorkItem Include="Device Startup - Desktop Maui Default">
<PayloadDirectory>$(ScenariosDir)mauidesktop</PayloadDirectory>
<PreCommands>$(Python) pre.py publish -c Release -f $(PERFLAB_Framework)-windows10.0.19041.0</PreCommands>
<Command>$(Python) test.py startup --scenario-name &quot;%(Identity)&quot;</Command>
</HelixWorkItem>

<!-- SOD & Device Startup for Windows Desktop MAUI Blazor -->
<HelixWorkItem Include="SOD - Desktop Maui Blazor Unpackaged">
<PayloadDirectory>$(ScenariosDir)mauiblazordesktop</PayloadDirectory>
<PreCommands>$(Python) pre.py publish -c Release -f $(PERFLAB_Framework)-windows10.0.19041.0</PreCommands>
<Command>$(Python) test.py sod --scenario-name &quot;%(Identity)&quot;</Command>
</HelixWorkItem>
<HelixWorkItem Include="Device Startup - Desktop Maui Blazor Default">
<PayloadDirectory>$(ScenariosDir)mauiblazordesktop</PayloadDirectory>
<PreCommands>$(Python) pre.py publish -c Release -f $(PERFLAB_Framework)-windows10.0.19041.0</PreCommands>
<Command>$(Python) test.py startup --scenario-name &quot;%(Identity)&quot;</Command>
</HelixWorkItem>
</ItemGroup>

<!--
This is useful for local testing to print the produced helix items
To use this when you are changing how items are produced, uncomment the target
Expand Down
9 changes: 6 additions & 3 deletions scripts/dotnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,17 +381,20 @@ def new(template: str,
force: bool = False,
exename: str = None,
language: str = None,
no_https: bool = False
no_https: bool = False,
no_restore: bool = True
):
'''
Creates a new project with the specified template
'''
cmdline = [
'dotnet', 'new',
template,
'--output', output_dir,
'--no-restore'
'--output', output_dir
]
if no_restore:
cmdline += ['--no-restore']

if force:
cmdline += ['--force']

Expand Down
9 changes: 9 additions & 0 deletions src/scenarios/mauiblazordesktop/post.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'''
post cleanup script
'''

from shared.postcommands import PostCommands, clean_directories

postcommands = PostCommands()
clean_directories()
postcommands.uninstall_workload('maui')
86 changes: 86 additions & 0 deletions src/scenarios/mauiblazordesktop/pre.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'''
pre-command: Example call 'python .\pre.py publish -f net7.0-windows10.0.19041.0 -c Release'
'''
import shutil
import subprocess
import sys
import os
from performance.logger import setup_loggers, getLogger
from shared.codefixes import insert_after
from shared.precommands import PreCommands
from shared import const
from test import EXENAME
import requests
import winreg

setup_loggers(True)
NugetURL = 'https://raw.githubusercontent.com/dotnet/maui/main/NuGet.config'
WebViewURL = 'https://go.microsoft.com/fwlink/p/?LinkId=2124703' # Obtained from https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section
WebViewInstalled = False
NugetFile = requests.get(NugetURL)
open('./Nuget.config', 'wb').write(NugetFile.content)

lmkey = r"SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
cukey = r"Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as hklm_hive:
try:
with winreg.OpenKey(hklm_hive, lmkey) as openkey:
pvvalue = winreg.QueryValueEx(openkey, 'pv')[0]
if pvvalue and pvvalue != '' and pvvalue != '0.0.0.0':
WebViewInstalled = True
getLogger().info(f"WebView Found; pvvalue(version) {pvvalue}")
except:
getLogger().warning("WebView not verified in Local_Machine Registry")
if not WebViewInstalled:
try:
with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as hkcu_hive:
with winreg.OpenKey(hkcu_hive, cukey) as openkey:
pvvalue = winreg.QueryValueEx(openkey, 'pv')[0]
if pvvalue and pvvalue != '' and pvvalue != '0.0.0.0':
WebViewInstalled = True
getLogger().info(f"WebView Found; pvvalue(version) {pvvalue}")
except:
getLogger().warning("WebView not verified in Current_Machine Registry")
if not WebViewInstalled:
getLogger().info("Installing WebView2")
WebViewInstallFile = requests.get(WebViewURL)
open('./MicrosoftEdgeWebview2Setup.exe', 'wb').write(WebViewInstallFile.content)
subprocess.run(['powershell', '-Command', r'Start-Process "./MicrosoftEdgeWebview2Setup.exe" -Wait'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as hklm_hive:
try:
with winreg.OpenKey(hklm_hive, lmkey) as openkey:
pvvalue = winreg.QueryValueEx(openkey, 'pv')[0]
if pvvalue and pvvalue != '' and pvvalue != '0.0.0.0':
WebViewInstalled = True
getLogger().info(f"WebView Found; pvvalue(version) {pvvalue}")
except:
getLogger().warning("WebView not verified in Local_Machine Registry")
if not WebViewInstalled:
try:
with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as hkcu_hive:
with winreg.OpenKey(hkcu_hive, cukey) as openkey:
pvvalue = winreg.QueryValueEx(openkey, 'pv')[0]
if pvvalue and pvvalue != '' and pvvalue != '0.0.0.0':
WebViewInstalled = True
getLogger().info(f"WebView Found; pvvalue(version) {pvvalue}")
except:
getLogger().warning("WebView not verified in Current_Machine Registry.")
getLogger().error("Blazor cannot run without WebView installed, exiting execution.")
sys.exit(-1)
else:
getLogger().info("WebViewAlreadyInstalled")


precommands = PreCommands()
precommands.install_workload('maui', ['--from-rollback-file', 'https://aka.ms/dotnet/maui/net7.0.json', '--configfile', './Nuget.config'])
precommands.new(template='maui-blazor',
output_dir=const.APPDIR,
bin_dir=const.BINDIR,
exename=EXENAME,
working_directory=sys.path[0],
no_restore=False)

subprocess.run(["dotnet", "add", "./app", "package", "Microsoft.WindowsAppSDK"]) # Add the package reference for the Microsoft.WindowsAppSDK for self-contained running
shutil.copy2(os.path.join(const.SRCDIR, 'Replacement.Index.razor.cs'), os.path.join(const.APPDIR, 'Pages', 'Index.razor.cs'))
precommands.add_startup_logging(os.path.join('Pages', 'Index.razor.cs'), "if (firstRender) {")
precommands.execute(['/p:Platform=x64','/p:WindowsAppSDKSelfContained=True','/p:WindowsPackageType=None','/p:WinUISDKReferences=False','/p:PublishReadyToRun=true'])
14 changes: 14 additions & 0 deletions src/scenarios/mauiblazordesktop/src/Replacement.Index.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Components;
using System.Diagnostics.Tracing;
namespace MauiBlazorDesktopTesting.Pages
{
public partial class Index
{
protected override void OnAfterRender(bool firstRender)
{
if (firstRender) {
// Startup logging is added here via the setup script.
}
}
}
}
26 changes: 26 additions & 0 deletions src/scenarios/mauiblazordesktop/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os
import subprocess
from shared.runner import TestTraits, Runner

EXENAME = 'MauiBlazorDesktopTesting'

def main():
traits = TestTraits(exename=EXENAME,
guiapp='true',
startupmetric='WinUIBlazor',
timeout=30,
measurementdelay='6',
runwithoutexit='false',
processwillexit="false",
)
runner = Runner(traits)
runner.run()


if __name__ == "__main__":
result = subprocess.run(['powershell', '-Command', r'Get-ChildItem .\pub\Microsoft.Maui.dll | Select-Object -ExpandProperty VersionInfo | Select-Object ProductVersion | Select-Object -ExpandProperty ProductVersion'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
os.environ["MAUI_VERSION"] = result.stdout.decode('utf-8').strip()
print(f'Env: MAUI_VERSION: {os.environ["MAUI_VERSION"]}')
if("sha" not in os.environ["MAUI_VERSION"] and "azdo" not in os.environ["MAUI_VERSION"]):
raise ValueError(f"MAUI_VERSION does not contain sha and azdo indicating failure to retrieve or set the value. MAUI_VERSION: {os.environ['MAUI_VERSION']}")
main()
9 changes: 9 additions & 0 deletions src/scenarios/mauidesktop/post.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'''
post cleanup script
'''

from shared.postcommands import PostCommands, clean_directories

postcommands = PostCommands()
clean_directories()
postcommands.uninstall_workload('maui')
29 changes: 29 additions & 0 deletions src/scenarios/mauidesktop/pre.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'''
pre-command: Example call 'python .\pre.py publish -f net7.0-windows10.0.19041.0 -c Release'
'''
import shutil
import subprocess
import sys
import os
from performance.logger import setup_loggers
from shared.precommands import PreCommands
from shared import const
from test import EXENAME
import requests

setup_loggers(True)
NugetURL = 'https://raw.githubusercontent.com/dotnet/maui/main/NuGet.config'
NugetFile = requests.get(NugetURL)
open('./Nuget.config', 'wb').write(NugetFile.content)

precommands = PreCommands()
precommands.install_workload('maui', ['--from-rollback-file', 'https://aka.ms/dotnet/maui/net7.0.json', '--configfile', './Nuget.config'])
precommands.new(template='maui',
output_dir=const.APPDIR,
bin_dir=const.BINDIR,
exename=EXENAME,
working_directory=sys.path[0],
no_restore=False)

subprocess.run(["dotnet", "add", "./app", "package", "Microsoft.WindowsAppSDK"]) # Add the package reference for the Microsoft.WindowsAppSDK for self-contained running
precommands.execute(['/p:Platform=x64','/p:WindowsAppSDKSelfContained=True','/p:WindowsPackageType=None','/p:WinUISDKReferences=False','/p:PublishReadyToRun=true'])
26 changes: 26 additions & 0 deletions src/scenarios/mauidesktop/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os
import subprocess
from shared.runner import TestTraits, Runner

EXENAME = 'MauiDesktopTesting'

def main():
traits = TestTraits(exename=EXENAME,
guiapp='true',
startupmetric='WinUI',
timeout=30,
measurementdelay='6',
runwithoutexit='false',
processwillexit="false",
)
runner = Runner(traits)
runner.run()


if __name__ == "__main__":
result = subprocess.run(['powershell', '-Command', r'Get-ChildItem .\pub\Microsoft.Maui.dll | Select-Object -ExpandProperty VersionInfo | Select-Object ProductVersion | Select-Object -ExpandProperty ProductVersion'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
os.environ["MAUI_VERSION"] = result.stdout.decode('utf-8').strip()
print(f'Env: MAUI_VERSION: {os.environ["MAUI_VERSION"]}')
if("sha" not in os.environ["MAUI_VERSION"] and "azdo" not in os.environ["MAUI_VERSION"]):
raise ValueError(f"MAUI_VERSION does not contain sha and azdo indicating failure to retrieve or set the value. MAUI_VERSION: {os.environ['MAUI_VERSION']}")
main()
10 changes: 6 additions & 4 deletions src/scenarios/shared/precommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ def new(self,
exename: str,
working_directory: str,
language: str = None,
no_https: bool = False):
no_https: bool = False,
no_restore: bool = True):
'makes a new app with the given template'
self.project = CSharpProject.new(template=template,
output_dir=output_dir,
Expand All @@ -114,7 +115,8 @@ def new(self,
force=True,
verbose=True,
language=language,
no_https=no_https)
no_https=no_https,
no_restore=no_restore)
self._updateframework(self.project.csproj_file)
self._addstaticmsbuildproperty(self.project.csproj_file)

Expand Down Expand Up @@ -214,12 +216,12 @@ def add_event_source(self, file: str, line: str, trace_statement: str):
filepath = os.path.join(projpath, file)
insert_after(filepath, line, trace_statement)

def install_workload(self, workloadid: str):
def install_workload(self, workloadid: str, install_args: list = ["--skip-manifest-update"]):
'Installs the workload, if needed'
if not self.has_workload:
if self.readonly_dotnet:
raise Exception('workload needed to build, but has_workload=false, and readonly_dotnet=true')
subprocess.run(["dotnet", "workload", "install", workloadid, "--skip-manifest-update"])
subprocess.run(["dotnet", "workload", "install", workloadid] + install_args)

def uninstall_workload(self, workloadid: str):
'Uninstalls the workload, if possible'
Expand Down
10 changes: 9 additions & 1 deletion src/tools/ScenarioMeasurement/Startup/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ enum MetricType
InnerLoopMsBuild,
DotnetWatch,
DeviceTimeToMain,
PDN
PDN,
WinUI,
WinUIBlazor
}

public class InnerLoopMarkerEventSource : EventSource
Expand Down Expand Up @@ -280,6 +282,12 @@ static void checkArg(string arg, string name)
case MetricType.PDN:
parser = new PDNStartupParser();
break;
case MetricType.WinUI:
parser = new WinUIParser();
break;
case MetricType.WinUIBlazor:
parser = new WinUIBlazorParser();
break;
}

var pids = new List<int>();
Expand Down
Loading

0 comments on commit 89e9ed2

Please sign in to comment.