]>
src.bluestatic.org Git - mailpopbox.git/blob - pop3/conn_test.go
15 "github.com/uber-go/zap"
18 func _fl(depth
int) string {
19 _
, file
, line
, _
:= runtime
.Caller(depth
+ 1)
20 return fmt
.Sprintf("[%s:%d]", filepath
.Base(file
), line
)
23 func ok(t testing
.TB
, err error
) {
25 t
.Errorf("%s unexpected error: %v", _fl(1), err
)
29 func responseOK(t testing
.TB
, conn
*textproto
.Conn
) string {
30 line
, err
:= conn
.ReadLine()
32 t
.Errorf("%s responseOK: %v", _fl(1), err
)
34 if !strings
.HasPrefix(line
, "+OK") {
35 t
.Errorf("%s expected +OK, got %q", _fl(1), line
)
40 func responseERR(t testing
.TB
, conn
*textproto
.Conn
) string {
41 line
, err
:= conn
.ReadLine()
43 t
.Errorf("%s responseERR: %v", _fl(1), err
)
45 if !strings
.HasPrefix(line
, "-ERR") {
46 t
.Errorf("%s expected -ERR, got %q", _fl(1), line
)
51 func runServer(t
*testing
.T
, po PostOffice
) net
.Listener
{
52 l
, err
:= net
.Listen("tcp", "localhost:0")
60 conn
, err
:= l
.Accept()
64 go AcceptConnection(conn
, po
, zap
.New(zap
.NullEncoder()))
70 type testServer
struct {
75 func (s
*testServer
) Name() string {
79 func (s
*testServer
) OpenMailbox(user
, pass
string) (Mailbox
, error
) {
80 if s
.user
== user
&& s
.pass
== pass
{
83 return nil, fmt
.Errorf("bad username/pass")
86 type testMailbox
struct {
87 msgs
map[int]*testMessage
90 func (mb
*testMailbox
) ListMessages() ([]Message
, error
) {
91 msgs
:= make([]Message
, 0, len(mb
.msgs
))
92 for i
, _
:= range mb
.msgs
{
93 msgs
= append(msgs
, mb
.msgs
[i
])
98 func (mb
*testMailbox
) GetMessage(id
int) Message
{
99 if msg
, ok
:= mb
.msgs
[id
]; ok
{
105 func (mb
*testMailbox
) Retrieve(msg Message
) (io
.ReadCloser
, error
) {
106 r
:= strings
.NewReader(msg
.(*testMessage
).body
)
107 return ioutil
.NopCloser(r
), nil
110 func (mb
*testMailbox
) Delete(msg Message
) error
{
111 msg
.(*testMessage
).deleted
= true
115 func (mb
*testMailbox
) Close() error
{
119 func (mb
*testMailbox
) Reset() {
120 for _
, msg
:= range mb
.msgs
{
125 type testMessage
struct {
132 func (m
*testMessage
) UniqueID() string {
133 return fmt
.Sprintf("%p", m
)
136 func (m
*testMessage
) ID() int {
139 func (m
*testMessage
) Size() int {
142 func (m
*testMessage
) Deleted() bool {
146 func newTestServer() *testServer
{
151 msgs
: make(map[int]*testMessage
),
157 func TestExampleSession(t
*testing
.T
) {
162 s
.mb
.msgs
[1] = &testMessage
{1, 120, false, ""}
163 s
.mb
.msgs
[2] = &testMessage
{2, 200, false, ""}
165 conn
, err
:= textproto
.Dial(l
.Addr().Network(), l
.Addr().String())
168 line
:= responseOK(t
, conn
)
169 if !strings
.Contains(line
, s
.Name()) {
170 t
.Errorf("POP greeting did not include server name, got %q", line
)
173 ok(t
, conn
.PrintfLine("USER u"))
176 ok(t
, conn
.PrintfLine("PASS p"))
179 ok(t
, conn
.PrintfLine("STAT"))
180 line
= responseOK(t
, conn
)
181 expected
:= "+OK 2 320"
182 if line
!= expected
{
183 t
.Errorf("STAT expected %q, got %q", expected
, line
)
186 ok(t
, conn
.PrintfLine("LIST"))
188 lines
, err
:= conn
.ReadDotLines()
191 t
.Errorf("LIST expected 2 lines, got %d", len(lines
))
194 if lines
[0] != expected
{
195 t
.Errorf("LIST line 0 expected %q, got %q", expected
, lines
[0])
198 if lines
[1] != expected
{
199 t
.Errorf("LIST line 1 expected %q, got %q", expected
, lines
[1])
202 ok(t
, conn
.PrintfLine("QUIT"))
206 type requestResponse
struct {
208 expecter
func(testing
.TB
, *textproto
.Conn
) string
211 func expectOKResponse(predicate
func(string) bool) func(testing
.TB
, *textproto
.Conn
) string {
212 return func(t testing
.TB
, conn
*textproto
.Conn
) string {
213 line
:= responseOK(t
, conn
)
214 if !predicate(line
) {
215 t
.Errorf("%s Predicate failed, got %q", _fl(1), line
)
221 func clientServerTest(t
*testing
.T
, s
*testServer
, sequence
[]requestResponse
) {
225 conn
, err
:= textproto
.Dial(l
.Addr().Network(), l
.Addr().String())
230 for _
, pair
:= range sequence
{
231 ok(t
, conn
.PrintfLine(pair
.command
))
232 pair
.expecter(t
, conn
)
234 t
.Logf("command %q", pair
.command
)
239 func TestAuthStates(t
*testing
.T
) {
240 clientServerTest(t
, newTestServer(), []requestResponse
{
241 {"STAT", responseERR
},
242 {"NOOP", responseOK
},
243 {"USER bad", responseOK
},
244 {"PASS bad", responseERR
},
245 {"LIST", responseERR
},
246 {"USER u", responseOK
},
247 {"PASS bad", responseERR
},
248 {"STAT", responseERR
},
249 {"PASS p", responseOK
},
250 {"QUIT", responseOK
},
254 func TestDeleted(t
*testing
.T
) {
256 s
.mb
.msgs
[1] = &testMessage
{1, 999, false, ""}
257 s
.mb
.msgs
[2] = &testMessage
{2, 10, false, ""}
259 clientServerTest(t
, s
, []requestResponse
{
260 {"USER u", responseOK
},
261 {"PASS p", responseOK
},
262 {"STAT", expectOKResponse(func(s
string) bool {
263 return s
== "+OK 2 1009"
265 {"DELE 1", responseOK
},
266 {"RETR 1", responseERR
},
267 {"DELE 1", responseERR
},
268 {"STAT", expectOKResponse(func(s
string) bool {
269 return s
== "+OK 1 10"
271 {"RSET", responseOK
},
272 {"STAT", expectOKResponse(func(s
string) bool {
273 return s
== "+OK 2 1009"
275 {"QUIT", responseOK
},
279 func TestCaseSensitivty(t
*testing
.T
) {
281 s
.mb
.msgs
[999] = &testMessage
{999, 1, false, "a"}
283 clientServerTest(t
, s
, []requestResponse
{
284 {"user u", responseOK
},
285 {"PasS p", responseOK
},
286 {"sTaT", responseOK
},
287 {"retr 1", responseERR
},
288 {"dele 999", responseOK
},
289 {"QUIT", responseOK
},
293 func TestRetr(t
*testing
.T
) {
295 s
.mb
.msgs
[1] = &testMessage
{1, 5, false, "hello"}
296 s
.mb
.msgs
[2] = &testMessage
{2, 69, false, "this\r\nis a\r\n.\r\ntest"}
298 clientServerTest(t
, s
, []requestResponse
{
299 {"USER u", responseOK
},
300 {"PASS p", responseOK
},
301 {"STAT", responseOK
},
302 {"RETR 1", func(t testing
.TB
, tp
*textproto
.Conn
) string {
308 resp
, err
:= tp
.ReadDotLines()
314 expected
:= []string{"hello"}
315 if !reflect
.DeepEqual(resp
, expected
) {
316 t
.Errorf("Expected %v, got %v", expected
, resp
)
321 {"RETR 2", func(t testing
.TB
, tp
*textproto
.Conn
) string {
327 resp
, err
:= tp
.ReadDotLines()
333 expected
:= []string{"this", "is a", ".", "test"}
334 if !reflect
.DeepEqual(resp
, expected
) {
335 t
.Errorf("Expected %v, got %v", expected
, resp
)
340 {"QUIT", responseOK
},
344 func TestUidl(t
*testing
.T
) {
346 s
.mb
.msgs
[1] = &testMessage
{1, 3, false, "abc"}
347 s
.mb
.msgs
[2] = &testMessage
{2, 1, true, "Z"}
348 s
.mb
.msgs
[3] = &testMessage
{3, 4, false, "test"}
350 clientServerTest(t
, s
, []requestResponse
{
351 {"USER u", responseOK
},
352 {"PASS p", responseOK
},
353 {"UIDL", func(t testing
.TB
, tp
*textproto
.Conn
) string {
359 resp
, err
:= tp
.ReadDotLines()
365 expected
:= []string{
366 fmt
.Sprintf("1 %p", s
.mb
.msgs
[1]),
367 fmt
.Sprintf("3 %p", s
.mb
.msgs
[3]),
369 if !reflect
.DeepEqual(resp
, expected
) {
370 t
.Errorf("Expected %v, got %v", expected
, resp
)
375 {"QUIT", responseOK
},