125 lines
5.7 KiB
Python
125 lines
5.7 KiB
Python
from test_est_rea_parity import run
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
def test_attachment_size_prediction_includes_utf8_and_base64_overhead():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.name='한글';const file={name:'파일.bin',type:'',size:4};
|
|
const expected={...p,id:'0'.repeat(24),attachments:[{id:'0'.repeat(36),...file,data:'AAECAw=='}]};
|
|
return {predicted:EstAttachments.requiredBytes(p,[file]),actual:new Blob([JSON.stringify(expected)]).size,
|
|
large:EstAttachments.requiredBytes(p,[{name:'large',type:'',size:210000000}]),count:p.attachments.length};
|
|
})()""",
|
|
)
|
|
assert result["predicted"] == result["actual"]
|
|
assert result["large"] > 256 * 1024 * 1024
|
|
assert result["count"] == 0
|
|
|
|
|
|
def test_attachment_validation_keeps_valid_data_and_rejects_malformed_content():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.attachments=[{id:'one',name:'test.bin',type:'application/octet-stream',size:4,data:'AAECAw=='}];
|
|
const valid=EstModel.validate(p).attachments[0];let rejected=0;
|
|
for(const item of [{...valid,data:'AAECAw=A'},{...valid,size:5},{...valid,id:''},{...valid,name:''}]) {
|
|
const q=EstNative.empty();q.attachments=[item];try{EstModel.validate(q)}catch{rejected++}
|
|
}
|
|
const dup=EstNative.empty();dup.attachments=[valid,valid];try{EstModel.validate(dup)}catch{rejected++}
|
|
const empty=EstNative.empty();empty.attachments=[{id:'zero',name:'empty',type:'',size:0,data:''}];
|
|
return {valid,rejected,empty:EstModel.validate(empty).attachments[0].size};
|
|
})()""",
|
|
)
|
|
assert result["valid"]["data"] == "AAECAw=="
|
|
assert result["rejected"] == 5
|
|
assert result["empty"] == 0
|
|
|
|
|
|
def test_estx_export_rejects_web_attachments_instead_of_dropping_them():
|
|
script = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',attachments:[{}]});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result = subprocess.run(
|
|
["node", "-e", script],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result.stdout.decode("utf-8")
|
|
|
|
|
|
def test_estx_export_rejects_web_excel_links_instead_of_dropping_them():
|
|
script = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',excelQuantityLinks:[{}]});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result = subprocess.run(
|
|
["node", "-e", script],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result.stdout.decode("utf-8")
|
|
|
|
|
|
def test_estx_export_rejects_web_schedule_additions_or_changes_instead_of_dropping_them():
|
|
# 1) 일반 항목 추가
|
|
script_add = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',schedule:[{id:'1',Code:'A',Name:'새공정',start:'',end:'',weight:0,progress:0}]});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result_add = subprocess.run(
|
|
["node", "-e", script_add],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result_add.stdout.decode("utf-8")
|
|
assert "예정공정표" in result_add.stdout.decode("utf-8")
|
|
|
|
# 2) 빈 문자열 및 0값만 있는 행도 차단
|
|
script_empty = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',schedule:[{id:'2',Code:'',Name:'',start:'',end:'',weight:0,progress:0}]});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result_empty = subprocess.run(
|
|
["node", "-e", script_empty],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result_empty.stdout.decode("utf-8")
|
|
assert "예정공정표" in result_empty.stdout.decode("utf-8")
|
|
|
|
# 3) 다른 필드만 있거나 빈 객체 행도 차단
|
|
script_blank = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',schedule:[{custom:'field'}]});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result_blank = subprocess.run(
|
|
["node", "-e", script_blank],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result_blank.stdout.decode("utf-8")
|
|
assert "예정공정표" in result_blank.stdout.decode("utf-8")
|
|
|
|
|
|
def test_estx_export_rejects_web_custom_documents_instead_of_dropping_them():
|
|
script_doc = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',documents:{'173':'주요심사내용'}});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result_doc = subprocess.run(
|
|
["node", "-e", script_doc],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result_doc.stdout.decode("utf-8")
|
|
assert "서식 문서" in result_doc.stdout.decode("utf-8")
|
|
|
|
# 공백 문자열(" ")도 사용자 입력으로 보존하기 위해 ESTX 저장 차단
|
|
script_space = """try{require('./tools/est-test/export-estx.cjs').exportEstx({originalArchive:'AA==',documents:{'173':' '}});process.exit(1)}catch(e){process.stdout.write(e.message)}"""
|
|
result_space = subprocess.run(
|
|
["node", "-e", script_space],
|
|
cwd=Path(__file__).resolve().parents[2],
|
|
capture_output=True,
|
|
check=True,
|
|
timeout=10,
|
|
)
|
|
assert "JSON" in result_space.stdout.decode("utf-8")
|
|
assert "서식 문서" in result_space.stdout.decode("utf-8")
|