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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
package client
import (
"context"
"io"
"net"
"os"
"strings"
"testing"
"time"
)
type mockNetConn struct {
*testing.T
In, Out chan string
in, out chan []byte
die context.CancelFunc
closed bool
rt, wt time.Time
}
func MockNetConn(t *testing.T) *mockNetConn {
// Our mock connection is a testing object
ctx, cancel := context.WithCancel(context.Background())
m := &mockNetConn{T: t, die: cancel}
// buffer input
m.In = make(chan string, 20)
m.in = make(chan []byte)
go func() {
for {
select {
case <-ctx.Done():
return
case s := <-m.In:
m.in <- []byte(s)
}
}
}()
// buffer output
m.Out = make(chan string)
m.out = make(chan []byte, 20)
go func() {
for {
select {
case <-ctx.Done():
return
case b := <-m.out:
m.Out <- string(b)
}
}
}()
return m
}
// Test helpers
func (m *mockNetConn) Send(s string) {
m.In <- s + "\r\n"
}
func (m *mockNetConn) Expect(e string) {
select {
case <-time.After(time.Millisecond):
m.Errorf("Mock connection did not receive expected output.\n\t"+
"Expected: '%s', got nothing.", e)
case s := <-m.Out:
s = strings.Trim(s, "\r\n")
if e != s {
m.Errorf("Mock connection received unexpected value.\n\t"+
"Expected: '%s'\n\tGot: '%s'", e, s)
}
}
}
func (m *mockNetConn) ExpectNothing() {
select {
case <-time.After(time.Millisecond):
case s := <-m.Out:
s = strings.Trim(s, "\r\n")
m.Errorf("Mock connection received unexpected output.\n\t"+
"Expected nothing, got: '%s'", s)
}
}
// Implement net.Conn interface
func (m *mockNetConn) Read(b []byte) (int, error) {
if m.Closed() {
return 0, os.ErrInvalid
}
s, ok := <-m.in
copy(b, s)
if !ok {
return len(s), io.EOF
}
return len(s), nil
}
func (m *mockNetConn) Write(s []byte) (int, error) {
if m.Closed() {
return 0, os.ErrInvalid
}
b := make([]byte, len(s))
copy(b, s)
m.out <- b
return len(s), nil
}
func (m *mockNetConn) Close() error {
if m.Closed() {
return os.ErrInvalid
}
m.closed = true
// Shut down *ALL* the goroutines!
// This will trigger an EOF event in Read() too
m.die()
close(m.in)
return nil
}
func (m *mockNetConn) Closed() bool {
return m.closed
}
func (m *mockNetConn) LocalAddr() net.Addr {
return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}
}
func (m *mockNetConn) RemoteAddr() net.Addr {
return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}
}
func (m *mockNetConn) SetDeadline(t time.Time) error {
m.rt = t
m.wt = t
return nil
}
func (m *mockNetConn) SetReadDeadline(t time.Time) error {
m.rt = t
return nil
}
func (m *mockNetConn) SetWriteDeadline(t time.Time) error {
m.wt = t
return nil
}
|