mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-28 17:57:45 +00:00
100 lines
3.2 KiB
Python
100 lines
3.2 KiB
Python
|
|
"""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)
|