Merge branch 'master' into xmpp-check

This commit is contained in:
Mickaël Rémond 2019-05-31 19:02:10 +02:00 committed by GitHub
commit c55257cbed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 122 additions and 46 deletions

View file

@ -1,5 +1,5 @@
FROM golang:1.11 FROM golang:1.11
WORKDIR /go/src/gosrc.io/xmpp WORKDIR /xmpp
RUN curl -o codecov.sh -s https://codecov.io/bash && chmod +x codecov.sh RUN curl -o codecov.sh -s https://codecov.io/bash && chmod +x codecov.sh
COPY . ./ COPY . ./
RUN go get -t ./... # RUN go get -t ./...

View file

@ -1,4 +1,4 @@
package xmpp package xmpp // import "gosrc.io/xmpp"
import ( import (
"crypto/tls" "crypto/tls"

View file

@ -119,7 +119,7 @@ func (c *Client) Connect() (*Session, error) {
var try = 0 var try = 0
var success bool var success bool
c.Metrics = initMetrics() c.Metrics = initMetrics()
for try <= c.config.Retry || !success { for try <= c.config.Retry && !success {
if tcpconn, err = net.DialTimeout("tcp", c.config.Address, time.Duration(c.config.ConnectTimeout)*time.Second); err == nil { if tcpconn, err = net.DialTimeout("tcp", c.config.Address, time.Duration(c.config.ConnectTimeout)*time.Second); err == nil {
c.Metrics.setConnectTime() c.Metrics.setConnectTime()
success = true success = true

28
cmd/xmpp-check/README.md Normal file
View file

@ -0,0 +1,28 @@
# XMPP Check
XMPP check is a tool to check TLS certificate on a remote server.
## Installation
```
$ go get -u gosrc.io/xmpp/cmd/xmpp-check
```
## Usage
If you server is on standard port and XMPP domains matches the hostname you can simply use:
```
$ xmpp-check myhost.net
2019/05/16 16:04:36 All checks passed
```
You can also pass the port and the XMPP domain if different from the server hostname:
```
$ xmpp-check myhost.net:5222 xmppdomain.net
2019/05/16 16:05:21 All checks passed
```
Error code will be non-zero in case of error. You can thus use it directly with your usual
monitoring scripts.

View file

@ -1,4 +1,4 @@
package xmpp // import "gosrc.io/xmpp" package xmpp_test // import "gosrc.io/xmpp"
import ( import (
"encoding/xml" "encoding/xml"
@ -6,20 +6,22 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"gosrc.io/xmpp"
) )
func TestUnmarshalIqs(t *testing.T) { func TestUnmarshalIqs(t *testing.T) {
//var cs1 = new(iot.ControlSet) //var cs1 = new(iot.ControlSet)
var tests = []struct { var tests = []struct {
iqString string iqString string
parsedIQ IQ parsedIQ xmpp.IQ
}{ }{
{"<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 id=\"1\" type=\"set\" to=\"test@localhost\"/>",
xmpp.IQ{XMLName: xml.Name{Space: "", Local: "iq"}, PacketAttrs: xmpp.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}}, //{"<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}},
} }
for _, test := range tests { for _, test := range tests {
parsedIQ := IQ{} parsedIQ := xmpp.IQ{}
err := xml.Unmarshal([]byte(test.iqString), &parsedIQ) err := xml.Unmarshal([]byte(test.iqString), &parsedIQ)
if err != nil { if err != nil {
t.Errorf("Unmarshal(%s) returned error", test.iqString) t.Errorf("Unmarshal(%s) returned error", test.iqString)
@ -33,14 +35,14 @@ func TestUnmarshalIqs(t *testing.T) {
} }
func TestGenerateIq(t *testing.T) { func TestGenerateIq(t *testing.T) {
iq := NewIQ("result", "admin@localhost", "test@localhost", "1", "en") iq := xmpp.NewIQ("result", "admin@localhost", "test@localhost", "1", "en")
payload := DiscoInfo{ payload := xmpp.DiscoInfo{
Identity: Identity{ Identity: xmpp.Identity{
Name: "Test Gateway", Name: "Test Gateway",
Category: "gateway", Category: "gateway",
Type: "mqtt", Type: "mqtt",
}, },
Features: []Feature{ Features: []xmpp.Feature{
{Var: "http://jabber.org/protocol/disco#info"}, {Var: "http://jabber.org/protocol/disco#info"},
{Var: "http://jabber.org/protocol/disco#item"}, {Var: "http://jabber.org/protocol/disco#item"},
}, },
@ -56,7 +58,7 @@ func TestGenerateIq(t *testing.T) {
t.Error("empty error should not be serialized") t.Error("empty error should not be serialized")
} }
parsedIQ := IQ{} parsedIQ := xmpp.IQ{}
if err = xml.Unmarshal(data, &parsedIQ); err != nil { if err = xml.Unmarshal(data, &parsedIQ); err != nil {
t.Errorf("Unmarshal(%s) returned error", data) t.Errorf("Unmarshal(%s) returned error", data)
} }
@ -67,7 +69,7 @@ func TestGenerateIq(t *testing.T) {
} }
func TestErrorTag(t *testing.T) { func TestErrorTag(t *testing.T) {
xError := Err{ xError := xmpp.Err{
XMLName: xml.Name{Local: "error"}, XMLName: xml.Name{Local: "error"},
Code: 503, Code: 503,
Type: "cancel", Type: "cancel",
@ -80,7 +82,7 @@ func TestErrorTag(t *testing.T) {
t.Errorf("cannot marshal xml structure: %s", err) t.Errorf("cannot marshal xml structure: %s", err)
} }
parsedError := Err{} parsedError := xmpp.Err{}
if err = xml.Unmarshal(data, &parsedError); err != nil { if err = xml.Unmarshal(data, &parsedError); err != nil {
t.Errorf("Unmarshal(%s) returned error", data) t.Errorf("Unmarshal(%s) returned error", data)
} }
@ -91,8 +93,8 @@ func TestErrorTag(t *testing.T) {
} }
func TestDiscoItems(t *testing.T) { func TestDiscoItems(t *testing.T) {
iq := NewIQ("get", "romeo@montague.net/orchard", "catalog.shakespeare.lit", "items3", "en") iq := xmpp.NewIQ("get", "romeo@montague.net/orchard", "catalog.shakespeare.lit", "items3", "en")
payload := DiscoItems{ payload := xmpp.DiscoItems{
Node: "music", Node: "music",
} }
iq.AddPayload(&payload) iq.AddPayload(&payload)
@ -102,7 +104,7 @@ func TestDiscoItems(t *testing.T) {
t.Errorf("cannot marshal xml structure") t.Errorf("cannot marshal xml structure")
} }
parsedIQ := IQ{} parsedIQ := xmpp.IQ{}
if err = xml.Unmarshal(data, &parsedIQ); err != nil { if err = xml.Unmarshal(data, &parsedIQ); err != nil {
t.Errorf("Unmarshal(%s) returned error", data) t.Errorf("Unmarshal(%s) returned error", data)
} }
@ -111,25 +113,3 @@ func TestDiscoItems(t *testing.T) {
t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ.Payload, iq.Payload)) 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)
}

View file

@ -1,14 +1,15 @@
package xmpp // import "gosrc.io/xmpp" package xmpp_test
import ( import (
"encoding/xml" "encoding/xml"
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"gosrc.io/xmpp"
) )
func TestGenerateMessage(t *testing.T) { func TestGenerateMessage(t *testing.T) {
message := NewMessage("chat", "admin@localhost", "test@localhost", "1", "en") message := xmpp.NewMessage("chat", "admin@localhost", "test@localhost", "1", "en")
message.Body = "Hi" message.Body = "Hi"
message.Subject = "Msg Subject" message.Subject = "Msg Subject"
@ -17,7 +18,7 @@ func TestGenerateMessage(t *testing.T) {
t.Errorf("cannot marshal xml structure") t.Errorf("cannot marshal xml structure")
} }
parsedMessage := Message{} parsedMessage := xmpp.Message{}
if err = xml.Unmarshal(data, &parsedMessage); err != nil { if err = xml.Unmarshal(data, &parsedMessage); err != nil {
t.Errorf("Unmarshal(%s) returned error", data) t.Errorf("Unmarshal(%s) returned error", data)
} }

View file

@ -1,14 +1,16 @@
package xmpp // import "gosrc.io/xmpp" package xmpp_test
import ( import (
"encoding/xml" "encoding/xml"
"testing" "testing"
"gosrc.io/xmpp"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
) )
func TestGeneratePresence(t *testing.T) { func TestGeneratePresence(t *testing.T) {
presence := NewPresence("admin@localhost", "test@localhost", "1", "en") presence := xmpp.NewPresence("admin@localhost", "test@localhost", "1", "en")
presence.Show = "chat" presence.Show = "chat"
data, err := xml.Marshal(presence) data, err := xml.Marshal(presence)
@ -16,7 +18,7 @@ func TestGeneratePresence(t *testing.T) {
t.Errorf("cannot marshal xml structure") t.Errorf("cannot marshal xml structure")
} }
parsedPresence := Presence{} var parsedPresence xmpp.Presence
if err = xml.Unmarshal(data, &parsedPresence); err != nil { if err = xml.Unmarshal(data, &parsedPresence); err != nil {
t.Errorf("Unmarshal(%s) returned error", data) t.Errorf("Unmarshal(%s) returned error", data)
} }
@ -25,3 +27,38 @@ func TestGeneratePresence(t *testing.T) {
t.Errorf("non matching items\n%s", cmp.Diff(parsedPresence, presence)) t.Errorf("non matching items\n%s", cmp.Diff(parsedPresence, presence))
} }
} }
func TestPresenceSubElt(t *testing.T) {
// Test structure to ensure that show, status and priority are correctly defined as presence
// package sub-elements
type pres struct {
Show string `xml:"show"`
Status string `xml:"status"`
Priority string `xml:"priority"`
}
presence := xmpp.NewPresence("admin@localhost", "test@localhost", "1", "en")
presence.Show = "xa"
presence.Status = "Coding"
presence.Priority = "10"
data, err := xml.Marshal(presence)
if err != nil {
t.Errorf("cannot marshal xml structure")
}
var parsedPresence pres
if err = xml.Unmarshal(data, &parsedPresence); err != nil {
t.Errorf("Unmarshal(%s) returned error", data)
}
if parsedPresence.Show != presence.Show {
t.Errorf("cannot read 'show' as presence subelement (%s)", parsedPresence.Show)
}
if parsedPresence.Status != presence.Status {
t.Errorf("cannot read 'status' as presence subelement (%s)", parsedPresence.Status)
}
if parsedPresence.Priority != presence.Priority {
t.Errorf("cannot read 'priority' as presence subelement (%s)", parsedPresence.Priority)
}
}

View file

@ -1,6 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
export GO111MODULE=on
echo "" > coverage.txt echo "" > coverage.txt
for d in $(go list ./... | grep -v vendor); do for d in $(go list ./... | grep -v vendor); do

29
xmpp_test.go Normal file
View file

@ -0,0 +1,29 @@
package xmpp_test
import (
"encoding/xml"
"github.com/google/go-cmp/cmp"
)
// 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)
}