using System.Text;
using XFEEDToolBox.NativeSupport;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public class NativeSupportPackageTests
{
private static Dictionary<string, byte[]> Resources(string version = "one")
=> NativeSupportPackage.ResourcePaths.ToDictionary(path => path,
path => Encoding.UTF8.GetBytes(version + ":" + path));
[Test]
public void CompleteBundleExtractsNestedModulesAndReusesMatchingFiles()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
var directory = NativeSupportPackage.ExtractPackage(temporary.Path, resources);
foreach (var pair in resources)
Check.Equal(Encoding.UTF8.GetString(pair.Value), File.ReadAllText(Path.Combine(directory, pair.Key)));
var module = Path.Combine(directory, "dinput8.dll");
File.SetLastWriteTimeUtc(module, new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc));
var before = File.GetLastWriteTimeUtc(module);
Check.Equal(directory, NativeSupportPackage.ExtractPackage(temporary.Path, resources));
Check.Equal(before, File.GetLastWriteTimeUtc(module));
}
[Test]
public void ChangedBundleGetsItsOwnDirectoryAndPreservesPreviousBuild()
{
using var temporary = new TemporaryDirectory();
var old = NativeSupportPackage.ExtractPackage(temporary.Path, Resources("old"));
var current = NativeSupportPackage.ExtractPackage(temporary.Path, Resources("current"));
Check.That(old != current);
Check.Equal("old:dinput8.dll", File.ReadAllText(Path.Combine(old, "dinput8.dll")));
Check.Equal("current:dinput8.dll", File.ReadAllText(Path.Combine(current, "dinput8.dll")));
}
[Test]
public void MissingAndModifiedCachedFilesAreRepairedFromEmbeddedPayloads()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
var directory = NativeSupportPackage.ExtractPackage(temporary.Path, resources);
var module = Path.Combine(directory, "DockingControl", "XFEEDInteraction.dll");
var manifest = Path.Combine(directory, "interaction.json");
File.WriteAllText(module, "changed");
File.Delete(manifest);
Check.Equal(directory, NativeSupportPackage.ExtractPackage(temporary.Path, resources));
Check.Equal("one:DockingControl/XFEEDInteraction.dll", File.ReadAllText(module));
Check.Equal("one:interaction.json", File.ReadAllText(manifest));
Check.That(!Directory.EnumerateFiles(directory, "*.tmp", SearchOption.AllDirectories).Any());
}
[Test]
public async Task ConcurrentExtractionProducesOnlyCompleteMatchingPayloads()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
var paths = await Task.WhenAll(Enumerable.Range(0, 8)
.Select(_ => Task.Run(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources))));
Check.Equal(1, paths.Distinct().Count());
foreach (var pair in resources)
Check.Equal(Encoding.UTF8.GetString(pair.Value), File.ReadAllText(Path.Combine(paths[0], pair.Key)));
Check.That(!Directory.EnumerateFiles(paths[0], "*.tmp", SearchOption.AllDirectories).Any());
}
[Test]
public void IncompleteEmptyOrUnexpectedResourcesAreRejectedBeforeExtraction()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
resources.Remove("dinput8.dll");
Check.Throws<InvalidDataException>(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources));
resources["../dinput8.dll"] = Encoding.UTF8.GetBytes("unexpected");
Check.Throws<InvalidDataException>(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources));
resources = Resources();
resources["dinput8.dll"] = [];
Check.Throws<InvalidDataException>(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources));
Check.That(!Directory.EnumerateFileSystemEntries(temporary.Path).Any());
}
}
using System.Text;
using XFEEDToolBox.NativeSupport;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public class NativeSupportPackageTests
{
private static Dictionary<string, byte[]> Resources(string version = "one")
=> NativeSupportPackage.ResourcePaths.ToDictionary(path => path,
path => Encoding.UTF8.GetBytes(version + ":" + path));
[Test]
public void CompleteBundleExtractsNestedModulesAndReusesMatchingFiles()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
var directory = NativeSupportPackage.ExtractPackage(temporary.Path, resources);
foreach (var pair in resources)
Check.Equal(Encoding.UTF8.GetString(pair.Value), File.ReadAllText(Path.Combine(directory, pair.Key)));
var module = Path.Combine(directory, "dinput8.dll");
File.SetLastWriteTimeUtc(module, new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc));
var before = File.GetLastWriteTimeUtc(module);
Check.Equal(directory, NativeSupportPackage.ExtractPackage(temporary.Path, resources));
Check.Equal(before, File.GetLastWriteTimeUtc(module));
}
[Test]
public void ChangedBundleGetsItsOwnDirectoryAndPreservesPreviousBuild()
{
using var temporary = new TemporaryDirectory();
var old = NativeSupportPackage.ExtractPackage(temporary.Path, Resources("old"));
var current = NativeSupportPackage.ExtractPackage(temporary.Path, Resources("current"));
Check.That(old != current);
Check.Equal("old:dinput8.dll", File.ReadAllText(Path.Combine(old, "dinput8.dll")));
Check.Equal("current:dinput8.dll", File.ReadAllText(Path.Combine(current, "dinput8.dll")));
}
[Test]
public void MissingAndModifiedCachedFilesAreRepairedFromEmbeddedPayloads()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
var directory = NativeSupportPackage.ExtractPackage(temporary.Path, resources);
var module = Path.Combine(directory, "DockingControl", "XFEEDInteraction.dll");
var manifest = Path.Combine(directory, "interaction.json");
File.WriteAllText(module, "changed");
File.Delete(manifest);
Check.Equal(directory, NativeSupportPackage.ExtractPackage(temporary.Path, resources));
Check.Equal("one:DockingControl/XFEEDInteraction.dll", File.ReadAllText(module));
Check.Equal("one:interaction.json", File.ReadAllText(manifest));
Check.That(!Directory.EnumerateFiles(directory, "*.tmp", SearchOption.AllDirectories).Any());
}
[Test]
public async Task ConcurrentExtractionProducesOnlyCompleteMatchingPayloads()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
var paths = await Task.WhenAll(Enumerable.Range(0, 8)
.Select(_ => Task.Run(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources))));
Check.Equal(1, paths.Distinct().Count());
foreach (var pair in resources)
Check.Equal(Encoding.UTF8.GetString(pair.Value), File.ReadAllText(Path.Combine(paths[0], pair.Key)));
Check.That(!Directory.EnumerateFiles(paths[0], "*.tmp", SearchOption.AllDirectories).Any());
}
[Test]
public void IncompleteEmptyOrUnexpectedResourcesAreRejectedBeforeExtraction()
{
using var temporary = new TemporaryDirectory();
var resources = Resources();
resources.Remove("dinput8.dll");
Check.Throws<InvalidDataException>(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources));
resources["../dinput8.dll"] = Encoding.UTF8.GetBytes("unexpected");
Check.Throws<InvalidDataException>(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources));
resources = Resources();
resources["dinput8.dll"] = [];
Check.Throws<InvalidDataException>(() => NativeSupportPackage.ExtractPackage(temporary.Path, resources));
Check.That(!Directory.EnumerateFileSystemEntries(temporary.Path).Any());
}
}