144 lines
5.4 KiB
C#
144 lines
5.4 KiB
C#
using MBN_STOCK_WEBVIEW.Playout.Diagnostics;
|
|
using MBN_STOCK_WEBVIEW.Playout.Interop;
|
|
using MBN_STOCK_WEBVIEW.Playout.Registration;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace MBN_STOCK_WEBVIEW.Playout.Tests;
|
|
|
|
public sealed class InstalledK3dInteropMetadataTests
|
|
{
|
|
[Fact]
|
|
public void ApprovedSha256_RequiresAndDecodesExactly64HexCharacters()
|
|
{
|
|
var parsed = InstalledK3dInteropMetadata.ParseApprovedSha256(
|
|
"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF");
|
|
|
|
Assert.Equal(32, parsed.Length);
|
|
Assert.Equal(0x01, parsed[0]);
|
|
Assert.Equal(0xEF, parsed[^1]);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
[InlineData("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde")]
|
|
[InlineData(" 123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")]
|
|
[InlineData("g123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")]
|
|
public void ApprovedSha256_RejectsMissingMalformedOrWhitespaceValues(string? value)
|
|
{
|
|
Assert.Throws<InstalledK3dInteropMetadataUnavailableException>(
|
|
() => InstalledK3dInteropMetadata.ParseApprovedSha256(value));
|
|
}
|
|
|
|
[Fact]
|
|
public void ApprovedSha256_RequiresExactContentForEitherBinaryPin()
|
|
{
|
|
byte[] content = [1, 2, 3, 4];
|
|
var approved = Convert.ToHexString(SHA256.HashData(content));
|
|
using var matching = new MemoryStream(content);
|
|
using var different = new MemoryStream([1, 2, 3, 5]);
|
|
|
|
InstalledK3dInteropMetadata.ValidateApprovedSha256(matching, approved);
|
|
Assert.Throws<InstalledK3dInteropMetadataUnavailableException>(
|
|
() => InstalledK3dInteropMetadata.ValidateApprovedSha256(different, approved));
|
|
Assert.Equal(
|
|
"MBN_STOCK_K3D_NATIVE_SHA256",
|
|
InstalledK3dInteropMetadata.ApprovedNativeSha256EnvironmentVariable);
|
|
Assert.Equal(
|
|
"MBN_STOCK_K3D_INTEROP_SHA256",
|
|
InstalledK3dInteropMetadata.ApprovedSha256EnvironmentVariable);
|
|
}
|
|
|
|
[Fact]
|
|
public void FileLease_KeepsNativeAndInteropFilesWriteLocked()
|
|
{
|
|
var directory = Path.Combine(Path.GetTempPath(), $"k3d-lease-{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(directory);
|
|
var nativePath = Path.Combine(directory, "native.dll");
|
|
var interopPath = Path.Combine(directory, "interop.dll");
|
|
File.WriteAllBytes(nativePath, [1]);
|
|
File.WriteAllBytes(interopPath, [2]);
|
|
|
|
InstalledK3dInteropFileLease? lease = null;
|
|
try
|
|
{
|
|
lease = new InstalledK3dInteropFileLease(
|
|
new FileStream(nativePath, FileMode.Open, FileAccess.Read, FileShare.Read),
|
|
new FileStream(interopPath, FileMode.Open, FileAccess.Read, FileShare.Read));
|
|
|
|
Assert.Throws<IOException>(() => OpenForWrite(nativePath).Dispose());
|
|
Assert.Throws<IOException>(() => OpenForWrite(interopPath).Dispose());
|
|
}
|
|
finally
|
|
{
|
|
lease?.InteropStream.Dispose();
|
|
lease?.NativeStream.Dispose();
|
|
Directory.Delete(directory, recursive: true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void RegisteredPaths_MapOnlyExactX64VendorLayout()
|
|
{
|
|
const string native = @"C:\Vendor\K3DAsyncEngine\DLL\x64\Release\K3DAsyncEngine.dll";
|
|
var paths = InstalledK3dInteropMetadata.ResolveRegisteredPaths(ReadySnapshot(native));
|
|
|
|
Assert.Equal(Path.GetFullPath(native), paths.NativeBinaryPath);
|
|
Assert.Equal(
|
|
Path.GetFullPath(
|
|
@"C:\Vendor\K3DAsyncEngine\Bin\x64\C#\Interop.K3DAsyncEngineLib.dll"),
|
|
paths.InteropAssemblyPath);
|
|
}
|
|
|
|
[Fact]
|
|
public void RegisteredPaths_RejectDivergentClassBinary()
|
|
{
|
|
const string native = @"C:\Vendor\K3DAsyncEngine\DLL\x64\Release\K3DAsyncEngine.dll";
|
|
var snapshot = ReadySnapshot(native) with
|
|
{
|
|
EventHandler = ReadySnapshot(native).EventHandler with
|
|
{
|
|
InprocServerPath =
|
|
@"C:\Other\K3DAsyncEngine\DLL\x64\Release\K3DAsyncEngine.dll"
|
|
}
|
|
};
|
|
|
|
Assert.Throws<InstalledK3dInteropMetadataUnavailableException>(
|
|
() => InstalledK3dInteropMetadata.ResolveRegisteredPaths(snapshot));
|
|
}
|
|
|
|
[Fact]
|
|
public void RegisteredPaths_RejectUnexpectedNativeLayout()
|
|
{
|
|
const string native = @"C:\Vendor\K3DAsyncEngine\bin\K3DAsyncEngine.dll";
|
|
|
|
Assert.Throws<InstalledK3dInteropMetadataUnavailableException>(
|
|
() => InstalledK3dInteropMetadata.ResolveRegisteredPaths(ReadySnapshot(native)));
|
|
}
|
|
|
|
private static K3dRegistrySnapshot ReadySnapshot(string nativePath) => new(
|
|
true,
|
|
nativePath,
|
|
new K3dClassRegistrationSnapshot(
|
|
true,
|
|
K3dComConstants.KaEngineProgId,
|
|
K3dComConstants.KaEngineClassId,
|
|
nativePath,
|
|
K3dComConstants.ApartmentThreadingModel,
|
|
K3dComConstants.TypeLibraryId),
|
|
new K3dClassRegistrationSnapshot(
|
|
true,
|
|
K3dComConstants.KaEventHandlerProgId,
|
|
K3dComConstants.KaEventHandlerClassId,
|
|
nativePath,
|
|
K3dComConstants.ApartmentThreadingModel,
|
|
K3dComConstants.TypeLibraryId),
|
|
false);
|
|
|
|
private static FileStream OpenForWrite(string path) => new(
|
|
path,
|
|
FileMode.Open,
|
|
FileAccess.Write,
|
|
FileShare.ReadWrite | FileShare.Delete);
|
|
}
|