M internal/xmpptest/session.go => internal/xmpptest/session.go +54 -0
@@ 62,3 62,57 @@ func NewSession(state xmpp.SessionState, rw io.ReadWriter) *xmpp.Session {
}
return s
}
+
+// ClientServer is two coupled xmpp.Session's that can respond to one another in
+// tests.
+// The client session's methods are exposed to allow sending messages easily.
+type ClientServer struct {
+ *xmpp.Session
+ server *xmpp.Session
+}
+
+// NewClientServer returns a ClientServer with the client and server goroutines
+// started.
+// The server handler will be used to handle any messages sent through the
+// client (as if a server on the opposite end was responding).
+// Both serve goroutines are started when NewClient is called and shut down when
+// Client is closed.
+func NewClientServer(state xmpp.SessionState, server xmpp.Handler) ClientServer {
+ clientSessionReader, serverSessionWriter := io.Pipe()
+ serverSessionReader, clientSessionWriter := io.Pipe()
+ clientSession := NewSession(state, struct {
+ io.Reader
+ io.Writer
+ }{
+ Reader: clientSessionReader,
+ Writer: clientSessionWriter,
+ })
+ serverSession := NewSession(0, struct {
+ io.Reader
+ io.Writer
+ }{
+ Reader: serverSessionReader,
+ Writer: serverSessionWriter,
+ })
+ go func() {
+ /* #nosec */
+ clientSession.Serve(nil)
+ }()
+ go func() {
+ /* #nosec */
+ serverSession.Serve(server)
+ }()
+ return ClientServer{
+ Session: clientSession,
+ server: serverSession,
+ }
+}
+
+// Close calls the client and server sessions close methods.
+func (c ClientServer) Close() error {
+ err := c.Session.Close()
+ if e := c.server.Close(); e != nil {
+ err = e
+ }
+ return err
+}
M internal/xmpptest/session_test.go => internal/xmpptest/session_test.go +36 -0
@@ 6,10 6,14 @@ package xmpptest_test
import (
"bytes"
+ "context"
+ "encoding/xml"
"testing"
+ "mellium.im/xmlstream"
"mellium.im/xmpp"
"mellium.im/xmpp/internal/xmpptest"
+ "mellium.im/xmpp/stanza"
)
func TestNewSession(t *testing.T) {
@@ 25,3 29,35 @@ func TestNewSession(t *testing.T) {
t.Errorf("Buffer wrote unexpected tokens: `%s'", out)
}
}
+
+func TestNewClient(t *testing.T) {
+ state := xmpp.Secure
+ s := xmpptest.NewClientServer(state, xmpp.HandlerFunc(func(t xmlstream.TokenReadEncoder, start *xml.StartElement) error {
+ iq, err := stanza.NewIQ(*start)
+ if err != nil {
+ panic(err)
+ }
+ r := iq.Result(nil)
+ _, err = xmlstream.Copy(t, r)
+ return err
+ }))
+ origIQ := struct {
+ stanza.IQ
+ }{
+ IQ: stanza.IQ{
+ ID: "123",
+ },
+ }
+ resp, err := s.EncodeIQ(context.Background(), origIQ)
+ if err != nil {
+ t.Errorf("error encoding IQ: %v", err)
+ }
+ iq := stanza.IQ{}
+ err = xml.NewTokenDecoder(resp).Decode(&iq)
+ if err != nil {
+ t.Errorf("error decoding response: %v", err)
+ }
+ if iq.ID != origIQ.ID {
+ t.Errorf("Response IQ had wrong ID: want=%s, got=%s", origIQ.ID, iq.ID)
+ }
+}