init commit.

This commit is contained in:
wertyuilife
2026-03-23 03:17:59 +08:00
commit fce9166e87
99 changed files with 13778 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
# Copyright (c) 2021-2026, ETH Zurich and NVIDIA CORPORATION
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Tests for rsl_rl."""

View File

@@ -0,0 +1,6 @@
# Copyright (c) 2021-2026, ETH Zurich and NVIDIA CORPORATION
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Tests for the utils module of rsl_rl."""

View File

@@ -0,0 +1,148 @@
# Copyright (c) 2021-2026, ETH Zurich and NVIDIA CORPORATION
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Tests for resolve_callable utility function."""
import pytest
from rsl_rl.utils import resolve_callable
# Test fixtures - nested class for testing nested attribute resolution
class OuterClass:
"""Outer class for testing nested attribute resolution."""
class InnerClass:
"""Inner nested class."""
pass
@staticmethod
def static_method() -> str:
return "static"
def sample_function() -> str:
"""Sample function for testing."""
return "sample"
class TestResolveCallableDirect:
"""Tests for direct callable passing."""
def test_direct_class(self) -> None:
"""Passing a class directly should return it unchanged."""
from rsl_rl.algorithms import PPO
result = resolve_callable(PPO)
assert result is PPO
def test_direct_function(self) -> None:
"""Passing a function directly should return it unchanged."""
result = resolve_callable(sample_function)
assert result is sample_function
def test_direct_builtin(self) -> None:
"""Passing a builtin should return it unchanged."""
result = resolve_callable(len)
assert result is len
class TestResolveCallableColonFormat:
"""Tests for colon-separated format 'module:attr'."""
def test_colon_format_class(self) -> None:
"""Should resolve 'module:Class' format."""
result = resolve_callable("rsl_rl.algorithms:PPO")
from rsl_rl.algorithms import PPO
assert result is PPO
def test_colon_format_nested(self) -> None:
"""Should resolve 'module:Outer.Inner' nested format."""
result = resolve_callable("tests.utils.test_resolve_callable:OuterClass.InnerClass")
assert result is OuterClass.InnerClass
def test_colon_format_static_method(self) -> None:
"""Should resolve nested static methods."""
result = resolve_callable("tests.utils.test_resolve_callable:OuterClass.static_method")
assert result is OuterClass.static_method
def test_colon_format_invalid_module(self) -> None:
"""Should raise ImportError for invalid module."""
with pytest.raises(ImportError):
resolve_callable("nonexistent_module:SomeClass")
def test_colon_format_invalid_attr(self) -> None:
"""Should raise AttributeError for invalid attribute."""
with pytest.raises(AttributeError):
resolve_callable("rsl_rl.algorithms:NonexistentClass")
class TestResolveCallableDotFormat:
"""Tests for dot-separated format 'module.attr'."""
def test_dot_format_class(self) -> None:
"""Should resolve 'module.Class' format."""
result = resolve_callable("rsl_rl.algorithms.PPO")
from rsl_rl.algorithms import PPO
assert result is PPO
def test_dot_format_nested(self) -> None:
"""Should resolve 'module.Outer.Inner' nested format."""
# This tests the progressive module path splitting
result = resolve_callable("tests.utils.test_resolve_callable.OuterClass.InnerClass")
assert result is OuterClass.InnerClass
def test_dot_format_static_method(self) -> None:
"""Should resolve nested static methods."""
result = resolve_callable("tests.utils.test_resolve_callable.OuterClass.static_method")
assert result is OuterClass.static_method
def test_dot_format_invalid_module(self) -> None:
"""Should raise ImportError for invalid module."""
with pytest.raises(ImportError):
resolve_callable("nonexistent_module.SomeClass")
def test_dot_format_invalid_attr(self) -> None:
"""Should raise AttributeError for invalid attribute."""
with pytest.raises(AttributeError):
resolve_callable("rsl_rl.algorithms.NonexistentClass")
class TestResolveCallableSimpleName:
"""Tests for simple name resolution via rsl_rl packages."""
def test_simple_name(self) -> None:
"""Should resolve 'PPO' from rsl_rl.algorithms."""
result = resolve_callable("PPO")
from rsl_rl.algorithms import PPO
assert result is PPO
def test_simple_name_unknown(self) -> None:
"""Should raise ValueError for unknown simple names."""
with pytest.raises(ValueError, match="Could not resolve"):
resolve_callable("NonexistentClassName")
class TestResolveCallableErrors:
"""Tests for error handling."""
def test_type_error_none(self) -> None:
"""Should raise TypeError for None input."""
with pytest.raises(TypeError, match="Expected callable or string"):
resolve_callable(None)
def test_type_error_int(self) -> None:
"""Should raise TypeError for int input."""
with pytest.raises(TypeError, match="Expected callable or string"):
resolve_callable(42)
def test_type_error_list(self) -> None:
"""Should raise TypeError for list input."""
with pytest.raises(TypeError, match="Expected callable or string"):
resolve_callable(["PPO"])