60 lines
2.5 KiB
C#
60 lines
2.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using Xunit;
|
|
using XWorld.Server.Host;
|
|
|
|
namespace XWorld.Server.Host.Tests
|
|
{
|
|
// 字节加载去锁:模块加载期间磁盘 DLL 可被覆盖/删除(同版本覆盖重发的前提)
|
|
public class ModuleFileLockTests
|
|
{
|
|
// 把共享只读夹具 rps/1 拷到独立临时 gamesRoot(不许改 TestGames.Root 原件)
|
|
private static string CopyRps1ToTempRoot()
|
|
{
|
|
string root = Path.Combine(Path.GetTempPath(), "games_" + Guid.NewGuid().ToString("N"));
|
|
string dst = Path.Combine(root, "rps", "1");
|
|
Directory.CreateDirectory(dst);
|
|
string src = Path.Combine(TestGames.Root, "rps", "1");
|
|
foreach (var f in Directory.GetFiles(src))
|
|
File.Copy(f, Path.Combine(dst, Path.GetFileName(f)));
|
|
return root;
|
|
}
|
|
|
|
[Fact]
|
|
public void LoadedModule_DoesNotLockDlls_OverwriteAndDeleteSucceed()
|
|
{
|
|
string root = CopyRps1ToTempRoot();
|
|
var module = new GameModuleLoader().Load(root, "rps", 1);
|
|
try
|
|
{
|
|
// 先构造一次房间:RpsServerRoom 字段初始化器 new RpsLogic() 触发 RPS.Core
|
|
// 首次解析、经 GameModuleAlc 字节加载进本 ALC —— 此后两个 DLL 的 IL 都在内存。
|
|
// (不先触发的话,"删 Core 后 CreateRoom 成功"会被测试工程对 RPS.Core 的
|
|
// ProjectReference 经默认上下文回退兜住,测不到被测代码。)
|
|
Assert.NotNull(module.CreateRoom());
|
|
|
|
string serverDll = Path.Combine(root, "rps", "1", "RPS.Server.dll");
|
|
string coreDll = Path.Combine(root, "rps", "1", "RPS.Core.dll");
|
|
|
|
// 加载期间覆盖写入 —— LoadFromAssemblyPath 会锁文件抛 IOException,字节加载应成功
|
|
byte[] original = File.ReadAllBytes(serverDll);
|
|
File.WriteAllBytes(serverDll, original);
|
|
|
|
// 加载期间删除(两个都删:IL 已在内存,源文件不再被需要也不被锁定)
|
|
File.Delete(coreDll);
|
|
File.Delete(serverDll);
|
|
Assert.False(File.Exists(coreDll));
|
|
Assert.False(File.Exists(serverDll));
|
|
|
|
// 模块本体仍可用
|
|
Assert.NotNull(module.CreateRoom());
|
|
}
|
|
finally
|
|
{
|
|
module.Unload();
|
|
try { Directory.Delete(root, true); } catch { }
|
|
}
|
|
}
|
|
}
|
|
}
|