Files
Aislo/resources/tester/test_est_estplus.py
T
eomsangdonandClaude Opus 5.5 ae3ff96983 fix(est-test): 구버전 EST Plus 저장 — cp949 밖 글자·기계경비 Index·% 수량, 경쟁사 실물 시험
- cp949 에 없는 글자는 「?」 로 바꿔 씀(22MB 공사 저장 중 멈춤)
- 기계경비 본문 Index(−3·−2·−1) 유지
- % 단위 수량은 소수로 써서 음수·큰 값도 되돌아옴
- 경쟁사 예제 estx 2건 저장값 대조·구버전 왕복 시험 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 20:35:13 +09:00

98 lines
4.2 KiB
Python

"""구버전 EST Plus(.est): 394 바이트 레코드 쓰기→읽기 왕복, 단가비교 자리, 짝짓기."""
import json
import subprocess
from pathlib import Path
from test_est_rea_parity import run
ROOT = Path(__file__).resolve().parents[2]
EST = ROOT / "tools/est-test"
def node(code):
out = subprocess.check_output(
["node", "-e", code], cwd=EST, text=True, encoding="utf-8"
)
return json.loads(out)
def test_extended_and_round_trip_of_sample():
result = node(
"""
const L=require('./legacy-estplus.cjs'),s=require('./sample.json');
const b=Buffer.alloc(10),xs=[0,1,-2.5,1234567.891,0.001,1e15].map(v=>(L.writeX(b,0,v),L.readX(b,0)));
const buf=L.write(s),p=L.read(buf,'t');
const same=(t,keys)=>s.tables[t].every((r,i)=>keys.every(k=>Math.abs((Number(r[k])||0)-(Number(p.tables[t][i][k])||0))<1e-6));
console.log(JSON.stringify({xs,
est:same('EstMainDat',['GN','TU','TC','NC','GC','JC','Level']),
head:same('HeadMainDat',['GN','TC','NC','GC','JC']),
cost:s.tables.CostMainDat.every((r,i)=>r.Index>0||(r.LineData||'')===(p.tables.CostMainDat[i].LineData||'')),
title:p.tables.CostTitleDat[0].Name,labor:p.tables.LaborcDat.length,
linked:p.tables.EstMainDat.find(r=>r.Name==='터파기').Code,auto:p.options.AutoCalc,
cmp:L.compare(buf,2)[0]}));
""")
assert result["xs"] == [0, 1, -2.5, 1234567.891, 0.001, 1e15]
assert result["est"] and result["head"] and result["cost"]
assert result["title"] == "터파기"
assert result["labor"] == 9
assert result["linked"] == "D0000000001"
assert result["auto"] is False
assert result["cmp"] == {"ONU": 66841, "OGU": 1336, "OJU": 0}
def test_pair_flags_sum_mismatch_in_order():
result = run(
"math",
"""(()=>{
const p=EstNative.empty();p.tables.HeadMainDat=[{Index:1,Code:'U1',Name:'a',NC:10,GC:5},{Index:0},
{Index:2,Code:'U2',Name:'b',NC:3}];
return EstEstPlus.pair(p,2,[{ONU:10,OGU:5,OJU:0},{ONU:4,OGU:0,OJU:0}]).map(r=>[r.Code,r.UsesCheck]);
})()""",
)
assert result == [["U1", False], ["U2", True]]
def test_percent_quantity_machine_index_and_non_cp949_text():
result = node(
"""
const L=require('./legacy-estplus.cjs');
const p={name:'t',options:{},tables:{EstMainDat:[],HeadMainDat:[{Index:1,Name:'a'},
{Index:0,LinkIndex:0,Name:'사용고재',Unite:'%',GN:-500},{Index:0,LinkIndex:0,Name:'공구손료',Unite:'%',GN:3},
{Index:0,LinkIndex:0,Name:'x'+String.fromCodePoint(0x1F600)+'y',GN:1}],
MachMainDat:[{Index:1,Name:'굴삭기',TC:10},{Index:-3,Selected:1,Name:'손료',GN:2,JC:5},{Index:-1,Selected:11,Name:'운전사',GN:1,NC:7}],
CostMainDat:[],LaborcDat:[],StuffcDat:[],SilJukDat:[],Wonga:[]}};
const b=L.read(L.write(p),'t');
console.log(JSON.stringify({gn:b.tables.HeadMainDat.slice(1,3).map(r=>r.GN),name:b.tables.HeadMainDat[3].Name,
mach:b.tables.MachMainDat.map(r=>[r.Index,r.Selected,r.TC])}));
""")
assert result["gn"] == [-500, 3]
assert result["name"] == "x?y"
assert result["mach"] == [[1, 0, 10], [-3, 1, 5], [-1, 11, 7]]
def test_competitor_examples_keep_stored_values_and_round_trip_to_legacy():
folder = ROOT / "resources/knowledge/original/경쟁사 프로그램/EST Plus 2/example"
files = sorted(folder.glob("*.estx"))
assert len(files) >= 2
for file in files:
parity = json.loads(
subprocess.check_output(
["node", str(ROOT / "resources/tester/helper_est_archive.cjs"), str(file)],
text=True,
encoding="utf-8",
timeout=300,
)
)
assert parity["differences"] == [], file.name
result = node(
f"""
const L=require('./legacy-estplus.cjs'),{{importEstx}}=require('./import-estx.cjs');
const p=importEstx(require('fs').readFileSync({json.dumps(str(file))}),'x'),b=L.read(L.write(p),'t');
const diff=(t,ks)=>p.tables[t].filter((r,i)=>ks.some(k=>Math.abs((Number(r[k])||0)-(Number(b.tables[t][i][k])||0))>1e-6)).length;
console.log(JSON.stringify({{est:diff('EstMainDat',['GN','TC','NC','GC','JC']),head:diff('HeadMainDat',['GN','TC','NC','GC','JC']),
cmp:L.compare(L.write(p),2).length===p.tables.HeadMainDat.filter(r=>r.Index>0).length}}));
"""
)
assert result == {"est": 0, "head": 0, "cmp": True}, file.name