d705d47b34
单元测试没过
307 lines
9.0 KiB
C#
307 lines
9.0 KiB
C#
using System.Data.SQLite;
|
|
using Dapper;
|
|
using OCES.Resonance.Core;
|
|
|
|
namespace Core.Tests;
|
|
|
|
public class DatabaseTests
|
|
{
|
|
static string NewDbName() => $"test_{Guid.NewGuid():N}";
|
|
|
|
[Fact]
|
|
public void InitializeDatabase_ShouldCreateAudioFilesTable()
|
|
{
|
|
string dbName = NewDbName();
|
|
string dbPath = $"{Path.Combine(PreferencesManager.GetDefaultDatabasePath(), dbName)}.rdb";
|
|
|
|
try
|
|
{
|
|
// Act
|
|
Database.InitializeDatabase(dbName);
|
|
|
|
// Assert — 用自己的 SQLite 连接验证
|
|
using var conn = new SQLiteConnection($"Data Source={dbPath};Version=3;");
|
|
conn.Open();
|
|
|
|
// 1. 表存在
|
|
var tableCount = conn.ExecuteScalar<int>(
|
|
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='audio_files';");
|
|
Assert.Equal(1, tableCount);
|
|
|
|
// 2. 核心列存在(抽查)
|
|
var columns = conn.Query<string>(
|
|
"SELECT name FROM pragma_table_info('audio_files') ORDER BY cid;").ToHashSet();
|
|
Assert.Contains("id", columns);
|
|
Assert.Contains("unique_id", columns);
|
|
Assert.Contains("md5", columns);
|
|
Assert.Contains("path", columns);
|
|
Assert.Contains("filename", columns);
|
|
Assert.Contains("duration", columns);
|
|
Assert.Contains("bpm", columns);
|
|
Assert.Contains("description", columns);
|
|
|
|
// 3. 索引存在
|
|
var indexes = conn.Query<string>(
|
|
"SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='audio_files';")
|
|
.ToHashSet();
|
|
Assert.Contains("idx_file_name", indexes);
|
|
Assert.Contains("idx_md5", indexes);
|
|
Assert.Contains("idx_path", indexes);
|
|
Assert.Contains("idx_unique_id", indexes);
|
|
Assert.Contains("idx_description", indexes);
|
|
}
|
|
finally
|
|
{
|
|
if (File.Exists(dbPath)) File.Delete(dbPath);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void InitializeDatabase_ShouldBeIdempotent()
|
|
{
|
|
string dbName = NewDbName();
|
|
string dbPath = $"{Path.Combine(PreferencesManager.GetDefaultDatabasePath(), dbName)}.rdb";
|
|
|
|
try
|
|
{
|
|
// Act — 连续调用两次
|
|
Database.InitializeDatabase(dbName);
|
|
Exception? exception = Record.Exception(() => Database.InitializeDatabase(dbName));
|
|
|
|
// Assert — 不应抛出异常
|
|
Assert.Null(exception);
|
|
|
|
// 表仍然只有一个
|
|
using var conn = new SQLiteConnection($"Data Source={dbPath};Version=3;");
|
|
conn.Open();
|
|
var tableCount = conn.ExecuteScalar<int>(
|
|
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='audio_files';");
|
|
Assert.Equal(1, tableCount);
|
|
}
|
|
finally
|
|
{
|
|
if (File.Exists(dbPath)) File.Delete(dbPath);
|
|
}
|
|
}
|
|
|
|
#region 读取方法测试
|
|
|
|
private static AudioFileMeta CreateSampleMeta(int id = 0)
|
|
{
|
|
var guid = Guid.NewGuid().ToString("N");
|
|
return new AudioFileMeta
|
|
{
|
|
Id = id,
|
|
UniqueId = guid,
|
|
ShortId = "TEST",
|
|
Md5 = guid[..16],
|
|
Path = $"/test/path/{guid}.wav",
|
|
Filename = $"{guid}.wav",
|
|
Folder = "test",
|
|
Directory = "/test/path",
|
|
Duration = 2.5,
|
|
BitDepth = 24,
|
|
Channels = 2,
|
|
SampleRate = 48000,
|
|
Type = "WAV",
|
|
DateAdded = DateTime.UtcNow,
|
|
LastWriteTime = DateTime.UtcNow,
|
|
CreationTime = DateTime.UtcNow,
|
|
Description = "Test explosion sound",
|
|
Category = "SFX",
|
|
Keywords = "test,boom,explosion",
|
|
FxName = "Test Explosion Boom"
|
|
};
|
|
}
|
|
|
|
private static string GetDefaultDbPath() =>
|
|
Path.Combine(PreferencesManager.GetDefaultDatabasePath(), "default.rdb");
|
|
|
|
private static void DeleteTestEntries(params string[] uniqueIds)
|
|
{
|
|
using var conn = new SQLiteConnection($"Data Source={GetDefaultDbPath()};Version=3;");
|
|
conn.Open();
|
|
foreach (var uid in uniqueIds)
|
|
conn.Execute("DELETE FROM audio_files WHERE unique_id = @UniqueId", new { UniqueId = uid });
|
|
}
|
|
|
|
[Fact]
|
|
public void AddEntry_Then_GetEntryById_ShouldReturnRecord()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var meta = CreateSampleMeta();
|
|
Assert.True(Database.AddEntry(meta));
|
|
|
|
try
|
|
{
|
|
var retrieved = Database.GetEntryById(meta.Id);
|
|
Assert.NotNull(retrieved);
|
|
Assert.Equal(meta.UniqueId, retrieved!.UniqueId);
|
|
Assert.Equal(meta.Filename, retrieved.Filename);
|
|
Assert.Equal(meta.Duration, retrieved.Duration);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(meta.UniqueId);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void GetEntryById_NotFound_ShouldReturnNull()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var result = Database.GetEntryById(int.MaxValue);
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddEntry_Then_GetEntryByUniqueId_ShouldReturnRecord()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var meta = CreateSampleMeta();
|
|
Database.AddEntry(meta);
|
|
|
|
try
|
|
{
|
|
var retrieved = Database.GetEntryByUniqueId(meta.UniqueId);
|
|
Assert.NotNull(retrieved);
|
|
Assert.Equal(meta.Md5, retrieved!.Md5);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(meta.UniqueId);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void GetEntryByUniqueId_NotFound_ShouldReturnNull()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var result = Database.GetEntryByUniqueId("nonexistent-guid");
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void QueryEntries_ShouldFilterBySearchText()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var meta = CreateSampleMeta();
|
|
meta.Description = "Unique underwater ambience loop";
|
|
meta.Keywords = "water,ocean,deep";
|
|
Database.AddEntry(meta);
|
|
|
|
try
|
|
{
|
|
var results = Database.QueryEntries(searchText: "underwater").ToList();
|
|
Assert.Single(results);
|
|
Assert.Equal(meta.UniqueId, results[0].UniqueId);
|
|
|
|
var empty = Database.QueryEntries(searchText: "zzz_nonexistent_zzz").ToList();
|
|
Assert.Empty(empty);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(meta.UniqueId);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void QueryEntries_ShouldFilterByDuration()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var shortMeta = CreateSampleMeta();
|
|
shortMeta.Duration = 1.0;
|
|
var longMeta = CreateSampleMeta();
|
|
longMeta.Duration = 10.0;
|
|
|
|
Database.AddEntries(new[] { shortMeta, longMeta });
|
|
|
|
try
|
|
{
|
|
var results = Database.QueryEntries(minDuration: 5.0).ToList();
|
|
Assert.Single(results);
|
|
Assert.Equal(longMeta.UniqueId, results[0].UniqueId);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(shortMeta.UniqueId, longMeta.UniqueId);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void QueryEntries_ShouldSupportPagination()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var entries = Enumerable.Range(0, 5).Select(_ => CreateSampleMeta()).ToList();
|
|
Database.AddEntries(entries);
|
|
|
|
try
|
|
{
|
|
var page = Database.QueryEntries(limit: 2, offset: 1).ToList();
|
|
Assert.Equal(2, page.Count);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(entries.Select(e => e.UniqueId).ToArray());
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void SearchEntries_ShouldFindByKeyword()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var meta = CreateSampleMeta();
|
|
meta.Keywords = "magic,spell,fireball";
|
|
Database.AddEntry(meta);
|
|
|
|
try
|
|
{
|
|
var results = Database.SearchEntries("fireball").ToList();
|
|
Assert.Single(results);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(meta.UniqueId);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void GetTotalCount_ShouldRespectSearchFilter()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var meta = CreateSampleMeta();
|
|
var uniqueTag = $"UNIQUE_TAG_{meta.UniqueId[..8]}";
|
|
meta.Description = uniqueTag;
|
|
Database.AddEntry(meta);
|
|
|
|
try
|
|
{
|
|
var count = Database.GetTotalCount(searchText: uniqueTag);
|
|
Assert.Equal(1, count);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(meta.UniqueId);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void AddEntries_ShouldReturnCorrectCount()
|
|
{
|
|
Database.InitializeDatabase();
|
|
var entries = Enumerable.Range(0, 3).Select(_ => CreateSampleMeta()).ToList();
|
|
|
|
try
|
|
{
|
|
var count = Database.AddEntries(entries);
|
|
Assert.Equal(3, count);
|
|
}
|
|
finally
|
|
{
|
|
DeleteTestEntries(entries.Select(e => e.UniqueId).ToArray());
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|