"""Tests for mcilspy.ilspy_wrapper module.""" import pytest from mcilspy.ilspy_wrapper import ILSpyWrapper from mcilspy.models import DecompileRequest, ListTypesRequest class TestILSpyWrapperInit: """Tests for ILSpyWrapper initialization.""" def test_init_finds_ilspycmd_or_raises(self): """Test that init either finds ilspycmd or raises RuntimeError.""" try: wrapper = ILSpyWrapper() # If we get here, ilspycmd was found assert wrapper.ilspycmd_path is not None except RuntimeError as e: # ilspycmd not installed - that's okay for testing assert "ILSpyCmd not found" in str(e) class TestILSpyWrapperTypeParsing: """Tests for type name parsing utilities.""" def test_parse_types_output_empty(self): """Test parsing empty output.""" # Create wrapper only if ilspycmd is available try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") types = wrapper._parse_types_output("") assert types == [] def test_parse_types_output_single_type(self): """Test parsing single type.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") output = "Class: MyNamespace.MyClass" types = wrapper._parse_types_output(output) assert len(types) == 1 assert types[0].name == "MyClass" assert types[0].namespace == "MyNamespace" assert types[0].kind == "Class" assert types[0].full_name == "MyNamespace.MyClass" def test_parse_types_output_multiple_types(self): """Test parsing multiple types.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") output = """Class: NS.ClassA Interface: NS.IService Struct: NS.MyStruct Enum: NS.MyEnum Delegate: NS.MyDelegate""" types = wrapper._parse_types_output(output) assert len(types) == 5 # Check kinds kinds = [t.kind for t in types] assert "Class" in kinds assert "Interface" in kinds assert "Struct" in kinds assert "Enum" in kinds assert "Delegate" in kinds def test_parse_types_output_nested_type(self): """Test parsing nested types.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") output = "Class: MyNamespace.Outer+Nested" types = wrapper._parse_types_output(output) assert len(types) == 1 assert types[0].name == "Outer+Nested" assert types[0].namespace == "MyNamespace" def test_parse_types_output_no_namespace(self): """Test parsing type with no namespace.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") output = "Class: MyClass" types = wrapper._parse_types_output(output) assert len(types) == 1 assert types[0].name == "MyClass" assert types[0].namespace is None def test_parse_types_output_skips_invalid_lines(self): """Test that invalid lines are skipped.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") output = """Class: NS.Valid This is not a valid line Another invalid line Interface: NS.AlsoValid""" types = wrapper._parse_types_output(output) assert len(types) == 2 assert types[0].full_name == "NS.Valid" assert types[1].full_name == "NS.AlsoValid" class TestILSpyWrapperDecompile: """Tests for decompilation functionality.""" @pytest.mark.asyncio async def test_decompile_nonexistent_assembly(self): """Test decompiling nonexistent assembly.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") request = DecompileRequest(assembly_path="/nonexistent/assembly.dll") response = await wrapper.decompile(request) assert response.success is False assert "not found" in response.error_message.lower() @pytest.mark.asyncio async def test_list_types_nonexistent_assembly(self): """Test listing types from nonexistent assembly.""" try: wrapper = ILSpyWrapper() except RuntimeError: pytest.skip("ilspycmd not installed") request = ListTypesRequest(assembly_path="/nonexistent/assembly.dll") response = await wrapper.list_types(request) assert response.success is False assert "not found" in response.error_message.lower() class TestILSpyWrapperHelpers: """Tests for ILSpyWrapper helper methods.""" def test_split_type_name_simple(self): """Test splitting simple type names.""" assert ILSpyWrapper._split_type_name("MyClass") == ("MyClass", None) assert ILSpyWrapper._split_type_name("NS.MyClass") == ("MyClass", "NS") assert ILSpyWrapper._split_type_name("Deep.NS.MyClass") == ("MyClass", "Deep.NS") def test_split_type_name_nested(self): """Test splitting nested type names.""" assert ILSpyWrapper._split_type_name("NS.Outer+Nested") == ("Outer+Nested", "NS") assert ILSpyWrapper._split_type_name("Outer+Nested") == ("Outer+Nested", None) assert ILSpyWrapper._split_type_name("NS.A+B+C") == ("A+B+C", "NS") def test_split_type_name_deep_namespace(self): """Test splitting types with deep namespaces.""" assert ILSpyWrapper._split_type_name("A.B.C.D.MyClass") == ("MyClass", "A.B.C.D") def test_split_type_name_nested_with_deep_namespace(self): """Test nested types with deep namespaces.""" assert ILSpyWrapper._split_type_name("A.B.C.Outer+Inner") == ("Outer+Inner", "A.B.C")