Test and code refactor
This commit is contained in:
parent
d33490cdc0
commit
993ca630f7
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
component.go
14
component.go
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
18
iq.go
18
iq.go
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,16 +233,22 @@ func (*Node) IsIQPayload() {}
|
||||||
|
|
||||||
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
84
iq_test.go
84
iq_test.go
|
@ -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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue