synor/sdk/python/tests/test_tensor.py
Gulshan Yadav e2a3b66123 test(sdk): add comprehensive unit tests for all SDKs
Adds unit tests covering tensor operations, type enums, client
functionality, and serialization for all 12 SDK implementations:

- JavaScript (Vitest): tensor, types, client tests
- Python (pytest): tensor, types, client tests
- Go: standard library tests with httptest
- Flutter (flutter_test): tensor, types tests
- Java (JUnit 5): tensor, types tests
- Rust: embedded module tests
- Ruby (minitest): tensor, types tests
- C# (xUnit): tensor, types tests

Tests cover:
- Tensor creation (zeros, ones, random, randn, eye, arange, linspace)
- Tensor operations (reshape, transpose, indexing)
- Reductions (sum, mean, std, min, max)
- Activations (relu, sigmoid, softmax)
- Serialization/deserialization
- Type enums and configuration
- Client request building
- Error handling
2026-01-11 17:56:11 +05:30

239 lines
7.4 KiB
Python

"""Unit tests for Tensor class."""
import pytest
import numpy as np
from synor_compute import Tensor
from synor_compute.types import Precision
class TestTensorCreation:
"""Tests for tensor creation methods."""
def test_from_numpy_array(self):
"""Should create tensor from numpy array."""
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)
tensor = Tensor.from_numpy(arr)
assert tensor.shape == (2, 3)
assert tensor.size == 6
assert tensor.ndim == 2
assert tensor.dtype == Precision.FP32
def test_from_numpy_with_dtype(self):
"""Should create tensor with specified dtype."""
arr = np.array([1, 2, 3])
tensor = Tensor.from_numpy(arr, dtype=Precision.FP16)
assert tensor.dtype == Precision.FP16
def test_infer_dtype_fp64(self):
"""Should infer FP64 from float64 array."""
arr = np.array([1.0, 2.0], dtype=np.float64)
tensor = Tensor.from_numpy(arr)
assert tensor.dtype == Precision.FP64
def test_infer_dtype_int8(self):
"""Should infer INT8 from int8 array."""
arr = np.array([1, 2, 3], dtype=np.int8)
tensor = Tensor.from_numpy(arr)
assert tensor.dtype == Precision.INT8
class TestTensorFactoryMethods:
"""Tests for tensor factory methods."""
def test_zeros(self):
"""Should create tensor of zeros."""
tensor = Tensor.zeros((2, 3))
assert tensor.shape == (2, 3)
assert np.allclose(tensor.data, 0)
def test_zeros_with_dtype(self):
"""Should create zeros tensor with specified dtype."""
tensor = Tensor.zeros((2, 2), dtype=Precision.FP64)
assert tensor.dtype == Precision.FP64
assert tensor.data.dtype == np.float64
def test_ones(self):
"""Should create tensor of ones."""
tensor = Tensor.ones((3, 2))
assert tensor.shape == (3, 2)
assert np.allclose(tensor.data, 1)
def test_random(self):
"""Should create tensor with random values in [0, 1)."""
tensor = Tensor.random((10, 10))
assert tensor.shape == (10, 10)
assert tensor.data.min() >= 0
assert tensor.data.max() < 1
def test_randn(self):
"""Should create tensor with normal distribution."""
tensor = Tensor.randn((1000,))
# Check approximate normal distribution properties
assert abs(tensor.data.mean()) < 0.2 # Mean ~= 0
assert 0.8 < tensor.data.std() < 1.2 # Std ~= 1
class TestTensorOperations:
"""Tests for tensor operations."""
def test_reshape(self):
"""Should reshape tensor."""
tensor = Tensor.from_numpy(np.arange(6))
reshaped = tensor.reshape((2, 3))
assert reshaped.shape == (2, 3)
assert reshaped.size == 6
def test_reshape_preserves_data(self):
"""Should preserve data when reshaping."""
arr = np.array([1, 2, 3, 4, 5, 6])
tensor = Tensor.from_numpy(arr)
reshaped = tensor.reshape((2, 3))
assert reshaped.data[0, 0] == 1
assert reshaped.data[1, 2] == 6
def test_to_different_dtype(self):
"""Should convert to different dtype."""
tensor = Tensor.from_numpy(np.array([1.5, 2.5], dtype=np.float32))
converted = tensor.to(Precision.FP64)
assert converted.dtype == Precision.FP64
assert converted.data.dtype == np.float64
def test_to_same_dtype_returns_self(self):
"""Should return self when converting to same dtype."""
tensor = Tensor.from_numpy(np.array([1.0, 2.0], dtype=np.float32))
same = tensor.to(Precision.FP32)
assert same is tensor
def test_numpy_returns_underlying_array(self):
"""Should return underlying numpy array."""
arr = np.array([1, 2, 3], dtype=np.float32)
tensor = Tensor.from_numpy(arr)
assert np.array_equal(tensor.numpy(), arr)
class TestTensorProperties:
"""Tests for tensor properties."""
def test_shape(self):
"""Should return correct shape."""
tensor = Tensor.zeros((3, 4, 5))
assert tensor.shape == (3, 4, 5)
def test_size(self):
"""Should return correct size."""
tensor = Tensor.zeros((3, 4, 5))
assert tensor.size == 60
def test_ndim(self):
"""Should return correct number of dimensions."""
tensor = Tensor.zeros((3, 4, 5))
assert tensor.ndim == 3
def test_nbytes(self):
"""Should return correct byte size."""
tensor = Tensor.zeros((10,), dtype=Precision.FP32)
assert tensor.nbytes == 40 # 10 * 4 bytes
class TestTensorSerialization:
"""Tests for tensor serialization."""
def test_serialize(self):
"""Should serialize tensor to dict."""
tensor = Tensor.from_numpy(np.array([[1, 2], [3, 4]], dtype=np.float32))
serialized = tensor.serialize()
assert "data" in serialized
assert "shape" in serialized
assert "dtype" in serialized
assert serialized["shape"] == [2, 2]
assert serialized["dtype"] == "fp32"
def test_deserialize(self):
"""Should deserialize tensor from dict."""
original = Tensor.from_numpy(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32))
serialized = original.serialize()
restored = Tensor.deserialize(serialized)
assert restored.shape == original.shape
assert restored.dtype == original.dtype
assert np.array_equal(restored.data, original.data)
def test_serialize_deserialize_fp64(self):
"""Should preserve FP64 precision."""
original = Tensor.from_numpy(np.array([1.234567890123456], dtype=np.float64))
serialized = original.serialize()
restored = Tensor.deserialize(serialized)
assert restored.dtype == Precision.FP64
assert np.allclose(restored.data, original.data)
def test_serialize_deserialize_large_tensor(self):
"""Should handle large tensors."""
original = Tensor.random((100, 100))
serialized = original.serialize()
restored = Tensor.deserialize(serialized)
assert restored.shape == original.shape
assert np.allclose(restored.data, original.data)
class TestTensorRepr:
"""Tests for tensor string representations."""
def test_repr(self):
"""Should return informative repr."""
tensor = Tensor.zeros((2, 3), dtype=Precision.FP32)
rep = repr(tensor)
assert "Tensor" in rep
assert "(2, 3)" in rep
assert "fp32" in rep
def test_str(self):
"""Should return string with data."""
tensor = Tensor.from_numpy(np.array([1, 2, 3], dtype=np.float32))
s = str(tensor)
assert "Tensor" in s
assert "fp32" in s
class TestTensorEdgeCases:
"""Tests for edge cases."""
def test_scalar_like_tensor(self):
"""Should handle 1-element tensor."""
tensor = Tensor.from_numpy(np.array([42], dtype=np.float32))
assert tensor.shape == (1,)
assert tensor.size == 1
assert tensor.ndim == 1
def test_empty_shape_dimension(self):
"""Should handle tensors with zero-size dimensions."""
tensor = Tensor.zeros((0, 3))
assert tensor.shape == (0, 3)
assert tensor.size == 0
def test_high_dimensional_tensor(self):
"""Should handle high-dimensional tensors."""
tensor = Tensor.zeros((2, 3, 4, 5, 6))
assert tensor.ndim == 5
assert tensor.size == 720