22using MCServerLauncher . Common . ProtoType . Instance ;
33using MCServerLauncher . Daemon . Management ;
44using MCServerLauncher . Daemon . Management . Communicate ;
5+ using System . Diagnostics ;
56
67namespace MCServerLauncher . ProtocolTests ;
78
@@ -69,6 +70,35 @@ public async Task TryStartInstance_RegistersInstanceBeforeStartCompletes()
6970 Assert . True ( manager . RunningInstances . ContainsKey ( config . Uuid ) ) ;
7071 }
7172
73+ [ Fact ]
74+ public async Task TryStartInstance_ReportShowsRunningAfterProcessStartSucceeds ( )
75+ {
76+ var manager = new InstanceManager ( ) ;
77+ var config = CreateConfig ( InstanceType . MCJava ) ;
78+ var instance = new FakeInstance ( config , InstanceStatus . Stopped ) ;
79+ manager . Instances [ config . Uuid ] = instance ;
80+
81+ var started = await manager . TryStartInstance ( config . Uuid ) ;
82+ var report = await manager . GetInstanceReport ( config . Uuid ) ;
83+
84+ Assert . Same ( instance , started ) ;
85+ Assert . NotNull ( report ) ;
86+ Assert . Equal ( InstanceStatus . Running , report . Status ) ;
87+ }
88+
89+ [ Fact ]
90+ public async Task InstanceProcess_MinecraftProcessIsRunningBeforeDoneLog ( )
91+ {
92+ var startInfo = CreateShortLivedProcessStartInfo ( ) ;
93+ using var process = new InstanceProcess ( startInfo , isMcServer : true ) ;
94+
95+ var started = await process . StartAsync ( delayToCheck : 100 ) ;
96+
97+ Assert . True ( started ) ;
98+ Assert . Equal ( InstanceStatus . Running , process . Status ) ;
99+ process . KillProcess ( ) ;
100+ }
101+
72102 [ Fact ]
73103 public void InstanceStatus_ContainsOnlyStableLifecycleStates ( )
74104 {
@@ -95,6 +125,33 @@ private static InstanceConfig CreateConfig(InstanceType type)
95125 } ;
96126 }
97127
128+ private static ProcessStartInfo CreateShortLivedProcessStartInfo ( )
129+ {
130+ if ( OperatingSystem . IsWindows ( ) )
131+ {
132+ return new ProcessStartInfo
133+ {
134+ FileName = "cmd.exe" ,
135+ Arguments = "/c ping -n 6 127.0.0.1 > nul" ,
136+ UseShellExecute = false ,
137+ RedirectStandardOutput = true ,
138+ RedirectStandardError = true ,
139+ RedirectStandardInput = true ,
140+ CreateNoWindow = true
141+ } ;
142+ }
143+
144+ return new ProcessStartInfo
145+ {
146+ FileName = "/bin/sh" ,
147+ Arguments = "-c \" sleep 5\" " ,
148+ UseShellExecute = false ,
149+ RedirectStandardOutput = true ,
150+ RedirectStandardError = true ,
151+ RedirectStandardInput = true
152+ } ;
153+ }
154+
98155 private sealed class FakeInstance : IInstance
99156 {
100157 private readonly TaskCompletionSource < bool > ? _startGate ;
@@ -111,7 +168,7 @@ public FakeInstance(
111168
112169 public InstanceConfig Config { get ; }
113170 public InstanceProcess ? Process => null ;
114- public InstanceStatus Status { get ; }
171+ public InstanceStatus Status { get ; private set ; }
115172 public int ServerProcessId => - 1 ;
116173 public TaskCompletionSource < bool > StartEntered { get ; } =
117174 new ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
@@ -127,7 +184,9 @@ public Task<InstanceReport> GetReportAsync(CancellationToken ct = default)
127184 public Task < bool > StartAsync ( int delayToCheck = 500 , CancellationToken ct = default )
128185 {
129186 StartEntered . TrySetResult ( true ) ;
130- return _startGate ? . Task ?? Task . FromResult ( false ) ;
187+ if ( _startGate is not null ) return _startGate . Task ;
188+ Status = InstanceStatus . Running ;
189+ return Task . FromResult ( true ) ;
131190 }
132191
133192 public void Stop ( )
0 commit comments