Test and code refactor

This commit is contained in:
Mickael Remond 2018-01-17 18:47:34 +01:00
parent d33490cdc0
commit 993ca630f7
No known key found for this signature in database
GPG Key ID: E6F6045D79965AA3
5 changed files with 75 additions and 75 deletions

View File

@ -127,6 +127,7 @@ func (c *Client) Recv() <-chan interface{} {
} }
// Send sends message text. // Send sends message text.
// TODO Move to Go XML Marshaller
func (c *Client) Send(packet string) error { func (c *Client) Send(packet string) error {
fmt.Fprintf(c.Session.socketProxy, packet) // TODO handle errors fmt.Fprintf(c.Session.socketProxy, packet) // TODO handle errors
return nil return nil

View File

@ -58,20 +58,21 @@ func (c MyComponent) processIQ(iqType, id, from string, inner *xmpp.Node) {
switch inner.XMLName.Space + " " + iqType { switch inner.XMLName.Space + " " + iqType {
case NSDiscoInfo + " get": case NSDiscoInfo + " get":
fmt.Println("Send Disco Info") fmt.Println("Send Disco Info")
result := fmt.Sprintf(`<iq type='result'
from='%s' iq := xmpp.NewIQ("result", "admin@localhost", "test@localhost", "1", "en")
to='%s' payload := xmpp.DiscoInfo{
id='%s'> Identity: xmpp.Identity{
<query xmlns='http://jabber.org/protocol/disco#info'> Name: "Test Gateway",
<identity Category: "gateway",
category='%s' Type: "mqtt",
type='%s' },
name='%s'/> Features: []xmpp.Feature{
<feature var='http://jabber.org/protocol/disco#info'/> {Var: "http://jabber.org/protocol/disco#info"},
<feature var='http://jabber.org/protocol/disco#items'/> {Var: "http://jabber.org/protocol/disco#item"},
</query> },
</iq>`, c.xmpp.Host, from, id, c.Category, c.Type, c.Name) }
c.xmpp.Send(result) iq.AddPayload(&payload)
c.xmpp.Send(iq)
default: default:
iqErr := fmt.Sprintf(`<iq type='error' iqErr := fmt.Sprintf(`<iq type='error'
from='%s' from='%s'
@ -81,6 +82,6 @@ func (c MyComponent) processIQ(iqType, id, from string, inner *xmpp.Node) {
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> <feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error> </error>
</iq>`, c.xmpp.Host, from, id) </iq>`, c.xmpp.Host, from, id)
c.xmpp.Send(iqErr) c.xmpp.SendOld(iqErr) // FIXME Remove that method
} }
} }

View File

@ -94,7 +94,19 @@ func (c *Component) ReadPacket() (Packet, error) {
return next(c.decoder) return next(c.decoder)
} }
func (c *Component) Send(packet string) error { func (c *Component) Send(packet Packet) error {
data, err := xml.Marshal(packet)
if err != nil {
return errors.New("cannot marshal packet " + err.Error())
}
if _, err := fmt.Fprintf(c.conn, string(data)); err != nil {
return errors.New("cannot send packet " + err.Error())
}
return nil
}
func (c *Component) SendOld(packet string) error {
if _, err := fmt.Fprintf(c.conn, packet); err != nil { if _, err := fmt.Fprintf(c.conn, packet); err != nil {
return errors.New("cannot send packet " + err.Error()) return errors.New("cannot send packet " + err.Error())
} }

20
iq.go
View File

@ -152,7 +152,7 @@ func (iq *IQ) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if err != nil { if err != nil {
return err return err
} }
iq.Payload = append(iq.Payload, iqPl) // []IQPayload{iqPl} iq.Payload = append(iq.Payload, iqPl)
} }
} }
@ -232,17 +232,23 @@ func (*Node) IsIQPayload() {}
// Disco // Disco
type DiscoInfo struct { type DiscoInfo struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"` XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"`
Identity Identity Identity Identity `xml:"identity"`
Features []Feature `xml:"feature"`
} }
func (*DiscoInfo) IsIQPayload() {} func (*DiscoInfo) IsIQPayload() {}
type Identity struct { type Identity struct {
XMLName xml.Name `xml:"identity"` XMLName xml.Name `xml:"identity,omitempty"`
Name string `xml:"name,attr"` Name string `xml:"name,attr,omitempty"`
Category string `xml:"category,attr"` Category string `xml:"category,attr,omitempty"`
Type string `xml:"type,attr"` Type string `xml:"type,attr,omitempty"`
}
type Feature struct {
XMLName xml.Name `xml:"feature"`
Var string `xml:"var,attr"`
} }
// ============================================================================ // ============================================================================

View File

@ -2,9 +2,10 @@ package xmpp // import "fluux.io/xmpp"
import ( import (
"encoding/xml" "encoding/xml"
"fmt"
"reflect" "reflect"
"testing" "testing"
"github.com/google/go-cmp/cmp"
) )
func TestUnmarshalIqs(t *testing.T) { func TestUnmarshalIqs(t *testing.T) {
@ -30,63 +31,20 @@ func TestUnmarshalIqs(t *testing.T) {
} }
func TestGenerateIq(t *testing.T) { func TestGenerateIq(t *testing.T) {
iq := NewIQ("get", "admin@localhost", "test@localhost", "1", "en") iq := NewIQ("result", "admin@localhost", "test@localhost", "1", "en")
payload := Node{
XMLName: xml.Name{
Space: "http://jabber.org/protocol/disco#info",
Local: "query",
},
Nodes: []Node{
{XMLName: xml.Name{
Space: "http://jabber.org/protocol/disco#info",
Local: "identity",
},
Attrs: []xml.Attr{
{Name: xml.Name{Local: "category"}, Value: "gateway"},
{Name: xml.Name{Local: "type"}, Value: "mqtt"},
{Name: xml.Name{Local: "name"}, Value: "Test Gateway"},
},
Nodes: nil,
}},
}
iq.AddPayload(&payload)
data, err := xml.Marshal(iq)
if err != nil {
t.Errorf("cannot marshal xml structure")
}
fmt.Printf("XML Struct: %s\n", data)
var parsedIQ = new(IQ)
if err = xml.Unmarshal(data, parsedIQ); err != nil {
t.Errorf("Unmarshal(%s) returned error", data)
}
if !reflect.DeepEqual(parsedIQ.Payload[0], iq.Payload[0]) {
t.Errorf("expecting result %+v = %+v", parsedIQ.Payload[0], iq.Payload[0])
}
fmt.Println("ParsedIQ", parsedIQ)
}
func TestGenerateIqNew(t *testing.T) {
iq := NewIQ("get", "admin@localhost", "test@localhost", "1", "en")
payload := DiscoInfo{ payload := DiscoInfo{
XMLName: xml.Name{
Space: "http://jabber.org/protocol/disco#info",
Local: "query",
},
Identity: Identity{ Identity: Identity{
XMLName: xml.Name{
Space: "http://jabber.org/protocol/disco#info",
Local: "identity",
},
Name: "Test Gateway", Name: "Test Gateway",
Category: "gateway", Category: "gateway",
Type: "mqtt", Type: "mqtt",
}, },
Features: []Feature{
{Var: "http://jabber.org/protocol/disco#info"},
{Var: "http://jabber.org/protocol/disco#item"},
},
} }
iq.AddPayload(&payload) iq.AddPayload(&payload)
data, err := xml.Marshal(iq) data, err := xml.Marshal(iq)
if err != nil { if err != nil {
t.Errorf("cannot marshal xml structure") t.Errorf("cannot marshal xml structure")
@ -97,7 +55,29 @@ func TestGenerateIqNew(t *testing.T) {
t.Errorf("Unmarshal(%s) returned error", data) t.Errorf("Unmarshal(%s) returned error", data)
} }
if !reflect.DeepEqual(parsedIQ.Payload[0], iq.Payload[0]) { if !xmlEqual(parsedIQ.Payload, iq.Payload) {
t.Errorf("expecting result %+v = %+v", parsedIQ.Payload[0], iq.Payload[0]) t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ.Payload, iq.Payload))
} }
} }
// Compare iq structure but ignore empty namespace as they are set properly on
// marshal / unmarshal. There is no need to manage them on the manually
// crafted structure.
func xmlEqual(x, y interface{}) bool {
alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
opts := cmp.Options{
cmp.FilterValues(func(x, y interface{}) bool {
xx, xok := x.(xml.Name)
yy, yok := y.(xml.Name)
if xok && yok {
zero := xml.Name{}
if xx == zero || yy == zero {
return true
}
}
return false
}, alwaysEqual),
}
return cmp.Equal(x, y, opts)
}