sum7
/
yaja
Archived
1
0
Fork 0

improve JID struct

This commit is contained in:
Martin/Geno 2018-02-15 22:03:49 +01:00
parent 02ee2f2087
commit 3e39507f5a
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
14 changed files with 275 additions and 95 deletions

View File

@ -61,8 +61,8 @@ func (client *Client) auth(password string) error {
cnonceStr := cnonce() cnonceStr := cnonce()
digestURI := "xmpp/" + client.JID.Domain digestURI := "xmpp/" + client.JID.Domain
nonceCount := fmt.Sprintf("%08x", 1) nonceCount := fmt.Sprintf("%08x", 1)
digest := saslDigestResponse(client.JID.Node, realm, password, nonce, cnonceStr, "AUTHENTICATE", digestURI, nonceCount) digest := saslDigestResponse(client.JID.Local, realm, password, nonce, cnonceStr, "AUTHENTICATE", digestURI, nonceCount)
message := "username=\"" + client.JID.Node + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", cnonce=\"" + cnonceStr + message := "username=\"" + client.JID.Local + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", cnonce=\"" + cnonceStr +
"\", nc=" + nonceCount + ", qop=" + qop + ", digest-uri=\"" + digestURI + "\", response=" + digest + ", charset=" + charset "\", nc=" + nonceCount + ", qop=" + qop + ", digest-uri=\"" + digestURI + "\", response=" + digest + ", charset=" + charset
response.Body = base64.StdEncoding.EncodeToString([]byte(message)) response.Body = base64.StdEncoding.EncodeToString([]byte(message))
@ -72,7 +72,7 @@ func (client *Client) auth(password string) error {
if m == "PLAIN" { if m == "PLAIN" {
mechanism = m mechanism = m
// Plain authentication: send base64-encoded \x00 user \x00 password. // Plain authentication: send base64-encoded \x00 user \x00 password.
raw := "\x00" + client.JID.Node + "\x00" + password raw := "\x00" + client.JID.Local + "\x00" + password
enc := make([]byte, base64.StdEncoding.EncodedLen(len(raw))) enc := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
base64.StdEncoding.Encode(enc, []byte(raw)) base64.StdEncoding.Encode(enc, []byte(raw))
client.Send(&xmpp.SASLAuth{ client.Send(&xmpp.SASLAuth{

View File

@ -120,7 +120,7 @@ func (client *Client) connect(password string) error {
if bind == nil { if bind == nil {
return errors.New("bind is nil") return errors.New("bind is nil")
} else if bind.JID != nil { } else if bind.JID != nil {
client.JID.Node = bind.JID.Node client.JID.Local = bind.JID.Local
client.JID.Domain = bind.JID.Domain client.JID.Domain = bind.JID.Domain
client.JID.Resource = bind.JID.Resource client.JID.Resource = bind.JID.Resource
client.Logging.Infof("set jid by server bind '%s'", bind.JID.Full()) client.Logging.Infof("set jid by server bind '%s'", bind.JID.Full())

View File

@ -110,21 +110,22 @@ func (t *Tester) StartBot(status *Status) {
first := true first := true
allAdmins := "" allAdmins := ""
isAdmin := false isAdmin := false
fromBare := msg.From
for _, jid := range botAllowed(t.Admins, status.account.Admins) { for _, jid := range botAllowed(t.Admins, status.account.Admins) {
if first { if first {
first = false first = false
allAdmins += jid.Bare()
} else { } else {
allAdmins += ", " + jid.Bare() allAdmins += ", "
} }
if jid.Bare() == msg.From.Bare() { allAdmins += jid.Bare().String()
if jid.Bare().IsEqual(fromBare) {
isAdmin = true isAdmin = true
status.client.Send(xmpp.MessageClient{Type: msg.Type, To: jid, Body: "last message, disconnect requested by " + msg.From.Bare()}) status.client.Send(xmpp.MessageClient{Type: msg.Type, To: jid, Body: "last message, disconnect requested by " + fromBare.String()})
} }
} }
if isAdmin { if isAdmin {
status.Disconnect(fmt.Sprintf("disconnect by admin '%s'", msg.From.Bare())) status.Disconnect(fmt.Sprintf("disconnect by admin '%s'", fromBare.String()))
return return
} }
status.client.Send(xmpp.MessageClient{Type: msg.Type, To: msg.From, Body: "not allowed, ask " + allAdmins}) status.client.Send(xmpp.MessageClient{Type: msg.Type, To: msg.From, Body: "not allowed, ask " + allAdmins})

View File

@ -57,17 +57,17 @@ func (t *Tester) Output() *Output {
toJID := xmppbase.NewJID(to) toJID := xmppbase.NewJID(to)
link := &Link{ link := &Link{
Source: status.JID.Domain, Source: status.JID.Domain,
SourceJID: status.JID.Bare(), SourceJID: status.JID.Bare().String(),
Target: toJID.Domain, Target: toJID.Domain,
TargetJID: toJID.Bare(), TargetJID: toJID.Bare().String(),
FromSource: linkOK, FromSource: linkOK,
FromTarget: false, FromTarget: false,
} }
if switchSourceTarget { if switchSourceTarget {
link.Source = toJID.Domain link.Source = toJID.Domain
link.SourceJID = toJID.Bare() link.SourceJID = toJID.Bare().String()
link.Target = status.JID.Domain link.Target = status.JID.Domain
link.TargetJID = status.JID.Bare() link.TargetJID = status.JID.Bare().String()
link.FromSource = false link.FromSource = false
link.FromTarget = linkOK link.FromTarget = linkOK
} }

View File

@ -59,7 +59,7 @@ func (s *Status) Update(timeout time.Duration) {
} }
c := &client.Client{ c := &client.Client{
JID: xmppbase.NewJID(s.account.JID.Bare()), JID: s.account.JID.Bare(),
Protocol: "tcp4", Protocol: "tcp4",
Logging: s.client.Logging, Logging: s.client.Logging,
Timeout: timeout / 2, Timeout: timeout / 2,
@ -72,7 +72,7 @@ func (s *Status) Update(timeout time.Duration) {
s.IPv4 = false s.IPv4 = false
} }
c.JID = xmppbase.NewJID(s.account.JID.Bare()) c.JID = s.account.JID.Bare()
c.Protocol = "tcp6" c.Protocol = "tcp6"
if err := c.Connect(s.account.Password); err == nil { if err := c.Connect(s.account.Password); err == nil {

View File

@ -44,7 +44,7 @@ func (t *Tester) Start(mainClient *client.Client, password string) {
t.mux.Lock() t.mux.Lock()
defer t.mux.Unlock() defer t.mux.Unlock()
t.Status[mainClient.JID.Bare()] = status t.Status[mainClient.JID.Bare().String()] = status
go t.StartBot(status) go t.StartBot(status)
for _, acc := range t.Accounts { for _, acc := range t.Accounts {
@ -58,11 +58,12 @@ func (t *Tester) Close() {
} }
func (t *Tester) Connect(acc *Account) { func (t *Tester) Connect(acc *Account) {
logCTX := log.WithField("jid", acc.JID.Full()) logCTX := log.WithField("jid", acc.JID.Full().String())
status, ok := t.Status[acc.JID.Bare()] bare := acc.JID.Bare().String()
status, ok := t.Status[bare]
if !ok { if !ok {
status = NewStatus(t.mainClient, acc) status = NewStatus(t.mainClient, acc)
t.Status[acc.JID.Bare()] = status t.Status[bare] = status
} else if status.JID == nil { } else if status.JID == nil {
status.JID = acc.JID status.JID = acc.JID
} }
@ -99,19 +100,20 @@ func (t *Tester) UpdateConnectionStatus(from, to *xmppbase.JID, recvmsg string)
t.mux.Lock() t.mux.Lock()
defer t.mux.Unlock() defer t.mux.Unlock()
status, ok := t.Status[from.Bare()] status, ok := t.Status[from.Bare().String()]
if !ok { if !ok {
logCTX.Warn("recv msg without receiver") logCTX.Warn("recv msg without receiver")
return return
} }
msg, ok := status.MessageForConnection[to.Bare()] toBare := to.Bare().String()
msg, ok := status.MessageForConnection[toBare]
logCTX = logCTX.WithField("msg-send", msg) logCTX = logCTX.WithField("msg-send", msg)
if !ok || msg != recvmsg || msg == "" || recvmsg == "" { if !ok || msg != recvmsg || msg == "" || recvmsg == "" {
logCTX.Warn("recv wrong msg") logCTX.Warn("recv wrong msg")
return return
} }
delete(status.MessageForConnection, to.Bare()) delete(status.MessageForConnection, toBare)
status.Connections[to.Bare()] = true status.Connections[toBare] = true
logCTX.Info("recv msg") logCTX.Info("recv msg")
} }
@ -163,7 +165,7 @@ func (t *Tester) CheckStatus() {
Type: xmpp.MessageTypeChat, Type: xmpp.MessageTypeChat,
To: s.JID, To: s.JID,
}) })
own.MessageForConnection[s.JID.Bare()] = msg own.MessageForConnection[s.JID.Bare().String()] = msg
logCTXTo.Debug("test send") logCTXTo.Debug("test send")
send++ send++
} }

View File

@ -16,7 +16,7 @@ type State struct {
} }
func (s *State) AddAccount(a *model.Account) error { func (s *State) AddAccount(a *model.Account) error {
if a.Node == "" { if a.Local == "" {
return errors.New("No localpart exists in account") return errors.New("No localpart exists in account")
} }
if d := a.Domain; d != nil { if d := a.Domain; d != nil {
@ -39,11 +39,11 @@ func (s *State) AddAccount(a *model.Account) error {
if domain.Accounts == nil { if domain.Accounts == nil {
domain.Accounts = make(map[string]*model.Account) domain.Accounts = make(map[string]*model.Account)
} }
_, ok = domain.Accounts[a.Node] _, ok = domain.Accounts[a.Local]
if ok { if ok {
return errors.New("exists already") return errors.New("exists already")
} }
domain.Accounts[a.Node] = a domain.Accounts[a.Local] = a
a.Domain = d a.Domain = d
return nil return nil
} }
@ -54,7 +54,7 @@ func (s *State) Authenticate(jid *xmppbase.JID, password string) (bool, error) {
logger := log.WithField("database", "auth") logger := log.WithField("database", "auth")
if domain, ok := s.Domains[jid.Domain]; ok { if domain, ok := s.Domains[jid.Domain]; ok {
if acc, ok := domain.Accounts[jid.Node]; ok { if acc, ok := domain.Accounts[jid.Local]; ok {
if acc.ValidatePassword(password) { if acc.ValidatePassword(password) {
return true, nil return true, nil
} else { } else {
@ -73,7 +73,7 @@ func (s *State) GetAccount(jid *xmppbase.JID) *model.Account {
logger := log.WithField("database", "get") logger := log.WithField("database", "get")
if domain, ok := s.Domains[jid.Domain]; ok { if domain, ok := s.Domains[jid.Domain]; ok {
if acc, ok := domain.Accounts[jid.Node]; ok { if acc, ok := domain.Accounts[jid.Local]; ok {
return acc return acc
} else { } else {
logger.Debug("account not found") logger.Debug("account not found")

View File

@ -20,18 +20,18 @@ func (d *Domain) GetJID() *xmppbase.JID {
} }
func (d *Domain) UpdateAccount(a *Account) error { func (d *Domain) UpdateAccount(a *Account) error {
if a.Node == "" { if a.Local == "" {
return errors.New("No localpart exists in account") return errors.New("No localpart exists in account")
} }
d.Lock() d.Lock()
d.Accounts[a.Node] = a d.Accounts[a.Local] = a
d.Unlock() d.Unlock()
a.Domain = d a.Domain = d
return nil return nil
} }
type Account struct { type Account struct {
Node string `json:"-"` Local string `json:"-"`
Domain *Domain `json:"-"` Domain *Domain `json:"-"`
Password string `json:"password"` Password string `json:"password"`
Roster map[string]*Buddy `json:"roster"` Roster map[string]*Buddy `json:"roster"`
@ -43,7 +43,7 @@ func NewAccount(jid *xmppbase.JID, password string) *Account {
return nil return nil
} }
return &Account{ return &Account{
Node: jid.Node, Local: jid.Local,
Domain: &Domain{ Domain: &Domain{
FQDN: jid.Domain, FQDN: jid.Domain,
}, },
@ -54,7 +54,7 @@ func NewAccount(jid *xmppbase.JID, password string) *Account {
func (a *Account) GetJID() *xmppbase.JID { func (a *Account) GetJID() *xmppbase.JID {
return &xmppbase.JID{ return &xmppbase.JID{
Domain: a.Domain.FQDN, Domain: a.Domain.FQDN,
Node: a.Node, Local: a.Local,
} }
} }

View File

@ -76,7 +76,7 @@ func (state *TLSStream) Process() state.State {
</mechanisms> </mechanisms>
</stream:features>`, </stream:features>`,
xmpp.CreateCookie(), xmpp.NSClient, xmpp.NSStream, xmpp.CreateCookie(), xmpp.NSClient, xmpp.NSStream,
xmpp.NSSASL, xmppiq.NSFeaturesIQRegister) xmpp.NSSASL, xmppiq.NSFeatureRegister)
} else { } else {
fmt.Fprintf(state.Client.Conn, `<?xml version='1.0'?> fmt.Fprintf(state.Client.Conn, `<?xml version='1.0'?>
<stream:stream id='%x' version='1.0' xmlns='%s' xmlns:stream='%s'> <stream:stream id='%x' version='1.0' xmlns='%s' xmlns:stream='%s'>
@ -134,7 +134,7 @@ func (state *SASLAuth) Process() state.State {
} }
info := strings.Split(string(data), "\x00") info := strings.Split(string(data), "\x00")
// should check that info[1] starts with state.Client.JID // should check that info[1] starts with state.Client.JID
state.Client.JID.Node = info[1] state.Client.JID.Local = info[1]
state.Client.Log = state.Client.Log.WithField("jid", state.Client.JID.Full()) state.Client.Log = state.Client.Log.WithField("jid", state.Client.JID.Full())
success, err := state.database.Authenticate(state.Client.JID, info[2]) success, err := state.database.Authenticate(state.Client.JID, info[2])
if err != nil { if err != nil {

View File

@ -44,7 +44,7 @@ func (state *RegisterFormRequest) Process() state.State {
return state return state
} }
if msg.PrivateRegister == nil { if msg.Register == nil {
state.Client.Log.Warn("is no iq register") state.Client.Log.Warn("is no iq register")
return nil return nil
} }
@ -53,7 +53,7 @@ func (state *RegisterFormRequest) Process() state.State {
To: state.Client.JID, To: state.Client.JID,
From: xmppbase.NewJID(state.Client.JID.Domain), From: xmppbase.NewJID(state.Client.JID.Domain),
ID: msg.ID, ID: msg.ID,
PrivateRegister: &xmppiq.IQPrivateRegister{ Register: &xmppiq.Register{
Instructions: "Choose a username and password for use with this service.", Instructions: "Choose a username and password for use with this service.",
Username: "", Username: "",
Password: "", Password: "",
@ -98,14 +98,14 @@ func (state *RegisterRequest) Process() state.State {
state.Client.Log.Warn("iq with error: ", msg.Error.Code) state.Client.Log.Warn("iq with error: ", msg.Error.Code)
return state return state
} }
if msg.PrivateRegister == nil { if msg.Register == nil {
state.Client.Log.Warn("is no iq register: ", err) state.Client.Log.Warn("is no iq register: ", err)
return nil return nil
} }
state.Client.JID.Node = msg.PrivateRegister.Username state.Client.JID.Local = msg.Register.Username
state.Client.Log = state.Client.Log.WithField("jid", state.Client.JID.Full()) state.Client.Log = state.Client.Log.WithField("jid", state.Client.JID.Full())
account := model.NewAccount(state.Client.JID, msg.PrivateRegister.Password) account := model.NewAccount(state.Client.JID, msg.Register.Password)
err = state.database.AddAccount(account) err = state.database.AddAccount(account)
if err != nil { if err != nil {
state.Client.Out.Encode(&xmpp.IQClient{ state.Client.Out.Encode(&xmpp.IQClient{
@ -113,7 +113,7 @@ func (state *RegisterRequest) Process() state.State {
To: state.Client.JID, To: state.Client.JID,
From: xmppbase.NewJID(state.Client.JID.Domain), From: xmppbase.NewJID(state.Client.JID.Domain),
ID: msg.ID, ID: msg.ID,
PrivateRegister: msg.PrivateRegister, Register: msg.Register,
Error: &xmpp.ErrorClient{ Error: &xmpp.ErrorClient{
Code: "409", Code: "409",
Type: "cancel", Type: "cancel",

View File

@ -11,9 +11,9 @@ func init() {
jidRegex = regexp.MustCompile(`^(?:([^@/<>'\" ]+)@)?([^@/<>'\"]+)(?:/([^<>'\" ][^<>'\"]*))?$`) jidRegex = regexp.MustCompile(`^(?:([^@/<>'\" ]+)@)?([^@/<>'\"]+)(?:/([^<>'\" ][^<>'\"]*))?$`)
} }
// JID struct // JID implements RFC6122: XMPP - Address Format
type JID struct { type JID struct {
Node string Local string
Domain string Domain string
Resource string Resource string
} }
@ -28,49 +28,57 @@ func NewJID(jidString string) *JID {
jidSplit := jidSplitTmp[0] jidSplit := jidSplitTmp[0]
return &JID{ return &JID{
Node: jidSplit[1], Local: jidSplit[1],
Domain: jidSplit[2], Domain: jidSplit[2],
Resource: jidSplit[3], Resource: jidSplit[3],
} }
} }
// Bare get the "bare" jid // Clone JID struct address/pointer
func (jid *JID) Bare() string { func (jid *JID) Clone() *JID {
if jid == nil { if jid != nil {
return "" return &JID{
Local: jid.Local,
Domain: jid.Domain,
Resource: jid.Resource,
} }
if jid.Node != "" {
return jid.Node + "@" + jid.Domain
} }
return jid.Domain return nil
}
// IsBare checks if jid has node and domain but no resource
func (jid *JID) IsBare() bool {
return jid != nil && jid.Node != "" && jid.Domain != "" && jid.Resource == ""
} }
// Full get the "full" jid as string // Full get the "full" jid as string
func (jid *JID) Full() string { func (jid *JID) Full() *JID {
return jid.Clone()
}
// Bare get the "bare" jid
func (jid *JID) Bare() *JID {
if jid != nil {
return &JID{
Local: jid.Local,
Domain: jid.Domain,
}
}
return nil
}
func (jid *JID) String() string {
if jid == nil { if jid == nil {
return "" return ""
} }
str := jid.Domain
if jid.Local != "" {
str = jid.Local + "@" + str
}
if jid.Resource != "" { if jid.Resource != "" {
return jid.Bare() + "/" + jid.Resource str = str + "/" + jid.Resource
} }
return jid.Bare() return str
} }
// IsFull checks if jid has all three parts of a JID
func (jid *JID) IsFull() bool {
return jid != nil && jid.Node != "" && jid.Domain != "" && jid.Resource != ""
}
func (jid *JID) String() string { return jid.Bare() }
//MarshalText to bytearray //MarshalText to bytearray
func (jid JID) MarshalText() ([]byte, error) { func (jid JID) MarshalText() ([]byte, error) {
return []byte(jid.Full()), nil return []byte(jid.String()), nil
} }
// UnmarshalText from bytearray // UnmarshalText from bytearray
@ -79,7 +87,7 @@ func (jid *JID) UnmarshalText(data []byte) (err error) {
if newJID == nil { if newJID == nil {
return errors.New("not a valid jid") return errors.New("not a valid jid")
} }
jid.Node = newJID.Node jid.Local = newJID.Local
jid.Domain = newJID.Domain jid.Domain = newJID.Domain
jid.Resource = newJID.Resource jid.Resource = newJID.Resource
return nil return nil

24
xmpp/base/jid_is.go Normal file
View File

@ -0,0 +1,24 @@
package xmppbase
// IsDomain checks if jid has only domain but no local and resource
func (jid *JID) IsDomain() bool {
return jid != nil && jid.Local == "" && jid.Domain != "" && jid.Resource == ""
}
// IsBare checks if jid has local and domain but no resource
func (jid *JID) IsBare() bool {
return jid != nil && jid.Local != "" && jid.Domain != "" && jid.Resource == ""
}
// IsFull checks if jid has all three parts of a JID
func (jid *JID) IsFull() bool {
return jid != nil && jid.Local != "" && jid.Domain != "" && jid.Resource != ""
}
// IsEqual to check if two jid has same values
func (a *JID) IsEqual(b *JID) bool {
if a == nil || b == nil {
return false
}
return a.Local == b.Local && a.Domain == b.Domain && a.Resource == b.Resource
}

123
xmpp/base/jid_is_test.go Normal file
View File

@ -0,0 +1,123 @@
package xmppbase
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestJIDIsDomain(t *testing.T) {
assert := assert.New(t)
var jid *JID
assert.False(jid.IsDomain())
jid = &JID{}
assert.False(jid.IsDomain())
jid = &JID{Local: "a"}
assert.False(jid.IsDomain())
jid = &JID{Domain: "a"}
assert.True(jid.IsDomain())
jid = &JID{Resource: "a"}
assert.False(jid.IsDomain())
jid = &JID{Local: "a", Domain: "b"}
assert.False(jid.IsDomain())
jid = &JID{Local: "a", Resource: "b"}
assert.False(jid.IsDomain())
jid = &JID{Domain: "a", Resource: "b"}
assert.False(jid.IsDomain())
jid = &JID{Local: "a", Domain: "b", Resource: "a"}
assert.False(jid.IsDomain())
}
func TestJIDIsBare(t *testing.T) {
assert := assert.New(t)
var jid *JID
assert.False(jid.IsBare())
jid = &JID{}
assert.False(jid.IsBare())
jid = &JID{Local: "a"}
assert.False(jid.IsBare())
jid = &JID{Domain: "a"}
assert.False(jid.IsBare())
jid = &JID{Resource: "a"}
assert.False(jid.IsBare())
jid = &JID{Local: "a", Domain: "b"}
assert.True(jid.IsBare())
jid = &JID{Local: "a", Resource: "b"}
assert.False(jid.IsBare())
jid = &JID{Domain: "a", Resource: "b"}
assert.False(jid.IsBare())
jid = &JID{Local: "a", Domain: "b", Resource: "a"}
assert.False(jid.IsBare())
}
func TestJIDIsFull(t *testing.T) {
assert := assert.New(t)
var jid *JID
assert.False(jid.IsFull())
jid = &JID{}
assert.False(jid.IsFull())
jid = &JID{Local: "a"}
assert.False(jid.IsFull())
jid = &JID{Domain: "a"}
assert.False(jid.IsFull())
jid = &JID{Resource: "a"}
assert.False(jid.IsFull())
jid = &JID{Local: "a", Domain: "b"}
assert.False(jid.IsFull())
jid = &JID{Local: "a", Resource: "b"}
assert.False(jid.IsFull())
jid = &JID{Domain: "a", Resource: "b"}
assert.False(jid.IsFull())
jid = &JID{Local: "a", Domain: "b", Resource: "a"}
assert.True(jid.IsFull())
}
func TestJIDIsEqual(t *testing.T) {
assert := assert.New(t)
// just one null
var a *JID
b := &JID{}
assert.False(a.IsEqual(b))
a = &JID{}
// two empty JID
assert.True(a.IsEqual(b))
a.Local = "bot"
b.Local = "bot"
a.Domain = "example.org"
b.Domain = "example.org"
a.Resource = "notebook"
b.Resource = "notebook"
assert.True(a.IsEqual(b))
b.Resource = "mobile"
assert.False(a.IsEqual(b))
}

View File

@ -13,57 +13,57 @@ func TestNewJID(t *testing.T) {
checkList := map[string]*JID{ checkList := map[string]*JID{
"juliet@example.com": { "juliet@example.com": {
Node: "juliet", Local: "juliet",
Domain: "example.com", Domain: "example.com",
}, },
"juliet@example.com/foo": { "juliet@example.com/foo": {
Node: "juliet", Local: "juliet",
Domain: "example.com", Domain: "example.com",
Resource: "foo", Resource: "foo",
}, },
"juliet@example.com/foo bar": { "juliet@example.com/foo bar": {
Node: "juliet", Local: "juliet",
Domain: "example.com", Domain: "example.com",
Resource: "foo bar", Resource: "foo bar",
}, },
"juliet@example.com/foo@bar": { "juliet@example.com/foo@bar": {
Node: "juliet", Local: "juliet",
Domain: "example.com", Domain: "example.com",
Resource: "foo@bar", Resource: "foo@bar",
}, },
"foo\\20bar@example.com": { "foo\\20bar@example.com": {
Node: "foo\\20bar", Local: "foo\\20bar",
Domain: "example.com", Domain: "example.com",
}, },
"fussball@example.com": { "fussball@example.com": {
Node: "fussball", Local: "fussball",
Domain: "example.com", Domain: "example.com",
}, },
"fu&#xDF;ball@example.com": { "fu&#xDF;ball@example.com": {
Node: "fu&#xDF;ball", Local: "fu&#xDF;ball",
Domain: "example.com", Domain: "example.com",
}, },
"&#x3C0;@example.com": { "&#x3C0;@example.com": {
Node: "&#x3C0;", Local: "&#x3C0;",
Domain: "example.com", Domain: "example.com",
}, },
"&#x3A3;@example.com/foo": { "&#x3A3;@example.com/foo": {
Node: "&#x3A3;", Local: "&#x3A3;",
Domain: "example.com", Domain: "example.com",
Resource: "foo", Resource: "foo",
}, },
"&#x3C3;@example.com/foo": { "&#x3C3;@example.com/foo": {
Node: "&#x3C3;", Local: "&#x3C3;",
Domain: "example.com", Domain: "example.com",
Resource: "foo", Resource: "foo",
}, },
"&#x3C2;@example.com/foo": { "&#x3C2;@example.com/foo": {
Node: "&#x3C2;", Local: "&#x3C2;",
Domain: "example.com", Domain: "example.com",
Resource: "foo", Resource: "foo",
}, },
"king@example.com/&#x265A;": { "king@example.com/&#x265A;": {
Node: "king", Local: "king",
Domain: "example.com", Domain: "example.com",
Resource: "&#x265A;", Resource: "&#x265A;",
}, },
@ -97,10 +97,10 @@ func TestNewJID(t *testing.T) {
continue continue
} }
assert.Equal(jidValid.Node, jid.Node, "the local part was not right detectet:"+jidString) assert.Equal(jidValid.Local, jid.Local, "the local part was not right detectet:"+jidString)
assert.Equal(jidValid.Domain, jid.Domain, "the domain part was not right detectet:"+jidString) assert.Equal(jidValid.Domain, jid.Domain, "the domain part was not right detectet:"+jidString)
assert.Equal(jidValid.Resource, jid.Resource, "the resource part was not right detectet:"+jidString) assert.Equal(jidValid.Resource, jid.Resource, "the resource part was not right detectet:"+jidString)
assert.Equal(jidValid.Full(), jidString, "the function full of jid did not work") assert.Equal(jidValid.Full().String(), jidString, "the function full of jid did not work")
} else { } else {
assert.Nil(jid, "this should not be a valid JID:"+jidString) assert.Nil(jid, "this should not be a valid JID:"+jidString)
} }
@ -113,11 +113,11 @@ func TestJIDBare(t *testing.T) {
checkList := map[string]*JID{ checkList := map[string]*JID{
"aaa@example.com": { "aaa@example.com": {
Node: "aaa", Local: "aaa",
Domain: "example.com", Domain: "example.com",
}, },
"aab@example.com": { "aab@example.com": {
Node: "aab", Local: "aab",
Domain: "example.com", Domain: "example.com",
Resource: "foo", Resource: "foo",
}, },
@ -127,10 +127,32 @@ func TestJIDBare(t *testing.T) {
}, },
} }
for jidValid, jid := range checkList { for jidValid, jid := range checkList {
jidBase := jid.Bare() jidBase := jid.Bare().String()
assert.Equal(jidValid, jidBase) assert.Equal(jidValid, jidBase)
} }
// check nil value
var jid *JID
assert.Equal("", jid.Bare().String())
}
func TestClone(t *testing.T) {
assert := assert.New(t)
var jid *JID
cloneJID := jid.Clone()
assert.Nil(jid)
assert.Nil(cloneJID)
originString := "bot@example.org"
jid = NewJID(originString)
cloneJID = jid.Clone()
cloneJID.Resource = "notebook"
assert.Equal(originString, jid.String())
assert.NotEqual(cloneJID.String(), jid.String())
assert.Equal(cloneJID.Bare().String(), jid.String())
} }
func TestMarshal(t *testing.T) { func TestMarshal(t *testing.T) {
@ -140,7 +162,7 @@ func TestMarshal(t *testing.T) {
err := jid.UnmarshalText([]byte("juliet@example.com/foo")) err := jid.UnmarshalText([]byte("juliet@example.com/foo"))
assert.NoError(err) assert.NoError(err)
assert.Equal(jid.Node, "juliet") assert.Equal(jid.Local, "juliet")
assert.Equal(jid.Domain, "example.com") assert.Equal(jid.Domain, "example.com")
assert.Equal(jid.Resource, "foo") assert.Equal(jid.Resource, "foo")
@ -149,7 +171,7 @@ func TestMarshal(t *testing.T) {
assert.Error(err) assert.Error(err)
jid = &JID{ jid = &JID{
Node: "romeo", Local: "romeo",
Domain: "example.com", Domain: "example.com",
Resource: "bar", Resource: "bar",
} }