github.com/getlantern/eventual@v1.0.0/eventual_test.go (about) 1 package eventual 2 3 import ( 4 "sync" 5 "sync/atomic" 6 "testing" 7 "time" 8 9 "github.com/getlantern/grtrack" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 const ( 14 concurrency = 200 15 ) 16 17 func TestSingle(t *testing.T) { 18 goroutines := grtrack.Start() 19 v := NewValue() 20 go func() { 21 time.Sleep(20 * time.Millisecond) 22 v.Set("hi") 23 }() 24 25 r, ok := v.Get(0) 26 assert.False(t, ok, "Get with no timeout should have failed") 27 28 r, ok = v.Get(10 * time.Millisecond) 29 assert.False(t, ok, "Get with short timeout should have timed out") 30 31 r, ok = v.Get(-1) 32 assert.True(t, ok, "Get with really long timeout should have succeeded") 33 assert.Equal(t, "hi", r, "Wrong result") 34 35 // Set a different value 36 v.Set("bye") 37 r, ok = v.Get(0) 38 assert.True(t, ok, "Subsequent get with no timeout should have succeeded") 39 assert.Equal(t, "bye", r, "Value should have changed") 40 41 goroutines.CheckAfter(t, 50*time.Millisecond) 42 } 43 44 func TestNoSet(t *testing.T) { 45 goroutines := grtrack.Start() 46 v := NewValue() 47 48 _, ok := v.Get(10 * time.Millisecond) 49 assert.False(t, ok, "Get before setting value should not be okay") 50 51 goroutines.CheckAfter(t, 50*time.Millisecond) 52 } 53 54 func TestCancelImmediate(t *testing.T) { 55 v := NewValue() 56 go func() { 57 time.Sleep(10 * time.Millisecond) 58 v.Cancel() 59 }() 60 61 _, ok := v.Get(200 * time.Millisecond) 62 assert.False(t, ok, "Get after cancel should have failed") 63 } 64 65 func TestCancelAfterSet(t *testing.T) { 66 v := NewValue() 67 v.Set(5) 68 r, ok := v.Get(10 * time.Millisecond) 69 assert.True(t, ok, "Get before cancel should have succeeded") 70 assert.Equal(t, 5, r, "Get got wrong value before cancel") 71 72 v.Cancel() 73 r, ok = v.Get(0) 74 assert.True(t, ok, "Get after cancel should have succeeded") 75 assert.Equal(t, 5, r, "Get got wrong value after cancel") 76 77 v.Set(10) 78 r, _ = v.Get(0) 79 assert.Equal(t, 5, r, "Set after cancel should have no effect") 80 } 81 82 func BenchmarkGet(b *testing.B) { 83 v := NewValue() 84 go func() { 85 time.Sleep(20 * time.Millisecond) 86 v.Set("hi") 87 }() 88 89 for i := 0; i < b.N; i++ { 90 v.Get(20 * time.Millisecond) 91 } 92 } 93 94 func TestConcurrent(t *testing.T) { 95 goroutines := grtrack.Start() 96 v := NewValue() 97 98 var sets int32 99 100 go func() { 101 var wg sync.WaitGroup 102 wg.Add(1) 103 // Do some concurrent setting to make sure that it works 104 for i := 0; i < concurrency; i++ { 105 go func() { 106 // Wait for waitGroup so that all goroutines run at basically the same 107 // time. 108 wg.Wait() 109 v.Set("hi") 110 atomic.AddInt32(&sets, 1) 111 }() 112 } 113 wg.Done() 114 }() 115 116 for i := 0; i < concurrency; i++ { 117 go func() { 118 r, ok := v.Get(200 * time.Millisecond) 119 assert.True(t, ok, "Get should have succeed") 120 assert.Equal(t, "hi", r, "Wrong result") 121 }() 122 } 123 124 goroutines.CheckAfter(t, 50*time.Millisecond) 125 assert.EqualValues(t, concurrency, atomic.LoadInt32(&sets), "Wrong number of successful Sets") 126 }