598 lines
22 KiB
C#
598 lines
22 KiB
C#
using System.Text;
|
|
using MMoneyCoderSharp.Data;
|
|
|
|
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
|
|
|
|
public sealed class LegacyRuntimeUiCatalogLoaderTests
|
|
{
|
|
private static readonly Encoding Cp949 = CreateCp949Encoding();
|
|
|
|
[Fact]
|
|
public void ConfiguredLegacyBinDebugFiles_MatchEveryRuntimeProjection()
|
|
{
|
|
var legacyBinDebug = Environment.GetEnvironmentVariable(
|
|
"MBN_STOCK_N_LEGACY_BIN_DEBUG");
|
|
if (string.IsNullOrWhiteSpace(legacyBinDebug))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
legacyBinDebug);
|
|
|
|
Assert.Empty(composition.Warnings);
|
|
AssertRuntimeFixedFile(
|
|
legacyBinDebug,
|
|
"해외.ini",
|
|
LegacyFixedMarket.Overseas,
|
|
LegacyFixedActionCatalog.ExpectedOverseasCount,
|
|
composition.FixedCatalog);
|
|
AssertRuntimeFixedFile(
|
|
legacyBinDebug,
|
|
"환율.ini",
|
|
LegacyFixedMarket.Exchange,
|
|
LegacyFixedActionCatalog.ExpectedExchangeCount,
|
|
composition.FixedCatalog);
|
|
AssertRuntimeFixedFile(
|
|
legacyBinDebug,
|
|
"지수.ini",
|
|
LegacyFixedMarket.Index,
|
|
LegacyFixedActionCatalog.ExpectedIndexCount,
|
|
composition.FixedCatalog);
|
|
AssertRuntimeIndustryFile(
|
|
legacyBinDebug,
|
|
"업종_코스피.ini",
|
|
IndustryMarket.Kospi,
|
|
composition.IndustryLayout);
|
|
AssertRuntimeIndustryFile(
|
|
legacyBinDebug,
|
|
"업종_코스닥.ini",
|
|
IndustryMarket.Kosdaq,
|
|
composition.IndustryLayout);
|
|
AssertRuntimeComparisonFile(
|
|
legacyBinDebug,
|
|
composition.ComparisonLayout);
|
|
}
|
|
|
|
[Fact]
|
|
public void RuntimeFiles_ControlOnlyTrustedDisplayOrder()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
var fixedOrders = Enum.GetValues<LegacyFixedMarket>()
|
|
.ToDictionary(
|
|
market => market,
|
|
market => LegacyFixedActionCatalog.Default.GetActions(market)
|
|
.Reverse()
|
|
.ToArray());
|
|
var kospi = LegacyIndustryActionCatalog.GetActions(IndustryMarket.Kospi)
|
|
.Reverse()
|
|
.ToArray();
|
|
var kosdaq = LegacyIndustryActionCatalog.GetActions(IndustryMarket.Kosdaq)
|
|
.Reverse()
|
|
.ToArray();
|
|
var targets = LegacyComparisonWorkflowCatalog.FixedTargets
|
|
.Reverse()
|
|
.ToArray();
|
|
var directActions = LegacyComparisonWorkflowCatalog.Actions
|
|
.Where(action => action.Kind != LegacyComparisonActionKind.Return)
|
|
.Reverse()
|
|
.ToArray();
|
|
var returnActions = LegacyComparisonWorkflowCatalog.Actions
|
|
.Where(action => action.Kind == LegacyComparisonActionKind.Return)
|
|
.Reverse()
|
|
.ToArray();
|
|
|
|
WriteAllValidFiles(
|
|
directory.Path,
|
|
fixedOrders,
|
|
kospi,
|
|
kosdaq,
|
|
targets,
|
|
directActions,
|
|
returnActions,
|
|
returnSectionFirst: true);
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
directory.Path);
|
|
|
|
Assert.Empty(composition.Warnings);
|
|
foreach (var market in Enum.GetValues<LegacyFixedMarket>())
|
|
{
|
|
Assert.Equal(
|
|
FlattenForIni(fixedOrders[market]).Select(action => action.Id),
|
|
composition.FixedCatalog.GetActions(market).Select(action => action.Id));
|
|
}
|
|
|
|
Assert.Equal(
|
|
kospi.Select(action => action.ActionId),
|
|
composition.IndustryLayout.GetActions(IndustryMarket.Kospi)
|
|
.Select(action => action.ActionId));
|
|
Assert.Equal(
|
|
kosdaq.Select(action => action.ActionId),
|
|
composition.IndustryLayout.GetActions(IndustryMarket.Kosdaq)
|
|
.Select(action => action.ActionId));
|
|
Assert.Equal(
|
|
targets.Select(target => target.TargetId),
|
|
composition.ComparisonLayout.FixedTargets.Select(target => target.TargetId));
|
|
Assert.Equal(
|
|
returnActions.Select(action => action.ActionId)
|
|
.Concat(directActions.Select(action => action.ActionId)),
|
|
composition.ComparisonLayout.CreateActionViews(null, null)
|
|
.Select(action => action.ActionId));
|
|
|
|
var industryWorkflow = new LegacyIndustrySelectionWorkflow(
|
|
new EmptyIndustrySelectionService(),
|
|
actionLayout: composition.IndustryLayout);
|
|
Assert.Equal(
|
|
kospi.Select(action => action.ActionId),
|
|
industryWorkflow.ResetForTabActivation(IndustryMarket.Kospi)
|
|
.Actions.Select(action => action.ActionId));
|
|
|
|
var comparisonWorkflow = new LegacyComparisonWorkflowController(
|
|
new EmptyComparisonDataService(),
|
|
new EmptyComparisonPairStore(),
|
|
composition.ComparisonLayout);
|
|
Assert.Equal(
|
|
targets.Select(target => target.DisplayName),
|
|
comparisonWorkflow.Current.FixedTargets.Select(target => target.DisplayName));
|
|
Assert.Equal(
|
|
returnActions.Select(action => action.ActionId)
|
|
.Concat(directActions.Select(action => action.ActionId)),
|
|
comparisonWorkflow.Current.Actions.Select(action => action.ActionId));
|
|
}
|
|
|
|
[Fact]
|
|
public void ResolveFromResourceDirectory_ReadsTheDirectNativeSelectedDirectory()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
WriteAllValidFiles(directory.Path);
|
|
var resourceDirectory = System.IO.Path.Combine(directory.Path, "Res");
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader
|
|
.ResolveFromResourceDirectory(resourceDirectory);
|
|
|
|
Assert.Empty(composition.Warnings);
|
|
AssertRuntimeFixedFile(
|
|
directory.Path,
|
|
"해외.ini",
|
|
LegacyFixedMarket.Overseas,
|
|
LegacyFixedActionCatalog.ExpectedOverseasCount,
|
|
composition.FixedCatalog);
|
|
}
|
|
|
|
[Fact]
|
|
public void UnknownFixedRow_FallsBackWithoutRegisteringAnAction()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
WriteAllValidFiles(directory.Path);
|
|
WriteFixedFile(
|
|
directory.Path,
|
|
LegacyFixedMarket.Overseas,
|
|
LegacyFixedActionCatalog.Default.GetActions(LegacyFixedMarket.Overseas),
|
|
(action, index) => index == 0 ? "untrusted-new-action" : action.Label);
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
directory.Path);
|
|
|
|
var warning = Assert.Single(composition.Warnings);
|
|
Assert.Equal("해외.ini", warning.FileName);
|
|
Assert.Equal(LegacyRuntimeUiCatalogFailure.UnknownEntry, warning.Failure);
|
|
Assert.Equal(
|
|
LegacyFixedActionCatalog.Default.GetActions(LegacyFixedMarket.Overseas)
|
|
.Select(action => action.Id),
|
|
composition.FixedCatalog.GetActions(LegacyFixedMarket.Overseas)
|
|
.Select(action => action.Id));
|
|
Assert.DoesNotContain(
|
|
composition.FixedCatalog.Actions,
|
|
action => string.Equals(
|
|
action.Label,
|
|
"untrusted-new-action",
|
|
StringComparison.Ordinal));
|
|
}
|
|
|
|
[Fact]
|
|
public void ExcessDuplicateRow_FallsBackWithDuplicateWarning()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
WriteAllValidFiles(directory.Path);
|
|
WriteFixedFile(
|
|
directory.Path,
|
|
LegacyFixedMarket.Exchange,
|
|
LegacyFixedActionCatalog.Default.GetActions(LegacyFixedMarket.Exchange),
|
|
appendDuplicate: true);
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
directory.Path);
|
|
|
|
var warning = Assert.Single(composition.Warnings);
|
|
Assert.Equal("환율.ini", warning.FileName);
|
|
Assert.Equal(LegacyRuntimeUiCatalogFailure.DuplicateEntry, warning.Failure);
|
|
Assert.Equal(
|
|
LegacyFixedActionCatalog.Default.GetActions(LegacyFixedMarket.Exchange)
|
|
.Select(action => action.Id),
|
|
composition.FixedCatalog.GetActions(LegacyFixedMarket.Exchange)
|
|
.Select(action => action.Id));
|
|
}
|
|
|
|
[Fact]
|
|
public void InvalidCp949_FallsBackOnlyForThatFile()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
WriteAllValidFiles(directory.Path);
|
|
File.WriteAllBytes(
|
|
System.IO.Path.Combine(directory.Path, "Res", "지수.ini"),
|
|
[0x81]);
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
directory.Path);
|
|
|
|
var warning = Assert.Single(composition.Warnings);
|
|
Assert.Equal("지수.ini", warning.FileName);
|
|
Assert.Equal(LegacyRuntimeUiCatalogFailure.InvalidEncoding, warning.Failure);
|
|
Assert.Equal(
|
|
LegacyFixedActionCatalog.Default.GetActions(LegacyFixedMarket.Index)
|
|
.Select(action => action.Id),
|
|
composition.FixedCatalog.GetActions(LegacyFixedMarket.Index)
|
|
.Select(action => action.Id));
|
|
}
|
|
|
|
[Fact]
|
|
public void RowLimit_FailsClosedBeforeCatalogJoin()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
WriteAllValidFiles(directory.Path);
|
|
var section = LegacyFixedActionCatalog.Default
|
|
.GetActions(LegacyFixedMarket.Overseas)[0].Section;
|
|
WriteCp949(
|
|
System.IO.Path.Combine(directory.Path, "Res", "해외.ini"),
|
|
[$"[{section}]", .. Enumerable.Range(1, 51).Select(index => $"row-{index}")]);
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
directory.Path);
|
|
|
|
var warning = Assert.Single(composition.Warnings);
|
|
Assert.Equal("해외.ini", warning.FileName);
|
|
Assert.Equal(LegacyRuntimeUiCatalogFailure.TooManyRows, warning.Failure);
|
|
}
|
|
|
|
[Fact]
|
|
public void ComparisonDirectActionCannotBeReinterpretedAsAChildRow()
|
|
{
|
|
using var directory = new TemporaryDirectory();
|
|
WriteAllValidFiles(directory.Path);
|
|
var directActions = LegacyComparisonWorkflowCatalog.Actions
|
|
.Where(action => action.Kind != LegacyComparisonActionKind.Return)
|
|
.ToArray();
|
|
var returnActions = LegacyComparisonWorkflowCatalog.Actions
|
|
.Where(action => action.Kind == LegacyComparisonActionKind.Return)
|
|
.ToArray();
|
|
var lines = new List<string> { "[지수]" };
|
|
lines.AddRange(LegacyComparisonWorkflowCatalog.FixedTargets
|
|
.Select(target => target.DisplayName));
|
|
foreach (var action in directActions)
|
|
{
|
|
lines.Add($"[{action.Label}]");
|
|
}
|
|
|
|
lines.Add($"[{returnActions[0].Section}]");
|
|
lines.Add(directActions[0].Label);
|
|
lines.AddRange(returnActions.Select(action => action.Label));
|
|
WriteCp949(
|
|
System.IO.Path.Combine(directory.Path, "Res", "종목비교.ini"),
|
|
lines);
|
|
|
|
var composition = LegacyRuntimeUiCatalogLoader.ResolveFromBaseDirectory(
|
|
directory.Path);
|
|
|
|
var warning = Assert.Single(composition.Warnings);
|
|
Assert.Equal("종목비교.ini", warning.FileName);
|
|
Assert.Equal(LegacyRuntimeUiCatalogFailure.UnknownEntry, warning.Failure);
|
|
Assert.Equal(
|
|
LegacyComparisonWorkflowCatalog.Actions.Select(action => action.ActionId),
|
|
composition.ComparisonLayout.CreateActionViews(null, null)
|
|
.Select(action => action.ActionId));
|
|
}
|
|
|
|
private static void WriteAllValidFiles(
|
|
string baseDirectory,
|
|
IReadOnlyDictionary<LegacyFixedMarket, LegacyFixedAction[]>? fixedOrders = null,
|
|
IReadOnlyList<LegacyIndustryActionDefinition>? kospi = null,
|
|
IReadOnlyList<LegacyIndustryActionDefinition>? kosdaq = null,
|
|
IReadOnlyList<LegacyComparisonTarget>? targets = null,
|
|
IReadOnlyList<LegacyComparisonActionDefinition>? directActions = null,
|
|
IReadOnlyList<LegacyComparisonActionDefinition>? returnActions = null,
|
|
bool returnSectionFirst = false)
|
|
{
|
|
Directory.CreateDirectory(System.IO.Path.Combine(baseDirectory, "Res"));
|
|
foreach (var market in Enum.GetValues<LegacyFixedMarket>())
|
|
{
|
|
WriteFixedFile(
|
|
baseDirectory,
|
|
market,
|
|
fixedOrders is not null && fixedOrders.TryGetValue(market, out var ordered)
|
|
? ordered
|
|
: LegacyFixedActionCatalog.Default.GetActions(market));
|
|
}
|
|
|
|
WriteIndustryFile(
|
|
baseDirectory,
|
|
IndustryMarket.Kospi,
|
|
kospi ?? LegacyIndustryActionCatalog.GetActions(IndustryMarket.Kospi));
|
|
WriteIndustryFile(
|
|
baseDirectory,
|
|
IndustryMarket.Kosdaq,
|
|
kosdaq ?? LegacyIndustryActionCatalog.GetActions(IndustryMarket.Kosdaq));
|
|
WriteComparisonFile(
|
|
baseDirectory,
|
|
targets ?? LegacyComparisonWorkflowCatalog.FixedTargets,
|
|
directActions ?? LegacyComparisonWorkflowCatalog.Actions
|
|
.Where(action => action.Kind != LegacyComparisonActionKind.Return)
|
|
.ToArray(),
|
|
returnActions ?? LegacyComparisonWorkflowCatalog.Actions
|
|
.Where(action => action.Kind == LegacyComparisonActionKind.Return)
|
|
.ToArray(),
|
|
returnSectionFirst);
|
|
}
|
|
|
|
private static void WriteFixedFile(
|
|
string baseDirectory,
|
|
LegacyFixedMarket market,
|
|
IReadOnlyList<LegacyFixedAction> actions,
|
|
Func<LegacyFixedAction, int, string>? labelSelector = null,
|
|
bool appendDuplicate = false)
|
|
{
|
|
var lines = new List<string>();
|
|
var rowIndex = 0;
|
|
foreach (var section in actions.GroupBy(action => action.Section, StringComparer.Ordinal))
|
|
{
|
|
lines.Add($"[{section.Key}]");
|
|
foreach (var action in section)
|
|
{
|
|
lines.Add(labelSelector?.Invoke(action, rowIndex) ?? action.Label);
|
|
rowIndex++;
|
|
}
|
|
|
|
if (appendDuplicate)
|
|
{
|
|
lines.Add(section.First().Label);
|
|
appendDuplicate = false;
|
|
}
|
|
}
|
|
|
|
WriteCp949(
|
|
System.IO.Path.Combine(baseDirectory, "Res", FixedFileName(market)),
|
|
lines);
|
|
}
|
|
|
|
private static IEnumerable<LegacyFixedAction> FlattenForIni(
|
|
IEnumerable<LegacyFixedAction> actions) =>
|
|
actions.GroupBy(action => action.Section, StringComparer.Ordinal)
|
|
.SelectMany(group => group);
|
|
|
|
private static void WriteIndustryFile(
|
|
string baseDirectory,
|
|
IndustryMarket market,
|
|
IReadOnlyList<LegacyIndustryActionDefinition> actions)
|
|
{
|
|
var section = market == IndustryMarket.Kospi ? "코스피" : "코스닥";
|
|
WriteCp949(
|
|
System.IO.Path.Combine(baseDirectory, "Res", IndustryFileName(market)),
|
|
[$"[{section}]", .. actions.Select(action => action.Label)]);
|
|
}
|
|
|
|
private static void WriteComparisonFile(
|
|
string baseDirectory,
|
|
IReadOnlyList<LegacyComparisonTarget> targets,
|
|
IReadOnlyList<LegacyComparisonActionDefinition> directActions,
|
|
IReadOnlyList<LegacyComparisonActionDefinition> returnActions,
|
|
bool returnSectionFirst)
|
|
{
|
|
var lines = new List<string> { "[지수]" };
|
|
lines.AddRange(targets.Select(target => target.DisplayName));
|
|
void AddDirectSections()
|
|
{
|
|
foreach (var action in directActions)
|
|
{
|
|
lines.Add($"[{action.Label}]");
|
|
}
|
|
}
|
|
|
|
void AddReturnSection()
|
|
{
|
|
lines.Add($"[{returnActions[0].Section}]");
|
|
lines.AddRange(returnActions.Select(action => action.Label));
|
|
}
|
|
|
|
if (returnSectionFirst)
|
|
{
|
|
AddReturnSection();
|
|
AddDirectSections();
|
|
}
|
|
else
|
|
{
|
|
AddDirectSections();
|
|
AddReturnSection();
|
|
}
|
|
|
|
WriteCp949(
|
|
System.IO.Path.Combine(baseDirectory, "Res", "종목비교.ini"),
|
|
lines);
|
|
}
|
|
|
|
private static void WriteCp949(string path, IEnumerable<string> lines) =>
|
|
File.WriteAllText(path, string.Join("\r\n", lines) + "\r\n", Cp949);
|
|
|
|
private static void AssertRuntimeFixedFile(
|
|
string baseDirectory,
|
|
string fileName,
|
|
LegacyFixedMarket market,
|
|
int expectedCount,
|
|
LegacyFixedActionCatalog catalog)
|
|
{
|
|
var document = ReadTestIni(baseDirectory, fileName);
|
|
var actions = catalog.GetActions(market);
|
|
Assert.Equal(expectedCount, actions.Count);
|
|
Assert.Equal(
|
|
document.SelectMany(section => section.Rows),
|
|
actions.Select(action => action.Label));
|
|
Assert.Equal(
|
|
document.SelectMany(section => section.Rows.Select(_ => section.Name)),
|
|
actions.Select(action => action.Section));
|
|
}
|
|
|
|
private static void AssertRuntimeIndustryFile(
|
|
string baseDirectory,
|
|
string fileName,
|
|
IndustryMarket market,
|
|
LegacyIndustryActionLayout layout)
|
|
{
|
|
var section = Assert.Single(ReadTestIni(baseDirectory, fileName));
|
|
var actions = layout.GetActions(market);
|
|
Assert.Equal(LegacyIndustryActionCatalog.ActionsPerMarket, actions.Count);
|
|
Assert.Equal(section.Rows, actions.Select(action => action.Label));
|
|
Assert.All(actions, action => Assert.Equal(section.Name, action.Section));
|
|
}
|
|
|
|
private static void AssertRuntimeComparisonFile(
|
|
string baseDirectory,
|
|
LegacyComparisonUiLayout layout)
|
|
{
|
|
var document = ReadTestIni(baseDirectory, "종목비교.ini");
|
|
Assert.Equal(6, document.Count);
|
|
Assert.Equal(24, layout.FixedTargets.Count);
|
|
Assert.Equal(
|
|
document[0].Rows,
|
|
layout.FixedTargets.Select(target => target.DisplayName));
|
|
var expectedActions = document.Skip(1).SelectMany(section =>
|
|
section.Rows.Count == 0
|
|
? new[] { (Label: section.Name, Section: section.Name) }
|
|
: section.Rows.Select(row => (Label: row, Section: section.Name)));
|
|
var actualActions = layout.CreateActionViews(null, null);
|
|
Assert.Equal(9, actualActions.Count);
|
|
Assert.Equal(
|
|
expectedActions,
|
|
actualActions.Select(action => (action.Label, action.Section)));
|
|
}
|
|
|
|
private static IReadOnlyList<TestIniSection> ReadTestIni(
|
|
string baseDirectory,
|
|
string fileName)
|
|
{
|
|
var sections = new List<TestIniSection>();
|
|
List<string>? rows = null;
|
|
foreach (var source in File.ReadAllLines(
|
|
System.IO.Path.Combine(baseDirectory, "Res", fileName),
|
|
Cp949))
|
|
{
|
|
var line = source.Trim();
|
|
if (line.Length == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (line[0] == '[' && line[^1] == ']')
|
|
{
|
|
rows = [];
|
|
sections.Add(new TestIniSection(line[1..^1].Trim(), rows));
|
|
}
|
|
else
|
|
{
|
|
Assert.NotNull(rows);
|
|
rows.Add(line);
|
|
}
|
|
}
|
|
|
|
return sections;
|
|
}
|
|
|
|
private static string FixedFileName(LegacyFixedMarket market) => market switch
|
|
{
|
|
LegacyFixedMarket.Overseas => "해외.ini",
|
|
LegacyFixedMarket.Exchange => "환율.ini",
|
|
LegacyFixedMarket.Index => "지수.ini",
|
|
_ => throw new ArgumentOutOfRangeException(nameof(market), market, null)
|
|
};
|
|
|
|
private static string IndustryFileName(IndustryMarket market) => market switch
|
|
{
|
|
IndustryMarket.Kospi => "업종_코스피.ini",
|
|
IndustryMarket.Kosdaq => "업종_코스닥.ini",
|
|
_ => throw new ArgumentOutOfRangeException(nameof(market), market, null)
|
|
};
|
|
|
|
private static Encoding CreateCp949Encoding()
|
|
{
|
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
|
return Encoding.GetEncoding(
|
|
949,
|
|
EncoderFallback.ExceptionFallback,
|
|
DecoderFallback.ExceptionFallback);
|
|
}
|
|
|
|
private sealed class EmptyIndustrySelectionService : IIndustrySelectionService
|
|
{
|
|
public Task<IReadOnlyList<IndustrySelection>> GetAsync(
|
|
IndustryMarket market,
|
|
CancellationToken cancellationToken = default) =>
|
|
Task.FromResult<IReadOnlyList<IndustrySelection>>(
|
|
Array.Empty<IndustrySelection>());
|
|
}
|
|
|
|
private sealed class EmptyComparisonDataService : ILegacyComparisonDataService
|
|
{
|
|
public Task<IReadOnlyList<LegacyComparisonTarget>> SearchDomesticAsync(
|
|
string query,
|
|
int maximumResults,
|
|
CancellationToken cancellationToken = default) =>
|
|
Task.FromResult<IReadOnlyList<LegacyComparisonTarget>>(
|
|
Array.Empty<LegacyComparisonTarget>());
|
|
|
|
public Task<IReadOnlyList<LegacyComparisonTarget>> SearchWorldAsync(
|
|
string query,
|
|
int maximumResults,
|
|
CancellationToken cancellationToken = default) =>
|
|
Task.FromResult<IReadOnlyList<LegacyComparisonTarget>>(
|
|
Array.Empty<LegacyComparisonTarget>());
|
|
|
|
public Task<LegacyComparisonTarget?> ResolveStoredTargetAsync(
|
|
LegacyComparisonStoredTargetReference target,
|
|
CancellationToken cancellationToken = default) =>
|
|
Task.FromResult<LegacyComparisonTarget?>(null);
|
|
}
|
|
|
|
private sealed class EmptyComparisonPairStore : ILegacyComparisonPairStore
|
|
{
|
|
public Task<byte[]?> ReadCp949Async(
|
|
CancellationToken cancellationToken = default) =>
|
|
Task.FromResult<byte[]?>(null);
|
|
|
|
public Task WriteCp949Async(
|
|
IReadOnlyList<LegacyComparisonPairWriteRow> rows,
|
|
CancellationToken cancellationToken = default) =>
|
|
Task.CompletedTask;
|
|
}
|
|
|
|
private sealed class TemporaryDirectory : IDisposable
|
|
{
|
|
public TemporaryDirectory()
|
|
{
|
|
Path = System.IO.Path.Combine(
|
|
System.IO.Path.GetTempPath(),
|
|
$"MBN_STOCK_WEBVIEW_UI_INI_{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(Path);
|
|
}
|
|
|
|
public string Path { get; }
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(Path))
|
|
{
|
|
Directory.Delete(Path, recursive: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed record TestIniSection(string Name, IReadOnlyList<string> Rows);
|
|
}
|