@@ -242,6 +242,163 @@ public async Task GetServerLatencyAsync_ShouldCancel_WhenTokenIsCancelled()
242242 cts . IsCancellationRequested . ShouldBeTrue ( ) ;
243243 }
244244
245+ // --- GetServerLatencyAsync with Progress ---
246+
247+ [ Fact ]
248+ public async Task GetServerLatencyAsync_WithProgress_ShouldReportProgress_ForEachIteration ( )
249+ {
250+ // Given
251+ using var mockHttp = new MockHttpMessageHandler ( ) ;
252+ mockHttp . When ( "http://testserver.com/latency.txt" )
253+ . Respond ( "text/plain" , "test=test" ) ;
254+
255+ var httpClient = mockHttp . ToHttpClient ( ) ;
256+ var settings = new OoklaSpeedtestSettings
257+ {
258+ LatencyTest = new ( )
259+ {
260+ LatencyTestIterations = 4
261+ }
262+ } ;
263+
264+ var speedtest = new OoklaSpeedtest ( settings , httpClient ) ;
265+ var server = new Server { Url = "http://testserver.com/" , Sponsor = "Sponsor" , Location = "Location" } ;
266+ var progressReports = new List < int > ( ) ;
267+
268+ // When
269+ var result = await speedtest . GetServerLatencyAsync ( server , progress => progressReports . Add ( progress . PercentageComplete ) ) ;
270+
271+ // Then
272+ result . ShouldNotBeNull ( ) ;
273+ result . Server . ShouldBe ( server ) ;
274+ result . Latency . ShouldBeGreaterThanOrEqualTo ( 0 ) ;
275+ progressReports . ShouldBe ( new [ ] { 25 , 50 , 75 , 100 } ) ;
276+ }
277+
278+ [ Fact ]
279+ public async Task GetServerLatencyAsync_ByUrl_WithProgress_ShouldReportProgress_ForEachIteration ( )
280+ {
281+ // Given
282+ using var mockHttp = new MockHttpMessageHandler ( ) ;
283+ mockHttp . When ( "http://testserver.com/latency.txt" )
284+ . Respond ( "text/plain" , "test=test" ) ;
285+
286+ var httpClient = mockHttp . ToHttpClient ( ) ;
287+ var settings = new OoklaSpeedtestSettings
288+ {
289+ LatencyTest = new ( )
290+ {
291+ LatencyTestIterations = 4
292+ }
293+ } ;
294+
295+ var speedtest = new OoklaSpeedtest ( settings , httpClient ) ;
296+ var progressReports = new List < int > ( ) ;
297+
298+ // When
299+ var result = await speedtest . GetServerLatencyAsync ( "http://testserver.com/" , progress => progressReports . Add ( progress . PercentageComplete ) ) ;
300+
301+ // Then
302+ result . ShouldNotBeNull ( ) ;
303+ result . Server . Url . ShouldBe ( "http://testserver.com/" ) ;
304+ result . Latency . ShouldBeGreaterThanOrEqualTo ( 0 ) ;
305+ progressReports . ShouldBe ( new [ ] { 25 , 50 , 75 , 100 } ) ;
306+ }
307+
308+ [ Theory ]
309+ [ InlineData ( 1 , new [ ] { 100 } ) ]
310+ [ InlineData ( 2 , new [ ] { 50 , 100 } ) ]
311+ [ InlineData ( 5 , new [ ] { 20 , 40 , 60 , 80 , 100 } ) ]
312+ [ InlineData ( 10 , new [ ] { 10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 , 90 , 100 } ) ]
313+ public async Task GetServerLatencyAsync_WithProgress_CustomIterations_ShouldReportCorrectPercentages ( int iterations , int [ ] expectedProgress )
314+ {
315+ // Given
316+ using var mockHttp = new MockHttpMessageHandler ( ) ;
317+ mockHttp . When ( "http://testserver.com/latency.txt" )
318+ . Respond ( "text/plain" , "test=test" ) ;
319+
320+ var httpClient = mockHttp . ToHttpClient ( ) ;
321+ var settings = new OoklaSpeedtestSettings
322+ {
323+ LatencyTest = new ( )
324+ {
325+ LatencyTestIterations = iterations
326+ }
327+ } ;
328+
329+ var speedtest = new OoklaSpeedtest ( settings , httpClient ) ;
330+ var server = new Server { Url = "http://testserver.com/" , Sponsor = "Sponsor" , Location = "Location" } ;
331+ var progressReports = new List < int > ( ) ;
332+
333+ // When
334+ var result = await speedtest . GetServerLatencyAsync ( server , progress => progressReports . Add ( progress . PercentageComplete ) ) ;
335+
336+ // Then
337+ result . ShouldNotBeNull ( ) ;
338+ progressReports . ShouldBe ( expectedProgress ) ;
339+ }
340+
341+ [ Fact ]
342+ public async Task GetServerLatencyAsync_WithProgress_ShouldCancel_WhenTokenIsCancelled ( )
343+ {
344+ // Given
345+ using var mockHttp = new MockHttpMessageHandler ( ) ;
346+ mockHttp . When ( "*" ) . Respond ( async _ =>
347+ {
348+ // Simulate slow response.
349+ await Task . Delay ( 1000 ) ;
350+ return new HttpResponseMessage ( HttpStatusCode . OK ) ;
351+ } ) ;
352+
353+ var httpClient = mockHttp . ToHttpClient ( ) ;
354+ var speedtest = new OoklaSpeedtest ( httpClientOverride : httpClient ) ;
355+ var server = new Server { Url = "http://testserver.com/" , Sponsor = "Sponsor" , Location = "Location" } ;
356+ var progressReports = new List < int > ( ) ;
357+
358+ using var cts = new CancellationTokenSource ( ) ;
359+ cts . CancelAfter ( 200 ) ;
360+
361+ // When
362+ var exception = await Record . ExceptionAsync ( ( ) => speedtest . GetServerLatencyAsync ( server , progress => progressReports . Add ( progress . PercentageComplete ) , cts . Token ) ) ;
363+
364+ // Then
365+ exception . ShouldNotBeNull ( ) ;
366+ exception . ShouldBeAssignableTo < OperationCanceledException > ( ) ;
367+ cts . IsCancellationRequested . ShouldBeTrue ( ) ;
368+ }
369+
370+ [ Fact ]
371+ public async Task GetServerLatencyAsync_WithProgress_ShouldPropagateException_WhenProgressCallbackThrows ( )
372+ {
373+ // Given
374+ using var mockHttp = new MockHttpMessageHandler ( ) ;
375+ mockHttp . When ( "http://testserver.com/latency.txt" )
376+ . Respond ( "text/plain" , "test=test" ) ;
377+
378+ var httpClient = mockHttp . ToHttpClient ( ) ;
379+ var settings = new OoklaSpeedtestSettings
380+ {
381+ LatencyTest = new ( )
382+ {
383+ LatencyTestIterations = 4
384+ }
385+ } ;
386+
387+ var speedtest = new OoklaSpeedtest ( settings , httpClient ) ;
388+ var server = new Server { Url = "http://testserver.com/" , Sponsor = "Sponsor" , Location = "Location" } ;
389+
390+ // When
391+ var exception = await Record . ExceptionAsync ( ( ) => speedtest . GetServerLatencyAsync ( server , progress =>
392+ {
393+ throw new InvalidOperationException ( "Progress callback failed" ) ;
394+ } ) ) ;
395+
396+ // Then
397+ exception . ShouldNotBeNull ( ) ;
398+ exception . ShouldBeOfType < InvalidOperationException > ( ) ;
399+ exception . Message . ShouldBe ( "Progress callback failed" ) ;
400+ }
401+
245402 // --- GetFastestServerByLatencyAsync ---
246403
247404 [ Fact ]
0 commit comments