using System; using System.Linq; using NUnit.Framework; using UnityEngine; using MCPForUnity.Editor.Data; namespace MCPForUnityTests.Editor.Data { public class PythonToolsAssetTests { private PythonToolsAsset _asset; [SetUp] public void SetUp() { _asset = ScriptableObject.CreateInstance(); } [TearDown] public void TearDown() { if (_asset != null) { UnityEngine.Object.DestroyImmediate(_asset, true); } } [Test] public void GetValidFiles_ReturnsEmptyList_WhenNoFilesAdded() { var validFiles = _asset.GetValidFiles().ToList(); Assert.IsEmpty(validFiles, "Should return empty list when no files added"); } [Test] public void GetValidFiles_FiltersOutNullReferences() { _asset.pythonFiles.Add(null); _asset.pythonFiles.Add(new TextAsset("print('test')")); _asset.pythonFiles.Add(null); var validFiles = _asset.GetValidFiles().ToList(); Assert.AreEqual(1, validFiles.Count, "Should filter out null references"); } [Test] public void GetValidFiles_ReturnsAllNonNullFiles() { var file1 = new TextAsset("print('test1')"); var file2 = new TextAsset("print('test2')"); _asset.pythonFiles.Add(file1); _asset.pythonFiles.Add(file2); var validFiles = _asset.GetValidFiles().ToList(); Assert.AreEqual(2, validFiles.Count, "Should return all non-null files"); CollectionAssert.Contains(validFiles, file1); CollectionAssert.Contains(validFiles, file2); } [Test] public void NeedsSync_ReturnsTrue_WhenHashingDisabled() { _asset.useContentHashing = false; var textAsset = new TextAsset("print('test')"); bool needsSync = _asset.NeedsSync(textAsset, "any_hash"); Assert.IsTrue(needsSync, "Should always need sync when hashing disabled"); } [Test] public void NeedsSync_ReturnsTrue_WhenFileNotInStates() { _asset.useContentHashing = true; var textAsset = new TextAsset("print('test')"); bool needsSync = _asset.NeedsSync(textAsset, "new_hash"); Assert.IsTrue(needsSync, "Should need sync for new file"); } [Test] public void NeedsSync_ReturnsFalse_WhenHashMatches() { _asset.useContentHashing = true; var textAsset = new TextAsset("print('test')"); string hash = "test_hash_123"; // Record the file with a hash _asset.RecordSync(textAsset, hash); // Check if needs sync with same hash bool needsSync = _asset.NeedsSync(textAsset, hash); Assert.IsFalse(needsSync, "Should not need sync when hash matches"); } [Test] public void NeedsSync_ReturnsTrue_WhenHashDiffers() { _asset.useContentHashing = true; var textAsset = new TextAsset("print('test')"); // Record with one hash _asset.RecordSync(textAsset, "old_hash"); // Check with different hash bool needsSync = _asset.NeedsSync(textAsset, "new_hash"); Assert.IsTrue(needsSync, "Should need sync when hash differs"); } [Test] public void RecordSync_AddsNewFileState() { var textAsset = new TextAsset("print('test')"); string hash = "test_hash"; _asset.RecordSync(textAsset, hash); Assert.AreEqual(1, _asset.fileStates.Count, "Should add one file state"); Assert.AreEqual(hash, _asset.fileStates[0].contentHash, "Should store the hash"); Assert.IsNotNull(_asset.fileStates[0].assetGuid, "Should store the GUID"); } [Test] public void RecordSync_UpdatesExistingFileState() { var textAsset = new TextAsset("print('test')"); // Record first time _asset.RecordSync(textAsset, "hash1"); var firstTime = _asset.fileStates[0].lastSyncTime; // Wait a tiny bit to ensure time difference System.Threading.Thread.Sleep(10); // Record second time with different hash _asset.RecordSync(textAsset, "hash2"); Assert.AreEqual(1, _asset.fileStates.Count, "Should still have only one state"); Assert.AreEqual("hash2", _asset.fileStates[0].contentHash, "Should update the hash"); Assert.Greater(_asset.fileStates[0].lastSyncTime, firstTime, "Should update sync time"); } [Test] public void CleanupStaleStates_KeepsStatesForCurrentFiles() { var file1 = new TextAsset("print('test1')"); _asset.pythonFiles.Add(file1); _asset.RecordSync(file1, "hash1"); _asset.CleanupStaleStates(); Assert.AreEqual(1, _asset.fileStates.Count, "Should keep state for current file"); } [Test] public void CleanupStaleStates_HandlesEmptyFilesList() { // Add some states without corresponding files _asset.fileStates.Add(new PythonFileState { assetGuid = "fake_guid_1", contentHash = "hash1", fileName = "test1.py", lastSyncTime = DateTime.UtcNow }); _asset.CleanupStaleStates(); Assert.IsEmpty(_asset.fileStates, "Should remove all states when no files exist"); } } }