Added a test runner UI, built on Avalonia.

This commit is contained in:
José Pedro 2018-01-23 16:46:12 +00:00
parent 11e9fcd174
commit 5d6fe31c62
No known key found for this signature in database
GPG key ID: B8247B9301707B83
10 changed files with 404 additions and 0 deletions

View file

@ -2,6 +2,7 @@
<configuration>
<packageSources>
<add key="Cosmos MyGet Feed" value="https://www.myget.org/F/cosmos/api/v3/index.json" />
<add key="Avalonia MyGet Feed" value="https://www.myget.org/F/avalonia-ci/api/v2" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />

View file

@ -0,0 +1,11 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
<Style Selector="DropDown">
<Setter Property="MinHeight" Value="28" />
</Style>
</Application.Styles>
</Application>

View file

@ -0,0 +1,38 @@
using System.Diagnostics;
using Avalonia;
using Avalonia.Logging.Serilog;
using Avalonia.Markup.Xaml;
using Serilog;
using Cosmos.TestRunner.UI.Views;
namespace Cosmos.TestRunner.UI
{
internal class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
base.Initialize();
}
static void Main(string[] args)
{
InitializeLogging();
AppBuilder.Configure<App>()
.UsePlatformDetect()
.Start<MainWindow>();
}
[Conditional("DEBUG")]
private static void InitializeLogging()
{
SerilogLogger.Initialize(new LoggerConfiguration()
.MinimumLevel.Warning()
.WriteTo.Trace(outputTemplate: "{Area}: {Message}")
.CreateLogger());
}
}
}

View file

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<AssemblyName>Cosmos.TestRunner.UI</AssemblyName>
<RootNamespace>Cosmos.TestRunner.UI</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Update="**\*.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<EmbeddedResource Include="**\*.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Cosmos.TestRunner.Core\Cosmos.TestRunner.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.5.2-build4485-alpha" />
<PackageReference Include="Avalonia.Desktop" Version="0.5.2-build4485-alpha" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,42 @@
using System;
using System.ComponentModel;
using System.Threading;
using Cosmos.TestRunner.Core;
namespace Cosmos.TestRunner.UI.ViewModels
{
internal class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainWindowViewModel(IEngineConfiguration aEngineConfiguration)
{
var xEngine = new Engine(aEngineConfiguration)
{
OutputHandler = new OutputHandler(
m =>
{
TestRunnerLog += m + Environment.NewLine;
OnPropertyChanged(nameof(TestRunnerLog));
})
};
new Thread(() => xEngine.Execute()).Start();
}
public string TestRunnerLog { get; set; }
private void OnPropertyChanged(string aPropertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(aPropertyName));
internal class OutputHandler : OutputHandlerFullTextBase
{
private Action<string> mLog;
public OutputHandler(Action<string> aLog) => mLog = aLog;
protected override void Log(string message) => mLog(message);
}
}
}

View file

@ -0,0 +1,158 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using PropertyChangedEventArgs = System.ComponentModel.PropertyChangedEventArgs;
using Avalonia.Controls;
using Cosmos.Build.Common;
using Cosmos.TestRunner.Core;
namespace Cosmos.TestRunner.UI.ViewModels
{
internal class SettingsDialogViewModel : IEngineConfiguration, INotifyPropertyChanged
{
private static IEngineConfiguration defaultEngineConfiguration = new DefaultEngineConfiguration();
private static IEnumerable<Type> stableKernelTypes = TestKernelSets.GetStableKernelTypes();
public event PropertyChangedEventHandler PropertyChanged;
public SettingsDialogViewModel(Window aWindow)
{
KernelTypesToRun = new ObservableCollection<Type>(stableKernelTypes);
RunTests = new RunTestsCommand(aWindow, this);
}
#region Engine Configuration
private int mAllowedSecondsInKernel = defaultEngineConfiguration.AllowedSecondsInKernel;
public int AllowedSecondsInKernel
{
get => mAllowedSecondsInKernel;
set => SetProperty(ref mAllowedSecondsInKernel, value);
}
public IEnumerable<RunTargetEnum> RunTargets
{
get
{
yield return RunTarget;
}
set => RunTarget = value.Single();
}
private bool mRunWithGDB = defaultEngineConfiguration.RunWithGDB;
public bool RunWithGDB
{
get => mRunWithGDB;
set => SetProperty(ref mRunWithGDB, value);
}
private bool mStartBochsDebugGUI = defaultEngineConfiguration.StartBochsDebugGUI;
public bool StartBochsDebugGUI
{
get => mStartBochsDebugGUI;
set => SetProperty(ref mStartBochsDebugGUI, value);
}
private bool mDebugIL2CPU = defaultEngineConfiguration.DebugIL2CPU;
public bool DebugIL2CPU
{
get => mDebugIL2CPU;
set => SetProperty(ref mDebugIL2CPU, value);
}
private string mKernelPkg = defaultEngineConfiguration.KernelPkg;
public string KernelPkg
{
get => mKernelPkg;
set => SetProperty(ref mKernelPkg, value);
}
private TraceAssemblies mTraceAssembliesLevel = defaultEngineConfiguration.TraceAssembliesLevel;
public TraceAssemblies TraceAssembliesLevel
{
get => mTraceAssembliesLevel;
set => SetProperty(ref mTraceAssembliesLevel, value);
}
private bool mEnableStackCorruptionChecks = defaultEngineConfiguration.EnableStackCorruptionChecks;
public bool EnableStackCorruptionChecks
{
get => mEnableStackCorruptionChecks;
set => SetProperty(ref mEnableStackCorruptionChecks, value);
}
private StackCorruptionDetectionLevel mStackCorruptionDetectionLevel = defaultEngineConfiguration.StackCorruptionDetectionLevel;
public StackCorruptionDetectionLevel StackCorruptionDetectionLevel
{
get => mStackCorruptionDetectionLevel;
set => SetProperty(ref mStackCorruptionDetectionLevel, value);
}
IEnumerable<Type> IEngineConfiguration.KernelTypesToRun => KernelTypesToRun;
#endregion
private RunTargetEnum mRunTarget = defaultEngineConfiguration.RunTargets.FirstOrDefault();
public RunTargetEnum RunTarget
{
get => mRunTarget;
set => SetProperty(ref mRunTarget, value);
}
public ObservableCollection<Type> KernelTypesToRun { get; }
#region Items
public IEnumerable<Type> TestKernels { get; } = stableKernelTypes;
public IEnumerable RunTargetItems { get; } = Enum.GetValues(typeof(RunTargetEnum));
public IEnumerable TraceAssembliesLevelItems { get; } = Enum.GetValues(typeof(TraceAssemblies));
public IEnumerable StackCorruptionDetectionLevelItems { get; } = Enum.GetValues(typeof(StackCorruptionDetectionLevel));
#endregion
public ICommand RunTests { get; set; }
private void SetProperty<T>(ref T aProperty, T aValue, [CallerMemberName]string aPropertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(aProperty, aValue))
{
aProperty = aValue;
OnPropertyChanged(aPropertyName);
}
}
private void OnPropertyChanged(string aPropertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(aPropertyName));
internal class RunTestsCommand : ICommand
{
private Window mWindow;
private SettingsDialogViewModel mViewModel;
public RunTestsCommand(Window aWindow, SettingsDialogViewModel aViewModel)
{
mWindow = aWindow;
mViewModel = aViewModel;
mViewModel.KernelTypesToRun.CollectionChanged += KernelTypesToRun_CollectionChanged;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => mViewModel.KernelTypesToRun.Any();
public void Execute(object parameter) => mWindow.Close(mViewModel);
private void KernelTypesToRun_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) =>
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
}

View file

@ -0,0 +1,10 @@
<Window xmlns="https://github.com/avaloniaui"
Title="Cosmos Test Runner">
<Grid>
<TextBox IsReadOnly="True"
Text="{Binding TestRunnerLog}"
CaretIndex="{Binding TestRunnerLog.Length}"/>
</Grid>
</Window>

View file

@ -0,0 +1,42 @@
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using Cosmos.TestRunner.Core;
using Cosmos.TestRunner.UI.ViewModels;
namespace Cosmos.TestRunner.UI.Views
{
internal class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.AttachDevTools();
Dispatcher.UIThread.InvokeAsync(async () => await ShowSettingsDialog().ConfigureAwait(false));
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private async Task ShowSettingsDialog()
{
var xSettingsDialog = new SettingsDialog();
var xEngineConfiguration = await xSettingsDialog.ShowDialog<IEngineConfiguration>();
if (xEngineConfiguration == null)
{
Application.Current.Exit();
return;
}
DataContext = new MainWindowViewModel(xEngineConfiguration);
}
}
}

View file

@ -0,0 +1,49 @@
<Window xmlns="https://github.com/avaloniaui"
Title="Cosmos Test Runner Settings"
SizeToContent="WidthAndHeight">
<StackPanel Gap="8"
Margin="16">
<StackPanel Orientation="Horizontal"
Gap="16">
<StackPanel Gap="8">
<TextBlock>Allowed seconds in kernel:</TextBlock>
<TextBox Text="{Binding AllowedSecondsInKernel}" />
<CheckBox IsChecked="{Binding RunWithGDB}">Run with GDB</CheckBox>
<CheckBox IsChecked="{Binding StartBochsDebugGUI}">Start Bochs debug GUI</CheckBox>
<TextBlock>Run target:</TextBlock>
<DropDown Items="{Binding RunTargetItems}"
SelectedItem="{Binding RunTarget}" />
</StackPanel>
<StackPanel Gap="8">
<CheckBox IsChecked="{Binding DebugIL2CPU}">Debug IL2CPU</CheckBox>
<TextBlock>Kernel package:</TextBlock>
<TextBox Text="{Binding KernelPkg}" />
<TextBlock>Trace assemblies level:</TextBlock>
<DropDown Items="{Binding TraceAssembliesLevelItems}"
SelectedItem="{Binding TraceAssembliesLevel}" />
<CheckBox IsChecked="{Binding EnableStackCorruptionChecks}">Enable stack corruption checks</CheckBox>
<TextBlock>Stack corruption detection level:</TextBlock>
<DropDown Items="{Binding StackCorruptionDetectionLevelItems}"
SelectedItem="{Binding StackCorruptionDetectionLevel}" />
</StackPanel>
</StackPanel>
<ListBox Items="{Binding TestKernels}"
Padding="8"
SelectedItems="{Binding KernelTypesToRun}"
SelectionMode="Multiple" />
<Button Command="{Binding RunTests}">Run Tests</Button>
</StackPanel>
</Window>

View file

@ -0,0 +1,24 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Cosmos.TestRunner.UI.ViewModels;
namespace Cosmos.TestRunner.UI.Views
{
internal class SettingsDialog : Window
{
public SettingsDialog()
{
InitializeComponent();
this.AttachDevTools();
DataContext = new SettingsDialogViewModel(this);
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}