"""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'