unity-mcp/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/Matrix4x4ConverterTests.cs

135 lines
5.1 KiB
C#
Raw Normal View History

Test/478 matrix4x4 serialization crash (#481) * Fix #478: Add Matrix4x4Converter to prevent Cinemachine serialization crash The `get_components` action crashes Unity when serializing Cinemachine camera components because Newtonsoft.Json accesses computed Matrix4x4 properties (lossyScale, rotation) that call ValidTRS() on non-TRS matrices. This fix adds a safe Matrix4x4Converter that only accesses raw matrix elements (m00-m33), avoiding the dangerous computed properties entirely. Changes: - Add Matrix4x4Converter to UnityTypeConverters.cs - Register converter in GameObjectSerializer serializer settings Tested with Cinemachine 3.1.5 on Unity 6 - get_components now returns full component data without crashing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add unit tests for Matrix4x4Converter Tests cover: - Identity matrix serialization/deserialization - Translation matrix round-trip - Degenerate matrix (determinant=0) - key regression test - Non-TRS matrix (projection) - validates ValidTRS() is never called - Null handling - Ensures dangerous properties are not in output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Address code review feedback - Fix null handling consistency: return zero matrix instead of identity (consistent with missing field defaults of 0f) - Improve degenerate matrix test to verify: - JSON only contains raw mXY properties - Values roundtrip correctly - Rename test to reflect expanded coverage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Move tests to TestProject per review feedback Moved Matrix4x4ConverterTests from MCPForUnity/Editor/Tests/ to TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/ as requested. Also added MCPForUnity.Runtime reference to the test asmdef since the converter lives in the Runtime assembly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix Matrix4x4 deserialization guard + UI Toolkit USS warning --------- Co-authored-by: Alexander Mangel <cygnusfear@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 07:53:14 +08:00
using System.Linq;
using MCPForUnity.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using UnityEngine;
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
namespace MCPForUnityTests.Editor.Helpers
Test/478 matrix4x4 serialization crash (#481) * Fix #478: Add Matrix4x4Converter to prevent Cinemachine serialization crash The `get_components` action crashes Unity when serializing Cinemachine camera components because Newtonsoft.Json accesses computed Matrix4x4 properties (lossyScale, rotation) that call ValidTRS() on non-TRS matrices. This fix adds a safe Matrix4x4Converter that only accesses raw matrix elements (m00-m33), avoiding the dangerous computed properties entirely. Changes: - Add Matrix4x4Converter to UnityTypeConverters.cs - Register converter in GameObjectSerializer serializer settings Tested with Cinemachine 3.1.5 on Unity 6 - get_components now returns full component data without crashing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add unit tests for Matrix4x4Converter Tests cover: - Identity matrix serialization/deserialization - Translation matrix round-trip - Degenerate matrix (determinant=0) - key regression test - Non-TRS matrix (projection) - validates ValidTRS() is never called - Null handling - Ensures dangerous properties are not in output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Address code review feedback - Fix null handling consistency: return zero matrix instead of identity (consistent with missing field defaults of 0f) - Improve degenerate matrix test to verify: - JSON only contains raw mXY properties - Values roundtrip correctly - Rename test to reflect expanded coverage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Move tests to TestProject per review feedback Moved Matrix4x4ConverterTests from MCPForUnity/Editor/Tests/ to TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/ as requested. Also added MCPForUnity.Runtime reference to the test asmdef since the converter lives in the Runtime assembly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix Matrix4x4 deserialization guard + UI Toolkit USS warning --------- Co-authored-by: Alexander Mangel <cygnusfear@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 07:53:14 +08:00
{
/// <summary>
/// Tests for Matrix4x4Converter to ensure it safely serializes matrices
/// without accessing dangerous computed properties (lossyScale, rotation).
/// Regression test for https://github.com/CoplayDev/unity-mcp/issues/478
/// </summary>
public class Matrix4x4ConverterTests
{
private JsonSerializerSettings _settings;
[SetUp]
public void SetUp()
{
_settings = new JsonSerializerSettings
{
Converters = { new Matrix4x4Converter() }
};
}
[Test]
public void Serialize_IdentityMatrix_ReturnsCorrectJson()
{
var matrix = Matrix4x4.identity;
var json = JsonConvert.SerializeObject(matrix, _settings);
Assert.That(json, Does.Contain("\"m00\":1"));
Assert.That(json, Does.Contain("\"m11\":1"));
Assert.That(json, Does.Contain("\"m22\":1"));
Assert.That(json, Does.Contain("\"m33\":1"));
Assert.That(json, Does.Contain("\"m01\":0"));
}
[Test]
public void Deserialize_IdentityMatrix_ReturnsIdentity()
{
var original = Matrix4x4.identity;
var json = JsonConvert.SerializeObject(original, _settings);
var result = JsonConvert.DeserializeObject<Matrix4x4>(json, _settings);
Assert.That(result, Is.EqualTo(original));
}
[Test]
public void Serialize_TranslationMatrix_PreservesValues()
{
var matrix = Matrix4x4.Translate(new Vector3(10, 20, 30));
var json = JsonConvert.SerializeObject(matrix, _settings);
var result = JsonConvert.DeserializeObject<Matrix4x4>(json, _settings);
Assert.That(result.m03, Is.EqualTo(10f));
Assert.That(result.m13, Is.EqualTo(20f));
Assert.That(result.m23, Is.EqualTo(30f));
}
[Test]
public void Serialize_DegenerateMatrix_DoesNotCrashAndRoundtrips()
{
// This is the key test - a degenerate matrix that would crash
// if we accessed lossyScale or rotation properties
var matrix = new Matrix4x4();
matrix.m00 = 0; matrix.m11 = 0; matrix.m22 = 0; // Degenerate - determinant = 0
// This should NOT throw or crash - the old code would fail here
var json = JsonConvert.SerializeObject(matrix, _settings);
var result = JsonConvert.DeserializeObject<Matrix4x4>(json, _settings);
// Verify JSON only contains raw mXY properties
var jo = JObject.Parse(json);
var expectedProps = new[]
{
"m00", "m01", "m02", "m03",
"m10", "m11", "m12", "m13",
"m20", "m21", "m22", "m23",
"m30", "m31", "m32", "m33"
};
CollectionAssert.AreEquivalent(expectedProps, jo.Properties().Select(p => p.Name).ToArray());
// Verify values roundtrip correctly (all zeros for degenerate matrix)
Assert.That(result.m00, Is.EqualTo(0f));
Assert.That(result.m11, Is.EqualTo(0f));
Assert.That(result.m22, Is.EqualTo(0f));
Assert.That(result, Is.EqualTo(matrix));
}
[Test]
public void Serialize_NonTRSMatrix_DoesNotCrash()
{
// Projection matrices are NOT valid TRS matrices
// Accessing lossyScale/rotation on them causes ValidTRS() assertion
var matrix = Matrix4x4.Perspective(60f, 1.77f, 0.1f, 1000f);
// Verify it's not a valid TRS matrix
Assert.That(matrix.ValidTRS(), Is.False, "Test requires non-TRS matrix");
// This should NOT throw - the fix ensures we never access computed properties
Assert.DoesNotThrow(() =>
{
var json = JsonConvert.SerializeObject(matrix, _settings);
var result = JsonConvert.DeserializeObject<Matrix4x4>(json, _settings);
});
}
[Test]
public void Deserialize_NullToken_ReturnsZeroMatrix()
{
var json = "null";
var result = JsonConvert.DeserializeObject<Matrix4x4>(json, _settings);
// Returns zero matrix (consistent with missing field defaults of 0f)
Assert.That(result, Is.EqualTo(new Matrix4x4()));
}
[Test]
public void Serialize_DoesNotContainDangerousProperties()
{
var matrix = Matrix4x4.TRS(Vector3.one, Quaternion.identity, Vector3.one);
var json = JsonConvert.SerializeObject(matrix, _settings);
// Ensure we're not serializing the dangerous computed properties
Assert.That(json, Does.Not.Contain("lossyScale"));
Assert.That(json, Does.Not.Contain("rotation"));
Assert.That(json, Does.Not.Contain("inverse"));
Assert.That(json, Does.Not.Contain("transpose"));
}
}
}