升级XR插件版本
This commit is contained in:
150
Packages/MCPForUnity/Editor/Services/TestRunnerNoThrottle.cs
Normal file
150
Packages/MCPForUnity/Editor/Services/TestRunnerNoThrottle.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
// TestRunnerNoThrottle.cs
|
||||
// Sets Unity Editor to "No Throttling" mode during test runs.
|
||||
// This helps tests that don't trigger compilation run smoothly in the background.
|
||||
// Note: Tests that trigger mid-run compilation may still stall due to OS-level throttling.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using MCPForUnity.Editor.Helpers;
|
||||
using UnityEditor;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MCPForUnity.Editor.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Automatically sets the editor to "No Throttling" mode during test runs.
|
||||
///
|
||||
/// This helps prevent background stalls for normal tests. However, tests that trigger
|
||||
/// script compilation mid-run may still stall because:
|
||||
/// - Internal Unity coroutine waits rely on editor ticks
|
||||
/// - OS-level throttling affects the main thread when Unity is backgrounded
|
||||
/// - No amount of internal nudging can overcome OS thread scheduling
|
||||
///
|
||||
/// The MCP workflow is unaffected because socket messages provide external stimulus
|
||||
/// that wakes Unity's main thread.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public static class TestRunnerNoThrottle
|
||||
{
|
||||
private const string ApplicationIdleTimeKey = "ApplicationIdleTime";
|
||||
private const string InteractionModeKey = "InteractionMode";
|
||||
|
||||
// SessionState keys to persist across domain reload
|
||||
private const string SessionKey_TestRunActive = "TestRunnerNoThrottle_TestRunActive";
|
||||
private const string SessionKey_PrevIdleTime = "TestRunnerNoThrottle_PrevIdleTime";
|
||||
private const string SessionKey_PrevInteractionMode = "TestRunnerNoThrottle_PrevInteractionMode";
|
||||
private const string SessionKey_SettingsCaptured = "TestRunnerNoThrottle_SettingsCaptured";
|
||||
|
||||
// Keep reference to avoid GC and set HideFlags to avoid serialization issues
|
||||
private static TestRunnerApi _api;
|
||||
|
||||
static TestRunnerNoThrottle()
|
||||
{
|
||||
try
|
||||
{
|
||||
_api = ScriptableObject.CreateInstance<TestRunnerApi>();
|
||||
_api.hideFlags = HideFlags.HideAndDontSave;
|
||||
_api.RegisterCallbacks(new TestCallbacks());
|
||||
|
||||
// Check if recovering from domain reload during an active test run
|
||||
if (IsTestRunActive())
|
||||
{
|
||||
McpLog.Info("[TestRunnerNoThrottle] Recovered from domain reload - reapplying No Throttling.");
|
||||
ApplyNoThrottling();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
McpLog.Warn($"[TestRunnerNoThrottle] Failed to register callbacks: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
#region State Persistence
|
||||
|
||||
private static bool IsTestRunActive() => SessionState.GetBool(SessionKey_TestRunActive, false);
|
||||
private static void SetTestRunActive(bool active) => SessionState.SetBool(SessionKey_TestRunActive, active);
|
||||
private static bool AreSettingsCaptured() => SessionState.GetBool(SessionKey_SettingsCaptured, false);
|
||||
private static void SetSettingsCaptured(bool captured) => SessionState.SetBool(SessionKey_SettingsCaptured, captured);
|
||||
private static int GetPrevIdleTime() => SessionState.GetInt(SessionKey_PrevIdleTime, 4);
|
||||
private static void SetPrevIdleTime(int value) => SessionState.SetInt(SessionKey_PrevIdleTime, value);
|
||||
private static int GetPrevInteractionMode() => SessionState.GetInt(SessionKey_PrevInteractionMode, 0);
|
||||
private static void SetPrevInteractionMode(int value) => SessionState.SetInt(SessionKey_PrevInteractionMode, value);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Apply no-throttling preemptively before tests start.
|
||||
/// Call this before Execute() for PlayMode tests to ensure Unity isn't throttled
|
||||
/// during the Play mode transition (before RunStarted fires).
|
||||
/// </summary>
|
||||
public static void ApplyNoThrottlingPreemptive()
|
||||
{
|
||||
SetTestRunActive(true);
|
||||
ApplyNoThrottling();
|
||||
}
|
||||
|
||||
private static void ApplyNoThrottling()
|
||||
{
|
||||
if (!AreSettingsCaptured())
|
||||
{
|
||||
SetPrevIdleTime(EditorPrefs.GetInt(ApplicationIdleTimeKey, 4));
|
||||
SetPrevInteractionMode(EditorPrefs.GetInt(InteractionModeKey, 0));
|
||||
SetSettingsCaptured(true);
|
||||
}
|
||||
|
||||
// 0ms idle + InteractionMode=1 (No Throttling)
|
||||
EditorPrefs.SetInt(ApplicationIdleTimeKey, 0);
|
||||
EditorPrefs.SetInt(InteractionModeKey, 1);
|
||||
|
||||
ForceEditorToApplyInteractionPrefs();
|
||||
McpLog.Info("[TestRunnerNoThrottle] Applied No Throttling for test run.");
|
||||
}
|
||||
|
||||
private static void RestoreThrottling()
|
||||
{
|
||||
if (!AreSettingsCaptured()) return;
|
||||
|
||||
EditorPrefs.SetInt(ApplicationIdleTimeKey, GetPrevIdleTime());
|
||||
EditorPrefs.SetInt(InteractionModeKey, GetPrevInteractionMode());
|
||||
ForceEditorToApplyInteractionPrefs();
|
||||
|
||||
SetSettingsCaptured(false);
|
||||
SetTestRunActive(false);
|
||||
McpLog.Info("[TestRunnerNoThrottle] Restored Interaction Mode after test run.");
|
||||
}
|
||||
|
||||
private static void ForceEditorToApplyInteractionPrefs()
|
||||
{
|
||||
try
|
||||
{
|
||||
var method = typeof(EditorApplication).GetMethod(
|
||||
"UpdateInteractionModeSettings",
|
||||
BindingFlags.Static | BindingFlags.NonPublic
|
||||
);
|
||||
method?.Invoke(null, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore reflection errors
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class TestCallbacks : ICallbacks
|
||||
{
|
||||
public void RunStarted(ITestAdaptor testsToRun)
|
||||
{
|
||||
SetTestRunActive(true);
|
||||
ApplyNoThrottling();
|
||||
}
|
||||
|
||||
public void RunFinished(ITestResultAdaptor result)
|
||||
{
|
||||
RestoreThrottling();
|
||||
}
|
||||
|
||||
public void TestStarted(ITestAdaptor test) { }
|
||||
public void TestFinished(ITestResultAdaptor result) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user