@@ -181,4 +181,77 @@ public async Task IsNotValid_If_ExitOnProcess_Not_Running()
181181 Assert . IsFalse ( validateOptionsResult . IsValid ) ;
182182 Assert . IsTrue ( validateOptionsResult . ErrorMessage . StartsWith ( $ "Invalid PID '{ pid } '", StringComparison . OrdinalIgnoreCase ) ) ;
183183 }
184+
185+ [ TestMethod ]
186+ [ DataRow ( "1.5s" ) ]
187+ [ DataRow ( "2.0m" ) ]
188+ [ DataRow ( "0.5h" ) ]
189+ [ DataRow ( "10s" ) ]
190+ [ DataRow ( "30m" ) ]
191+ [ DataRow ( "1h" ) ]
192+ public async Task IsValid_If_Timeout_Has_CorrectFormat_InvariantCulture ( string timeout )
193+ {
194+ var provider = new PlatformCommandLineProvider ( ) ;
195+ CommandLineOption option = provider . GetCommandLineOptions ( ) . First ( x => x . Name == PlatformCommandLineProvider . TimeoutOptionKey ) ;
196+
197+ // Save current culture
198+ CultureInfo originalCulture = CultureInfo . CurrentCulture ;
199+ try
200+ {
201+ // Test with various cultures to ensure invariant parsing works
202+ foreach ( string cultureName in new [ ] { "en-US" , "de-DE" , "fr-FR" } )
203+ {
204+ CultureInfo . CurrentCulture = CultureInfo . GetCultureInfo ( cultureName ) ;
205+ ValidationResult validateOptionsResult = await provider . ValidateOptionArgumentsAsync ( option , [ timeout ] ) ;
206+ Assert . IsTrue ( validateOptionsResult . IsValid , $ "Failed with culture { cultureName } and timeout { timeout } ") ;
207+ Assert . IsTrue ( string . IsNullOrEmpty ( validateOptionsResult . ErrorMessage ) ) ;
208+ }
209+ }
210+ finally
211+ {
212+ // Restore original culture
213+ CultureInfo . CurrentCulture = originalCulture ;
214+ }
215+ }
216+
217+ [ TestMethod ]
218+ [ DataRow ( "1,5s" ) ] // German decimal separator
219+ [ DataRow ( "invalid" ) ]
220+ [ DataRow ( "1.5" ) ] // Missing unit
221+ [ DataRow ( "abc.5s" ) ]
222+ public async Task IsInvalid_If_Timeout_Has_IncorrectFormat ( string timeout )
223+ {
224+ var provider = new PlatformCommandLineProvider ( ) ;
225+ CommandLineOption option = provider . GetCommandLineOptions ( ) . First ( x => x . Name == PlatformCommandLineProvider . TimeoutOptionKey ) ;
226+
227+ ValidationResult validateOptionsResult = await provider . ValidateOptionArgumentsAsync ( option , [ timeout ] ) ;
228+ Assert . IsFalse ( validateOptionsResult . IsValid ) ;
229+ Assert . AreEqual ( PlatformResources . PlatformCommandLineTimeoutArgumentErrorMessage , validateOptionsResult . ErrorMessage ) ;
230+ }
231+
232+ [ TestMethod ]
233+ public async Task Timeout_Parsing_Uses_InvariantCulture_NotCurrentCulture ( )
234+ {
235+ var provider = new PlatformCommandLineProvider ( ) ;
236+ CommandLineOption option = provider . GetCommandLineOptions ( ) . First ( x => x . Name == PlatformCommandLineProvider . TimeoutOptionKey ) ;
237+
238+ // Save current culture
239+ CultureInfo originalCulture = CultureInfo . CurrentCulture ;
240+ try
241+ {
242+ // Set culture to German where decimal separator is comma
243+ CultureInfo . CurrentCulture = CultureInfo . GetCultureInfo ( "de-DE" ) ;
244+ // This should work because we use invariant culture (period as decimal separator)
245+ ValidationResult validResult = await provider . ValidateOptionArgumentsAsync ( option , [ "1.5s" ] ) ;
246+ Assert . IsTrue ( validResult . IsValid , "1.5s should be valid when using invariant culture" ) ;
247+ // This should fail because comma is not valid in invariant culture
248+ ValidationResult invalidResult = await provider . ValidateOptionArgumentsAsync ( option , [ "1,5s" ] ) ;
249+ Assert . IsFalse ( invalidResult . IsValid , "1,5s should be invalid when using invariant culture" ) ;
250+ }
251+ finally
252+ {
253+ // Restore original culture
254+ CultureInfo . CurrentCulture = originalCulture ;
255+ }
256+ }
184257}
0 commit comments