1package xmpp
2
3import (
4	"encoding/xml"
5	"errors"
6
7	"github.com/coyim/coyim/xmpp/data"
8
9	. "gopkg.in/check.v1"
10)
11
12type StreamsXMPPSuite struct{}
13
14var _ = Suite(&StreamsXMPPSuite{})
15
16func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_returnsErrorIfSomethingGoesWrongWithFmtPrintf(c *C) {
17	conn := conn{
18		out:          &mockConnIOReaderWriter{err: errors.New("Hello")},
19		originDomain: "foo.com",
20	}
21
22	err := conn.SendInitialStreamHeader()
23	c.Assert(err, Not(IsNil))
24}
25
26func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_returnsErrorIfSomethingGoesWrongWithReadingAStream(c *C) {
27	mockIn := &mockConnIOReaderWriter{err: errors.New("Hello")}
28	conn := conn{
29		out:          &mockConnIOReaderWriter{},
30		in:           xml.NewDecoder(mockIn),
31		originDomain: "foo.com",
32	}
33
34	err := conn.SendInitialStreamHeader()
35	c.Assert(err, Not(IsNil))
36}
37
38func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_sendsInitialStreamHeaderToOutput(c *C) {
39	mockOut := &mockConnIOReaderWriter{}
40	mockIn := &mockConnIOReaderWriter{err: errors.New("Hello")}
41	conn := conn{
42		out:          mockOut,
43		in:           xml.NewDecoder(mockIn),
44		originDomain: "somewhere.org",
45	}
46	conn.SendInitialStreamHeader()
47	c.Assert(string(mockOut.write), Equals, "<?xml version='1.0'?><stream:stream to='somewhere.org' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n")
48}
49
50func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_expectsResponseStreamHeaderInReturn(c *C) {
51	mockOut := &mockConnIOReaderWriter{}
52	mockIn := &mockConnIOReaderWriter{read: []byte("<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0'></stream:stream>")}
53	conn := conn{
54		out:          mockOut,
55		in:           xml.NewDecoder(mockIn),
56		originDomain: "somewhereElse.org",
57	}
58
59	err := conn.SendInitialStreamHeader()
60	c.Assert(err.Error(), Equals, "xmpp: error to unmarshal <features>: EOF")
61}
62
63func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_failsIfReturnedStreamIsNotCorrectNamespace(c *C) {
64	mockOut := &mockConnIOReaderWriter{}
65	mockIn := &mockConnIOReaderWriter{read: []byte("<?xml version='1.0'?><str:stream xmlns:str='http://etherx.jabber.org/streams2' version='1.0'>")}
66	conn := conn{
67		out:          mockOut,
68		in:           xml.NewDecoder(mockIn),
69		originDomain: "somewhereElse.org",
70	}
71
72	err := conn.SendInitialStreamHeader()
73	c.Assert(err.Error(), Equals, "xmpp: expected <stream> but got <stream> in http://etherx.jabber.org/streams2")
74}
75
76func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_failsIfReturnedElementIsNotStream(c *C) {
77	mockOut := &mockConnIOReaderWriter{}
78	mockIn := &mockConnIOReaderWriter{read: []byte("<?xml version='1.0'?><str:feature xmlns:str='http://etherx.jabber.org/streams' version='1.0'>")}
79	conn := conn{
80		out:          mockOut,
81		in:           xml.NewDecoder(mockIn),
82		originDomain: "somewhereElse.org",
83	}
84
85	err := conn.SendInitialStreamHeader()
86	c.Assert(err.Error(), Equals, "xmpp: expected <stream> but got <feature> in http://etherx.jabber.org/streams")
87}
88
89func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_expectsFeaturesInReturn(c *C) {
90	mockOut := &mockConnIOReaderWriter{}
91	mockIn := &mockConnIOReaderWriter{read: []byte("<?xml version='1.0'?><str:stream xmlns:str='http://etherx.jabber.org/streams' version='1.0'><str:features></str:features>")}
92	conn := conn{
93		out:          mockOut,
94		in:           xml.NewDecoder(mockIn),
95		originDomain: "somewhereElse.org",
96	}
97
98	err := conn.SendInitialStreamHeader()
99	c.Assert(err, IsNil)
100	expected := data.StreamFeatures{}
101	expected.XMLName = xml.Name{Space: "http://etherx.jabber.org/streams", Local: "features"}
102	c.Assert(conn.features, DeepEquals, expected)
103}
104
105func (s *StreamsXMPPSuite) Test_sendInitialStreamHeader_receiveResponseStreamHeaderInReturn(c *C) {
106	mockOut := &mockConnIOReaderWriter{}
107	mockIn := &mockConnIOReaderWriter{read: []byte(`
108	<?xml version='1.0'?>
109	<str:stream xmlns:str='http://etherx.jabber.org/streams' version='1.0'>
110		<str:features>
111			<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' />
112			<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
113				<required/>
114			</starttls>
115			<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
116				<mechanism>PLAIN</mechanism>
117				<mechanism>X-OAUTH2</mechanism>
118				<mechanism>X-GOOGLE-TOKEN</mechanism>
119			</mechanisms>
120			<register xmlns='http://jabber.org/features/iq-register'/>
121		</str:features>
122	`)}
123	conn := conn{
124		out:          mockOut,
125		in:           xml.NewDecoder(mockIn),
126		originDomain: "somewhereElse.org",
127	}
128
129	err := conn.SendInitialStreamHeader()
130	c.Assert(err, IsNil)
131	expected := data.StreamFeatures{
132		XMLName: xml.Name{Space: "http://etherx.jabber.org/streams", Local: "features"},
133		Bind: data.BindBind{
134			XMLName: xml.Name{Space: "urn:ietf:params:xml:ns:xmpp-bind", Local: "bind"}, Resource: "", Jid: "",
135		},
136		StartTLS: data.StartTLS{
137			XMLName:  xml.Name{Space: "urn:ietf:params:xml:ns:xmpp-tls", Local: "starttls"},
138			Required: xml.Name{Space: "urn:ietf:params:xml:ns:xmpp-tls", Local: "required"},
139		},
140		Mechanisms: data.SaslMechanisms{
141			XMLName:   xml.Name{Space: "urn:ietf:params:xml:ns:xmpp-sasl", Local: "mechanisms"},
142			Mechanism: []string{"PLAIN", "X-OAUTH2", "X-GOOGLE-TOKEN"},
143		},
144		InBandRegistration: &data.InBandRegistration{
145			XMLName: xml.Name{Space: "http://jabber.org/features/iq-register", Local: "register"},
146		},
147	}
148
149	c.Assert(conn.features, DeepEquals, expected)
150}
151