육안 검증 준비 — 전 페이지 렌더 + 제자리 갱신 E_SctMst 어서션 정정
[전 페이지 렌더] --db-render 가 첫 페이지만 뽑던 것을 전 페이지로 확장했다(이름_p1.png …). 운영 서식 128건이 다중 페이지라 첫 장만 봐서는 검증이 되지 않는다. [E_SctMst 어서션 정정] --db-save-smoke 가 제자리 갱신 경로에서도 sctCount == walkerCount 를 요구하고 있었는데, 이 불변식은 버저닝 경로에만 성립한다. 제자리 갱신은 레거시와 동일하게 삭제된 컨트롤의 행을 지우지 않으므로(SctKey 안정성) 과거에 지워진 컨트롤의 고아 행이 누적된다. P347 에서 실제로 걸렸다 — E_SctMst 3행(MDesignerHost1, TextBox1, TextBox2) 대 현재 XML 2개(MDesignerHost1, TextBox2)로, TextBox1 은 과거에 지워진 컨트롤의 잔존 행이었다. 기존 데이터이지 저장 경로의 결함이 아니다. 제자리 갱신은 "워커 산출 행이 전부 존재"(sctCount >= walkerCount)로 바꾸고 잔존 행 수를 리포트에 표시한다. 버저닝은 전량 재생성이므로 정확히 일치 요구를 유지한다. [검증 준비 결과] 위험도 상위 16건을 SheetMe 로 재저장하고 저장 전/후 렌더를 픽셀 비교했다 — 39페이지 전부 동일(J209 6장, S256 7장 포함). 대상 선정은 운영 활성 디자인을 전수 스캔해 위험 요소로 가중치를 매겼다: 자리표시 15건 · Spread 7건 · Binary 569건(45%) · 배경이미지 315건 · 다중페이지 128건 · 제자리갱신 36건. 레거시 뷰어 대조는 사용자가 직접 수행한다(공용 ServerInfo ini 의 CurrentServer 를 운영에서 테스트로 바꿔야 하는데, 그 파일을 레거시 EXE 187개가 공유하므로 자동화하지 않았다). 바탕화면 'SheetMe-검증패키지' 에 체크리스트·렌더 PNG 39장·자동검증 리포트를 준비했다. 검증: 테스트 70/70, edit-smoke 실패 0, 왕복 1,271건 diff 0/예외 0, db-save-smoke 제자리 갱신(P163 정상/P347 잔존 1건 정상)·버저닝(S999) 양쪽 통과. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
71862c2986
commit
d1e488625e
@@ -201,7 +201,11 @@ public partial class App : Application
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>DB 서식 첫 페이지 오프스크린 렌더 → PNG (Spread 격자 주입 경로 포함 검증)</summary>
|
||||
/// <summary>
|
||||
/// DB 서식 오프스크린 렌더 → PNG (Spread 격자 주입 경로 포함 검증).
|
||||
/// 페이지가 여럿이면 <c>이름_p1.png</c>, <c>이름_p2.png</c> … 로 전부 뽑는다 —
|
||||
/// 운영 서식 128건이 다중 페이지라 첫 장만 봐서는 검증이 되지 않는다.
|
||||
/// </summary>
|
||||
private static int RunDbRenderSmoke(string shtCod, string pngPath)
|
||||
{
|
||||
try
|
||||
@@ -215,22 +219,32 @@ public partial class App : Application
|
||||
}
|
||||
|
||||
var designer = new ViewModels.DesignerViewModel(document, dataBusiness.LoadSpreadGrids(shtCod));
|
||||
var page = designer.Pages[0];
|
||||
var directory = Path.GetDirectoryName(pngPath) ?? ".";
|
||||
var stem = Path.GetFileNameWithoutExtension(pngPath);
|
||||
|
||||
var view = new PageView { DataContext = page };
|
||||
var size = new Size(page.WidthDip, page.HeightDip);
|
||||
view.Measure(size);
|
||||
view.Arrange(new Rect(size));
|
||||
view.UpdateLayout();
|
||||
for (var i = 0; i < designer.Pages.Count; i++)
|
||||
{
|
||||
var page = designer.Pages[i];
|
||||
var view = new PageView { DataContext = page };
|
||||
var size = new Size(page.WidthDip, page.HeightDip);
|
||||
view.Measure(size);
|
||||
view.Arrange(new Rect(size));
|
||||
view.UpdateLayout();
|
||||
|
||||
var bitmap = new RenderTargetBitmap(
|
||||
(int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height), 96, 96, PixelFormats.Pbgra32);
|
||||
bitmap.Render(view);
|
||||
var bitmap = new RenderTargetBitmap(
|
||||
(int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height), 96, 96, PixelFormats.Pbgra32);
|
||||
bitmap.Render(view);
|
||||
|
||||
var encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(bitmap));
|
||||
using var stream = File.Create(pngPath);
|
||||
encoder.Save(stream);
|
||||
var encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(bitmap));
|
||||
var target = designer.Pages.Count == 1
|
||||
? pngPath
|
||||
: Path.Combine(directory, $"{stem}_p{i + 1}.png");
|
||||
using var stream = File.Create(target);
|
||||
encoder.Save(stream);
|
||||
}
|
||||
|
||||
Console.WriteLine($"{shtCod}: 페이지 {designer.Pages.Count} 렌더 완료");
|
||||
return 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -519,15 +519,29 @@ public static class DbSmoke
|
||||
|
||||
var sctCount = store.CountSctRows(savedKey);
|
||||
var walkerCount = SctMstXmlWalker.Walk(after.Xml).Count;
|
||||
lines.Add($"[E_SctMst] 저장본 행 {sctCount}건 / 워커 기대 {walkerCount}건 → {(sctCount == walkerCount ? "일치" : "불일치")}");
|
||||
|
||||
if (cneYon != "Y")
|
||||
bool sctOk;
|
||||
if (cneYon == "Y")
|
||||
{
|
||||
// 제자리 갱신은 레거시와 동일하게 삭제된 컨트롤의 행을 지우지 않는다(SctKey 안정성).
|
||||
// 따라서 과거에 지워진 컨트롤의 고아 행이 누적될 수 있고, 행 수 동일은 성립하지 않는다.
|
||||
// 옳은 불변식은 "워커가 낸 행이 전부 존재하고, 재저장으로 늘지 않는다" 이다.
|
||||
sctOk = sctCount >= walkerCount;
|
||||
var orphans = sctCount - walkerCount;
|
||||
lines.Add($"[E_SctMst] 저장본 행 {sctCount}건 / 워커 기대 {walkerCount}건 → " +
|
||||
(sctOk ? $"정상{(orphans > 0 ? $" (과거 삭제 컨트롤의 잔존 행 {orphans}건 — 레거시도 지우지 않음)" : "")}"
|
||||
: "부족! 워커 산출 행이 DB 에 없음"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 버저닝은 E_SctMst 를 새 키로 전량 재생성하므로 정확히 일치해야 한다
|
||||
sctOk = sctCount == walkerCount;
|
||||
lines.Add($"[E_SctMst] 저장본 행 {sctCount}건 / 워커 기대 {walkerCount}건 → {(sctOk ? "일치" : "불일치")}");
|
||||
|
||||
var oldVersion = versionsAfter.FirstOrDefault(v => v.SdgKey == before.SdgKey);
|
||||
lines.Add($"[이력] 이전 버전 SdgKey={before.SdgKey} SdgDelYon='Y' 처리: {(oldVersion?.Deleted == true ? "확인" : "미확인!")}");
|
||||
}
|
||||
|
||||
var ok = diffs.Count == 0 && sctCount == walkerCount;
|
||||
var ok = diffs.Count == 0 && sctOk;
|
||||
|
||||
// 제자리 갱신 경로에서만 의미가 있는 검사 — 무변경 재저장으로는 SctObjTxt 갱신을 증명할 수 없으므로
|
||||
// 문구를 실제로 바꿔 E_SctMst 에 반영되는지 확인하고 원복한다(레거시는 SctObjTxt 만 덮어쓴다).
|
||||
|
||||
Reference in New Issue
Block a user