master
1package speedtest
2
3import (
4 "context"
5 "fmt"
6 "time"
7
8 "github.com/kahnwong/swissknife/configs/color"
9 "github.com/showwin/speedtest-go/speedtest"
10)
11
12func SpeedTest() error {
13 // ref: <https://github.com/showwin/speedtest-go#api-usage>
14 var speedtestClient = speedtest.New()
15 serverList, _ := speedtestClient.FetchServers()
16 targets, _ := serverList.FindServer([]int{})
17
18 // print test server location
19 fmt.Printf("%s: %s\n", color.Green("Server"), targets[0].Name)
20
21 // start tests
22 var s *speedtest.Server
23 tests := make(chan struct{})
24 ctx, cancel := context.WithCancel(context.Background())
25
26 // Store error from goroutine
27 errChan := make(chan error, 1)
28
29 // -- background progress report -- //
30 go func(ctx context.Context) {
31 for {
32 select {
33 case <-ctx.Done():
34 tests <- struct{}{}
35 return
36 default:
37 fmt.Print(".") // for progress report
38 }
39
40 time.Sleep(500 * time.Millisecond)
41 }
42 }(ctx)
43
44 // -- actual tests -- //
45 go func() {
46 for _, s = range targets {
47 fmt.Print("Pinging")
48 err := s.PingTest(nil)
49 if err != nil {
50 errChan <- fmt.Errorf("error pinging server: %w", err)
51 cancel()
52 return
53 }
54 fmt.Printf("\033[2K\r") // clear line
55
56 fmt.Print("Downloading")
57 err = s.DownloadTest()
58 if err != nil {
59 errChan <- fmt.Errorf("error testing download speed: %w", err)
60 cancel()
61 return
62 }
63 fmt.Printf("\033[2K\r") // clear line
64
65 fmt.Print("Uploading")
66 err = s.UploadTest()
67 if err != nil {
68 errChan <- fmt.Errorf("error testing upload speed: %w", err)
69 cancel()
70 return
71 }
72 fmt.Printf("\033[2K\r") // clear line
73 }
74
75 errChan <- nil
76 cancel()
77 }()
78 <-tests
79
80 // Check for errors
81 if err := <-errChan; err != nil {
82 return err
83 }
84
85 // print results
86 fmt.Print(
87 fmt.Sprintf("%s: %s\n", color.Green("Latency"), s.Latency.Truncate(time.Millisecond)) +
88 fmt.Sprintf("%s: %s\n", color.Green("Download"), s.DLSpeed) +
89 fmt.Sprintf("%s: %s\n", color.Green("Upload"), s.ULSpeed),
90 )
91
92 s.Context.Reset()
93 return nil
94}