func NewClient(clientName, clientVersion string) *Client {
	results := map[spec.TestKind]*LatestMeasurements{
		spec.TestDownload: {},
		spec.TestUpload:   {},
	}
	return &Client{
		ClientName:    clientName,
		ClientVersion: clientVersion,
		connect: func(
			dialer websocket.Dialer, ctx context.Context, urlStr string,
			requestHeader http.Header) (*websocket.Conn, *http.Response, error,
		) {
			return dialer.DialContext(ctx, urlStr, requestHeader)
		},
		Dialer: websocket.Dialer{
			HandshakeTimeout: DefaultWebSocketHandshakeTimeout,
		},
		download: download.Run,
		Locate: locate.NewClient(
			makeUserAgent(clientName, clientVersion),
		),
		tIndex:  map[string]int{},
		upload:  upload.Run,
		Scheme:  "wss",
		results: results,
	}
}
NewClient creates a new client instance identified by the specified
clientName and clientVersion. M-Lab services may reject requests coming
from clients that do not identify themselves properly.
package ndt7
import (
	"context"
	"errors"
	"net/http"
	"net/url"
	"runtime"
	"time"
	"github.com/gorilla/websocket"
	"github.com/m-lab/locate/api/locate"
	v2 "github.com/m-lab/locate/api/v2"
	"github.com/m-lab/ndt7-client-go/internal/download"
	"github.com/m-lab/ndt7-client-go/internal/params"
	"github.com/m-lab/ndt7-client-go/internal/upload"
	"github.com/m-lab/ndt7-client-go/internal/websocketx"
	"github.com/m-lab/ndt7-client-go/spec"
)
const (
	libraryName = "ndt7-client-go"
	libraryVersion = "0.5.0"
)
var (
	ErrServiceUnsupported = errors.New("unsupported service url")
	ErrNoTargets = errors.New("no targets available")
)
type Locator interface {
	Nearest(ctx context.Context, service string) ([]v2.Target, error)
}
type connectFn = func(
	dialer websocket.Dialer,
	ctx context.Context, urlStr string,
	requestHeader http.Header,
) (*websocket.Conn, *http.Response, error)
type testFn = func(
	ctx context.Context, conn websocketx.Conn, ch chan<- spec.Measurement,
) error
const DefaultWebSocketHandshakeTimeout = 7 * time.Second
type LatestMeasurements struct {
	Server         spec.Measurement
	Client         spec.Measurement
	ConnectionInfo *spec.ConnectionInfo
}
type Client struct {
	ClientName string
	ClientVersion string
	Dialer websocket.Dialer
	FQDN string
	Server string
	ServiceURL *url.URL
	Locate Locator
	Scheme string
	connect connectFn
	download testFn
	upload testFn
	targets []v2.Target
	tIndex  map[string]int
	results map[spec.TestKind]*LatestMeasurements
}
func makeUserAgent(clientName, clientVersion string) string {
	return clientName + "/" + clientVersion + " " + libraryName + "/" + libraryVersion
}