storj.io/uplink@v1.13.0/private/storage/streams/buffer/cursor_test.go (about) 1 // Copyright (C) 2023 Storj Labs, Inc. 2 // See LICENSE for copying information. 3 4 package buffer 5 6 import ( 7 "runtime" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 "github.com/zeebo/errs" 12 ) 13 14 func TestCursor(t *testing.T) { 15 type result struct { 16 n int64 17 ok bool 18 err error 19 } 20 wrap := func(n int64, ok bool, err error) result { return result{n, ok, err} } 21 canceled := errs.New("canceled") 22 23 t.Run("ReadBlocksUntilFinished", func(t *testing.T) { 24 done := make(chan result) 25 cursor := NewCursor(10) 26 go func() { done <- wrap(cursor.WaitRead(1)) }() 27 runtime.Gosched() // attempt to cause the goroutine to run 28 cursor.DoneWriting(nil) 29 require.Equal(t, result{0, false, nil}, <-done) 30 }) 31 32 t.Run("ReadBlocksUntilFinished_With_Error", func(t *testing.T) { 33 done := make(chan result) 34 cursor := NewCursor(10) 35 go func() { done <- wrap(cursor.WaitRead(1)) }() 36 runtime.Gosched() // attempt to cause the goroutine to run 37 cursor.DoneWriting(canceled) 38 require.Equal(t, result{0, false, canceled}, <-done) 39 }) 40 41 t.Run("WriteBlocksUntilFinished_With_Error", func(t *testing.T) { 42 done := make(chan result) 43 cursor := NewCursor(10) 44 cursor.WroteTo(10) 45 go func() { done <- wrap(cursor.WaitWrite(11)) }() 46 runtime.Gosched() // attempt to cause the goroutine to run 47 cursor.DoneReading(canceled) 48 require.Equal(t, result{0, false, canceled}, <-done) 49 }) 50 51 t.Run("WriteBlocksUntilFinished", func(t *testing.T) { 52 done := make(chan result) 53 cursor := NewCursor(10) 54 cursor.WroteTo(10) 55 go func() { done <- wrap(cursor.WaitWrite(11)) }() 56 runtime.Gosched() // attempt to cause the goroutine to run 57 cursor.DoneReading(nil) 58 require.Equal(t, result{10, false, nil}, <-done) 59 }) 60 61 t.Run("ReadAllWritten", func(t *testing.T) { 62 cursor := NewCursor(10) 63 cursor.WroteTo(1) 64 cursor.DoneWriting(nil) 65 require.Equal(t, result{1, false, nil}, wrap(cursor.WaitRead(1))) 66 require.Equal(t, result{1, false, nil}, wrap(cursor.WaitRead(2))) 67 }) 68 69 t.Run("WriteUnblocksRead", func(t *testing.T) { 70 done := make(chan result) 71 cursor := NewCursor(10) 72 go func() { done <- wrap(cursor.WaitRead(1)) }() 73 runtime.Gosched() // attempt to cause the goroutine to run 74 cursor.WroteTo(1) 75 require.Equal(t, result{1, true, nil}, <-done) 76 }) 77 78 t.Run("ReadUnblocksWrite", func(t *testing.T) { 79 done := make(chan result) 80 cursor := NewCursor(10) 81 cursor.WroteTo(10) 82 go func() { done <- wrap(cursor.WaitWrite(11)) }() 83 runtime.Gosched() // attempt to cause the goroutine to run 84 cursor.ReadTo(1) 85 require.Equal(t, result{11, true, nil}, <-done) 86 }) 87 } 88 89 func BenchmarkNewCursor(b *testing.B) { 90 b.ReportAllocs() 91 92 var c *Cursor 93 for i := 0; i < b.N; i++ { 94 c = NewCursor(1024) 95 } 96 runtime.KeepAlive(c) 97 }