Files
jundot--omlx/tests/test_optimizations.py
T
wehub-resource-sync e9a2f726c9
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / test (3.13) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:29:51 +08:00

110 lines
4.6 KiB
Python

# SPDX-License-Identifier: Apache-2.0
"""Tests for omlx/optimizations.py — a thin hardware/MLX status helper.
The re-exported symbols (HardwareInfo, detect_hardware, get_total_memory_gb)
are covered by test_utils_hardware.py; here we pin the dict shape and the
flash-attention detection.
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
import mlx.core as mx
from omlx import optimizations
from omlx.optimizations import (
HardwareInfo,
detect_hardware,
get_optimization_status,
get_system_memory_gb,
)
from omlx.utils.hardware import HardwareInfo as CanonicalInfo
from omlx.utils.hardware import detect_hardware as canonical_detect
from omlx.utils.hardware import get_total_memory_gb
class TestReExports:
def test_hardware_symbols_importable_from_optimizations(self):
"""The module's docstring promises these names. Removing one
would silently break ``from omlx.optimizations import ...``
used by external scripts."""
assert detect_hardware is canonical_detect
assert HardwareInfo is CanonicalInfo
def test_get_system_memory_gb_aliases_get_total_memory_gb(self):
"""The re-export renames ``get_total_memory_gb`` →
``get_system_memory_gb``. The alias must stay in place."""
assert get_system_memory_gb is get_total_memory_gb
def test_all_lists_documented_surface(self):
assert set(optimizations.__all__) == {
"HardwareInfo",
"detect_hardware",
"get_system_memory_gb",
"get_optimization_status",
}
class TestGetOptimizationStatus:
def test_returns_top_level_keys(self):
status = get_optimization_status()
assert set(status.keys()) == {"hardware", "mlx_memory", "mlx_lm_features"}
def test_hardware_section_shape(self):
status = get_optimization_status()
hw = status["hardware"]
assert set(hw.keys()) == {"chip", "total_memory_gb", "device_name"}
# chip is populated from detect_hardware().chip_name — non-empty
# string on any Apple Silicon test runner.
assert isinstance(hw["chip"], str)
assert isinstance(hw["total_memory_gb"], (int, float))
assert hw["total_memory_gb"] > 0
assert isinstance(hw["device_name"], str)
def test_mlx_memory_section_is_byte_counters(self):
status = get_optimization_status()
mem = status["mlx_memory"]
assert set(mem.keys()) == {"active_bytes", "cache_bytes", "peak_bytes"}
# All three come straight from mx.get_*_memory(); non-negative ints
for key in mem:
assert isinstance(mem[key], int), f"{key} not an int"
assert mem[key] >= 0
def test_mlx_lm_features_static_strings(self):
"""These strings appear in the admin dashboard. Pin them so a
typo or accidental rewording shows up as a test failure rather
than a confusing UI change."""
features = get_optimization_status()["mlx_lm_features"]
assert features["metal_kernels"] == "optimized for Apple Silicon"
assert features["kv_cache"] == "managed by mlx-lm"
assert features["quantization"] == "4-bit and 8-bit supported"
def test_flash_attention_reports_built_in_when_available(self):
"""``mlx.core.fast.scaled_dot_product_attention`` exists in all
recent MLX versions — the test environment is one of them."""
assert hasattr(mx, "fast")
assert hasattr(mx.fast, "scaled_dot_product_attention")
status = get_optimization_status()
assert status["mlx_lm_features"]["flash_attention"] == "built-in"
def test_flash_attention_reports_not_available_when_missing(self):
"""The fallback branch runs on hypothetical MLX builds without
the fused SDPA. Simulated by replacing ``mx.fast`` with an
object that lacks the attribute."""
fake_fast = MagicMock(spec=[]) # spec=[] → no attributes
with patch.object(mx, "fast", fake_fast):
status = get_optimization_status()
assert status["mlx_lm_features"]["flash_attention"] == "not available"
def test_active_bytes_reflects_real_mlx_state(self):
"""Verify the value isn't hardcoded — allocating an array
should bump active memory above the pre-allocation baseline.
Defensive: the loop ensures eval happens so memory shows up."""
before = mx.get_active_memory()
arr = mx.zeros((1024, 1024), dtype=mx.float32)
mx.eval(arr)
after = get_optimization_status()["mlx_memory"]["active_bytes"]
# 1024*1024*4 bytes = 4 MiB allocation must register somewhere
# in the active memory delta.
assert after >= before