forked from rosspeoples/go-snmplib
-
Notifications
You must be signed in to change notification settings - Fork 1
/
udp_stub_connection.go
138 lines (113 loc) · 3.55 KB
/
udp_stub_connection.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
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
package snmplib
import (
"encoding/hex"
"net"
"testing"
"time"
)
// Internal structure to take care of responses.
type expectAndRespond struct {
expect string
respond []string
}
/* A udpStub is a UDP stubbing tool.
You test UDP programs by using
NewUdpStub().Expect("aabbcc").andReturn([]string("ddeeff")
This will return a net.Conn that will simulate receiving a "ddeeff"
packet when you send a "aabbcc" packet (expressed as hexdumps for
readability).
*/
type udpStub struct {
ignoreUnknownPackets bool
expectResponses []*expectAndRespond
queuedPackets []string
t *testing.T
closed bool
}
// NewUdpStub creates a new udpStub.
func NewUdpStub(t *testing.T) *udpStub {
return &udpStub{t: t}
}
// Expect declares that you expect this connection to be sent a hex-encoded string.
func (u *udpStub) Expect(packet string) *expectAndRespond {
e := &expectAndRespond{packet, []string{}}
u.expectResponses = append(u.expectResponses, e)
return e
}
// AndRespond registers a response for a string you set to be expected with Expect.
func (e *expectAndRespond) AndRespond(packets []string) *expectAndRespond {
for _, packet := range packets {
e.respond = append(e.respond, packet)
}
return e
}
/* Read reads bytes from the connection.
Only returns stuff you put in the object with the AndRespond method.
*/
func (u *udpStub) Read(b []byte) (n int, err error) {
if len(u.queuedPackets) > 0 {
val, err := hex.DecodeString(u.queuedPackets[0])
if err != nil {
u.t.Fatalf("Error while decoding expected packet : '%v'", err)
}
for idx, vb := range val {
b[idx] = vb
}
return len(val), nil
u.queuedPackets = u.queuedPackets[1:]
}
return 0, nil
}
/* Write writes bytes to the connection.
If the bytes were expected, it can trigger responses.
If an unexpected packet is written it will trigger an error.
*/
func (u *udpStub) Write(b []byte) (n int, err error) {
// We're expecting the first packet in the expectResponses array.
realPacket := hex.EncodeToString(b)
expectedPacket := u.expectResponses[0].expect
if realPacket == expectedPacket {
for _, response := range u.expectResponses[0].respond {
u.queuedPackets = append(u.queuedPackets, response)
}
u.expectResponses = u.expectResponses[1:]
} else {
if !u.ignoreUnknownPackets {
u.t.Errorf("Error : received '%v'\n expected '%v'", realPacket, expectedPacket)
}
}
return len(b), nil
}
/* Close closes the udpStub.
This sets a boolean flag so you can check the connection was really closed.
*/
func (u *udpStub) Close() error {
u.closed = true
return nil
}
// CheckClosed checks if the udpStub was closed, signaling an error if it wasn't.
func (u *udpStub) CheckClosed() {
if !u.closed {
u.t.Errorf("Connection was not closed")
}
}
// LocalAddr so udpStub implements the net.conn interface, but doesn't actually return anything.
func (_ *udpStub) LocalAddr() net.Addr {
return nil
}
// RemoteAddr so udpStub implements the net.conn interface, but doesn't actually return anything.
func (_ *udpStub) RemoteAddr() net.Addr {
return nil
}
// SetDeadline so udpStub implements the net.conn interface, but doesn't actually return anything.
func (_ *udpStub) SetDeadline(t time.Time) error {
return nil
}
// SetReadDeadline so udpStub implements the net.conn interface, but doesn't actually return anything.
func (_ *udpStub) SetReadDeadline(t time.Time) error {
return nil
}
// SetWriteDeadline so udpStub implements the net.conn interface, but doesn't actually return anything.
func (_ *udpStub) SetWriteDeadline(t time.Time) error {
return nil
}