using Microsoft.Data.Sqlite; using Microsoft.VisualStudio.TestTools.UnitTesting; using YMhut.Box.Core.App; using YMhut.Box.Core.Logging; namespace YMhut.Box.Tests; [TestClass] public sealed class LogServiceTests { [TestMethod] public void LogDisplayLocalizerUsesEmptyDetailTextInsteadOfUnknownError() { Assert.AreEqual("暂无详情", LogDisplayLocalizer.Detail(null, "zh-CN")); Assert.AreEqual("No details", LogDisplayLocalizer.Detail(" ", "en-US")); Assert.AreEqual("真实详情", LogDisplayLocalizer.Detail("真实详情", "zh-CN")); } [TestMethod] public void LogDisplayLocalizerTranslatesCommonEnglishMessagesInChineseMode() { Assert.AreEqual("打开启动自检结果", LogDisplayLocalizer.Message("Open startup check results", "zh-CN")); Assert.AreEqual("工具目录已重建", LogDisplayLocalizer.Message("Tool catalog rebuilt", "zh-CN")); StringAssert.Contains(LogDisplayLocalizer.Message("External tool success: launch", "zh-CN"), "外部工具成功"); Assert.AreEqual("外部工具成功", LogDisplayLocalizer.Message("External tool success", "zh-CN")); StringAssert.Contains(LogDisplayLocalizer.Message("Tool result canceled: export", "zh-CN"), "工具结果已取消"); Assert.AreEqual("工具工作进程已就绪", LogDisplayLocalizer.Message("Tool worker ready", "zh-CN")); Assert.AreEqual("下载宿主进程已启动", LogDisplayLocalizer.Message("Download host process started", "zh-CN")); Assert.AreEqual("打开插件页面:sample/main", LogDisplayLocalizer.Message("Open plugin surface: sample/main", "zh-CN")); Assert.AreEqual("打开 JSON formatter", LogDisplayLocalizer.Message("Open JSON formatter", "zh-CN")); Assert.AreEqual("\u66f4\u65b0\u901a\u77e5\u68c0\u67e5\u5931\u8d25", LogDisplayLocalizer.Message("Update notice check failed", "zh-CN")); Assert.AreEqual("\u542f\u52a8\u81ea\u68c0\u7ed3\u679c\u9884\u52a0\u8f7d\u5931\u8d25", LogDisplayLocalizer.Message("Startup check result preload failed", "zh-CN")); Assert.AreEqual("\u8bbe\u7f6e\u9875\u52a0\u8f7d\u5931\u8d25", LogDisplayLocalizer.Message("Settings page load failed", "zh-CN")); Assert.AreEqual("\u5df2\u8bb0\u4f4f\u5173\u95ed\u786e\u8ba4\u9009\u62e9", LogDisplayLocalizer.Message("Close confirmation remembered", "zh-CN")); } [TestMethod] public void LogDisplayLocalizerTranslatesCommonDetailKeysInChineseMode() { var detail = LogDisplayLocalizer.Detail("result=success; operation=launch; elapsedMs=12; root=C:\\Tools; count=8", "zh-CN"); StringAssert.Contains(detail, "结果=成功"); StringAssert.Contains(detail, "操作=启动"); StringAssert.Contains(detail, "耗时毫秒=12"); StringAssert.Contains(detail, "根目录=C:\\Tools"); StringAssert.Contains(detail, "数量=8"); var windowDetail = LogDisplayLocalizer.Detail("source=tray; behavior=minimize_to_tray; result=primary; dialog=com_exception", "zh-CN"); StringAssert.Contains(windowDetail, "来源=托盘"); StringAssert.Contains(windowDetail, "行为=最小化到托盘"); StringAssert.Contains(windowDetail, "结果=主按钮"); StringAssert.Contains(windowDetail, "弹窗=COM 异常"); } [TestMethod] public async Task ClearFilteredTodayDeletesOnlyMatchingRows() { var tempRoot = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N")); try { var service = new SqliteLogService(AppPaths.ForCurrentUser(tempRoot)); await service.WriteAsync("Information", "tool", "Open tool: JSON formatter"); await service.WriteAsync("Warning", "network", "Proxy diagnostic failed"); await service.ClearFilteredTodayAsync("Information", "JSON"); var entries = await service.ReadAsync(take: 10); Assert.HasCount(1, entries); Assert.AreEqual("network", entries[0].Category); } finally { SqliteConnection.ClearAllPools(); Directory.Delete(tempRoot, recursive: true); } } [TestMethod] public async Task ReadByDateReturnsAllMatchingRowsForSelectedDay() { var tempRoot = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N")); try { var service = new SqliteLogService(AppPaths.ForCurrentUser(tempRoot)); await service.WriteAsync("Information", "tool", "Open JSON formatter"); await service.WriteAsync("Information", "tool", "Open URL codec"); await service.WriteAsync("Warning", "network", "Proxy diagnostic failed"); var allToday = await service.ReadByDateAsync(DateOnly.FromDateTime(DateTime.Now)); var filtered = await service.ReadByDateAsync(DateOnly.FromDateTime(DateTime.Now), "Information", "Open"); Assert.HasCount(3, allToday); Assert.HasCount(2, filtered); } finally { SqliteConnection.ClearAllPools(); Directory.Delete(tempRoot, recursive: true); } } [TestMethod] public async Task ReadByDatePageReturnsStablePages() { var tempRoot = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N")); try { var service = new SqliteLogService(AppPaths.ForCurrentUser(tempRoot)); for (var index = 0; index < 25; index++) { await service.WriteAsync("Information", "stream", $"Row {index:00}"); } var today = DateOnly.FromDateTime(DateTime.Now); var first = await service.ReadByDatePageAsync(today, "Information", "Row", skip: 0, take: 20); var second = await service.ReadByDatePageAsync(today, "Information", "Row", skip: 20, take: 20); Assert.HasCount(20, first); Assert.HasCount(5, second); CollectionAssert.AreNotEquivalent( first.Select(entry => entry.Message).ToArray(), second.Select(entry => entry.Message).ToArray()); } finally { SqliteConnection.ClearAllPools(); Directory.Delete(tempRoot, recursive: true); } } }