import json import pytest from server.profile_generator import ( build_lpa_activation_code, create_esim_profile, derive_opc, enc_iccid, enc_imsi, generate_iccid, generate_imsi, generate_ki, luhn_checksum, swap_nibbles, ) _OP = bytes.fromhex("63bfa50ee6523365ff14c1f45f88737d") class TestIMSI: def test_length(self): assert len(generate_imsi("302", "720")) == 15 def test_prefix(self): imsi = generate_imsi("302", "720") assert imsi.startswith("302720") def test_digits_only(self): assert generate_imsi("302", "720").isdigit() def test_uniqueness(self): imsis = {generate_imsi("302", "720") for _ in range(100)} assert len(imsis) > 90 def test_different_mcc_mnc(self): imsi = generate_imsi("001", "01") assert imsi.startswith("00101") assert len(imsi) == 15 class TestKi: def test_length(self): assert len(generate_ki()) == 16 def test_randomness(self): keys = {generate_ki() for _ in range(50)} assert len(keys) == 50 class TestICCID: def test_length(self): assert len(generate_iccid()) == 19 def test_digits_only(self): assert generate_iccid().isdigit() def test_luhn_valid(self): iccid = generate_iccid() assert luhn_checksum(iccid[:-1]) == int(iccid[-1]) def test_starts_with_prefix(self): assert generate_iccid().startswith("8910") def test_uniqueness(self): iccids = {generate_iccid() for _ in range(50)} assert len(iccids) == 50 class TestOPc: KI_HEX = "000102030405060708090a0b0c0d0e0f" def test_output_length(self): ki = bytes.fromhex(self.KI_HEX) assert len(derive_opc(ki, _OP)) == 16 def test_deterministic(self): ki = bytes.fromhex(self.KI_HEX) assert derive_opc(ki, _OP) == derive_opc(ki, _OP) def test_different_from_inputs(self): ki = bytes.fromhex(self.KI_HEX) opc = derive_opc(ki, _OP) assert opc != _OP assert opc != ki def test_different_ki_gives_different_opc(self): ki1 = bytes.fromhex(self.KI_HEX) ki2 = bytes.fromhex("0f0e0d0c0b0a09080706050403020100") assert derive_opc(ki1, _OP) != derive_opc(ki2, _OP) class TestProfile: def _make_profile(self): ki = generate_ki() opc = derive_opc(ki, _OP) imsi = generate_imsi("302", "720") iccid = generate_iccid() return create_esim_profile(imsi, ki, opc, iccid, "Test Profile", "Test Carrier") def test_returns_bytes(self): assert isinstance(self._make_profile(), bytes) def test_non_empty(self): assert len(self._make_profile()) > 0 def test_valid_json(self): data = json.loads(self._make_profile()) assert "imsi" in data assert "ki" in data assert "opc" in data assert "iccid" in data def test_imsi_in_profile(self): ki = generate_ki() opc = derive_opc(ki, _OP) imsi = generate_imsi("302", "720") iccid = generate_iccid() profile = create_esim_profile(imsi, ki, opc, iccid, "P", "C") data = json.loads(profile) assert data["imsi"] == imsi assert data["iccid"] == iccid def test_v2_type_and_activation_code(self): ki = generate_ki() opc = derive_opc(ki, _OP) data = json.loads( create_esim_profile(generate_imsi("302", "720"), ki, opc, generate_iccid(), "P", "C") ) assert data["type"] == "profile-package-v2" assert data["activation_code"].startswith("LPA:1$") assert "iccid" in data["ef"] and "imsi" in data["ef"] def _dec_nibble_swapped_digits(b: bytes) -> str: return swap_nibbles(b.hex()) class TestEncoding: def test_swap_nibbles(self): assert swap_nibbles("1234") == "2143" assert swap_nibbles("89") == "98" def test_swap_nibbles_rejects_odd(self): with pytest.raises(ValueError): swap_nibbles("123") def test_enc_iccid_length_10_bytes(self): assert len(enc_iccid("8910302720000000001")) == 10 def test_enc_iccid_nibble_swap(self): # First two ICCID digits "89" -> byte 0x98 assert enc_iccid("8910302720000000001")[0] == 0x98 def test_enc_iccid_roundtrip(self): iccid = generate_iccid() decoded = _dec_nibble_swapped_digits(enc_iccid(iccid)).rstrip("f") assert decoded == iccid def test_enc_imsi_length_octet(self): # 15-digit IMSI + 1 parity nibble = 16 nibbles = 8 value bytes out = enc_imsi("302720974348443") assert out[0] == 8 assert len(out) == 9 # length octet + 8 value bytes def test_enc_imsi_roundtrip(self): imsi = generate_imsi("302", "720") value = _dec_nibble_swapped_digits(enc_imsi(imsi)[1:]) # first nibble is the parity indicator; the rest is the IMSI assert value[1:] == imsi def test_lpa_activation_code_format(self): code = build_lpa_activation_code("8910302720000000001", "smdp.example") assert code == "LPA:1$smdp.example$8910302720000000001"