github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/utils/voyeur/value_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package voyeur
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  
    10  	gc "launchpad.net/gocheck"
    11  
    12  	jc "launchpad.net/juju-core/testing/checkers"
    13  	"launchpad.net/juju-core/testing/testbase"
    14  )
    15  
    16  type suite struct {
    17  	testbase.LoggingSuite
    18  }
    19  
    20  var _ = gc.Suite(&suite{})
    21  
    22  func Test(t *testing.T) { gc.TestingT(t) }
    23  
    24  func ExampleWatcher_Next() {
    25  	v := NewValue(nil)
    26  
    27  	// The channel is not necessary for normal use of the watcher.
    28  	// It just makes the test output predictable.
    29  	ch := make(chan bool)
    30  
    31  	go func() {
    32  		for x := 0; x < 3; x++ {
    33  			v.Set(fmt.Sprintf("value%d", x))
    34  			ch <- true
    35  		}
    36  		v.Close()
    37  	}()
    38  	w := v.Watch()
    39  	for w.Next() {
    40  		fmt.Println(w.Value())
    41  		<-ch
    42  	}
    43  
    44  	// output:
    45  	// value0
    46  	// value1
    47  	// value2
    48  }
    49  
    50  func (s *suite) TestValueGetSet(c *gc.C) {
    51  	v := NewValue(nil)
    52  	expected := "12345"
    53  	v.Set(expected)
    54  	got := v.Get()
    55  	c.Assert(got, gc.Equals, expected)
    56  	c.Assert(v.Closed(), jc.IsFalse)
    57  }
    58  
    59  func (s *suite) TestValueInitial(c *gc.C) {
    60  	expected := "12345"
    61  	v := NewValue(expected)
    62  	got := v.Get()
    63  	c.Assert(got, gc.Equals, expected)
    64  	c.Assert(v.Closed(), jc.IsFalse)
    65  }
    66  
    67  func (s *suite) TestValueClose(c *gc.C) {
    68  	expected := "12345"
    69  	v := NewValue(expected)
    70  	c.Assert(v.Close(), gc.IsNil)
    71  
    72  	isClosed := v.Closed()
    73  	c.Assert(isClosed, jc.IsTrue)
    74  	got := v.Get()
    75  	c.Assert(got, gc.Equals, expected)
    76  
    77  	// test that we can close multiple times without a problem
    78  	c.Assert(v.Close(), gc.IsNil)
    79  }
    80  
    81  func (s *suite) TestWatcher(c *gc.C) {
    82  	vals := []string{"one", "two", "three"}
    83  
    84  	// blocking on the channel forces the scheduler to let the other goroutine
    85  	// run for a bit, so we get predictable results.  This is not necessary for
    86  	// normal use of the watcher.
    87  	ch := make(chan bool)
    88  
    89  	v := NewValue(nil)
    90  
    91  	go func() {
    92  		for _, s := range vals {
    93  			v.Set(s)
    94  			ch <- true
    95  		}
    96  		v.Close()
    97  	}()
    98  
    99  	w := v.Watch()
   100  	c.Assert(w.Next(), jc.IsTrue)
   101  	c.Assert(w.Value(), gc.Equals, vals[0])
   102  
   103  	// test that we can get the same value multiple times
   104  	c.Assert(w.Value(), gc.Equals, vals[0])
   105  	<-ch
   106  
   107  	// now try skipping a value by calling next without getting the value
   108  	c.Assert(w.Next(), jc.IsTrue)
   109  	<-ch
   110  
   111  	c.Assert(w.Next(), jc.IsTrue)
   112  	c.Assert(w.Value(), gc.Equals, vals[2])
   113  	<-ch
   114  
   115  	c.Assert(w.Next(), jc.IsFalse)
   116  }
   117  
   118  func (s *suite) TestDoubleSet(c *gc.C) {
   119  	vals := []string{"one", "two", "three"}
   120  
   121  	// blocking on the channel forces the scheduler to let the other goroutine
   122  	// run for a bit, so we get predictable results.  This is not necessary for
   123  	// normal use of the watcher.
   124  	ch := make(chan bool)
   125  
   126  	v := NewValue(nil)
   127  
   128  	go func() {
   129  		v.Set(vals[0])
   130  		ch <- true
   131  		v.Set(vals[1])
   132  		v.Set(vals[2])
   133  		ch <- true
   134  		v.Close()
   135  		ch <- true
   136  	}()
   137  
   138  	w := v.Watch()
   139  	c.Assert(w.Next(), jc.IsTrue)
   140  	c.Assert(w.Value(), gc.Equals, vals[0])
   141  	<-ch
   142  
   143  	// since we did two sets before sending on the channel,
   144  	// we should just get vals[2] here and not get vals[1]
   145  	c.Assert(w.Next(), jc.IsTrue)
   146  	c.Assert(w.Value(), gc.Equals, vals[2])
   147  }
   148  
   149  func (s *suite) TestTwoReceivers(c *gc.C) {
   150  	vals := []string{"one", "two", "three"}
   151  
   152  	// blocking on the channel forces the scheduler to let the other goroutine
   153  	// run for a bit, so we get predictable results.  This is not necessary for
   154  	// normal use of the watcher.
   155  	ch := make(chan bool)
   156  
   157  	v := NewValue(nil)
   158  
   159  	watcher := func() {
   160  		w := v.Watch()
   161  		x := 0
   162  		for w.Next() {
   163  			c.Assert(w.Value(), gc.Equals, vals[x])
   164  			x++
   165  			<-ch
   166  		}
   167  		c.Assert(x, gc.Equals, len(vals))
   168  		<-ch
   169  	}
   170  
   171  	go watcher()
   172  	go watcher()
   173  
   174  	for _, val := range vals {
   175  		v.Set(val)
   176  		ch <- true
   177  		ch <- true
   178  	}
   179  
   180  	v.Close()
   181  	ch <- true
   182  	ch <- true
   183  }
   184  
   185  func (s *suite) TestCloseWatcher(c *gc.C) {
   186  	vals := []string{"one", "two", "three"}
   187  
   188  	// blocking on the channel forces the scheduler to let the other goroutine
   189  	// run for a bit, so we get predictable results.  This is not necessary for
   190  	// normal use of the watcher.
   191  	ch := make(chan bool)
   192  
   193  	v := NewValue(nil)
   194  
   195  	w := v.Watch()
   196  	go func() {
   197  		x := 0
   198  		for w.Next() {
   199  			c.Assert(w.Value(), gc.Equals, vals[x])
   200  			x++
   201  			<-ch
   202  		}
   203  		// the value will only get set once before the watcher is closed
   204  		c.Assert(x, gc.Equals, 1)
   205  		<-ch
   206  	}()
   207  
   208  	v.Set(vals[0])
   209  	ch <- true
   210  	w.Close()
   211  	ch <- true
   212  
   213  	// prove the value is not closed, even though the watcher is
   214  	c.Assert(v.Closed(), jc.IsFalse)
   215  }
   216  
   217  func (s *suite) TestWatchZeroValue(c *gc.C) {
   218  	var v Value
   219  	ch := make(chan bool)
   220  	go func() {
   221  		w := v.Watch()
   222  		ch <- true
   223  		ch <- w.Next()
   224  	}()
   225  	<-ch
   226  	v.Set(struct{}{})
   227  	c.Assert(<-ch, jc.IsTrue)
   228  }