package stanza_test
import (
"encoding/xml"
"errors"
"gosrc.io/xmpp/stanza"
"strings"
"testing"
)
var submitFormExample = stanza.NewForm([]*stanza.Field{
{Var: "FORM_TYPE", Type: stanza.FieldTypeHidden, ValuesList: []string{"http://jabber.org/protocol/pubsub#node_config"}},
{Var: "pubsub#title", ValuesList: []string{"Princely Musings (Atom)"}},
{Var: "pubsub#deliver_notifications", ValuesList: []string{"1"}},
{Var: "pubsub#access_model", ValuesList: []string{"roster"}},
{Var: "pubsub#roster_groups_allowed", ValuesList: []string{"friends", "servants", "courtiers"}},
{Var: "pubsub#type", ValuesList: []string{"http://www.w3.org/2005/Atom"}},
{
Var: "pubsub#notification_type",
Type: "list-single",
Label: "Specify the delivery style for event notifications",
ValuesList: []string{"headline"},
Options: []stanza.Option{
{ValuesList: []string{"normal"}},
{ValuesList: []string{"headline"}},
},
},
}, stanza.FormTypeSubmit)
// ***********************************
// * 6.1 Subscribe to a Node
// ***********************************
func TestNewSubRequest(t *testing.T) {
expectedReq := " " +
"" +
" "
subInfo := stanza.SubInfo{
Node: "princely_musings", Jid: "francisco@denmark.lit",
}
subR, err := stanza.NewSubRq("pubsub.shakespeare.lit", subInfo)
if err != nil {
t.Fatalf("failed to create a sub request: %v", err)
}
subR.Id = "sub1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestNewSubResp(t *testing.T) {
response := `
`
pubsub, err := getPubSubGenericPayload(response)
if err != nil {
t.Fatalf(err.Error())
}
if pubsub.Subscription == nil {
t.Fatalf("subscription node is nil")
}
if pubsub.Subscription.Node == "" ||
pubsub.Subscription.Jid == "" ||
pubsub.Subscription.SubId == nil ||
pubsub.Subscription.SubStatus == "" {
t.Fatalf("one or more of the subscription attributes was not successfully decoded")
}
}
// ***********************************
// * 6.2 Unsubscribe from a Node
// ***********************************
func TestNewUnSubRequest(t *testing.T) {
expectedReq := " " +
" " +
""
subInfo := stanza.SubInfo{
Node: "princely_musings", Jid: "francisco@denmark.lit",
}
subR, err := stanza.NewUnsubRq("pubsub.shakespeare.lit", subInfo)
if err != nil {
t.Fatalf("failed to create an unsub request: %v", err)
}
subR.Id = "unsub1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Unsubscribe == nil {
t.Fatalf("Unsubscribe tag should be present in sub config options request")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestNewUnsubResp(t *testing.T) {
response := `
`
pubsub, err := getPubSubGenericPayload(response)
if err != nil {
t.Fatalf(err.Error())
}
if pubsub.Subscription == nil {
t.Fatalf("subscription node is nil")
}
if pubsub.Subscription.Node == "" ||
pubsub.Subscription.Jid == "" ||
pubsub.Subscription.SubId == nil ||
pubsub.Subscription.SubStatus == "" {
t.Fatalf("one or more of the subscription attributes was not successfully decoded")
}
}
// ***************************************
// * 6.3 Configure Subscription Options
// ***************************************
func TestNewSubOptsRq(t *testing.T) {
expectedReq := " " +
" " +
""
subInfo := stanza.SubInfo{
Node: "princely_musings", Jid: "francisco@denmark.lit",
}
subR, err := stanza.NewSubOptsRq("pubsub.shakespeare.lit", subInfo)
if err != nil {
t.Fatalf("failed to create a sub options request: %v", err)
}
subR.Id = "options1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.SubOptions == nil {
t.Fatalf("Options tag should be present in sub config options request")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestNewNewConfOptsRsp(t *testing.T) {
response := `
http://jabber.org/protocol/pubsub#subscribe_options10falsechatonline
`
pubsub, err := getPubSubGenericPayload(response)
if err != nil {
t.Fatalf(err.Error())
}
if pubsub.SubOptions == nil {
t.Fatalf("sub options node is nil")
}
if pubsub.SubOptions.Form == nil {
t.Fatalf("the response form is nil")
}
if len(pubsub.SubOptions.Form.Fields) != 5 {
t.Fatalf("one or more fields in the response form could not be parsed correctly")
}
}
// ***************************************
// * 6.3.5 Form Submission
// ***************************************
func TestNewFormSubmission(t *testing.T) {
expectedReq := " " +
" " +
"" +
" http://jabber.org/protocol/pubsub#node_config " +
"Princely Musings (Atom) " +
"1roster " +
"friendsservants" +
" courtiershttp://www.w3.org/2005/Atom " +
" " +
"headline " +
""
subInfo := stanza.SubInfo{
Node: "princely_musings", Jid: "francisco@denmark.lit",
}
subR, err := stanza.NewFormSubmission("pubsub.shakespeare.lit", subInfo, submitFormExample)
if err != nil {
t.Fatalf("failed to create a form submission request: %v", err)
}
subR.Id = "options2"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.SubOptions == nil {
t.Fatalf("Options tag should be present in sub config options request")
}
if pubsub.SubOptions.Form == nil {
t.Fatalf("No form in form submit request !")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
// ***************************************
// * 6.3.7 Subscribe and Configure
// ***************************************
func TestNewSubAndConfig(t *testing.T) {
expectedReq := "" +
" " +
"" +
"" +
" http://jabber.org/protocol/pubsub#node_config " +
"Princely Musings (Atom) " +
"1roster " +
"friendsservants" +
" courtiershttp://www.w3.org/2005/Atom " +
" " +
"headline " +
""
subInfo := stanza.SubInfo{
Node: "princely_musings", Jid: "francisco@denmark.lit",
}
subR, err := stanza.NewSubAndConfig("pubsub.shakespeare.lit", subInfo, submitFormExample)
if err != nil {
t.Fatalf("failed to create a sub and config request: %v", err)
}
subR.Id = "sub1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.SubOptions == nil {
t.Fatalf("Options tag should be present in sub config options request")
}
if pubsub.SubOptions.Form == nil {
t.Fatalf("No form in form submit request !")
}
// The element MUST NOT possess a 'node' attribute or 'jid' attribute
// See XEP-0060
if pubsub.SubOptions.SubInfo.Node != "" || pubsub.SubOptions.SubInfo.Jid != "" {
t.Fatalf("SubInfo node and jid should be empty for the options tag !")
}
if pubsub.Subscribe.Node == "" || pubsub.Subscribe.Jid == "" {
t.Fatalf("SubInfo node and jid should NOT be empty for the subscribe tag !")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestNewSubAndConfigResp(t *testing.T) {
response := `
http://jabber.org/protocol/pubsub#subscribe_options10falsechatonlineaway
`
pubsub, err := getPubSubGenericPayload(response)
if err != nil {
t.Fatalf(err.Error())
}
if pubsub.Subscription == nil {
t.Fatalf("sub node is nil")
}
if pubsub.SubOptions == nil {
t.Fatalf("sub options node is nil")
}
if pubsub.SubOptions.Form == nil {
t.Fatalf("the response form is nil")
}
if len(pubsub.SubOptions.Form.Fields) != 5 {
t.Fatalf("one or more fields in the response form could not be parsed correctly")
}
}
// ***************************************
// * 6.5.2 Requesting All List
// ***************************************
func TestNewItemsRequest(t *testing.T) {
subR, err := stanza.NewItemsRequest("pubsub.shakespeare.lit", "princely_musings", 0)
if err != nil {
t.Fatalf("Could not create an items request : %s", err)
}
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Items == nil {
t.Fatalf("List tag should be present to request items from a service")
}
if len(pubsub.Items.List) != 0 {
t.Fatalf("There should be no items in the tag to request all items from a service")
}
}
func TestNewItemsResp(t *testing.T) {
response := `
Alone Now I am alone. O, what a rogue and peasant slave am I! tag:denmark.lit,2003:entry-323962003-12-13T11:09:53Z2003-12-13T11:09:53ZSoliloquy To be, or not to be: that is the question: Whether 'tis nobler in the
mind to suffer The slings and arrows of outrageous fortune, Or to take arms
against a sea of troubles, And by opposing end them? tag:denmark.lit,2003:entry-323972003-12-13T18:30:02Z2003-12-13T18:30:02Z
`
pubsub, err := getPubSubGenericPayload(response)
if err != nil {
t.Fatalf(err.Error())
}
if pubsub.Items == nil {
t.Fatalf("sub options node is nil")
}
if pubsub.Items.List == nil {
t.Fatalf("the response form is nil")
}
if len(pubsub.Items.List) != 2 {
t.Fatalf("one or more items in the response could not be parsed correctly")
}
}
// ***************************************
// * 6.5.8 Requesting a Particular Item
// ***************************************
func TestNewSpecificItemRequest(t *testing.T) {
expectedReq := " " +
" " +
""
subR, err := stanza.NewSpecificItemRequest("pubsub.shakespeare.lit", "princely_musings", "ae890ac52d0df67ed7cfdf51b644e901")
if err != nil {
t.Fatalf("failed to create a specific item request: %v", err)
}
subR.Id = "items3"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Items == nil {
t.Fatalf("List tag should be present to request items from a service")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
// ***************************************
// * 7.1 Publish an Item to a Node
// ***************************************
func TestNewPublishItemRq(t *testing.T) {
item := stanza.Item{
XMLName: xml.Name{},
Id: "",
Publisher: "",
Any: &stanza.Node{
XMLName: xml.Name{
Space: "http://www.w3.org/2005/Atom",
Local: "entry",
},
Attrs: nil,
Content: "",
Nodes: []stanza.Node{
{
XMLName: xml.Name{Space: "", Local: "title"},
Attrs: nil,
Content: "My pub item title",
Nodes: nil,
},
{
XMLName: xml.Name{Space: "", Local: "summary"},
Attrs: nil,
Content: "My pub item content summary",
Nodes: nil,
},
{
XMLName: xml.Name{Space: "", Local: "link"},
Attrs: []xml.Attr{
{
Name: xml.Name{Space: "", Local: "rel"},
Value: "alternate",
},
{
Name: xml.Name{Space: "", Local: "type"},
Value: "text/html",
},
{
Name: xml.Name{Space: "", Local: "href"},
Value: "http://denmark.lit/2003/12/13/atom03",
},
},
},
{
XMLName: xml.Name{Space: "", Local: "id"},
Attrs: nil,
Content: "My pub item content ID",
Nodes: nil,
},
{
XMLName: xml.Name{Space: "", Local: "published"},
Attrs: nil,
Content: "2003-12-13T18:30:02Z",
Nodes: nil,
},
{
XMLName: xml.Name{Space: "", Local: "updated"},
Attrs: nil,
Content: "2003-12-13T18:30:02Z",
Nodes: nil,
},
},
},
}
subR, err := stanza.NewPublishItemRq("pubsub.shakespeare.lit", "princely_musings", "bnd81g37d61f49fgn581", item)
if err != nil {
t.Fatalf("Could not create an item pub request : %s", err)
}
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated sub request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if strings.TrimSpace(pubsub.Publish.Node) == "" {
t.Fatalf("the element MUST possess a 'node' attribute, specifying the NodeID of the node.")
}
if pubsub.Publish.Items[0].Id == "" {
t.Fatalf("an id was provided for the item and it should be used")
}
}
// ***************************************
// * 7.1.5 Publishing Options
// ***************************************
func TestNewPublishItemOptsRq(t *testing.T) {
expectedReq := " " +
" " +
"Soliloquy " +
" To be, or not to be: that is the question: Whether \"tis nobler in the mind to suffer The " +
"slings and arrows of outrageous fortune, Or to take arms against a sea of troubles, And by opposing end them? " +
" " +
"tag:denmark.lit,2003:entry-323972003-12-13T18:30:02Z " +
"2003-12-13T18:30:02Z " +
" " +
"http://jabber.org/protocol/pubsub#publish-options " +
"presence"
var iq stanza.IQ
err := xml.Unmarshal([]byte(expectedReq), &iq)
if err != nil {
t.Fatalf("could not unmarshal example request : %s", err)
}
pubsub, ok := iq.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Publish == nil {
t.Fatalf("Publish tag is empty")
}
if len(pubsub.Publish.Items) != 1 {
t.Fatalf("could not parse item properly")
}
}
// ***************************************
// * 7.2 Delete an Item from a Node
// ***************************************
func TestNewDelItemFromNode(t *testing.T) {
expectedReq := " " +
" " +
""
subR, err := stanza.NewDelItemFromNode("pubsub.shakespeare.lit", "princely_musings", "ae890ac52d0df67ed7cfdf51b644e901", nil)
if err != nil {
t.Fatalf("failed to create a delete item from node request: %v", err)
}
subR.Id = "retract1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated del item request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Retract == nil {
t.Fatalf("Retract tag should be present to del an item from a service")
}
if strings.TrimSpace(pubsub.Retract.Items[0].Id) == "" {
t.Fatalf("Item id, for the item to delete, should be non empty")
}
if pubsub.Retract.Items[0].Any != nil {
t.Fatalf("Item node must be empty")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
// ***************************************
// * 8.1 Create a Node
// ***************************************
func TestNewCreateNode(t *testing.T) {
expectedReq := " " +
""
subR, err := stanza.NewCreateNode("pubsub.shakespeare.lit", "princely_musings")
if err != nil {
t.Fatalf("failed to create a create node request: %v", err)
}
subR.Id = "create1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated del item request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Create == nil {
t.Fatalf("Create tag should be present to create a node on a service")
}
if strings.TrimSpace(pubsub.Create.Node) == "" {
t.Fatalf("Expected node name to be present")
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestNewCreateNodeResp(t *testing.T) {
response := `
`
pubsub, err := getPubSubGenericPayload(response)
if err != nil {
t.Fatalf(err.Error())
}
if pubsub.Create == nil {
t.Fatalf("create segment is nil")
}
if pubsub.Create.Node == "" {
t.Fatalf("could not parse generated nodeId")
}
}
// ***************************************
// * 8.1.3 Create and Configure a Node
// ***************************************
func TestNewCreateAndConfigNode(t *testing.T) {
expectedReq := " " +
" " +
" " +
"http://jabber.org/protocol/pubsub#node_config " +
"00 " +
"1028"
subR, err := stanza.NewCreateAndConfigNode("pubsub.shakespeare.lit",
"princely_musings",
&stanza.Form{
Type: stanza.FormTypeSubmit,
Fields: []*stanza.Field{
{Var: "FORM_TYPE", Type: stanza.FieldTypeHidden, ValuesList: []string{"http://jabber.org/protocol/pubsub#node_config"}},
{Var: "pubsub#notify_retract", ValuesList: []string{"0"}},
{Var: "pubsub#notify_sub", ValuesList: []string{"0"}},
{Var: "pubsub#max_payload_size", ValuesList: []string{"1028"}},
},
})
if err != nil {
t.Fatalf("failed to create a create and config node request: %v", err)
}
subR.Id = "create1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated del item request : %s", e)
}
pubsub, ok := subR.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("payload is not a pubsub !")
}
if pubsub.Create == nil {
t.Fatalf("Create tag should be present to create a node on a service")
}
if strings.TrimSpace(pubsub.Create.Node) == "" {
t.Fatalf("Expected node name to be present")
}
if pubsub.Configure == nil {
t.Fatalf("Configure tag should be present to configure a node during its creation on a service")
}
if pubsub.Configure.Form == nil {
t.Fatalf("Expected a form to be present, to configure the node")
}
if len(pubsub.Configure.Form.Fields) != 4 {
t.Fatalf("Expected 4 elements to be present in the config form but got : %v", len(pubsub.Configure.Form.Fields))
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expectedReq, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
// ********************************
// * 5.7 Retrieve Subscriptions
// ********************************
func TestNewRetrieveAllSubsRequest(t *testing.T) {
expected := " " +
""
subR, err := stanza.NewRetrieveAllSubsRequest("pubsub.shakespeare.lit")
if err != nil {
t.Fatalf("failed to create a get all subs request: %v", err)
}
subR.Id = "subscriptions1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated del item request : %s", e)
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expected, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestRetrieveAllSubsResp(t *testing.T) {
response := `
`
var respIQ stanza.IQ
err := xml.Unmarshal([]byte(response), &respIQ)
if err != nil {
t.Fatalf("could not unmarshal response: %s", err)
}
pubsub, ok := respIQ.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("umarshalled payload is not a pubsub")
}
if pubsub.Subscriptions == nil {
t.Fatalf("subscriptions node is nil")
}
if len(pubsub.Subscriptions.List) != 5 {
t.Fatalf("incorrect number of decoded subscriptions")
}
}
// ********************************
// * 5.7 Retrieve Affiliations
// ********************************
func TestNewRetrieveAllAffilsRequest(t *testing.T) {
expected := " " +
""
subR, err := stanza.NewRetrieveAllAffilsRequest("pubsub.shakespeare.lit")
if err != nil {
t.Fatalf("failed to create a get all affiliations request: %v", err)
}
subR.Id = "affil1"
if _, e := checkMarshalling(t, subR); e != nil {
t.Fatalf("Failed to check marshalling for generated retreive all affiliations request : %s", e)
}
data, err := xml.Marshal(subR)
if err := compareMarshal(expected, string(data)); err != nil {
t.Fatalf(err.Error())
}
}
func TestRetrieveAllAffilsResp(t *testing.T) {
response := `
`
var respIQ stanza.IQ
err := xml.Unmarshal([]byte(response), &respIQ)
if err != nil {
t.Fatalf("could not unmarshal response: %s", err)
}
pubsub, ok := respIQ.Payload.(*stanza.PubSubGeneric)
if !ok {
t.Fatalf("umarshalled payload is not a pubsub")
}
if pubsub.Affiliations == nil {
t.Fatalf("subscriptions node is nil")
}
if len(pubsub.Affiliations.List) != 4 {
t.Fatalf("incorrect number of decoded subscriptions")
}
}
func getPubSubGenericPayload(response string) (*stanza.PubSubGeneric, error) {
var respIQ stanza.IQ
err := xml.Unmarshal([]byte(response), &respIQ)
if err != nil {
return &stanza.PubSubGeneric{}, err
}
pubsub, ok := respIQ.Payload.(*stanza.PubSubGeneric)
if !ok {
return nil, errors.New("this iq payload is not a pubsub")
}
return pubsub, nil
}