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  }