"""Unit tests for SQ_PROTOCOLS capability decoding — no server required. The masks below were captured from live servers on 2026-08-27. Their most interesting property is that the first eight bytes are identical across Informix 12.10, 14.10, and 15 — which is why those three releases speak an indistinguishable SQLI dialect. """ from __future__ import annotations import dataclasses import pytest from informix_db._capabilities import ( BIT_FOUR_BYTE_OFFSET, BIT_REMOVE_64K_LIMIT, BIT_USVER, BIT_VARCHAR_VAR_LEN, CLIENT_PROTOCOLS_MASK, ENHANCED_PROTOCOL_CAP, ServerCapabilities, _decode_bits, ) MASK_15 = bytes.fromhex("bdbe9ffe7fb7ffefff") MASK_1410 = bytes.fromhex("bdbe9ffe7fb7ffeff8") MASK_1210 = bytes.fromhex("bdbe9ffe7fb7ffeff0") ALL_MASKS = [ pytest.param(MASK_15, id="15.0.1.0.3"), pytest.param(MASK_1410, id="14.10.FC7W1"), pytest.param(MASK_1210, id="12.10.FC12W1DE"), ] # -------------------------------------------------------------------------- # Bit expansion # -------------------------------------------------------------------------- def test_bit_numbering_is_msb_first() -> None: assert _decode_bits(b"\x80") == {0} assert _decode_bits(b"\x01") == {7} assert _decode_bits(b"\x00\x80") == {8} assert _decode_bits(b"\x00\x01") == {15} def test_bit_expansion_of_first_captured_byte() -> None: """0xBD is 1011 1101 -> bits 0, 2, 3, 4, 5, 7.""" assert _decode_bits(b"\xbd") == {0, 2, 3, 4, 5, 7} def test_empty_mask_yields_no_bits() -> None: assert _decode_bits(b"") == set() # -------------------------------------------------------------------------- # The captured masks # -------------------------------------------------------------------------- def test_first_eight_bytes_identical_across_versions() -> None: """The finding this whole module exists to record: 12.10, 14.10, and 15 negotiate exactly the same 64-bit capability set. Only the 9th byte — which IBM's own JDBC driver discards — differs.""" assert MASK_15[:8] == MASK_1410[:8] == MASK_1210[:8] assert len({MASK_15[8], MASK_1410[8], MASK_1210[8]}) == 3 @pytest.mark.parametrize("mask", ALL_MASKS) def test_framing_bits_set_on_every_tested_server(mask: bytes) -> None: """Every wire-framing choice this driver hardcodes is one the server actually negotiated. If this ever fails, the row decoder is wrong.""" caps = ServerCapabilities.from_wire(mask, cap_1=ENHANCED_PROTOCOL_CAP) assert caps.four_byte_offset, "describe offsets would be misparsed" assert caps.varchar_var_len, "VARCHAR framing would be misparsed" assert caps.remove_64k_limit, "fast-path length prefix would be wrong" assert caps.bigint assert caps.long_id assert caps.lvarchar_gt_2k assert caps.gls @pytest.mark.parametrize("mask", ALL_MASKS) def test_no_violated_assumptions_on_tested_servers(mask: bytes) -> None: caps = ServerCapabilities.from_wire(mask, cap_1=ENHANCED_PROTOCOL_CAP) assert caps.violated_assumptions() == [] @pytest.mark.parametrize("mask", ALL_MASKS) def test_ninth_byte_is_decoded(mask: bytes) -> None: """JDBC drops bits 64+; we keep them because they're the only part that varies between releases.""" caps = ServerCapabilities.from_wire(mask, cap_1=ENHANCED_PROTOCOL_CAP) assert any(b >= 64 for b in caps.bits) # -------------------------------------------------------------------------- # Pre-set bits — the reason isUSVER is a dead end # -------------------------------------------------------------------------- def test_preset_bits_applied_when_cap1_nonzero() -> None: """JDBC pre-sets {0,2,3,4,49,51} for any non-zero Cap_1 and BitSet.set never clears, so these are true on any modern server regardless of the mask. That's why isUSVER never varies and can't explain version-specific behaviour.""" caps = ServerCapabilities.from_wire(b"\x00" * 9, cap_1=ENHANCED_PROTOCOL_CAP) assert {0, 2, 3, 4, 49, 51}.issubset(caps.bits) assert caps.usver def test_preset_bits_not_applied_when_cap1_zero() -> None: caps = ServerCapabilities.from_wire(b"\x00" * 9, cap_1=0) assert caps.bits == frozenset() assert not caps.usver def test_preset_cannot_clear_a_bit_the_mask_set() -> None: caps = ServerCapabilities.from_wire(MASK_15, cap_1=ENHANCED_PROTOCOL_CAP) assert caps.has(BIT_USVER) assert caps.has(BIT_FOUR_BYTE_OFFSET) # -------------------------------------------------------------------------- # Assumption violations — the diagnostic path # -------------------------------------------------------------------------- def test_missing_four_byte_offset_is_reported() -> None: # Everything set except bit 50. bits = bytearray(b"\xff" * 9) bits[BIT_FOUR_BYTE_OFFSET // 8] &= ~(0x80 >> (BIT_FOUR_BYTE_OFFSET % 8)) & 0xFF caps = ServerCapabilities.from_wire(bytes(bits), cap_1=ENHANCED_PROTOCOL_CAP) problems = caps.violated_assumptions() assert len(problems) == 1 assert "4-byte describe offsets" in problems[0] def test_missing_varchar_var_len_is_reported() -> None: bits = bytearray(b"\xff" * 9) bits[BIT_VARCHAR_VAR_LEN // 8] &= ~(0x80 >> (BIT_VARCHAR_VAR_LEN % 8)) & 0xFF caps = ServerCapabilities.from_wire(bytes(bits), cap_1=ENHANCED_PROTOCOL_CAP) problems = caps.violated_assumptions() assert len(problems) == 1 assert "variable-length VARCHAR" in problems[0] def test_missing_remove_64k_is_reported() -> None: bits = bytearray(b"\xff" * 9) bits[BIT_REMOVE_64K_LIMIT // 8] &= ~(0x80 >> (BIT_REMOVE_64K_LIMIT % 8)) & 0xFF caps = ServerCapabilities.from_wire(bytes(bits), cap_1=ENHANCED_PROTOCOL_CAP) problems = caps.violated_assumptions() assert len(problems) == 1 assert "64K limit" in problems[0] def test_all_zero_mask_reports_every_assumption() -> None: caps = ServerCapabilities.from_wire(b"\x00" * 9, cap_1=ENHANCED_PROTOCOL_CAP) assert len(caps.violated_assumptions()) == 3 # -------------------------------------------------------------------------- # Misc # -------------------------------------------------------------------------- def test_client_offer_matches_jdbc_reference() -> None: """IfxSqliConnect.clientProtocols, verbatim. Changing this changes what the server negotiates, so it is pinned.""" jdbc_reference = bytes([0xFF, 0xFC, 0x7F, 0xFC, 0x3C, 0x8C, 0xAA, 0x97]) assert jdbc_reference == CLIENT_PROTOCOLS_MASK assert len(CLIENT_PROTOCOLS_MASK) == 8 def test_enhanced_protocol_requires_exact_cap1() -> None: """JDBC tests == 316, not >=, because the server echoes the client's own declared level rather than reporting its own version.""" assert ServerCapabilities.from_wire(MASK_15, cap_1=316).enhanced_protocol assert not ServerCapabilities.from_wire(MASK_15, cap_1=315).enhanced_protocol assert not ServerCapabilities.from_wire(MASK_15, cap_1=317).enhanced_protocol def test_repr_is_readable_and_includes_mask() -> None: caps = ServerCapabilities.from_wire( MASK_15, cap_1=316, server_version="IBM Informix Dynamic Server Version 15" ) text = repr(caps) assert "bdbe9ffe7fb7ffefff" in text assert "usver" in text assert "cap_1=316" in text def test_capabilities_are_frozen() -> None: """Immutable so a connection's negotiated state can't be edited after the fact and quietly disagree with what's on the wire.""" caps = ServerCapabilities.from_wire(MASK_15, cap_1=316) with pytest.raises(dataclasses.FrozenInstanceError): caps.cap_1 = 1 # type: ignore[misc]