Files
QuanTAlib/python/tests/test_status_codes.py
T

100 lines
3.2 KiB
Python
Raw Normal View History

2026-02-28 14:14:35 -08:00
"""test_status_codes.py — Verify correct exceptions for bad inputs.
Tests that null pointers, invalid lengths, and invalid params raise
the expected quantalib exception types.
"""
from __future__ import annotations
import numpy as np
import pytest
@pytest.fixture(scope="module")
def qtl():
try:
import quantalib as _qtl
return _qtl
except (OSError, ImportError) as e:
pytest.skip(f"quantalib native lib not available: {e}")
@pytest.fixture(scope="module")
def bridge():
try:
from quantalib import _bridge
return _bridge
except (OSError, ImportError) as e:
pytest.skip(f"quantalib native lib not available: {e}")
class TestInvalidLength:
"""Period <= 0 should raise QtlInvalidParamError (ChkPeriod returns status 3)."""
def test_sma_zero_length(self, qtl) -> None:
close = np.ones(10, dtype=np.float64)
# ChkPeriod checks period > 0; returns QTL_ERR_INVALID_PARAM (3) for <= 0
with pytest.raises(qtl.QtlInvalidParamError):
qtl.sma(close, length=0)
def test_sma_negative_length(self, qtl) -> None:
close = np.ones(10, dtype=np.float64)
with pytest.raises(qtl.QtlInvalidParamError):
qtl.sma(close, length=-5)
class TestInvalidParam:
"""Bad parameter values should raise QtlInvalidParamError."""
def test_sma_period_exceeds_length(self, qtl) -> None:
"""SMA Batch processes whatever data is available;
period > n is not an error — it just computes with partial data."""
close = np.ones(5, dtype=np.float64)
# This should NOT raise; SMA handles period > n gracefully
result = qtl.sma(close, length=10)
assert len(result) == 5
class TestNullPointer:
"""Null pointer should raise QtlNullPointerError via raw bridge call."""
def test_null_src(self, bridge) -> None:
import ctypes as ct
null = ct.cast(None, bridge._dp)
dst = np.empty(10, dtype=np.float64)
status = bridge._lib.qtl_sma(null, 10, dst.ctypes.data_as(bridge._dp), 5)
assert status == bridge.QTL_ERR_NULL_PTR
def test_null_dst(self, bridge) -> None:
import ctypes as ct
src = np.ones(10, dtype=np.float64)
null = ct.cast(None, bridge._dp)
status = bridge._lib.qtl_sma(src.ctypes.data_as(bridge._dp), 10, null, 5)
assert status == bridge.QTL_ERR_NULL_PTR
class TestCheckHelper:
"""Verify _check() maps status codes to exceptions."""
def test_ok(self, bridge) -> None:
bridge._check(0) # Should not raise
def test_null_ptr(self, bridge) -> None:
with pytest.raises(bridge.QtlNullPointerError):
bridge._check(1)
def test_invalid_length(self, bridge) -> None:
with pytest.raises(bridge.QtlInvalidLengthError):
bridge._check(2)
def test_invalid_param(self, bridge) -> None:
with pytest.raises(bridge.QtlInvalidParamError):
bridge._check(3)
def test_internal(self, bridge) -> None:
with pytest.raises(bridge.QtlInternalError):
bridge._check(4)
def test_unknown(self, bridge) -> None:
with pytest.raises(bridge.QtlError):
bridge._check(99)