-
Notifications
You must be signed in to change notification settings - Fork 1k
Expand file tree
/
Copy pathTestJobManagerInitTimeoutTests.cs
More file actions
170 lines (142 loc) · 8.63 KB
/
TestJobManagerInitTimeoutTests.cs
File metadata and controls
170 lines (142 loc) · 8.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using System;
using System.Collections.Generic;
using System.Reflection;
using NUnit.Framework;
using UnityEditor;
using MCPForUnity.Editor.Services;
namespace MCPForUnityTests.Editor.Services
{
/// <summary>
/// Tests for TestJobManager's per-job InitTimeoutMs feature.
/// Uses reflection to manipulate internal state since StartJob triggers a real test run.
/// </summary>
public class TestJobManagerInitTimeoutTests
{
private FieldInfo _jobsField;
private FieldInfo _currentJobIdField;
private MethodInfo _getJobMethod;
private MethodInfo _persistMethod;
private MethodInfo _restoreMethod;
private Type _testJobType;
private string _originalJobId;
[SetUp]
public void SetUp()
{
var asm = typeof(MCPServiceLocator).Assembly;
var managerType = asm.GetType("MCPForUnity.Editor.Services.TestJobManager");
Assert.NotNull(managerType, "Could not find TestJobManager");
_testJobType = asm.GetType("MCPForUnity.Editor.Services.TestJob");
Assert.NotNull(_testJobType, "Could not find TestJob");
_jobsField = managerType.GetField("Jobs", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(_jobsField, "Could not find Jobs field");
_currentJobIdField = managerType.GetField("_currentJobId", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(_currentJobIdField, "Could not find _currentJobId field");
_getJobMethod = managerType.GetMethod("GetJob", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(_getJobMethod, "Could not find GetJob method");
_persistMethod = managerType.GetMethod("PersistToSessionState", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(_persistMethod, "Could not find PersistToSessionState method");
_restoreMethod = managerType.GetMethod("TryRestoreFromSessionState", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(_restoreMethod, "Could not find TryRestoreFromSessionState method");
// Snapshot original state
_originalJobId = _currentJobIdField.GetValue(null) as string;
// We'll restore _currentJobId in TearDown; Jobs dictionary is shared static state
}
[TearDown]
public void TearDown()
{
// Restore original state
_currentJobIdField.SetValue(null, _originalJobId);
// Clean up any test jobs we inserted
var jobs = _jobsField.GetValue(null) as System.Collections.IDictionary;
jobs?.Remove("test-init-timeout-job");
jobs?.Remove("test-init-timeout-default");
jobs?.Remove("test-init-timeout-persist");
}
[Test]
public void GetJob_WithCustomInitTimeout_UsesPerJobTimeout()
{
// Arrange: insert a job with a custom init timeout and a start time far enough in the
// past to exceed the default 15s but within the custom 120s.
var jobs = _jobsField.GetValue(null) as System.Collections.IDictionary;
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var job = Activator.CreateInstance(_testJobType);
_testJobType.GetProperty("JobId").SetValue(job, "test-init-timeout-job");
_testJobType.GetProperty("Status").SetValue(job, TestJobStatus.Running);
_testJobType.GetProperty("Mode").SetValue(job, "PlayMode");
_testJobType.GetProperty("StartedUnixMs").SetValue(job, now - 30_000); // 30s ago
_testJobType.GetProperty("LastUpdateUnixMs").SetValue(job, now - 30_000);
_testJobType.GetProperty("TotalTests").SetValue(job, null); // Not initialized yet
_testJobType.GetProperty("InitTimeoutMs").SetValue(job, 120_000L); // 120s custom timeout
_testJobType.GetProperty("FailuresSoFar").SetValue(job, new List<TestJobFailure>());
jobs["test-init-timeout-job"] = job;
_currentJobIdField.SetValue(null, "test-init-timeout-job");
// Act: GetJob should NOT auto-fail because 30s < 120s custom timeout
var result = _getJobMethod.Invoke(null, new object[] { "test-init-timeout-job" });
// Assert: job should still be running
var status = (TestJobStatus)_testJobType.GetProperty("Status").GetValue(result);
Assert.AreEqual(TestJobStatus.Running, status,
"Job with 120s custom timeout should not auto-fail after 30s");
}
[Test]
public void GetJob_WithDefaultTimeout_AutoFailsAfter15Seconds()
{
// Guard: GetJob skips the auto-fail path while compiling/updating, which would
// make this test pass for the wrong reason (job stays Running due to compile guard).
Assume.That(EditorApplication.isCompiling, Is.False, "Skipping: editor is compiling");
Assume.That(EditorApplication.isUpdating, Is.False, "Skipping: editor is updating");
// Arrange: insert a job with InitTimeoutMs=0 (use default) and start time 20s ago
var jobs = _jobsField.GetValue(null) as System.Collections.IDictionary;
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var job = Activator.CreateInstance(_testJobType);
_testJobType.GetProperty("JobId").SetValue(job, "test-init-timeout-default");
_testJobType.GetProperty("Status").SetValue(job, TestJobStatus.Running);
_testJobType.GetProperty("Mode").SetValue(job, "EditMode");
_testJobType.GetProperty("StartedUnixMs").SetValue(job, now - 20_000); // 20s ago
_testJobType.GetProperty("LastUpdateUnixMs").SetValue(job, now - 20_000);
_testJobType.GetProperty("TotalTests").SetValue(job, null);
_testJobType.GetProperty("InitTimeoutMs").SetValue(job, 0L); // Use default
_testJobType.GetProperty("FailuresSoFar").SetValue(job, new List<TestJobFailure>());
jobs["test-init-timeout-default"] = job;
_currentJobIdField.SetValue(null, "test-init-timeout-default");
// Act: GetJob should auto-fail because 20s > 15s default
var result = _getJobMethod.Invoke(null, new object[] { "test-init-timeout-default" });
// Assert: job should be failed
var status = (TestJobStatus)_testJobType.GetProperty("Status").GetValue(result);
Assert.AreEqual(TestJobStatus.Failed, status,
"Job with default timeout should auto-fail after 20s");
}
[Test]
public void InitTimeoutMs_SurvivesPersistAndRestore()
{
// Arrange: insert a job with custom InitTimeoutMs
var jobs = _jobsField.GetValue(null) as System.Collections.IDictionary;
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var job = Activator.CreateInstance(_testJobType);
_testJobType.GetProperty("JobId").SetValue(job, "test-init-timeout-persist");
_testJobType.GetProperty("Status").SetValue(job, TestJobStatus.Running);
_testJobType.GetProperty("Mode").SetValue(job, "PlayMode");
_testJobType.GetProperty("StartedUnixMs").SetValue(job, now);
_testJobType.GetProperty("LastUpdateUnixMs").SetValue(job, now);
_testJobType.GetProperty("TotalTests").SetValue(job, null);
_testJobType.GetProperty("InitTimeoutMs").SetValue(job, 90_000L);
_testJobType.GetProperty("FailuresSoFar").SetValue(job, new List<TestJobFailure>());
jobs["test-init-timeout-persist"] = job;
_currentJobIdField.SetValue(null, "test-init-timeout-persist");
// Act: persist then restore (simulates domain reload)
_persistMethod.Invoke(null, new object[] { true });
// Clear in-memory state
jobs.Remove("test-init-timeout-persist");
_currentJobIdField.SetValue(null, null);
// Restore from SessionState
_restoreMethod.Invoke(null, null);
// Assert: restored job should have the same InitTimeoutMs
var restoredJobs = _jobsField.GetValue(null) as System.Collections.IDictionary;
Assert.IsTrue(restoredJobs.Contains("test-init-timeout-persist"),
"Job should be restored from SessionState");
var restoredJob = restoredJobs["test-init-timeout-persist"];
var restoredTimeout = (long)_testJobType.GetProperty("InitTimeoutMs").GetValue(restoredJob);
Assert.AreEqual(90_000L, restoredTimeout,
"InitTimeoutMs should survive persist/restore cycle");
}
}
}