mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-05 12:37:43 +00:00
python wrapper
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user