mirror of
https://github.com/danbulant/Cosmos
synced 2026-06-11 02:31:22 +00:00
Added a test runner UI, built on Avalonia.
This commit is contained in:
parent
11e9fcd174
commit
5d6fe31c62
10 changed files with 404 additions and 0 deletions
|
|
@ -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)" />
|
||||
|
|
|
|||
11
Tests/Cosmos.TestRunner.UI.Avalonia/App.xaml
Normal file
11
Tests/Cosmos.TestRunner.UI.Avalonia/App.xaml
Normal 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>
|
||||
38
Tests/Cosmos.TestRunner.UI.Avalonia/App.xaml.cs
Normal file
38
Tests/Cosmos.TestRunner.UI.Avalonia/App.xaml.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Tests/Cosmos.TestRunner.UI.Avalonia/Views/MainWindow.xaml
Normal file
10
Tests/Cosmos.TestRunner.UI.Avalonia/Views/MainWindow.xaml
Normal 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>
|
||||
42
Tests/Cosmos.TestRunner.UI.Avalonia/Views/MainWindow.xaml.cs
Normal file
42
Tests/Cosmos.TestRunner.UI.Avalonia/Views/MainWindow.xaml.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue