go-xmpp/stanza/iq_test.go

241 lines
6.1 KiB
Go
Raw Permalink Normal View History

package stanza_test
2016-02-15 17:33:51 +00:00
import (
"encoding/xml"
2018-01-26 10:16:04 +00:00
"strings"
2016-02-15 17:33:51 +00:00
"testing"
2018-01-17 17:47:34 +00:00
"github.com/google/go-cmp/cmp"
2019-06-26 15:28:54 +00:00
"gosrc.io/xmpp/stanza"
2016-02-15 17:33:51 +00:00
)
func TestUnmarshalIqs(t *testing.T) {
2017-10-04 20:51:28 +00:00
//var cs1 = new(iot.ControlSet)
2016-02-15 17:33:51 +00:00
var tests = []struct {
iqString string
2019-06-26 15:28:54 +00:00
parsedIQ stanza.IQ
2016-02-15 17:33:51 +00:00
}{
{"<iq id=\"1\" type=\"set\" to=\"test@localhost\"/>",
2019-06-26 15:28:54 +00:00
stanza.IQ{XMLName: xml.Name{Local: "iq"}, Attrs: stanza.Attrs{Type: stanza.IQTypeSet, To: "test@localhost", Id: "1"}}},
2018-01-13 17:50:17 +00:00
//{"<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 17:33:51 +00:00
}
for _, test := range tests {
2019-06-26 15:28:54 +00:00
parsedIQ := stanza.IQ{}
2018-01-18 16:03:54 +00:00
err := xml.Unmarshal([]byte(test.iqString), &parsedIQ)
2016-02-15 17:33:51 +00:00
if err != nil {
t.Errorf("Unmarshal(%s) returned error", test.iqString)
}
2018-01-18 16:03:54 +00:00
if !xmlEqual(parsedIQ, test.parsedIQ) {
t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ, test.parsedIQ))
2016-02-15 17:33:51 +00:00
}
2018-01-18 16:03:54 +00:00
2016-02-15 17:33:51 +00:00
}
}
2018-01-15 11:28:34 +00:00
2019-10-28 20:21:35 +00:00
func TestGenerateIqId(t *testing.T) {
t.Parallel()
iq, err := stanza.NewIQ(stanza.Attrs{Id: "1", Type: "dummy type"})
if err != nil {
t.Fatalf("failed to create IQ: %v", err)
}
2019-10-28 20:21:35 +00:00
if iq.Id != "1" {
t.Errorf("NewIQ replaced id with %s", iq.Id)
}
iq, err = stanza.NewIQ(stanza.Attrs{Type: "dummy type"})
if err != nil {
t.Fatalf("failed to create IQ: %v", err)
}
2019-11-04 15:32:29 +00:00
if iq.Id == "" {
2019-10-28 20:21:35 +00:00
t.Error("NewIQ did not generate an Id")
}
otherIq, err := stanza.NewIQ(stanza.Attrs{Type: "dummy type"})
if err != nil {
t.Fatalf("failed to create IQ: %v", err)
}
2019-10-28 20:21:35 +00:00
if iq.Id == otherIq.Id {
t.Errorf("NewIQ generated two identical ids: %s", iq.Id)
}
}
2018-01-15 11:28:34 +00:00
func TestGenerateIq(t *testing.T) {
iq, err := stanza.NewIQ(stanza.Attrs{Type: stanza.IQTypeResult, From: "admin@localhost", To: "test@localhost", Id: "1"})
if err != nil {
t.Fatalf("failed to create IQ: %v", err)
}
2019-06-26 15:28:54 +00:00
payload := stanza.DiscoInfo{
Identity: []stanza.Identity{
{Name: "Test Gateway",
Category: "gateway",
Type: "mqtt",
}},
2019-06-26 15:28:54 +00:00
Features: []stanza.Feature{
{Var: stanza.NSDiscoInfo},
{Var: stanza.NSDiscoItems},
2018-01-17 17:47:34 +00:00
},
2018-01-16 21:33:21 +00:00
}
iq.Payload = &payload
2018-01-17 17:47:34 +00:00
2018-01-16 21:33:21 +00:00
data, err := xml.Marshal(iq)
if err != nil {
t.Errorf("cannot marshal xml structure")
}
2018-01-26 10:16:04 +00:00
if strings.Contains(string(data), "<error ") {
t.Error("empty error should not be serialized")
}
2019-06-26 15:28:54 +00:00
parsedIQ := stanza.IQ{}
2018-01-18 16:03:54 +00:00
if err = xml.Unmarshal(data, &parsedIQ); err != nil {
2018-01-15 11:28:34 +00:00
t.Errorf("Unmarshal(%s) returned error", data)
}
if !xmlEqual(iq.Payload, parsedIQ.Payload) {
t.Errorf("non matching items\n%s", xmlDiff(iq.Payload, parsedIQ.Payload))
2018-01-17 17:47:34 +00:00
}
}
2018-01-20 17:09:13 +00:00
func TestErrorTag(t *testing.T) {
2019-06-26 15:28:54 +00:00
xError := stanza.Err{
2018-01-20 17:09:13 +00:00
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)
}
2019-06-26 15:28:54 +00:00
parsedError := stanza.Err{}
2018-01-20 17:09:13 +00:00
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))
}
}
func TestDiscoItems(t *testing.T) {
iq, err := stanza.NewIQ(stanza.Attrs{Type: stanza.IQTypeGet, From: "romeo@montague.net/orchard", To: "catalog.shakespeare.lit", Id: "items3"})
if err != nil {
t.Fatalf("failed to create IQ: %v", err)
}
2019-06-26 15:28:54 +00:00
payload := stanza.DiscoItems{
Node: "music",
}
iq.Payload = &payload
data, err := xml.Marshal(iq)
if err != nil {
t.Errorf("cannot marshal xml structure")
}
2019-06-26 15:28:54 +00:00
parsedIQ := stanza.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))
}
}
2019-06-10 10:30:01 +00:00
func TestUnmarshalPayload(t *testing.T) {
query := "<iq to='service.localhost' type='get' id='1'><query xmlns='jabber:iq:version'/></iq>"
2019-06-26 15:28:54 +00:00
parsedIQ := stanza.IQ{}
2019-06-10 10:30:01 +00:00
err := xml.Unmarshal([]byte(query), &parsedIQ)
if err != nil {
t.Errorf("Unmarshal(%s) returned error", query)
}
if parsedIQ.Payload == nil {
t.Error("Missing payload")
2019-06-10 10:30:01 +00:00
}
2019-06-19 09:19:16 +00:00
namespace := parsedIQ.Payload.Namespace()
if namespace != "jabber:iq:version" {
t.Errorf("incorrect namespace: %s", namespace)
}
2019-06-10 10:30:01 +00:00
}
func TestPayloadWithError(t *testing.T) {
iq := `<iq xml:lang='en' to='test1@localhost/resource' from='test@localhost' type='error' id='aac1a'>
<query xmlns='jabber:iq:version'/>
<error code='407' type='auth'>
<subscription-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Not subscribed</text>
</error>
</iq>`
2019-06-26 15:28:54 +00:00
parsedIQ := stanza.IQ{}
err := xml.Unmarshal([]byte(iq), &parsedIQ)
if err != nil {
t.Errorf("Unmarshal error: %s", iq)
return
}
if parsedIQ.Error.Reason != "subscription-required" {
t.Errorf("incorrect error value: '%s'", parsedIQ.Error.Reason)
}
}
func TestUnknownPayload(t *testing.T) {
iq := `<iq type="get" to="service.localhost" id="1" >
<query xmlns="unknown:ns"/>
</iq>`
2019-06-26 15:28:54 +00:00
parsedIQ := stanza.IQ{}
err := xml.Unmarshal([]byte(iq), &parsedIQ)
if err != nil {
t.Errorf("Unmarshal error: %#v (%s)", err, iq)
return
}
if parsedIQ.Any.XMLName.Space != "unknown:ns" {
t.Errorf("could not extract namespace: '%s'", parsedIQ.Any.XMLName.Space)
}
}
func TestIsValid(t *testing.T) {
type testCase struct {
iq string
shouldErr bool
}
testIQs := make(map[string]testCase)
testIQs["Valid IQ"] = testCase{
`<iq type="get" to="service.localhost" id="1" >
<query xmlns="unknown:ns"/>
</iq>`,
false,
}
testIQs["Invalid IQ"] = testCase{
`<iq type="get" to="service.localhost">
<query xmlns="unknown:ns"/>
</iq>`,
true,
}
for name, tcase := range testIQs {
t.Run(name, func(st *testing.T) {
parsedIQ := stanza.IQ{}
err := xml.Unmarshal([]byte(tcase.iq), &parsedIQ)
if err != nil {
t.Errorf("Unmarshal error: %#v (%s)", err, tcase.iq)
return
}
isValid, err := parsedIQ.IsValid()
if !isValid && !tcase.shouldErr {
t.Errorf("failed validation for iq because: %s\nin test case : %s", err, tcase.iq)
}
})
}
}