db_query / tests /test_ue_capability_volte.py
DavMelchi's picture
feat: add 3gpp ue capability parser with volte assessment
7b6d659
from queries.process_ue_capability import assess_volte_support, parse_uecap_text
BASE_TEXT_NO_IMS = """
08:33:50.000 LTE RRC Signaling
{
ueCapabilityInformation
{
ueCapabilityInformation-r8
{
uE-EUTRA-Capability
{
UE-EUTRA-Capability
{
accessStratumRelease
{
rel15
}
interRAT-Parameters
{
utraFDD
{
supportedBandListUTRA-FDD
{
SupportedBandUTRA-FDD #1
{
bandI
}
}
}
geran
{
supportedBandListGERAN
{
SupportedBandGERAN #1
{
gsm900E
}
}
}
}
}
}
}
}
}
"""
TEXT_WITH_EXPLICIT_VOLTE = """
08:33:50.000 LTE RRC Signaling
{
ueCapabilityInformation
{
ueCapabilityInformation-r8
{
uE-EUTRA-Capability
{
UE-EUTRA-Capability
{
accessStratumRelease
{
rel15
}
ims-Parameters
{
voiceOverPS-HS
{
supported
}
srvcc-ToUTRA
{
supported
}
}
}
}
}
}
}
"""
TEXT_WITH_IMS_CONTEXT_ONLY = """
08:33:50.000 LTE RRC Signaling
{
ueCapabilityInformation
{
ueCapabilityInformation-r8
{
uE-EUTRA-Capability
{
UE-EUTRA-Capability
{
accessStratumRelease
{
rel15
}
ims-Parameters
{
ims-support
{
notsupported
}
}
}
}
}
}
}
"""
TEXT_WITH_EXPLICIT_NEGATIVE_VOPS = """
08:33:50.000 LTE RRC Signaling
{
ueCapabilityInformation
{
ueCapabilityInformation-r8
{
uE-EUTRA-Capability
{
UE-EUTRA-Capability
{
accessStratumRelease
{
rel15
}
ims-Parameters
{
voiceOverPS-HS
{
notsupported
}
srvcc-ToUTRA
{
notsupported
}
}
}
}
}
}
}
"""
def test_volte_assessment_without_explicit_markers_is_not_forced_supported() -> None:
sheets = parse_uecap_text(BASE_TEXT_NO_IMS, source_name="no_ims.txt")
assert not sheets["VoLTE_Assessment"].empty
status = str(sheets["VoLTE_Assessment"].iloc[0]["volte_status"])
assert status in {"Likely", "Unknown", "Not indicated"}
assert status != "Supported"
def test_volte_assessment_with_explicit_markers_supports_supported_status() -> None:
sheets = parse_uecap_text(TEXT_WITH_EXPLICIT_VOLTE, source_name="ims.txt")
assert not sheets["VoLTE_Assessment"].empty
status = str(sheets["VoLTE_Assessment"].iloc[0]["volte_status"])
score = float(sheets["VoLTE_Assessment"].iloc[0]["volte_score"])
assert status in {"Supported", "Likely"}
assert score > 0
def test_assess_volte_support_returns_expected_keys() -> None:
result = assess_volte_support({"evidence": ["ims-parameters", "voiceoverps-hs=supported"]})
assert "volte_status" in result
assert "volte_score" in result
assert "confidence" in result
def test_volte_assessment_ims_context_without_explicit_support_not_forced_supported() -> None:
sheets = parse_uecap_text(TEXT_WITH_IMS_CONTEXT_ONLY, source_name="ims_context.txt")
status = str(sheets["VoLTE_Assessment"].iloc[0]["volte_status"])
assert status in {"Likely", "Unknown", "Not indicated"}
assert status != "Supported"
def test_volte_assessment_explicit_notsupported_blocks_supported_status() -> None:
sheets = parse_uecap_text(TEXT_WITH_EXPLICIT_NEGATIVE_VOPS, source_name="ims_negative.txt")
status = str(sheets["VoLTE_Assessment"].iloc[0]["volte_status"])
notes = str(sheets["VoLTE_Assessment"].iloc[0]["notes"]).lower()
assert status in {"Unknown", "Not indicated"}
assert status != "Supported"
assert "negative" in notes
def test_assess_volte_support_notsupported_not_matched_as_positive() -> None:
result = assess_volte_support({"evidence": ["voiceoverps-hs=notsupported", "srvcc-toutra=notsupported"]})
assert result["volte_status"] in {"Unknown", "Not indicated"}
assert "explicit_ims_voice_over_ps" not in str(result["explicit_evidence"])
assert "explicit_srvcc_indicator" not in str(result["explicit_evidence"])