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}