github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/fix/testdata/reflect.script.go.in (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This package aids in the testing of code that uses channels. 6 package script 7 8 import ( 9 "fmt" 10 "os" 11 "rand" 12 "reflect" 13 "strings" 14 ) 15 16 // An Event is an element in a partially ordered set that either sends a value 17 // to a channel or expects a value from a channel. 18 type Event struct { 19 name string 20 occurred bool 21 predecessors []*Event 22 action action 23 } 24 25 type action interface { 26 // getSend returns nil if the action is not a send action. 27 getSend() sendAction 28 // getRecv returns nil if the action is not a receive action. 29 getRecv() recvAction 30 // getChannel returns the channel that the action operates on. 31 getChannel() interface{} 32 } 33 34 type recvAction interface { 35 recvMatch(interface{}) bool 36 } 37 38 type sendAction interface { 39 send() 40 } 41 42 // isReady returns true if all the predecessors of an Event have occurred. 43 func (e Event) isReady() bool { 44 for _, predecessor := range e.predecessors { 45 if !predecessor.occurred { 46 return false 47 } 48 } 49 50 return true 51 } 52 53 // A Recv action reads a value from a channel and uses reflect.DeepMatch to 54 // compare it with an expected value. 55 type Recv struct { 56 Channel interface{} 57 Expected interface{} 58 } 59 60 func (r Recv) getRecv() recvAction { return r } 61 62 func (Recv) getSend() sendAction { return nil } 63 64 func (r Recv) getChannel() interface{} { return r.Channel } 65 66 func (r Recv) recvMatch(chanEvent interface{}) bool { 67 c, ok := chanEvent.(channelRecv) 68 if !ok || c.channel != r.Channel { 69 return false 70 } 71 72 return reflect.DeepEqual(c.value, r.Expected) 73 } 74 75 // A RecvMatch action reads a value from a channel and calls a function to 76 // determine if the value matches. 77 type RecvMatch struct { 78 Channel interface{} 79 Match func(interface{}) bool 80 } 81 82 func (r RecvMatch) getRecv() recvAction { return r } 83 84 func (RecvMatch) getSend() sendAction { return nil } 85 86 func (r RecvMatch) getChannel() interface{} { return r.Channel } 87 88 func (r RecvMatch) recvMatch(chanEvent interface{}) bool { 89 c, ok := chanEvent.(channelRecv) 90 if !ok || c.channel != r.Channel { 91 return false 92 } 93 94 return r.Match(c.value) 95 } 96 97 // A Closed action matches if the given channel is closed. The closing is 98 // treated as an event, not a state, thus Closed will only match once for a 99 // given channel. 100 type Closed struct { 101 Channel interface{} 102 } 103 104 func (r Closed) getRecv() recvAction { return r } 105 106 func (Closed) getSend() sendAction { return nil } 107 108 func (r Closed) getChannel() interface{} { return r.Channel } 109 110 func (r Closed) recvMatch(chanEvent interface{}) bool { 111 c, ok := chanEvent.(channelClosed) 112 if !ok || c.channel != r.Channel { 113 return false 114 } 115 116 return true 117 } 118 119 // A Send action sends a value to a channel. The value must match the 120 // type of the channel exactly unless the channel if of type chan interface{}. 121 type Send struct { 122 Channel interface{} 123 Value interface{} 124 } 125 126 func (Send) getRecv() recvAction { return nil } 127 128 func (s Send) getSend() sendAction { return s } 129 130 func (s Send) getChannel() interface{} { return s.Channel } 131 132 type empty struct { 133 x interface{} 134 } 135 136 func newEmptyInterface(e empty) reflect.Value { 137 return reflect.NewValue(e).(*reflect.StructValue).Field(0) 138 } 139 140 func (s Send) send() { 141 // With reflect.ChanValue.Send, we must match the types exactly. So, if 142 // s.Channel is a chan interface{} we convert s.Value to an interface{} 143 // first. 144 c := reflect.NewValue(s.Channel).(*reflect.ChanValue) 145 var v reflect.Value 146 if iface, ok := c.Type().(*reflect.ChanType).Elem().(*reflect.InterfaceType); ok && iface.NumMethod() == 0 { 147 v = newEmptyInterface(empty{s.Value}) 148 } else { 149 v = reflect.NewValue(s.Value) 150 } 151 c.Send(v) 152 } 153 154 // A Close action closes the given channel. 155 type Close struct { 156 Channel interface{} 157 } 158 159 func (Close) getRecv() recvAction { return nil } 160 161 func (s Close) getSend() sendAction { return s } 162 163 func (s Close) getChannel() interface{} { return s.Channel } 164 165 func (s Close) send() { reflect.NewValue(s.Channel).(*reflect.ChanValue).Close() } 166 167 // A ReceivedUnexpected error results if no active Events match a value 168 // received from a channel. 169 type ReceivedUnexpected struct { 170 Value interface{} 171 ready []*Event 172 } 173 174 func (r ReceivedUnexpected) String() string { 175 names := make([]string, len(r.ready)) 176 for i, v := range r.ready { 177 names[i] = v.name 178 } 179 return fmt.Sprintf("received unexpected value on one of the channels: %#v. Runnable events: %s", r.Value, strings.Join(names, ", ")) 180 } 181 182 // A SetupError results if there is a error with the configuration of a set of 183 // Events. 184 type SetupError string 185 186 func (s SetupError) String() string { return string(s) } 187 188 func NewEvent(name string, predecessors []*Event, action action) *Event { 189 e := &Event{name, false, predecessors, action} 190 return e 191 } 192 193 // Given a set of Events, Perform repeatedly iterates over the set and finds the 194 // subset of ready Events (that is, all of their predecessors have 195 // occurred). From that subset, it pseudo-randomly selects an Event to perform. 196 // If the Event is a send event, the send occurs and Perform recalculates the ready 197 // set. If the event is a receive event, Perform waits for a value from any of the 198 // channels that are contained in any of the events. That value is then matched 199 // against the ready events. The first event that matches is considered to 200 // have occurred and Perform recalculates the ready set. 201 // 202 // Perform continues this until all Events have occurred. 203 // 204 // Note that uncollected goroutines may still be reading from any of the 205 // channels read from after Perform returns. 206 // 207 // For example, consider the problem of testing a function that reads values on 208 // one channel and echos them to two output channels. To test this we would 209 // create three events: a send event and two receive events. Each of the 210 // receive events must list the send event as a predecessor but there is no 211 // ordering between the receive events. 212 // 213 // send := NewEvent("send", nil, Send{c, 1}) 214 // recv1 := NewEvent("recv 1", []*Event{send}, Recv{c, 1}) 215 // recv2 := NewEvent("recv 2", []*Event{send}, Recv{c, 1}) 216 // Perform(0, []*Event{send, recv1, recv2}) 217 // 218 // At first, only the send event would be in the ready set and thus Perform will 219 // send a value to the input channel. Now the two receive events are ready and 220 // Perform will match each of them against the values read from the output channels. 221 // 222 // It would be invalid to list one of the receive events as a predecessor of 223 // the other. At each receive step, all the receive channels are considered, 224 // thus Perform may see a value from a channel that is not in the current ready 225 // set and fail. 226 func Perform(seed int64, events []*Event) (err os.Error) { 227 r := rand.New(rand.NewSource(seed)) 228 229 channels, err := getChannels(events) 230 if err != nil { 231 return 232 } 233 multiplex := make(chan interface{}) 234 for _, channel := range channels { 235 go recvValues(multiplex, channel) 236 } 237 238 Outer: 239 for { 240 ready, err := readyEvents(events) 241 if err != nil { 242 return err 243 } 244 245 if len(ready) == 0 { 246 // All events occurred. 247 break 248 } 249 250 event := ready[r.Intn(len(ready))] 251 if send := event.action.getSend(); send != nil { 252 send.send() 253 event.occurred = true 254 continue 255 } 256 257 v := <-multiplex 258 for _, event := range ready { 259 if recv := event.action.getRecv(); recv != nil && recv.recvMatch(v) { 260 event.occurred = true 261 continue Outer 262 } 263 } 264 265 return ReceivedUnexpected{v, ready} 266 } 267 268 return nil 269 } 270 271 // getChannels returns all the channels listed in any receive events. 272 func getChannels(events []*Event) ([]interface{}, os.Error) { 273 channels := make([]interface{}, len(events)) 274 275 j := 0 276 for _, event := range events { 277 if recv := event.action.getRecv(); recv == nil { 278 continue 279 } 280 c := event.action.getChannel() 281 if _, ok := reflect.NewValue(c).(*reflect.ChanValue); !ok { 282 return nil, SetupError("one of the channel values is not a channel") 283 } 284 285 duplicate := false 286 for _, other := range channels[0:j] { 287 if c == other { 288 duplicate = true 289 break 290 } 291 } 292 293 if !duplicate { 294 channels[j] = c 295 j++ 296 } 297 } 298 299 return channels[0:j], nil 300 } 301 302 // recvValues is a multiplexing helper function. It reads values from the given 303 // channel repeatedly, wrapping them up as either a channelRecv or 304 // channelClosed structure, and forwards them to the multiplex channel. 305 func recvValues(multiplex chan<- interface{}, channel interface{}) { 306 c := reflect.NewValue(channel).(*reflect.ChanValue) 307 308 for { 309 v, ok := c.Recv() 310 if !ok { 311 multiplex <- channelClosed{channel} 312 return 313 } 314 315 multiplex <- channelRecv{channel, v.Interface()} 316 } 317 } 318 319 type channelClosed struct { 320 channel interface{} 321 } 322 323 type channelRecv struct { 324 channel interface{} 325 value interface{} 326 } 327 328 // readyEvents returns the subset of events that are ready. 329 func readyEvents(events []*Event) ([]*Event, os.Error) { 330 ready := make([]*Event, len(events)) 331 332 j := 0 333 eventsWaiting := false 334 for _, event := range events { 335 if event.occurred { 336 continue 337 } 338 339 eventsWaiting = true 340 if event.isReady() { 341 ready[j] = event 342 j++ 343 } 344 } 345 346 if j == 0 && eventsWaiting { 347 names := make([]string, len(events)) 348 for _, event := range events { 349 if event.occurred { 350 continue 351 } 352 names[j] = event.name 353 } 354 355 return nil, SetupError("dependency cycle in events. These events are waiting to run but cannot: " + strings.Join(names, ", ")) 356 } 357 358 return ready[0:j], nil 359 }