forked from 0xERR0R/blocky
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmock_call_sequence.go
78 lines (60 loc) · 1.28 KB
/
mock_call_sequence.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
package helpertest
import (
"context"
"fmt"
"sync"
"time"
)
const mockCallTimeout = 2 * time.Second
type MockCallSequence[T any] struct {
driver func(chan<- T, chan<- error)
res chan T
err chan error
callCount uint
initOnce sync.Once
closeOnce sync.Once
}
func NewMockCallSequence[T any](driver func(chan<- T, chan<- error)) MockCallSequence[T] {
return MockCallSequence[T]{
driver: driver,
}
}
func (m *MockCallSequence[T]) Call() (T, error) {
m.callCount++
m.initOnce.Do(func() {
m.res = make(chan T)
m.err = make(chan error)
// This goroutine never stops
go func() {
defer m.Close()
m.driver(m.res, m.err)
}()
})
ctx, cancel := context.WithTimeout(context.Background(), mockCallTimeout)
defer cancel()
select {
case t, ok := <-m.res:
if !ok {
break
}
return t, nil
case err, ok := <-m.err:
if !ok {
break
}
var zero T
return zero, err
case <-ctx.Done():
panic(fmt.Sprintf("mock call sequence driver timed-out on call %d", m.CallCount()))
}
panic("mock call sequence called after driver returned (or sequence Close was called explicitly)")
}
func (m *MockCallSequence[T]) CallCount() uint {
return m.callCount
}
func (m *MockCallSequence[T]) Close() {
m.closeOnce.Do(func() {
close(m.res)
close(m.err)
})
}