2023-01-27 13:37:20 -08:00
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
2021-07-15 14:43:13 -04:00
package speedtest
import (
2025-09-29 13:57:04 -07:00
"flag"
2021-07-15 14:43:13 -04:00
"net"
"testing"
2022-09-14 17:52:47 -07:00
"time"
2025-09-29 13:57:04 -07:00
"tailscale.com/cmd/testwrapper/flakytest"
2021-07-15 14:43:13 -04:00
)
2025-09-29 13:57:04 -07:00
var manualTest = flag . Bool ( "do-speedtest" , false , "if true, run the speedtest TestDownload test. Otherwise skip it because it's slow and flaky; see https://github.com/tailscale/tailscale/issues/17338" )
2021-07-15 14:43:13 -04:00
func TestDownload ( t * testing . T ) {
2025-09-29 13:57:04 -07:00
if ! * manualTest {
t . Skip ( "skipping slow test without --do-speedtest" )
}
flakytest . Mark ( t , "https://github.com/tailscale/tailscale/issues/17338" )
2021-07-15 14:43:13 -04:00
// start a listener and find the port where the server will be listening.
2025-11-17 18:13:44 +00:00
ln , err := net . Listen ( "tcp" , ":0" )
2021-07-15 14:43:13 -04:00
if err != nil {
t . Fatal ( err )
}
2025-11-17 18:13:44 +00:00
t . Cleanup ( func ( ) { ln . Close ( ) } )
2021-07-15 14:43:13 -04:00
2025-11-17 18:13:44 +00:00
serverIP := ln . Addr ( ) . String ( )
2021-07-15 14:43:13 -04:00
t . Log ( "server IP found:" , serverIP )
type state struct {
err error
}
2022-09-14 17:52:47 -07:00
displayResult := func ( t * testing . T , r Result , start time . Time ) {
2021-07-15 14:43:13 -04:00
t . Helper ( )
2022-09-14 17:52:47 -07:00
t . Logf ( "{ Megabytes: %.2f, Start: %.1f, End: %.1f, Total: %t }" , r . MegaBytes ( ) , r . IntervalStart . Sub ( start ) . Seconds ( ) , r . IntervalEnd . Sub ( start ) . Seconds ( ) , r . Total )
2021-07-15 14:43:13 -04:00
}
stateChan := make ( chan state , 1 )
go func ( ) {
2025-11-17 18:13:44 +00:00
err := Serve ( ln )
2021-07-15 14:43:13 -04:00
stateChan <- state { err : err }
} ( )
// ensure that the test returns an appropriate number of Result structs
expectedLen := int ( DefaultDuration . Seconds ( ) ) + 1
t . Run ( "download test" , func ( t * testing . T ) {
// conduct a download test
results , err := RunClient ( Download , DefaultDuration , serverIP )
if err != nil {
t . Fatal ( "download test failed:" , err )
}
if len ( results ) < expectedLen {
t . Fatalf ( "download results: expected length: %d, actual length: %d" , expectedLen , len ( results ) )
}
2022-09-14 17:52:47 -07:00
start := results [ 0 ] . IntervalStart
2021-07-15 14:43:13 -04:00
for _ , result := range results {
2022-09-14 17:52:47 -07:00
displayResult ( t , result , start )
2021-07-15 14:43:13 -04:00
}
} )
t . Run ( "upload test" , func ( t * testing . T ) {
// conduct an upload test
results , err := RunClient ( Upload , DefaultDuration , serverIP )
if err != nil {
t . Fatal ( "upload test failed:" , err )
}
if len ( results ) < expectedLen {
t . Fatalf ( "upload results: expected length: %d, actual length: %d" , expectedLen , len ( results ) )
}
2022-09-14 17:52:47 -07:00
start := results [ 0 ] . IntervalStart
2021-07-15 14:43:13 -04:00
for _ , result := range results {
2022-09-14 17:52:47 -07:00
displayResult ( t , result , start )
2021-07-15 14:43:13 -04:00
}
} )
// causes the server goroutine to finish
2025-11-17 18:13:44 +00:00
ln . Close ( )
2021-07-15 14:43:13 -04:00
testState := <- stateChan
if testState . err != nil {
t . Error ( "server error:" , err )
}
}