2018-01-01 09:12:33 -08:00
|
|
|
package xmpp // import "fluux.io/xmpp"
|
2016-02-15 09:33:51 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/xml"
|
2018-01-26 02:16:04 -08:00
|
|
|
"strings"
|
2016-02-15 09:33:51 -08:00
|
|
|
"testing"
|
2018-01-17 09:47:34 -08:00
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
2016-02-15 09:33:51 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestUnmarshalIqs(t *testing.T) {
|
2017-10-04 13:51:28 -07:00
|
|
|
//var cs1 = new(iot.ControlSet)
|
2016-02-15 09:33:51 -08:00
|
|
|
var tests = []struct {
|
|
|
|
iqString string
|
2018-01-13 09:50:17 -08:00
|
|
|
parsedIQ IQ
|
2016-02-15 09:33:51 -08:00
|
|
|
}{
|
2018-01-13 09:50:17 -08:00
|
|
|
{"<iq id=\"1\" type=\"set\" to=\"test@localhost\"/>", IQ{XMLName: xml.Name{Space: "", Local: "iq"}, PacketAttrs: PacketAttrs{To: "test@localhost", Type: "set", Id: "1"}}},
|
|
|
|
//{"<iq xmlns=\"jabber:client\" id=\"2\" type=\"set\" to=\"test@localhost\" from=\"server\"><set xmlns=\"urn:xmpp:iot:control\"/></iq>", IQ{XMLName: xml.Name{Space: "jabber:client", Local: "iq"}, PacketAttrs: PacketAttrs{To: "test@localhost", From: "server", Type: "set", Id: "2"}, Payload: cs1}},
|
2016-02-15 09:33:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
2018-01-18 08:03:54 -08:00
|
|
|
parsedIQ := IQ{}
|
|
|
|
err := xml.Unmarshal([]byte(test.iqString), &parsedIQ)
|
2016-02-15 09:33:51 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unmarshal(%s) returned error", test.iqString)
|
|
|
|
}
|
2018-01-18 08:03:54 -08:00
|
|
|
|
|
|
|
if !xmlEqual(parsedIQ, test.parsedIQ) {
|
|
|
|
t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ, test.parsedIQ))
|
2016-02-15 09:33:51 -08:00
|
|
|
}
|
2018-01-18 08:03:54 -08:00
|
|
|
|
2016-02-15 09:33:51 -08:00
|
|
|
}
|
|
|
|
}
|
2018-01-15 03:28:34 -08:00
|
|
|
|
|
|
|
func TestGenerateIq(t *testing.T) {
|
2018-01-17 09:47:34 -08:00
|
|
|
iq := NewIQ("result", "admin@localhost", "test@localhost", "1", "en")
|
2018-01-16 13:33:21 -08:00
|
|
|
payload := DiscoInfo{
|
|
|
|
Identity: Identity{
|
|
|
|
Name: "Test Gateway",
|
|
|
|
Category: "gateway",
|
|
|
|
Type: "mqtt",
|
|
|
|
},
|
2018-01-17 09:47:34 -08:00
|
|
|
Features: []Feature{
|
|
|
|
{Var: "http://jabber.org/protocol/disco#info"},
|
|
|
|
{Var: "http://jabber.org/protocol/disco#item"},
|
|
|
|
},
|
2018-01-16 13:33:21 -08:00
|
|
|
}
|
|
|
|
iq.AddPayload(&payload)
|
2018-01-17 09:47:34 -08:00
|
|
|
|
2018-01-16 13:33:21 -08:00
|
|
|
data, err := xml.Marshal(iq)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("cannot marshal xml structure")
|
|
|
|
}
|
|
|
|
|
2018-01-26 02:16:04 -08:00
|
|
|
if strings.Contains(string(data), "<error ") {
|
|
|
|
t.Error("empty error should not be serialized")
|
|
|
|
}
|
|
|
|
|
2018-01-18 08:03:54 -08:00
|
|
|
parsedIQ := IQ{}
|
|
|
|
if err = xml.Unmarshal(data, &parsedIQ); err != nil {
|
2018-01-15 03:28:34 -08:00
|
|
|
t.Errorf("Unmarshal(%s) returned error", data)
|
|
|
|
}
|
|
|
|
|
2018-01-17 09:47:34 -08:00
|
|
|
if !xmlEqual(parsedIQ.Payload, iq.Payload) {
|
|
|
|
t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ.Payload, iq.Payload))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-20 09:09:13 -08:00
|
|
|
func TestErrorTag(t *testing.T) {
|
|
|
|
xError := Err{
|
|
|
|
XMLName: xml.Name{Local: "error"},
|
|
|
|
Code: 503,
|
|
|
|
Type: "cancel",
|
|
|
|
Reason: "service-unavailable",
|
|
|
|
Text: "User session not found",
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := xml.Marshal(xError)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("cannot marshal xml structure: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
parsedError := Err{}
|
|
|
|
if err = xml.Unmarshal(data, &parsedError); err != nil {
|
|
|
|
t.Errorf("Unmarshal(%s) returned error", data)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !xmlEqual(parsedError, xError) {
|
|
|
|
t.Errorf("non matching items\n%s", cmp.Diff(parsedError, xError))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-26 00:24:34 -08:00
|
|
|
func TestDiscoItems(t *testing.T) {
|
|
|
|
iq := NewIQ("get", "romeo@montague.net/orchard", "catalog.shakespeare.lit", "items3", "en")
|
|
|
|
payload := DiscoItems{
|
|
|
|
Node: "music",
|
|
|
|
}
|
|
|
|
iq.AddPayload(&payload)
|
|
|
|
|
|
|
|
data, err := xml.Marshal(iq)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("cannot marshal xml structure")
|
|
|
|
}
|
|
|
|
|
|
|
|
parsedIQ := IQ{}
|
|
|
|
if err = xml.Unmarshal(data, &parsedIQ); err != nil {
|
|
|
|
t.Errorf("Unmarshal(%s) returned error", data)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !xmlEqual(parsedIQ.Payload, iq.Payload) {
|
|
|
|
t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ.Payload, iq.Payload))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-17 09:47:34 -08:00
|
|
|
// 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),
|
2018-01-15 03:28:34 -08:00
|
|
|
}
|
2018-01-17 09:47:34 -08:00
|
|
|
|
|
|
|
return cmp.Equal(x, y, opts)
|
2018-01-15 03:28:34 -08:00
|
|
|
}
|