72 lines
2.8 KiB
Python
72 lines
2.8 KiB
Python
"""file_io PACKED-DECIMAL/COMP-3 小数位字节长度 + BINARY 大端序测试。
|
||
|
||
复现根因(JIN03RAN):
|
||
1. get_storage_length 对 COMP-3/PACKED-DECIMAL 用 (digits+2)//2,忽略 decimal。
|
||
9(3)V9(2) 应为 3 字节(5 位有效数字+符号),却按 2 字节 → R01 记录 199 字节
|
||
vs GnuCOBOL FD 200 字节 → 逐记录错位 → AVG-SCORE 运行时乱值 → 'A' 等级分支不可达。
|
||
2. pack_value/unpack_value 对 COMP/BINARY 用小端 '<',但本 GnuCOBOL(GC32-BDB-SP1,
|
||
主机兼容)COMP 按大端存储(见 test_sqlca_byteorder.py 记载)→ EMP-COUNT 运行时乱值。
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||
|
||
import pytest
|
||
|
||
from cobol_testgen.file_io import get_storage_length, pack_value, unpack_value
|
||
|
||
|
||
def _pd(digits, decimal, signed=False):
|
||
return {
|
||
'usage': 'PACKED-DECIMAL',
|
||
'pic_info': {'type': 'numeric', 'length': digits + decimal,
|
||
'digits': digits, 'decimal': decimal, 'signed': signed},
|
||
}
|
||
|
||
|
||
def _bin(digits, signed=False):
|
||
return {
|
||
'usage': 'BINARY',
|
||
'pic_info': {'type': 'numeric', 'length': digits,
|
||
'digits': digits, 'decimal': 0, 'signed': signed},
|
||
}
|
||
|
||
|
||
# ── 1. PACKED-DECIMAL 小数位字节长度 ──
|
||
|
||
def test_pd_storage_length_includes_decimal():
|
||
"""9(3)V9(2) = 5 位 + 符号 = 3 字节;9(2)(无小数)仍为 2 字节。"""
|
||
assert get_storage_length(_pd(3, 2)) == 3, '9(3)V9(2) PACKED-DECIMAL 应占 3 字节'
|
||
assert get_storage_length(_pd(2, 0)) == 2, '9(2) PACKED-DECIMAL 应占 2 字节'
|
||
assert get_storage_length(_pd(7, 2, signed=True)) == 5, 'S9(7)V99 PACKED-DECIMAL 应占 5 字节'
|
||
|
||
|
||
def test_pd_pack_decimal_full_digits():
|
||
"""900.00 应打包为 90 00 0F(3 字节,保留全部 5 位)。"""
|
||
b = pack_value('90000', _pd(3, 2))
|
||
assert b == bytes.fromhex('90000f'), f'900.00 打包应为 90000f, 实际 {b.hex()}'
|
||
b2 = pack_value('60000', _pd(3, 2))
|
||
assert b2 == bytes.fromhex('60000f'), f'600.00 打包应为 60000f, 实际 {b2.hex()}'
|
||
|
||
|
||
def test_pd_unpack_decimal_roundtrip():
|
||
"""打包/解包回读应保留 5 位(含小数位)。"""
|
||
f = _pd(3, 2)
|
||
for val in ('90000', '60000', '00423'):
|
||
assert unpack_value(pack_value(val, f), f) == val, f'{val} 回读应一致'
|
||
|
||
|
||
# ── 2. BINARY 大端序(匹配本 GnuCOBOL 的 COMP 存储)──
|
||
|
||
def test_binary_pack_big_endian():
|
||
"""203 在 PIC 9(5) BINARY 应打包为大端 00 00 00 CB(4 字节)。"""
|
||
b = pack_value('00203', _bin(5))
|
||
assert b == bytes.fromhex('000000cb'), f'203 BINARY 应大端 000000cb, 实际 {b.hex()}'
|
||
|
||
|
||
def test_binary_unpack_big_endian():
|
||
"""大端 00 00 00 CB 解包应得到 00203。"""
|
||
assert unpack_value(bytes.fromhex('000000cb'), _bin(5)) == '00203'
|