tailscale/util/race/race_test.go

100 lines
2.0 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package race
import (
"context"
"errors"
"testing"
"time"
"tailscale.com/tstest"
)
func TestRaceSuccess1(t *testing.T) {
tstest.ResourceCheck(t)
const want = "success"
rh := New[string](
10*time.Second,
func(context.Context) (string, error) {
return want, nil
}, func(context.Context) (string, error) {
t.Fatal("should not be called")
return "", nil
})
res, err := rh.Start(context.Background())
if err != nil {
t.Fatal(err)
}
if res != want {
t.Errorf("got res=%q, want %q", res, want)
}
}
func TestRaceRetry(t *testing.T) {
tstest.ResourceCheck(t)
const want = "fallback"
rh := New[string](
10*time.Second,
func(context.Context) (string, error) {
return "", errors.New("some error")
}, func(context.Context) (string, error) {
return want, nil
})
res, err := rh.Start(context.Background())
if err != nil {
t.Fatal(err)
}
if res != want {
t.Errorf("got res=%q, want %q", res, want)
}
}
func TestRaceTimeout(t *testing.T) {
tstest.ResourceCheck(t)
const want = "fallback"
rh := New[string](
100*time.Millisecond,
func(ctx context.Context) (string, error) {
// Block forever
<-ctx.Done()
return "", ctx.Err()
}, func(context.Context) (string, error) {
return want, nil
})
res, err := rh.Start(context.Background())
if err != nil {
t.Fatal(err)
}
if res != want {
t.Errorf("got res=%q, want %q", res, want)
}
}
func TestRaceError(t *testing.T) {
tstest.ResourceCheck(t)
err1 := errors.New("error 1")
err2 := errors.New("error 2")
rh := New[string](
100*time.Millisecond,
func(ctx context.Context) (string, error) {
return "", err1
}, func(context.Context) (string, error) {
return "", err2
})
_, err := rh.Start(context.Background())
if !errors.Is(err, err1) {
t.Errorf("wanted err to contain err1; got %v", err)
}
if !errors.Is(err, err2) {
t.Errorf("wanted err to contain err2; got %v", err)
}
}