func (s *SessionXmppSuite) Test_WatchStanzas_getsVersionInfoIQ(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='get' from='abc' to='cde'><query xmlns='jabber:iq:version'/></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, connStatus: DISCONNECTED, } sess.conn = conn stanzaChan := make(chan data.Stanza, 1) stanza, _ := conn.Next() stanzaChan <- stanza sess.receiveStanza(stanzaChan) c.Assert(string(mockIn.write), Equals, ""+ "<iq to='abc' from='[email protected]/foo' type='result' id=''>"+ "<query xmlns=\"jabber:iq:version\">"+ "<name>testing</name>"+ "<version>version</version>"+ "<os>none</os>"+ "</query>"+ "</iq>") }
func (s *SessionXmppSuite) Test_WatchStanzas_iq_set_roster_withFromContainingJid(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='set' from='[email protected]/foo' to='cde'><query xmlns='jabber:iq:roster'/></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() assertLogContains(c, observer, events.Log{ Level: events.Warn, Message: "Failed to parse roster push IQ", }) }
func (s *SessionXmppSuite) Test_WatchStanzas_presence_unavailable_forNoneKnownUser(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:presence xmlns:client='jabber:client' from='[email protected]/balcony' to='*****@*****.**' type='unavailable'><client:status>going on vacation</client:status></client:presence>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() select { case ev := <-observer: switch ev.(type) { case events.Presence: c.Error("Received presence event") return default: // ignore } case <-time.After(1 * time.Millisecond): return } }
func (s *SessionXmppSuite) Test_WatchStanzas_failsOnUnrecognizedIQ(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='something'></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() for { select { case ev := <-observer: t := ev.(events.Log) if t.Level != events.Info { continue } c.Assert(t.Message, Equals, "unrecognized iq: &data.ClientIQ{XMLName:xml.Name{Space:\"jabber:client\", Local:\"iq\"}, From:\"\", ID:\"\", To:\"\", Type:\"something\", Error:data.ClientError{XMLName:xml.Name{Space:\"\", Local:\"\"}, Code:\"\", Type:\"\", Any:xml.Name{Space:\"\", Local:\"\"}, Text:\"\"}, Bind:data.BindBind{XMLName:xml.Name{Space:\"\", Local:\"\"}, Resource:\"\", Jid:\"\"}, Query:[]uint8{}}") return case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionXmppSuite) Test_WatchStanzas_getsDiscoInfoIQ(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='get' from='abc' to='cde'><query xmlns='http://jabber.org/protocol/disco#info'/></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, connStatus: DISCONNECTED, } sess.conn = conn stanzaChan := make(chan data.Stanza, 1) stanza, _ := conn.Next() stanzaChan <- stanza sess.receiveStanza(stanzaChan) c.Assert(string(mockIn.write), Equals, ""+ "<iq to='abc' from='[email protected]/foo' type='result' id=''>"+ "<query xmlns=\"http://jabber.org/protocol/disco#info\">"+ "<node></node>"+ "<identity xmlns=\"http://jabber.org/protocol/disco#info\" category=\"client\" type=\"pc\" name=\"[email protected]\"></identity>"+ "</query>"+ "</iq>") }
func (s *SessionXmppSuite) Test_WatchStanzas_handlesUnknownMessage(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<bind:bind xmlns:bind='urn:ietf:params:xml:ns:xmpp-bind'></bind:bind>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() for { select { case ev := <-observer: t := ev.(events.Log) if t.Level != events.Info { continue } c.Assert(t.Message, Equals, "RECEIVED {urn:ietf:params:xml:ns:xmpp-bind bind} &{{urn:ietf:params:xml:ns:xmpp-bind bind} }") return case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionXmppSuite) Test_WatchStanzas_warnsAndExitsOnBadStanza(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<clientx:message xmlns:client='jabber:client' to='*****@*****.**' from='*****@*****.**' type='chat'><client:body>something</client:body></client:message>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() select { case ev := <-observer: t := ev.(events.Log) c.Assert(t.Message, Equals, "error reading XMPP message: unexpected XMPP message clientx <message/>") case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") } }
func (s *SessionXmppSuite) Test_HandleConfirmOrDeny_succeedsOnAllowedAndAskBack(c *C) { mockIn := &mockConnIOReaderWriter{} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) called := 0 sess := &session{ r: roster.New(), sessionEventHandler: &mockSessionEventHandler{ //warn: func(v string) { // called++ //}, }, } sess.conn = conn sess.r.SubscribeRequest("*****@*****.**", "123", "") sess.HandleConfirmOrDeny("*****@*****.**", true) c.Assert(called, Equals, 0) c.Assert(string(mockIn.write), Matches, "<presence id='123' to='*****@*****.**' type='subscribed'/><presence id='[0-9]+' to='*****@*****.**' type='subscribe'/>") _, inMap := sess.r.GetPendingSubscribe("*****@*****.**") c.Assert(inMap, Equals, false) }
func (s *SessionXmppSuite) Test_WatchStanzas_iq_set_roster_setsExistingRosterItem(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='set' to='cde'><query xmlns='jabber:iq:roster'>" + "<item jid='*****@*****.**' name='Romeo' subscription='both'>" + "<group>Friends</group>" + "</item>" + "</query></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) called := 0 sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn sess.r.AddOrReplace(peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Jill", Group: []string{"Foes"}}, sess.GetConfig())) sess.r.AddOrReplace(peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Mo", Group: []string{"Foes"}}, sess.GetConfig())) sess.watchStanzas() c.Assert(called, Equals, 0) c.Assert(sess.r.ToSlice(), DeepEquals, []*roster.Peer{ peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Jill", Group: []string{"Foes"}}, sess.GetConfig()), peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Romeo", Group: []string{"Friends"}}, sess.GetConfig()), }) }
func (s *SessionXmppSuite) Test_WatchStanzas_iq_set_roster_withBadFrom(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='set' from='*****@*****.**' to='cde'><query xmlns='jabber:iq:roster'/></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) stanzaChan := make(chan data.Stanza, 1) stanza, _ := conn.Next() stanzaChan <- stanza sess.receiveStanza(stanzaChan) assertLogContains(c, observer, events.Log{ Level: events.Warn, Message: "Ignoring roster IQ from bad address: [email protected]", }) c.Assert(string(mockIn.write), Equals, "") }
func (s *SessionXmppSuite) Test_WatchStanzas_iq_set_roster_removesRosterItems(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='set' to='cde'><query xmlns='jabber:iq:roster'>" + "<item jid='*****@*****.**' name='Romeo' subscription='remove'>" + "<group>Friends</group>" + "</item>" + "</query></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn sess.r.AddOrReplace(peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Mo", Group: []string{"Foes"}}, sess.GetConfig())) sess.r.AddOrReplace(peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Jill", Group: []string{"Foes"}}, sess.GetConfig())) sess.r.AddOrReplace(peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Mo", Group: []string{"Foes"}}, sess.GetConfig())) observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() c.Assert(sess.r.ToSlice(), DeepEquals, []*roster.Peer{ peerFrom(data.RosterEntry{Jid: "*****@*****.**", Subscription: "both", Name: "Jill", Group: []string{"Foes"}}, sess.GetConfig()), }) select { case ev := <-observer: switch ev.(type) { case events.Peer: c.Error("Received peer event") return default: // ignore } case <-time.After(1 * time.Millisecond): return } }
func (s *SessionXmppSuite) Test_WatchStanzas_presence_unavailable_forKnownUser(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:presence xmlns:client='jabber:client' from='[email protected]/balcony' to='*****@*****.**' type='unavailable'><client:status>going on vacation</client:status></client:presence>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{}, r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn sess.r.AddOrReplace(roster.PeerWithState("*****@*****.**", "somewhere", "", "")) observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() p, _ := sess.r.Get("*****@*****.**") c.Assert(p.Online, Equals, false) for { select { case ev := <-observer: switch t := ev.(type) { case events.Presence: c.Assert(t.Gone, Equals, true) return default: //ignore } case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionXmppSuite) Test_WatchStanzas_presence_subscribe(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:presence xmlns:client='jabber:client' from='[email protected]/balcony' to='*****@*****.**' type='subscribe' id='adf12112'/>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{}, r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn sess.watchStanzas() v, _ := sess.r.GetPendingSubscribe("*****@*****.**") c.Assert(v, Equals, "adf12112") }
func (s *SessionSuite) Test_WatchStanzas_receivesAMessage(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:message xmlns:client='jabber:client' type='chat' to='[email protected]/foo' from='[email protected]/somewhere'><client:body>well, hello there</client:body></client:message>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := Factory( &config.ApplicationConfig{}, &config.Account{InstanceTag: uint32(42)}, xmpp.DialerFactory, ).(*session) sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() for { select { case ev := <-observer: switch t := ev.(type) { case events.Message: c.Assert(t.Session, Equals, sess) c.Assert(t.Encrypted, Equals, false) c.Assert(t.From, Equals, "*****@*****.**") c.Assert(string(t.Body), Equals, "well, hello there") return default: //ignore } case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionXmppSuite) Test_WatchStanzas_presence_regularPresenceIsAdded(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:presence xmlns:client='jabber:client' from='[email protected]/balcony' to='*****@*****.**'><client:show>dnd</client:show></client:presence>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{}, r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() st, _, _ := sess.r.StateOf("*****@*****.**") c.Assert(st, Equals, "dnd") for { select { case ev := <-observer: switch t := ev.(type) { case events.Presence: c.Assert(t.Gone, Equals, false) default: //ignore } return case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionXmppSuite) Test_WatchStanzas_getsUnknown(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:iq xmlns:client='jabber:client' type='get' from='abc' to='cde'><query xmlns='jabber:iq:somethingStrange'/></client:iq>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{ Account: "*****@*****.**", }, connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() for { select { case ev := <-observer: t := ev.(events.Log) if t.Level != events.Info { continue } c.Assert(t.Message, Equals, "Unknown IQ: jabber:iq:somethingStrange query") return case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionXmppSuite) Test_WatchStanzas_presence_unknown(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:presence xmlns:client='jabber:client' from='[email protected]/balcony' to='*****@*****.**' type='weird'/>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{}, connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() select { case ev := <-observer: switch t := ev.(type) { case events.Presence: c.Error("Received presence event") return case events.Peer: if t.Type == events.SubscriptionRequest { c.Error("Received subscription request event") } return default: // ignore } case <-time.After(1 * time.Millisecond): return } }
func (s *SessionSuite) Test_WatchStanzas_presence_ignoresSameState(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<client:presence xmlns:client='jabber:client' from='[email protected]/balcony' to='*****@*****.**'><client:show>dnd</client:show></client:presence>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ config: &config.ApplicationConfig{}, accountConfig: &config.Account{}, r: roster.New(), connStatus: DISCONNECTED, } sess.conn = conn sess.r.AddOrReplace(roster.PeerWithState("*****@*****.**", "dnd", "", "", "")) observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() st, _, _ := sess.r.StateOf("*****@*****.**") c.Assert(st, Equals, "dnd") select { case ev := <-observer: switch ev.(type) { case events.Presence: c.Error("Received presence event") return default: // ignore } case <-time.After(1 * time.Millisecond): return } }
func (s *SessionXmppSuite) Test_WatchStanzas_handlesStreamError_withText(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<stream:error xmlns:stream='http://etherx.jabber.org/streams'><stream:text>bad horse showed up</stream:text></stream:error>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.watchStanzas() assertLogContains(c, observer, events.Log{ Level: events.Alert, Message: "Exiting in response to fatal error from server: bad horse showed up", }) }
func (s *SessionXmppSuite) Test_WatchStanzas_handlesStreamError_withEmbeddedTag(c *C) { mockIn := &mockConnIOReaderWriter{read: []byte("<stream:error xmlns:stream='http://etherx.jabber.org/streams'><not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/></stream:error>")} conn := xmpp.NewConn( xml.NewDecoder(mockIn), mockIn, "[email protected]/foo", ) sess := &session{ connStatus: DISCONNECTED, } sess.conn = conn observer := make(chan interface{}, 2) sess.Subscribe(observer) sess.watchStanzas() assertLogContains(c, observer, events.Log{ Level: events.Alert, Message: "Exiting in response to fatal error from server: {urn:ietf:params:xml:ns:xmpp-streams not-well-formed}", }) }
func (s *SessionXmppSuite) Test_HandleConfirmOrDeny_handlesSendPresenceError(c *C) { mockIn := &mockConnIOReaderWriter{} conn := xmpp.NewConn( xml.NewDecoder(mockIn), &mockConnIOReaderWriter{err: errors.New("foo bar")}, "[email protected]/foo", ) sess := &session{ r: roster.New(), } sess.conn = conn sess.r.SubscribeRequest("*****@*****.**", "123", "") observer := make(chan interface{}, 1) sess.Subscribe(observer) sess.HandleConfirmOrDeny("*****@*****.**", true) for { select { case ev := <-observer: t := ev.(events.Log) if t.Level != events.Warn { continue } c.Assert(t.Message, Equals, "Error sending presence stanza: foo bar") return case <-time.After(1 * time.Millisecond): c.Errorf("did not receive event") return } } }
func (s *SessionSuite) Test_watchTimeouts_cancelsTimedoutRequestsAndForgetsAboutThem(c *C) { now := time.Now() timeouts := map[data.Cookie]time.Time{ data.Cookie(1): now.Add(-1 * time.Second), data.Cookie(2): now.Add(10 * time.Second), } sess := &session{ connStatus: CONNECTED, timeouts: timeouts, conn: xmpp.NewConn(nil, nil, ""), } go func() { <-time.After(1 * time.Second) sess.connStatus = DISCONNECTED }() sess.watchTimeout() c.Check(sess.timeouts, HasLen, 1) _, ok := sess.timeouts[data.Cookie(2)] c.Check(ok, Equals, true) }