-
Notifications
You must be signed in to change notification settings - Fork 0
/
mockio.go
104 lines (91 loc) · 2.79 KB
/
mockio.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Package mockio provides a mock ReaderWriterCloser to test your software's i/o stream handling.
package mockio
/*
Package mockio implements a ReaderWriterCloser for mocking a ReaderWriterCloser
(such as a serial device).
You can program it to expect certain sequences of bytes and provide a response.
Alternatively, you can provide a function to determine if a sequence of bytes
written to the mock device matches your expectations, and send a response.
Or, you can create your own structure matching the Expect interface to handle
the incoming bytes and respond accordingly.
*/
import (
"bytes"
"sync"
"time"
)
// MockIO provides a mock I/O ReadWriteCloser to test your software's i/o stream handling.
type MockIO struct {
buffer *bytes.Buffer
holding []byte
timer chan time.Duration
Expects []Expect
lock sync.Mutex
}
// NewMockIO constructs a new MockIO.
func NewMockIO() *MockIO {
result := &MockIO{
buffer: bytes.NewBuffer([]byte{}),
holding: []byte{},
Expects: []Expect{},
timer: make(chan time.Duration, 5),
}
return result
}
// Read implements the Reader interface for the MockIO stream.
// Use this with your software to test that it reads correctly.
func (m *MockIO) Read(data []byte) (n int, err error) {
d := <-m.timer
<-time.NewTimer(d).C
return m.buffer.Read(data)
}
// Write implements the Writer interface for the MockIO stream.
// Use this with your software to test that it writes correctly.
func (m *MockIO) Write(data []byte) (n int, err error) {
m.lock.Lock()
defer m.lock.Unlock()
m.holding = append(m.holding, data...)
respond := []byte{}
dur := time.Millisecond
for _, test := range m.Expects {
response, count, ok := test.Match(m.holding)
if !ok {
continue
}
dur = test.Duration()
respond = append(respond, response...)
m.holding = m.holding[count:]
break
}
m.timer <- dur
m.buffer.Write(respond)
return len(data), nil
}
// Send writes data through the mock serial device to the Read function. It is
// meant to mimic the serial device sending data not in response to a Write,
// but on its own (perhaps due to an event on the hardware connected to the
// serial device you're mocking).
func (m *MockIO) Send(data []byte, wait time.Duration) {
m.lock.Lock()
defer m.lock.Unlock()
m.timer <- wait
m.buffer.Write(data)
}
// Expect adds a new Expect item to a list of things for the MockIO Write to expect.
func (m *MockIO) Expect(exp Expect) {
m.lock.Lock()
defer m.lock.Unlock()
m.Expects = append(m.Expects, exp)
}
// ClearExpectations removes all items stored in MockIO's Expect buffer.
func (m *MockIO) ClearExpectations() {
m.lock.Lock()
defer m.lock.Unlock()
m.Expects = []Expect{}
}
// Close implements the Closer interface for the MockIO stream.
func (m *MockIO) Close() (err error) {
m.buffer.Reset()
m.holding = []byte{}
return err
}