158 lines
6.3 KiB
C#
158 lines
6.3 KiB
C#
using System.Data;
|
|
using MBN_STOCK_WEBVIEW.LegacyApplication;
|
|
using MMoneyCoderSharp.Data;
|
|
|
|
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
|
|
|
|
public sealed class LegacyParityStockSearchServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task Search_PreservesProviderAndRowOrderWithoutLimitOrSort()
|
|
{
|
|
var executor = new RecordingExecutor(new Dictionary<string, DataTable>
|
|
{
|
|
["LEGACY_PARITY_KOSPI_MASTER"] = Table(("중복", "000001")),
|
|
["LEGACY_PARITY_KOSDAQ_MASTER"] = Table(("중복", "100001")),
|
|
["LEGACY_PARITY_NXT_KOSPI_MASTER"] = Table(("중복(NXT)", "200001")),
|
|
["LEGACY_PARITY_NXT_KOSDAQ_MASTER"] = Table(("중복", "300001")),
|
|
["LEGACY_PARITY_KOSPI"] = Table(("가-2", "000002"), ("가-1", "000001")),
|
|
["LEGACY_PARITY_KOSDAQ"] = Table(("나", "100001")),
|
|
["LEGACY_PARITY_NXT_KOSPI"] = Table(("다(NXT)", "200001")),
|
|
["LEGACY_PARITY_NXT_KOSDAQ"] = Table(("라(NXT)", "300001"))
|
|
});
|
|
var service = new LegacyParityStockSearchService(executor);
|
|
|
|
var result = await service.SearchAsync(" a%_ ");
|
|
|
|
Assert.Equal(["가-2", "가-1", "나", "다(NXT)", "라(NXT)"], result.DisplayNames);
|
|
Assert.Equal("300001", result.ResolveLastByDisplayName("중복")?.StockCode);
|
|
Assert.Equal(LegacyDomesticStockMarket.NxtKosdaq,
|
|
result.ResolveLastByDisplayName("중복")?.Market);
|
|
Assert.Equal(8, executor.Calls.Count);
|
|
|
|
foreach (var call in executor.Calls.Skip(4))
|
|
{
|
|
Assert.DoesNotContain("ORDER BY", call.Spec.Sql, StringComparison.OrdinalIgnoreCase);
|
|
Assert.DoesNotContain("LIMIT", call.Spec.Sql, StringComparison.OrdinalIgnoreCase);
|
|
Assert.DoesNotContain("ROWNUM", call.Spec.Sql, StringComparison.OrdinalIgnoreCase);
|
|
Assert.Single(call.Spec.Parameters);
|
|
Assert.Equal(" A%_ ", call.Spec.Parameters[0].Value);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task EmptySearch_IsAllowedAndMasterSnapshotIsCached()
|
|
{
|
|
var tables = new Dictionary<string, DataTable>();
|
|
foreach (var name in new[]
|
|
{
|
|
"LEGACY_PARITY_KOSPI", "LEGACY_PARITY_KOSDAQ",
|
|
"LEGACY_PARITY_NXT_KOSPI", "LEGACY_PARITY_NXT_KOSDAQ"
|
|
})
|
|
{
|
|
tables[name] = Table();
|
|
tables[$"{name}_MASTER"] = Table();
|
|
}
|
|
|
|
var executor = new RecordingExecutor(tables);
|
|
var service = new LegacyParityStockSearchService(executor);
|
|
|
|
await service.SearchAsync(string.Empty);
|
|
await service.SearchAsync(string.Empty);
|
|
|
|
Assert.Equal(12, executor.Calls.Count);
|
|
Assert.Equal(4, executor.Calls.Count(call => call.TableName.EndsWith("_MASTER", StringComparison.Ordinal)));
|
|
Assert.All(executor.Calls.Where(call => !call.TableName.EndsWith("_MASTER", StringComparison.Ordinal)),
|
|
call => Assert.Equal(string.Empty, call.Spec.Parameters[0].Value));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task InitialConsonantSearch_FiltersOnlyLegacySearchCandidatesInProviderOrder()
|
|
{
|
|
var executor = new RecordingExecutor(new Dictionary<string, DataTable>
|
|
{
|
|
["LEGACY_PARITY_KOSPI_MASTER"] = Table(
|
|
("삼성전자", "005930")),
|
|
["LEGACY_PARITY_KOSDAQ_MASTER"] = Table(
|
|
("삼성중공업", "010140")),
|
|
["LEGACY_PARITY_NXT_KOSPI_MASTER"] = Table(
|
|
("삼성전자(NXT)", "005930"),
|
|
("삼성화재(NXT)", "000810")),
|
|
["LEGACY_PARITY_NXT_KOSDAQ_MASTER"] = Table(
|
|
("카카오게임즈(NXT)", "293490")),
|
|
["LEGACY_PARITY_KOSPI"] = Table(
|
|
("삼성전자", "005930"),
|
|
("서울반도체", "046890")),
|
|
["LEGACY_PARITY_KOSDAQ"] = Table(
|
|
("삼성중공업", "010140")),
|
|
["LEGACY_PARITY_NXT_KOSPI"] = Table(
|
|
("삼성전자(NXT)", "005930")),
|
|
["LEGACY_PARITY_NXT_KOSDAQ"] = Table()
|
|
});
|
|
var service = new LegacyParityStockSearchService(executor);
|
|
|
|
var result = await service.SearchAsync("ㅅㅅ");
|
|
|
|
Assert.Equal(
|
|
["삼성전자", "삼성중공업", "삼성전자(NXT)"],
|
|
result.DisplayNames);
|
|
Assert.DoesNotContain("삼성화재(NXT)", result.DisplayNames);
|
|
Assert.NotNull(result.ResolveLastByDisplayName("삼성화재(NXT)"));
|
|
Assert.Equal(8, executor.Calls.Count);
|
|
Assert.All(
|
|
executor.Calls.Where(call => !call.TableName.EndsWith("_MASTER", StringComparison.Ordinal)),
|
|
call => Assert.Equal(string.Empty, call.Spec.Parameters[0].Value));
|
|
Assert.Contains(
|
|
executor.Calls,
|
|
call => call.TableName == "LEGACY_PARITY_NXT_KOSPI" &&
|
|
call.Spec.Sql.Contains("N_ONLINE", StringComparison.Ordinal));
|
|
}
|
|
|
|
private static DataTable Table(params (string Name, string Code)[] rows)
|
|
{
|
|
var table = new DataTable();
|
|
table.Columns.Add("STOCK_NAME", typeof(string));
|
|
table.Columns.Add("STOCK_CODE", typeof(string));
|
|
foreach (var row in rows)
|
|
{
|
|
table.Rows.Add(row.Name, row.Code);
|
|
}
|
|
|
|
return table;
|
|
}
|
|
|
|
private sealed class RecordingExecutor : IDataQueryExecutor
|
|
{
|
|
private readonly IReadOnlyDictionary<string, DataTable> _tables;
|
|
|
|
public RecordingExecutor(IReadOnlyDictionary<string, DataTable> tables)
|
|
{
|
|
_tables = tables;
|
|
}
|
|
|
|
public List<Call> Calls { get; } = [];
|
|
|
|
public DataTable Execute(DataSourceKind source, string tableName, string query) =>
|
|
throw new NotSupportedException();
|
|
|
|
public Task<DataTable> ExecuteAsync(
|
|
DataSourceKind source,
|
|
string tableName,
|
|
string query,
|
|
CancellationToken cancellationToken = default) =>
|
|
throw new NotSupportedException();
|
|
|
|
public Task<DataTable> ExecuteAsync(
|
|
DataSourceKind source,
|
|
string tableName,
|
|
DataQuerySpec query,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
Calls.Add(new Call(source, tableName, query));
|
|
return Task.FromResult(_tables[tableName].Copy());
|
|
}
|
|
}
|
|
|
|
private sealed record Call(DataSourceKind Source, string TableName, DataQuerySpec Spec);
|
|
}
|