unity-mcp/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/PackageLifecycleManagerTest...

167 lines
6.0 KiB
C#
Raw Normal View History

Remove old UI and do lots of cleanup (#340) * Remove legacy UI and correct priority ordering of menu items * Remove old UI screen Users now have the new UI alone, less confusing and more predictable * Remove unused config files * Remove test for window that doesn't exist * Remove unused code * Remove dangling .meta file * refactor: remove client configuration step from setup wizard * refactor: remove menu item attributes and manual window actions from Python tool sync * feat: update minimum Python version requirement from 3.10 to 3.11 The docs have 3.12. However, feature wise it seems that 3.11 is required * fix: replace emoji warning symbol with unicode character in setup wizard dialogs * docs: reorganize images into docs/images directory and update references * docs: add UI preview image to README * docs: add run_test function and resources section to available tools list The recent changes should close #311 * fix: add SystemRoot env var to Windows config to support Python path resolution Closes #315 * refactor: consolidate package installation and detection into unified lifecycle manager Duplicate code for pretty much no reason, as they both initialized there was a small chance of a race condition as well. Consolidating made sense here * Doc fixes from CodeRabbit * Excellent bug catch from CodeRabbit * fix: preserve existing environment variables when updating codex server config * Update docs so the paths match the original name * style: fix list indentation in README-DEV.md development docs * refactor: simplify env table handling in CodexConfigHelper by removing preservation logic * refactor: simplify configuration logic by removing redundant change detection Always overwrite configs * feat: ensure config directory exists before writing config files * feat: persist server installation errors and show retry UI instead of auto-marking as handled * refactor: consolidate configuration helpers by merging McpConfigFileHelper into McpConfigurationHelper * Small fixes from CodeRabbit * Remove test because we overwrite Codex configs * Remove unused function * feat: improve server cleanup and process handling on Windows - Added DeleteDirectoryWithRetry helper to handle Windows file locking with retries and readonly attribute clearing - Implemented KillWindowsUvProcesses to safely terminate Python processes in virtual environments using WMIC - Extended TryKillUvForPath to work on Windows, preventing file handle locks during server deletion - Improved error messages to be more descriptive about file locking issues - Replaced direct Directory.Delete calls with * fix: improve TCP socket cleanup to prevent CLOSE_WAIT states - Added proper socket shutdown sequence using Socket.Shutdown() before closing connections - Enhanced error handling with specific catches for SocketException vs general exceptions - Added debug logging for socket shutdown errors to help diagnose connection issues - Restructured HandleClientAsync to ensure socket cleanup happens in the correct order - Implemented proper socket teardown in both client handling and connection cleanup paths
2025-10-24 12:50:29 +08:00
using NUnit.Framework;
using UnityEditor;
using System.IO;
namespace MCPForUnityTests.Editor.Helpers
{
/// <summary>
/// Tests for PackageLifecycleManager.
/// Note: These tests verify the logic but cannot fully test [InitializeOnLoad] behavior.
/// </summary>
public class PackageLifecycleManagerTests
{
private const string TestVersionKey = "MCPForUnity.InstalledVersion:test-version";
private const string LegacyInstallFlagKey = "MCPForUnity.ServerInstalled";
[SetUp]
public void SetUp()
{
// Clean up test keys before each test
CleanupTestKeys();
}
[TearDown]
public void TearDown()
{
// Clean up test keys after each test
CleanupTestKeys();
}
private void CleanupTestKeys()
{
try
{
if (EditorPrefs.HasKey(TestVersionKey))
{
EditorPrefs.DeleteKey(TestVersionKey);
}
if (EditorPrefs.HasKey(LegacyInstallFlagKey))
{
EditorPrefs.DeleteKey(LegacyInstallFlagKey);
}
// Clean up any other test-related keys
string[] testKeys = {
"MCPForUnity.ServerSrc",
"MCPForUnity.PythonDirOverride",
"MCPForUnity.LegacyDetectLogged"
};
foreach (var key in testKeys)
{
if (EditorPrefs.HasKey(key))
{
EditorPrefs.DeleteKey(key);
}
}
}
catch { }
}
[Test]
public void FirstTimeInstall_ShouldNotHaveLegacyFlag()
{
// Verify that on a fresh install, the legacy flag doesn't exist
Assert.IsFalse(EditorPrefs.HasKey(LegacyInstallFlagKey),
"Fresh install should not have legacy installation flag");
}
[Test]
public void VersionKey_ShouldBeVersionScoped()
{
// Verify that version keys are properly scoped
string version1Key = "MCPForUnity.InstalledVersion:1.0.0";
string version2Key = "MCPForUnity.InstalledVersion:2.0.0";
Assert.AreNotEqual(version1Key, version2Key,
"Different versions should have different keys");
Assert.IsTrue(version1Key.StartsWith("MCPForUnity.InstalledVersion:"),
"Version key should have correct prefix");
}
[Test]
public void LegacyPrefsCleanup_ShouldRemoveOldKeys()
{
// Set up legacy keys
EditorPrefs.SetString("MCPForUnity.ServerSrc", "test");
EditorPrefs.SetString("MCPForUnity.PythonDirOverride", "test");
// Verify they exist
Assert.IsTrue(EditorPrefs.HasKey("MCPForUnity.ServerSrc"),
"Legacy key should exist before cleanup");
Assert.IsTrue(EditorPrefs.HasKey("MCPForUnity.PythonDirOverride"),
"Legacy key should exist before cleanup");
// Note: We can't directly test the cleanup since it's private,
// but we can verify the keys exist and document expected behavior
// In actual usage, PackageLifecycleManager will clean these up
}
[Test]
public void VersionKeyFormat_ShouldFollowConvention()
{
// Test that version key format follows the expected pattern
string testVersion = "1.2.3";
string expectedKey = $"MCPForUnity.InstalledVersion:{testVersion}";
Assert.AreEqual("MCPForUnity.InstalledVersion:1.2.3", expectedKey,
"Version key should follow format: prefix + version");
}
[Test]
public void MultipleVersions_ShouldHaveIndependentKeys()
{
// Simulate multiple version installations
EditorPrefs.SetBool("MCPForUnity.InstalledVersion:1.0.0", true);
EditorPrefs.SetBool("MCPForUnity.InstalledVersion:2.0.0", true);
Assert.IsTrue(EditorPrefs.GetBool("MCPForUnity.InstalledVersion:1.0.0"),
"Version 1.0.0 flag should be set");
Assert.IsTrue(EditorPrefs.GetBool("MCPForUnity.InstalledVersion:2.0.0"),
"Version 2.0.0 flag should be set");
// Clean up
EditorPrefs.DeleteKey("MCPForUnity.InstalledVersion:1.0.0");
EditorPrefs.DeleteKey("MCPForUnity.InstalledVersion:2.0.0");
}
[Test]
public void LegacyFlagMigration_ShouldPreserveBackwardCompatibility()
{
// Simulate a scenario where old PackageInstaller set the flag
EditorPrefs.SetBool(LegacyInstallFlagKey, true);
Assert.IsTrue(EditorPrefs.GetBool(LegacyInstallFlagKey),
"Legacy flag should be readable for backward compatibility");
}
[Test]
public void EditorPrefsKeys_ShouldNotConflict()
{
// Verify that our keys don't conflict with Unity or other packages
string[] ourKeys = {
"MCPForUnity.InstalledVersion:1.0.0",
"MCPForUnity.ServerInstalled",
"MCPForUnity.ServerSrc",
"MCPForUnity.PythonDirOverride"
};
foreach (var key in ourKeys)
{
Assert.IsTrue(key.StartsWith("MCPForUnity."),
$"Key '{key}' should be properly namespaced");
}
}
[Test]
public void VersionString_ShouldHandleUnknownGracefully()
{
// Test that "unknown" version is a valid fallback
string unknownVersion = "unknown";
string versionKey = $"MCPForUnity.InstalledVersion:{unknownVersion}";
Assert.IsNotNull(versionKey, "Version key should handle 'unknown' version");
Assert.IsTrue(versionKey.Contains("unknown"),
"Version key should contain the unknown version string");
}
}
}