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 }