OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [testing/] [script/] [script.go] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.