mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
177 lines
6.9 KiB
C#
177 lines
6.9 KiB
C#
using LanMountainDesktop.Launcher.Plugins;
|
|
using System.IO.Compression;
|
|
using System.Text.Json;
|
|
using Xunit;
|
|
|
|
namespace LanMountainDesktop.Tests;
|
|
|
|
public sealed class PluginInstallerServiceTests : IDisposable
|
|
{
|
|
private readonly string _tempRoot = Path.Combine(Path.GetTempPath(), "LanMountainDesktop.Tests", nameof(PluginInstallerServiceTests), Guid.NewGuid().ToString("N"));
|
|
|
|
[Fact]
|
|
public void InstallPackage_ReturnsElevationRequired_ForOutsideUserScope_OnWindows()
|
|
{
|
|
if (!OperatingSystem.IsWindows())
|
|
{
|
|
return;
|
|
}
|
|
|
|
Directory.CreateDirectory(_tempRoot);
|
|
var packagePath = Path.Combine(_tempRoot, "sample.lmdp");
|
|
File.WriteAllText(packagePath, "placeholder");
|
|
|
|
var service = new PluginInstallerService();
|
|
var result = service.InstallPackage(packagePath, Path.Combine(_tempRoot, "Plugins"));
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal("plugin_elevation_required", result.Code);
|
|
}
|
|
|
|
[Fact]
|
|
public void InstallPackage_InstallsLaappWithPluginJson_InsideUserScope()
|
|
{
|
|
var packagePath = Path.Combine(_tempRoot, "sample.laapp");
|
|
Directory.CreateDirectory(_tempRoot);
|
|
CreatePluginPackage(packagePath, "plugin.json", "plugin.install.sample", "Sample Plugin");
|
|
|
|
var pluginsDirectory = CreateConfiguredPortablePluginsDirectory(out var appRoot);
|
|
var service = new PluginInstallerService();
|
|
|
|
var result = service.InstallPackage(packagePath, pluginsDirectory, appRoot);
|
|
|
|
Assert.True(result.Success);
|
|
Assert.Equal("ok", result.Code);
|
|
Assert.Equal("plugin.install.sample", result.ManifestId);
|
|
Assert.Equal("Sample Plugin", result.ManifestName);
|
|
Assert.NotNull(result.InstalledPackagePath);
|
|
Assert.True(File.Exists(result.InstalledPackagePath));
|
|
Assert.EndsWith(".laapp", result.InstalledPackagePath, StringComparison.OrdinalIgnoreCase);
|
|
Assert.Empty(Directory.EnumerateFiles(pluginsDirectory, "*.incoming", SearchOption.AllDirectories));
|
|
}
|
|
|
|
[Fact]
|
|
public void InstallPackage_AllowsConfiguredPortableDataRootOutsideUserScope()
|
|
{
|
|
if (!OperatingSystem.IsWindows())
|
|
{
|
|
return;
|
|
}
|
|
|
|
Directory.CreateDirectory(_tempRoot);
|
|
var appRoot = Path.Combine(_tempRoot, "PackageRoot");
|
|
var portableDataRoot = Path.Combine(appRoot, "Desktop");
|
|
var launcherDataRoot = Path.Combine(appRoot, ".Launcher");
|
|
Directory.CreateDirectory(launcherDataRoot);
|
|
File.WriteAllText(
|
|
Path.Combine(launcherDataRoot, "data-location.config.json"),
|
|
JsonSerializer.Serialize(new
|
|
{
|
|
DataLocationMode = "Portable",
|
|
SystemDataPath = Path.Combine(_tempRoot, "System"),
|
|
PortableDataPath = portableDataRoot
|
|
}));
|
|
|
|
var packagePath = Path.Combine(_tempRoot, "portable.laapp");
|
|
CreatePluginPackage(packagePath, "plugin.json", "plugin.portable.sample", "Portable Plugin");
|
|
|
|
var pluginsDirectory = Path.Combine(portableDataRoot, "Extensions", "Plugins");
|
|
var service = new PluginInstallerService();
|
|
|
|
var result = service.InstallPackage(packagePath, pluginsDirectory, appRoot);
|
|
|
|
Assert.True(result.Success);
|
|
Assert.Equal("ok", result.Code);
|
|
Assert.True(File.Exists(result.InstalledPackagePath));
|
|
Assert.StartsWith(Path.GetFullPath(portableDataRoot), Path.GetFullPath(result.InstalledPackagePath!), StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void InstallPackage_ReplacesExistingPackageWithSamePluginId()
|
|
{
|
|
Directory.CreateDirectory(_tempRoot);
|
|
var firstPackagePath = Path.Combine(_tempRoot, "sample-1.laapp");
|
|
var secondPackagePath = Path.Combine(_tempRoot, "sample-2.laapp");
|
|
CreatePluginPackage(firstPackagePath, "plugin.json", "plugin.replace.sample", "Sample Plugin v1");
|
|
CreatePluginPackage(secondPackagePath, "plugin.json", "plugin.replace.sample", "Sample Plugin v2");
|
|
|
|
var pluginsDirectory = CreateConfiguredPortablePluginsDirectory(out var appRoot);
|
|
var service = new PluginInstallerService();
|
|
|
|
var first = service.InstallPackage(firstPackagePath, pluginsDirectory, appRoot);
|
|
var second = service.InstallPackage(secondPackagePath, pluginsDirectory, appRoot);
|
|
|
|
Assert.True(first.Success);
|
|
Assert.True(second.Success);
|
|
Assert.Single(Directory.EnumerateFiles(pluginsDirectory, "*.laapp", SearchOption.TopDirectoryOnly));
|
|
Assert.True(File.Exists(second.InstalledPackagePath));
|
|
}
|
|
|
|
[Fact]
|
|
public void InstallPackage_StillSupportsLegacyManifestJson()
|
|
{
|
|
var packagePath = Path.Combine(_tempRoot, "legacy.lmdp");
|
|
Directory.CreateDirectory(_tempRoot);
|
|
CreatePluginPackage(packagePath, "manifest.json", "plugin.legacy.sample", "Legacy Plugin");
|
|
|
|
var pluginsDirectory = CreateConfiguredPortablePluginsDirectory(out var appRoot);
|
|
var service = new PluginInstallerService();
|
|
|
|
var result = service.InstallPackage(packagePath, pluginsDirectory, appRoot);
|
|
|
|
Assert.True(result.Success);
|
|
Assert.Equal("plugin.legacy.sample", result.ManifestId);
|
|
Assert.True(File.Exists(result.InstalledPackagePath));
|
|
}
|
|
|
|
private static void CreatePluginPackage(string packagePath, string manifestFileName, string pluginId, string pluginName)
|
|
{
|
|
using var archive = ZipFile.Open(packagePath, ZipArchiveMode.Create);
|
|
var entry = archive.CreateEntry(manifestFileName);
|
|
using var stream = entry.Open();
|
|
using var writer = new StreamWriter(stream);
|
|
writer.Write(
|
|
$$"""
|
|
{
|
|
"id": "{{pluginId}}",
|
|
"name": "{{pluginName}}",
|
|
"version": "1.0.0"
|
|
}
|
|
""");
|
|
}
|
|
|
|
private string CreateConfiguredPortablePluginsDirectory(out string appRoot)
|
|
{
|
|
appRoot = Path.Combine(_tempRoot, "ConfiguredPackageRoot", Guid.NewGuid().ToString("N"));
|
|
var portableDataRoot = Path.Combine(appRoot, "Desktop");
|
|
var launcherDataRoot = Path.Combine(appRoot, ".Launcher");
|
|
Directory.CreateDirectory(launcherDataRoot);
|
|
File.WriteAllText(
|
|
Path.Combine(launcherDataRoot, "data-location.config.json"),
|
|
JsonSerializer.Serialize(new
|
|
{
|
|
DataLocationMode = "Portable",
|
|
SystemDataPath = Path.Combine(_tempRoot, "System"),
|
|
PortableDataPath = portableDataRoot
|
|
}));
|
|
|
|
var pluginsDirectory = Path.Combine(portableDataRoot, "Extensions", "Plugins");
|
|
Directory.CreateDirectory(pluginsDirectory);
|
|
return pluginsDirectory;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(_tempRoot))
|
|
{
|
|
Directory.Delete(_tempRoot, recursive: true);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|