csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
7.1 KiB
188 lines
7.1 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Avalonia.Remote.Protocol;
|
|
using Avalonia.Remote.Protocol.Designer;
|
|
using Avalonia.Remote.Protocol.Viewport;
|
|
using Xunit;
|
|
|
|
namespace Avalonia.DesignerSupport.Tests
|
|
{
|
|
public class DesignerSupportTests
|
|
{
|
|
private const string DesignerAppPath = "../../../../../src/tools/Avalonia.Designer.HostApp/bin/$BUILD/$TFM/Avalonia.Designer.HostApp.dll";
|
|
private readonly ITestOutputHelper outputHelper;
|
|
|
|
public DesignerSupportTests(ITestOutputHelper outputHelper)
|
|
{
|
|
this.outputHelper = outputHelper;
|
|
}
|
|
|
|
[Theory,
|
|
InlineData(
|
|
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/$TFM/",
|
|
"Avalonia.DesignerSupport.TestApp",
|
|
"Avalonia.DesignerSupport.TestApp.dll",
|
|
@"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml",
|
|
"win32"),
|
|
InlineData(
|
|
@"..\..\..\..\..\samples\ControlCatalog.Desktop\bin\$BUILD\$TFM\",
|
|
"ControlCatalog.Desktop",
|
|
"ControlCatalog.dll",
|
|
@"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml",
|
|
"win32"),
|
|
InlineData(
|
|
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/$TFM/",
|
|
"Avalonia.DesignerSupport.TestApp",
|
|
"Avalonia.DesignerSupport.TestApp.dll",
|
|
@"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml",
|
|
"avalonia-remote"),
|
|
InlineData(
|
|
@"..\..\..\..\..\samples\ControlCatalog.Desktop\bin\$BUILD\$TFM\",
|
|
"ControlCatalog.Desktop",
|
|
"ControlCatalog.dll",
|
|
@"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml",
|
|
"avalonia-remote")]
|
|
public async Task Designer_In_Win32_Mode_Should_Provide_Valid_Hwnd(
|
|
string outputDir,
|
|
string executableName,
|
|
string assemblyName,
|
|
string xamlFile,
|
|
string method)
|
|
{
|
|
outputDir = Path.GetFullPath(outputDir.Replace('\\', Path.DirectorySeparatorChar));
|
|
xamlFile = Path.GetFullPath(xamlFile.Replace('\\', Path.DirectorySeparatorChar));
|
|
|
|
if (method == "win32")
|
|
Assert.SkipUnless(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Windows-only");
|
|
|
|
var xaml = File.ReadAllText(xamlFile);
|
|
string buildType;
|
|
#if DEBUG
|
|
buildType = "Debug";
|
|
#else
|
|
buildType = "Release";
|
|
#endif
|
|
var tfm = $"net{Environment.Version.ToString(2)}";
|
|
|
|
outputDir = outputDir.Replace("$BUILD", buildType).Replace("$TFM", tfm);
|
|
|
|
var assemblyPath = Path.Combine(outputDir, assemblyName);
|
|
Assert.True(File.Exists(assemblyPath), "File.Exists(assemblyPath)");
|
|
|
|
var sessionId = Guid.NewGuid();
|
|
long handle = 0;
|
|
bool success = false;
|
|
string? error = null;
|
|
|
|
var resultMessageReceivedToken = new CancellationTokenSource();
|
|
|
|
var tcpListener = new TcpListener(IPAddress.Loopback, 0);
|
|
tcpListener.Start();
|
|
var port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
|
|
tcpListener.Stop();
|
|
var transport = new BsonTcpTransport();
|
|
transport.Listen(IPAddress.Loopback, port, conn =>
|
|
{
|
|
conn.OnMessage += async (_, msg) =>
|
|
{
|
|
if (msg is StartDesignerSessionMessage start)
|
|
{
|
|
Assert.Equal(sessionId, Guid.Parse(start.SessionId));
|
|
if (method == "avalonia-remote")
|
|
{
|
|
await conn.Send(new ClientSupportedPixelFormatsMessage
|
|
{
|
|
Formats = new[] { PixelFormat.Rgba8888 }
|
|
});
|
|
await conn.Send(new ClientViewportAllocatedMessage
|
|
{
|
|
DpiX = 96, DpiY = 96, Width = 1024, Height = 768
|
|
});
|
|
}
|
|
|
|
await conn.Send(new UpdateXamlMessage
|
|
{
|
|
AssemblyPath = assemblyPath,
|
|
Xaml = xaml
|
|
});
|
|
}
|
|
else if (msg is UpdateXamlResultMessage result)
|
|
{
|
|
if (result.Error != null)
|
|
{
|
|
error = result.Error;
|
|
outputHelper.WriteLine(result.Error);
|
|
}
|
|
else
|
|
success = true;
|
|
if (method == "win32")
|
|
handle = result.Handle != null ? long.Parse(result.Handle) : 0;
|
|
resultMessageReceivedToken.Cancel();
|
|
conn.Dispose();
|
|
}
|
|
};
|
|
});
|
|
|
|
var cmdline =
|
|
$"exec --runtimeconfig \"{outputDir}{executableName}.runtimeconfig.json\" --depsfile \"{outputDir}{executableName}.deps.json\" "
|
|
+ $" \"{DesignerAppPath.Replace("$BUILD", buildType).Replace("$TFM", tfm)}\" "
|
|
+ $"--transport tcp-bson://127.0.0.1:{port}/ --session-id {sessionId} --method {method} \"{outputDir}{executableName}.dll\"";
|
|
|
|
using (var proc = new Process
|
|
{
|
|
StartInfo = new ProcessStartInfo("dotnet", cmdline)
|
|
{
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
CreateNoWindow = true,
|
|
WorkingDirectory = outputDir,
|
|
},
|
|
EnableRaisingEvents = true
|
|
})
|
|
{
|
|
proc.Start();
|
|
|
|
var cancelled = false;
|
|
try
|
|
{
|
|
await Task.Delay(10000, resultMessageReceivedToken.Token);
|
|
}
|
|
catch (TaskCanceledException)
|
|
{
|
|
cancelled = true;
|
|
}
|
|
|
|
try
|
|
{
|
|
proc.Kill();
|
|
}
|
|
catch
|
|
{
|
|
//
|
|
}
|
|
|
|
proc.WaitForExit();
|
|
var stdout = proc.StandardOutput.ReadToEnd();
|
|
var stderr = proc.StandardError.ReadToEnd();
|
|
Assert.True(cancelled,
|
|
$"Message Not Received.\n" + proc.StandardOutput.ReadToEnd() + "\n" +
|
|
stderr + "\n" + stdout);
|
|
Assert.True(success, error);
|
|
if (method == "win32")
|
|
Assert.NotEqual(0, handle);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|