495 lines
13 KiB
C#
495 lines
13 KiB
C#
|
|
using System.IO;
|
||
|
|
using NUnit.Framework;
|
||
|
|
using MCPForUnity.Editor.Services.Server;
|
||
|
|
using MCPForUnity.Editor.Constants;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
namespace MCPForUnityTests.Editor.Services.Server
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Unit tests for PidFileManager component.
|
||
|
|
/// </summary>
|
||
|
|
[TestFixture]
|
||
|
|
public class PidFileManagerTests
|
||
|
|
{
|
||
|
|
private PidFileManager _manager;
|
||
|
|
private string _testPidFilePath;
|
||
|
|
|
||
|
|
[SetUp]
|
||
|
|
public void SetUp()
|
||
|
|
{
|
||
|
|
_manager = new PidFileManager();
|
||
|
|
// Clear any test state
|
||
|
|
ClearTestEditorPrefs();
|
||
|
|
}
|
||
|
|
|
||
|
|
[TearDown]
|
||
|
|
public void TearDown()
|
||
|
|
{
|
||
|
|
// Clean up test files
|
||
|
|
if (!string.IsNullOrEmpty(_testPidFilePath) && File.Exists(_testPidFilePath))
|
||
|
|
{
|
||
|
|
try { File.Delete(_testPidFilePath); } catch { }
|
||
|
|
}
|
||
|
|
// Clear test state
|
||
|
|
ClearTestEditorPrefs();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ClearTestEditorPrefs()
|
||
|
|
{
|
||
|
|
try { EditorPrefs.DeleteKey(EditorPrefKeys.LastLocalHttpServerPid); } catch { }
|
||
|
|
try { EditorPrefs.DeleteKey(EditorPrefKeys.LastLocalHttpServerPort); } catch { }
|
||
|
|
try { EditorPrefs.DeleteKey(EditorPrefKeys.LastLocalHttpServerStartedUtc); } catch { }
|
||
|
|
try { EditorPrefs.DeleteKey(EditorPrefKeys.LastLocalHttpServerPidArgsHash); } catch { }
|
||
|
|
try { EditorPrefs.DeleteKey(EditorPrefKeys.LastLocalHttpServerPidFilePath); } catch { }
|
||
|
|
try { EditorPrefs.DeleteKey(EditorPrefKeys.LastLocalHttpServerInstanceToken); } catch { }
|
||
|
|
}
|
||
|
|
|
||
|
|
#region GetPidFilePath Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void GetPidFilePath_ValidPort_ReturnsCorrectPath()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string path = _manager.GetPidFilePath(8080);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsNotNull(path);
|
||
|
|
Assert.That(path, Does.Contain("mcp_http_8080.pid"));
|
||
|
|
Assert.That(path, Does.Contain("MCPForUnity"));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void GetPidFilePath_DifferentPorts_ReturnsDifferentPaths()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string path1 = _manager.GetPidFilePath(8080);
|
||
|
|
string path2 = _manager.GetPidFilePath(9090);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreNotEqual(path1, path2);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void GetPidDirectory_ReturnsValidPath()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string dir = _manager.GetPidDirectory();
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsNotNull(dir);
|
||
|
|
Assert.That(dir, Does.Contain("MCPForUnity"));
|
||
|
|
Assert.That(dir, Does.Contain("RunState"));
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region TryReadPid Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_ValidFile_ReturnsTrueWithPid()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_testPidFilePath = _manager.GetPidFilePath(59998);
|
||
|
|
File.WriteAllText(_testPidFilePath, "12345");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(_testPidFilePath, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsTrue(result);
|
||
|
|
Assert.AreEqual(12345, pid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_FileWithWhitespace_ParsesCorrectly()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_testPidFilePath = _manager.GetPidFilePath(59997);
|
||
|
|
File.WriteAllText(_testPidFilePath, " 12345 \n");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(_testPidFilePath, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsTrue(result);
|
||
|
|
Assert.AreEqual(12345, pid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_MissingFile_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid("/nonexistent/path/file.pid", out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.AreEqual(0, pid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_NullPath_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(null, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.AreEqual(0, pid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_EmptyPath_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(string.Empty, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.AreEqual(0, pid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_InvalidContent_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_testPidFilePath = _manager.GetPidFilePath(59996);
|
||
|
|
File.WriteAllText(_testPidFilePath, "not a number");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(_testPidFilePath, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.AreEqual(0, pid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_ZeroPid_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_testPidFilePath = _manager.GetPidFilePath(59995);
|
||
|
|
File.WriteAllText(_testPidFilePath, "0");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(_testPidFilePath, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result, "Zero PID should be rejected");
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryReadPid_NegativePid_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_testPidFilePath = _manager.GetPidFilePath(59994);
|
||
|
|
File.WriteAllText(_testPidFilePath, "-1");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryReadPid(_testPidFilePath, out int pid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result, "Negative PID should be rejected");
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region TryGetPortFromPidFilePath Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetPortFromPidFilePath_ValidPath_ReturnsTrue()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
string path = "/some/path/mcp_http_8080.pid";
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetPortFromPidFilePath(path, out int port);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsTrue(result);
|
||
|
|
Assert.AreEqual(8080, port);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetPortFromPidFilePath_DifferentPort_ParsesCorrectly()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
string path = "/path/to/mcp_http_9999.pid";
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetPortFromPidFilePath(path, out int port);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsTrue(result);
|
||
|
|
Assert.AreEqual(9999, port);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetPortFromPidFilePath_NullPath_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetPortFromPidFilePath(null, out int port);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.AreEqual(0, port);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetPortFromPidFilePath_InvalidPrefix_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
string path = "/some/path/wrong_prefix_8080.pid";
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetPortFromPidFilePath(path, out int port);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Handshake Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void StoreHandshake_ValidData_StoresInEditorPrefs()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
string pidFilePath = "/test/path.pid";
|
||
|
|
string instanceToken = "test-token-123";
|
||
|
|
|
||
|
|
// Act
|
||
|
|
_manager.StoreHandshake(pidFilePath, instanceToken);
|
||
|
|
bool result = _manager.TryGetHandshake(out var storedPath, out var storedToken);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsTrue(result);
|
||
|
|
Assert.AreEqual(pidFilePath, storedPath);
|
||
|
|
Assert.AreEqual(instanceToken, storedToken);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetHandshake_NoHandshake_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetHandshake(out var pidFilePath, out var instanceToken);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.IsNull(pidFilePath);
|
||
|
|
Assert.IsNull(instanceToken);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void StoreHandshake_NullValues_DoesNotThrow()
|
||
|
|
{
|
||
|
|
// Act & Assert
|
||
|
|
Assert.DoesNotThrow(() =>
|
||
|
|
{
|
||
|
|
_manager.StoreHandshake(null, null);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Tracking Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void StoreTracking_ValidData_CanBeRetrieved()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
int pid = 12345;
|
||
|
|
int port = 8080;
|
||
|
|
|
||
|
|
// Act
|
||
|
|
_manager.StoreTracking(pid, port);
|
||
|
|
bool result = _manager.TryGetStoredPid(port, out int storedPid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsTrue(result);
|
||
|
|
Assert.AreEqual(pid, storedPid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetStoredPid_WrongPort_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_manager.StoreTracking(12345, 8080);
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetStoredPid(9090, out int storedPid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result, "Should return false for wrong port");
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void TryGetStoredPid_NoTracking_ReturnsFalse()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
bool result = _manager.TryGetStoredPid(8080, out int storedPid);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(result);
|
||
|
|
Assert.AreEqual(0, storedPid);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ClearTracking_RemovesAllKeys()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_manager.StoreTracking(12345, 8080, "somehash");
|
||
|
|
_manager.StoreHandshake("/path.pid", "token");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
_manager.ClearTracking();
|
||
|
|
bool hasTracking = _manager.TryGetStoredPid(8080, out _);
|
||
|
|
bool hasHandshake = _manager.TryGetHandshake(out _, out _);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(hasTracking);
|
||
|
|
Assert.IsFalse(hasHandshake);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void GetStoredArgsHash_WithHash_ReturnsHash()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_manager.StoreTracking(12345, 8080, "testhash123");
|
||
|
|
|
||
|
|
// Act
|
||
|
|
string hash = _manager.GetStoredArgsHash();
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreEqual("testhash123", hash);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void GetStoredArgsHash_NoHash_ReturnsEmpty()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string hash = _manager.GetStoredArgsHash();
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreEqual(string.Empty, hash);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region ComputeShortHash Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ComputeShortHash_ValidInput_Returns16CharHash()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
string input = "test input string";
|
||
|
|
|
||
|
|
// Act
|
||
|
|
string hash = _manager.ComputeShortHash(input);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsNotNull(hash);
|
||
|
|
Assert.AreEqual(16, hash.Length);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ComputeShortHash_SameInput_ReturnsSameHash()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
string input = "consistent input";
|
||
|
|
|
||
|
|
// Act
|
||
|
|
string hash1 = _manager.ComputeShortHash(input);
|
||
|
|
string hash2 = _manager.ComputeShortHash(input);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreEqual(hash1, hash2);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ComputeShortHash_DifferentInput_ReturnsDifferentHash()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string hash1 = _manager.ComputeShortHash("input1");
|
||
|
|
string hash2 = _manager.ComputeShortHash("input2");
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreNotEqual(hash1, hash2);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ComputeShortHash_NullInput_ReturnsEmpty()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string hash = _manager.ComputeShortHash(null);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreEqual(string.Empty, hash);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ComputeShortHash_EmptyInput_ReturnsEmpty()
|
||
|
|
{
|
||
|
|
// Act
|
||
|
|
string hash = _manager.ComputeShortHash(string.Empty);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.AreEqual(string.Empty, hash);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region DeletePidFile Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void DeletePidFile_ExistingFile_DeletesFile()
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
_testPidFilePath = _manager.GetPidFilePath(59993);
|
||
|
|
File.WriteAllText(_testPidFilePath, "12345");
|
||
|
|
Assert.IsTrue(File.Exists(_testPidFilePath));
|
||
|
|
|
||
|
|
// Act
|
||
|
|
_manager.DeletePidFile(_testPidFilePath);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert.IsFalse(File.Exists(_testPidFilePath));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void DeletePidFile_NonExistentFile_DoesNotThrow()
|
||
|
|
{
|
||
|
|
// Act & Assert
|
||
|
|
Assert.DoesNotThrow(() =>
|
||
|
|
{
|
||
|
|
_manager.DeletePidFile("/nonexistent/file.pid");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void DeletePidFile_NullPath_DoesNotThrow()
|
||
|
|
{
|
||
|
|
// Act & Assert
|
||
|
|
Assert.DoesNotThrow(() =>
|
||
|
|
{
|
||
|
|
_manager.DeletePidFile(null);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Interface Implementation Tests
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void PidFileManager_ImplementsIPidFileManager()
|
||
|
|
{
|
||
|
|
// Assert
|
||
|
|
Assert.IsInstanceOf<IPidFileManager>(_manager);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
}
|
||
|
|
}
|