Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

testutils: add require library #9

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions crencoding/var_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ import (
"math"
"math/rand/v2"
"testing"

"github.com/cockroachdb/crlib/testutils/require"
)

// TestUvarintLen tests UvarintLen32 and UvarintLen64.
func TestUvarintLen(t *testing.T) {
check := func(n uint64) {
t := require.WithMsgf(t, "n=%d", n)
res64 := UvarintLen64(n)
if expected := len(binary.AppendUvarint(nil, n)); res64 != expected {
t.Fatalf("invalid result for %d: %d instead of %d", n, res64, expected)
}
require.Equal(t, res64, len(binary.AppendUvarint(nil, n)))

res32 := UvarintLen32(uint32(n))
if expected := len(binary.AppendUvarint(nil, uint64(uint32(n)))); res32 != expected {
t.Fatalf("invalid result for %d: %d instead of %d", n, res32, expected)
}
require.Equal(t, res32, len(binary.AppendUvarint(nil, uint64(uint32(n)))))
}
check(0)
check(math.MaxUint64)
Expand Down
53 changes: 24 additions & 29 deletions crstrings/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"fmt"
"strings"
"testing"

"github.com/cockroachdb/crlib/testutils/require"
)

type num int
Expand All @@ -28,56 +30,49 @@ func (n num) String() string {

func TestJoinStringers(t *testing.T) {
nums := []num{0, 1, 2, 3}
expect(t, "", JoinStringers(", ", nums[:0]...))
expect(t, "000", JoinStringers(", ", nums[0]))
expect(t, "000, 001", JoinStringers(", ", nums[0], nums[1]))
expect(t, "000, 001, 002, 003", JoinStringers(", ", nums...))
require.Equal(t, "", JoinStringers(", ", nums[:0]...))
require.Equal(t, "000", JoinStringers(", ", nums[0]))
require.Equal(t, "000, 001", JoinStringers(", ", nums[0], nums[1]))
require.Equal(t, "000, 001, 002, 003", JoinStringers(", ", nums...))
}

func TestMapAndJoin(t *testing.T) {
nums := []int{0, 1, 2, 3}
fn := func(n int) string {
return fmt.Sprintf("%d", n)
}
expect(t, "", MapAndJoin(fn, ", ", nums[:0]...))
expect(t, "0", MapAndJoin(fn, ", ", nums[0]))
expect(t, "0, 1", MapAndJoin(fn, ", ", nums[0], nums[1]))
expect(t, "0, 1, 2, 3", MapAndJoin(fn, ", ", nums...))
}

func expect(t *testing.T, expected, actual string) {
t.Helper()
if actual != expected {
t.Errorf("expected %q got %q", expected, actual)
}
require.Equal(t, "", MapAndJoin(fn, ", ", nums[:0]...))
require.Equal(t, "0", MapAndJoin(fn, ", ", nums[0]))
require.Equal(t, "0, 1", MapAndJoin(fn, ", ", nums[0], nums[1]))
require.Equal(t, "0, 1, 2, 3", MapAndJoin(fn, ", ", nums...))
}

func TestIf(t *testing.T) {
expect(t, "", If(false, "true"))
expect(t, "true", If(true, "true"))
require.Equal(t, "", If(false, "true"))
require.Equal(t, "true", If(true, "true"))
}

func TestIfElse(t *testing.T) {
expect(t, "false", IfElse(false, "true", "false"))
expect(t, "true", IfElse(true, "true", "false"))
require.Equal(t, "false", IfElse(false, "true", "false"))
require.Equal(t, "true", IfElse(true, "true", "false"))
}

func TestWithSep(t *testing.T) {
expect(t, "a,b", WithSep("a", ",", "b"))
expect(t, "a", WithSep("a", ",", ""))
expect(t, "b", WithSep("", ",", "b"))
require.Equal(t, "a,b", WithSep("a", ",", "b"))
require.Equal(t, "a", WithSep("a", ",", ""))
require.Equal(t, "b", WithSep("", ",", "b"))
}

func TestFilterEmpty(t *testing.T) {
s := []string{"a", "", "b", "", "c", ""}
expect(t, "a,b,c", strings.Join(FilterEmpty(s), ","))
require.Equal(t, "a,b,c", strings.Join(FilterEmpty(s), ","))
}

func TestLines(t *testing.T) {
expect(t, `["a" "b" "c"]`, fmt.Sprintf("%q", Lines("a\nb\nc")))
expect(t, `["a" "b" "c"]`, fmt.Sprintf("%q", Lines("a\nb\nc\n")))
expect(t, `["a" "b" "c" ""]`, fmt.Sprintf("%q", Lines("a\nb\nc\n\n")))
expect(t, `["" "a" "b" "c"]`, fmt.Sprintf("%q", Lines("\na\nb\nc\n")))
expect(t, `[]`, fmt.Sprintf("%q", Lines("")))
expect(t, `[]`, fmt.Sprintf("%q", Lines("\n")))
require.Equal(t, `["a" "b" "c"]`, fmt.Sprintf("%q", Lines("a\nb\nc")))
require.Equal(t, `["a" "b" "c"]`, fmt.Sprintf("%q", Lines("a\nb\nc\n")))
require.Equal(t, `["a" "b" "c" ""]`, fmt.Sprintf("%q", Lines("a\nb\nc\n\n")))
require.Equal(t, `["" "a" "b" "c"]`, fmt.Sprintf("%q", Lines("\na\nb\nc\n")))
require.Equal(t, `[]`, fmt.Sprintf("%q", Lines("")))
require.Equal(t, `[]`, fmt.Sprintf("%q", Lines("\n")))
}
11 changes: 5 additions & 6 deletions crtime/monotonic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@ package crtime
import (
"testing"
"time"

"github.com/cockroachdb/crlib/testutils/require"
)

func TestMono(t *testing.T) {
a := NowMono()
time.Sleep(10 * time.Millisecond)
b := NowMono()
if delta := b.Sub(a); delta < 9*time.Millisecond {
t.Errorf("expected 10+ms, got %s", delta)
}
require.GE(t, b.Sub(a), 9*time.Millisecond)
c := MonoFromTime(time.Now())
d := NowMono()
if c < b || c > d {
t.Errorf("expected %d <= %d <= %d", b, c, d)
}
require.LE(t, b, c)
require.LE(t, c, d)
}
35 changes: 15 additions & 20 deletions fifo/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,36 @@ package fifo
import (
"math/rand"
"testing"

"github.com/cockroachdb/crlib/testutils/require"
)

var pool = MakeQueueBackingPool[int]()

func TestQueue(t *testing.T) {
q := MakeQueue[int](&pool)
requireEqual(t, q.PeekFront(), nil)
requireEqual(t, q.Len(), 0)
require.Equal(t, q.PeekFront(), nil)
require.Equal(t, q.Len(), 0)
q.PushBack(1)
q.PushBack(2)
q.PushBack(3)
requireEqual(t, q.Len(), 3)
requireEqual(t, *q.PeekFront(), 1)
require.Equal(t, q.Len(), 3)
require.Equal(t, *q.PeekFront(), 1)
q.PopFront()
requireEqual(t, *q.PeekFront(), 2)
require.Equal(t, *q.PeekFront(), 2)
q.PopFront()
requireEqual(t, *q.PeekFront(), 3)
require.Equal(t, *q.PeekFront(), 3)
q.PopFront()
requireEqual(t, q.PeekFront(), nil)
require.Equal(t, q.PeekFront(), nil)

for i := 1; i <= 1000; i++ {
q.PushBack(i)
requireEqual(t, q.Len(), i)
require.Equal(t, q.Len(), i)
}
for i := 1; i <= 1000; i++ {
requireEqual(t, *q.PeekFront(), i)
require.Equal(t, *q.PeekFront(), i)
q.PopFront()
requireEqual(t, q.Len(), 1000-i)
require.Equal(t, q.Len(), 1000-i)
}
}

Expand All @@ -55,20 +57,13 @@ func TestQueueRand(t *testing.T) {
for n := rand.Intn(100); n > 0; n-- {
r++
q.PushBack(r)
requireEqual(t, q.Len(), r-l)
require.Equal(t, q.Len(), r-l)
}
for n := rand.Intn(q.Len() + 1); n > 0; n-- {
l++
requireEqual(t, *q.PeekFront(), l)
require.Equal(t, *q.PeekFront(), l)
q.PopFront()
requireEqual(t, q.Len(), r-l)
require.Equal(t, q.Len(), r-l)
}
}
}

func requireEqual[T comparable](t *testing.T, actual, expected T) {
t.Helper()
if actual != expected {
t.Fatalf("expected %v, but found %v", expected, actual)
}
}
80 changes: 31 additions & 49 deletions fifo/semaphore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ import (
"sync"
"testing"
"time"

"github.com/cockroachdb/crlib/testutils/require"
)

func TestSemaphoreAPI(t *testing.T) {
s := NewSemaphore(10)
requireEqual(t, s.TryAcquire(5), true)
requireEqual(t, s.TryAcquire(10), false)
requireEqual(t, s.Acquire(context.Background(), 20), ErrRequestExceedsCapacity)
requireEqual(t, "capacity: 10, outstanding: 5, num-had-to-wait: 0", s.Stats().String())
require.Equal(t, s.TryAcquire(5), true)
require.Equal(t, s.TryAcquire(10), false)
require.Equal(t, s.Acquire(context.Background(), 20), ErrRequestExceedsCapacity)
require.Equal(t, "capacity: 10, outstanding: 5, num-had-to-wait: 0", s.Stats().String())

ch := make(chan struct{}, 10)
go func() {
Expand All @@ -46,15 +48,15 @@ func TestSemaphoreAPI(t *testing.T) {
}
ch <- struct{}{}
}()
assertNoRecv(t, ch)
require.NoRecv(t, ch)
s.Release(5)
assertRecv(t, ch)
assertRecv(t, ch)
assertNoRecv(t, ch)
require.Recv(t, ch)
require.Recv(t, ch)
require.NoRecv(t, ch)
s.Release(1)
assertNoRecv(t, ch)
require.NoRecv(t, ch)
s.Release(8)
assertRecv(t, ch)
require.Recv(t, ch)

// Test UpdateCapacity.
go func() {
Expand All @@ -66,16 +68,16 @@ func TestSemaphoreAPI(t *testing.T) {
t.Error(err)
}
ch <- struct{}{}
requireEqual(t, s.Acquire(context.Background(), 5), ErrRequestExceedsCapacity)
require.Equal(t, s.Acquire(context.Background(), 5), ErrRequestExceedsCapacity)
ch <- struct{}{}
}()
assertNoRecv(t, ch)
require.NoRecv(t, ch)
s.UpdateCapacity(15)
assertRecv(t, ch)
assertRecv(t, ch)
assertNoRecv(t, ch)
require.Recv(t, ch)
require.Recv(t, ch)
require.NoRecv(t, ch)
s.UpdateCapacity(2)
assertRecv(t, ch)
require.Recv(t, ch)
}

// TestSemaphoreBasic is a test with multiple goroutines acquiring a unit and
Expand Down Expand Up @@ -103,7 +105,7 @@ func TestSemaphoreBasic(t *testing.T) {
}

for i := 0; i < numGoroutines; i++ {
if err := assertRecv(t, resCh); err != nil {
if err := require.Recv(t, resCh); err != nil {
t.Fatal(err)
}
}
Expand Down Expand Up @@ -132,14 +134,14 @@ func TestSemaphoreContextCancellation(t *testing.T) {

cancel()

err := assertRecv(t, errCh)
err := require.Recv(t, errCh)
if !errors.Is(err, context.Canceled) {
t.Fatalf("expected context cancellation error, got %v", err)
}

stats := s.Stats()
requireEqual(t, stats.Capacity, 1)
requireEqual(t, stats.Outstanding, 1)
require.Equal(t, stats.Capacity, 1)
require.Equal(t, stats.Outstanding, 1)
}

// TestSemaphoreCanceledAcquisitions tests the behavior where we enqueue
Expand All @@ -163,7 +165,7 @@ func TestSemaphoreCanceledAcquisitions(t *testing.T) {
}

for i := 0; i < numGoroutines; i++ {
if err := assertRecv(t, errCh); !errors.Is(err, context.Canceled) {
if err := require.Recv(t, errCh); !errors.Is(err, context.Canceled) {
t.Fatalf("expected context cancellation error, got %v", err)
}
}
Expand All @@ -173,7 +175,7 @@ func TestSemaphoreCanceledAcquisitions(t *testing.T) {
errCh <- s.Acquire(context.Background(), 1)
}()

if err := assertRecv(t, errCh); err != nil {
if err := require.Recv(t, errCh); err != nil {
t.Fatal(err)
}
}
Expand Down Expand Up @@ -206,25 +208,25 @@ func TestSemaphoreNumHadToWait(t *testing.T) {
}
}
// Initially s should have no waiters.
requireEqual(t, s.Stats().NumHadToWait, 0)
require.Equal(t, s.Stats().NumHadToWait, 0)
if err := s.Acquire(ctx, 1); err != nil {
t.Fatal(err)
}
// Still no waiters.
requireEqual(t, s.Stats().NumHadToWait, 0)
require.Equal(t, s.Stats().NumHadToWait, 0)
for i := 0; i < 10; i++ {
go doAcquire(ctx)
}
assertNumWaitersSoon(10)
s.Release(1)
assertRecv(t, doneCh)
require.Recv(t, doneCh)
go doAcquire(ctx)
assertNumWaitersSoon(11)
for i := 0; i < 10; i++ {
s.Release(1)
assertRecv(t, doneCh)
require.Recv(t, doneCh)
}
requireEqual(t, s.Stats().NumHadToWait, 11)
require.Equal(t, s.Stats().NumHadToWait, 11)
}

func TestConcurrentUpdatesAndAcquisitions(t *testing.T) {
Expand Down Expand Up @@ -258,26 +260,6 @@ func TestConcurrentUpdatesAndAcquisitions(t *testing.T) {
wg.Wait()
s.UpdateCapacity(maxCap)
stats := s.Stats()
requireEqual(t, stats.Capacity, 100)
requireEqual(t, stats.Outstanding, 0)
}

func assertRecv[T any](t *testing.T, ch chan T) T {
t.Helper()
select {
case v := <-ch:
return v
case <-time.After(time.Second):
t.Fatal("did not receive notification")
panic("unreachable")
}
}

func assertNoRecv[T any](t *testing.T, ch chan T) {
t.Helper()
select {
case <-ch:
t.Fatal("received unexpected notification")
case <-time.After(10 * time.Millisecond):
}
require.Equal(t, stats.Capacity, 100)
require.Equal(t, stats.Outstanding, 0)
}
Loading
Loading