Skip to content

Commit

Permalink
Fix tests, change Serve and remove Close
Browse files Browse the repository at this point in the history
A couple of broken tests have been fixed. This was due to refactored
changes not being reflected everywhere. Serve was changed so that
it's closer to that in net/http (as I think was the original
intention). It takes a listener. This makes it possible to listen on
multiple interfaces and ports using the same server. Close was removed
as it's unnecessary now.
  • Loading branch information
ishbir committed Jul 20, 2015
1 parent 1e29585 commit 4021e9b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 58 deletions.
32 changes: 18 additions & 14 deletions mailstore/dummy_mailstore_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package mailstore

import "testing"
import (
"testing"

"github.com/jordwest/imap-server/types"
)

func getDefaultInbox(t *testing.T) DummyMailbox {
m := NewDummyMailstore()
Expand Down Expand Up @@ -38,37 +42,37 @@ func assertMessageUIDs(t *testing.T, msgs []Message, uids []uint32) {

func TestMessageSetBySequenceNumber(t *testing.T) {
inbox := getDefaultInbox(t)
msgs := inbox.MessageSetBySequenceNumber(SequenceSet{
SequenceRange{min: "1", max: ""},
SequenceRange{min: "4", max: "*"},
msgs := inbox.MessageSetBySequenceNumber(types.SequenceSet{
types.SequenceRange{Min: "1", Max: ""},
types.SequenceRange{Min: "4", Max: "*"},
})
assertMessageUIDs(t, msgs, []uint32{10})

msgs = inbox.MessageSetBySequenceNumber(SequenceSet{
SequenceRange{min: "2", max: "3"},
msgs = inbox.MessageSetBySequenceNumber(types.SequenceSet{
types.SequenceRange{Min: "2", Max: "3"},
})
assertMessageUIDs(t, msgs, []uint32{11, 12})
}

func TestMessageSetByUID(t *testing.T) {
inbox := getDefaultInbox(t)
msgs := inbox.MessageSetByUID(SequenceSet{
SequenceRange{min: "10", max: "*"},
msgs := inbox.MessageSetByUID(types.SequenceSet{
types.SequenceRange{Min: "10", Max: "*"},
})
assertMessageUIDs(t, msgs, []uint32{10, 11, 12})

msgs = inbox.MessageSetByUID(SequenceSet{
SequenceRange{min: "3", max: "9"},
msgs = inbox.MessageSetByUID(types.SequenceSet{
types.SequenceRange{Min: "3", Max: "9"},
})
assertMessageUIDs(t, msgs, []uint32{})

msgs = inbox.MessageSetByUID(SequenceSet{
SequenceRange{min: "11", max: "12"},
msgs = inbox.MessageSetByUID(types.SequenceSet{
types.SequenceRange{Min: "11", Max: "12"},
})
assertMessageUIDs(t, msgs, []uint32{11, 12})

msgs = inbox.MessageSetByUID(SequenceSet{
SequenceRange{min: "*", max: ""},
msgs = inbox.MessageSetByUID(types.SequenceSet{
types.SequenceRange{Min: "*", Max: ""},
})
assertMessageUIDs(t, msgs, []uint32{12})
}
62 changes: 22 additions & 40 deletions server.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package imap

import (
"errors"
"fmt"
"io"
"io/ioutil"
Expand All @@ -12,10 +11,16 @@ import (
"github.com/jordwest/imap-server/mailstore"
)

// Server represents an IMAP server instance
const (
// defaultAddress is the default address that the IMAP server should listen
// on.
defaultAddress = ":143"
)

// Server represents an IMAP server instance.
type Server struct {
Addr string
listener net.Listener
listeners []net.Listener
Transcript io.Writer
mailstore mailstore.Mailstore
}
Expand All @@ -24,44 +29,32 @@ type Server struct {
// You must called either Listen() followed by Serve() or call ListenAndServe()
func NewServer(store mailstore.Mailstore) *Server {
s := &Server{
Addr: ":143",
Addr: defaultAddress,
mailstore: store,
Transcript: ioutil.Discard,
}
return s
}

// ListenAndServe is shorthand for calling Listen() followed by Serve().
// ListenAndServe is shorthand for calling Serve() with
func (s *Server) ListenAndServe() (err error) {
err = s.Listen()
if err != nil {
return err
}
return s.Serve()
}

// Listen has the server begin listening for new connections.
// This function is non-blocking.
func (s *Server) Listen() error {
if s.listener != nil {
return errors.New("Listener already exists")
}
fmt.Fprintf(s.Transcript, "Listening on %s\n", s.Addr)
ln, err := net.Listen("tcp", s.Addr)
if err != nil {
fmt.Printf("Error listening: %s\n", err)
return err
}
s.listener = ln
return nil

return s.Serve(ln)
}

// Serve starts the server and spawns new goroutines to handle each client connection
// as they come in. This function blocks.
func (s *Server) Serve() error {
defer s.listener.Close()
// Serve starts the server and spawns new goroutines to handle each client
// connection as they come in. This function blocks.
func (s *Server) Serve(l net.Listener) error {
fmt.Fprintf(s.Transcript, "Serving on %s\n", l.Addr().String())
defer l.Close()
for {
conn, err := s.listener.Accept()
conn, err := l.Accept()
if err != nil {
fmt.Errorf("Error accepting connection: %s\n", err)
return err
Expand All @@ -77,19 +70,6 @@ func (s *Server) Serve() error {
}
}

// Close stops the server listening for all new connections
func (s *Server) Close() (err error) {
fmt.Fprintf(s.Transcript, "Closing server listener\n")
if s.listener == nil {
return errors.New("Server not started")
}
err = s.listener.Close()
if err == nil {
s.listener = nil
}
return err
}

func (s *Server) newConn(netConn net.Conn) (c *conn.Conn, err error) {
c = conn.NewConn(s.mailstore, netConn, s.Transcript)
c.SetState(conn.StateNew)
Expand All @@ -106,7 +86,9 @@ func NewTestConnection(transcript io.Writer) (s *Server, clientConn *textproto.C
s = NewServer(mStore)
s.Addr = ":10143"
s.Transcript = transcript
if err = s.Listen(); err != nil {

l, err := net.Listen("tcp", s.Addr)
if err != nil {
return nil, nil, nil, nil, err
}

Expand All @@ -118,7 +100,7 @@ func NewTestConnection(transcript io.Writer) (s *Server, clientConn *textproto.C
textc := textproto.NewConn(c)
clientConn = textc

conn, err := s.listener.Accept()
conn, err := l.Accept()
if err != nil {
return nil, nil, nil, nil, err
}
Expand Down
12 changes: 9 additions & 3 deletions server_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package imap

import (
"net"
"testing"
"time"

Expand All @@ -9,10 +10,15 @@ import (

func TestDataRace(t *testing.T) {
s := NewServer(mailstore.NewDummyMailstore())
s.Addr = "127.0.0.1:10143"
addr := "127.0.0.1:10143"
l, err := net.Listen("tcp", addr)
if err != nil {
t.Fatal(err)
}

go func() {
s.ListenAndServe()
s.Serve(l)
}()
time.Sleep(time.Millisecond)
s.Close()
l.Close()
}
2 changes: 1 addition & 1 deletion util/formatting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestSplitParams(t *testing.T) {
"FLAGS",
}
params := strings.Join(originalList, " ")
result := splitParams(params)
result := SplitParams(params)
for index, param := range originalList {
if result[index] != param {
t.Fatalf("Param %d does not match expected:\n"+
Expand Down

0 comments on commit 4021e9b

Please sign in to comment.