mirror of https://github.com/fluffle/goirc
Accept nick from 001 message. Fixes #110.
This commit is contained in:
parent
cb4b7e5d82
commit
1bb2dff298
|
@ -458,20 +458,22 @@ func TestRunLoop(t *testing.T) {
|
||||||
c, s := setUp(t, false)
|
c, s := setUp(t, false)
|
||||||
defer s.tearDown()
|
defer s.tearDown()
|
||||||
|
|
||||||
// Set up a handler to detect whether 001 handler is called
|
// Set up a handler to detect whether 002 handler is called.
|
||||||
h001 := callCheck(t)
|
// Don't use 001 here, since there's already a handler for that
|
||||||
c.HandleFunc("001", func(conn *Conn, line *Line) {
|
// and it hangs this test unless we mock the state tracker calls.
|
||||||
h001.call()
|
|
||||||
})
|
|
||||||
h002 := callCheck(t)
|
h002 := callCheck(t)
|
||||||
// Set up a handler to detect whether 002 handler is called
|
|
||||||
c.HandleFunc("002", func(conn *Conn, line *Line) {
|
c.HandleFunc("002", func(conn *Conn, line *Line) {
|
||||||
h002.call()
|
h002.call()
|
||||||
})
|
})
|
||||||
|
h003 := callCheck(t)
|
||||||
|
// Set up a handler to detect whether 002 handler is called
|
||||||
|
c.HandleFunc("003", func(conn *Conn, line *Line) {
|
||||||
|
h003.call()
|
||||||
|
})
|
||||||
|
|
||||||
l1 := ParseLine(":irc.server.org 001 test :First test line.")
|
l2 := ParseLine(":irc.server.org 002 test :First test line.")
|
||||||
c.in <- l1
|
c.in <- l2
|
||||||
h001.assertNotCalled("001 handler called before runLoop started.")
|
h002.assertNotCalled("002 handler called before runLoop started.")
|
||||||
|
|
||||||
// We want to test that the a goroutine calling runLoop will exit correctly.
|
// We want to test that the a goroutine calling runLoop will exit correctly.
|
||||||
// Now, we can expect the call to Dispatch to take place as runLoop starts.
|
// Now, we can expect the call to Dispatch to take place as runLoop starts.
|
||||||
|
@ -482,13 +484,13 @@ func TestRunLoop(t *testing.T) {
|
||||||
c.runLoop()
|
c.runLoop()
|
||||||
exited.call()
|
exited.call()
|
||||||
}()
|
}()
|
||||||
h001.assertWasCalled("001 handler not called after runLoop started.")
|
h002.assertWasCalled("002 handler not called after runLoop started.")
|
||||||
|
|
||||||
// Send another line, just to be sure :-)
|
// Send another line, just to be sure :-)
|
||||||
h002.assertNotCalled("002 handler called before expected.")
|
h003.assertNotCalled("003 handler called before expected.")
|
||||||
l2 := ParseLine(":irc.server.org 002 test :Second test line.")
|
l3 := ParseLine(":irc.server.org 003 test :Second test line.")
|
||||||
c.in <- l2
|
c.in <- l3
|
||||||
h002.assertWasCalled("002 handler not called while runLoop started.")
|
h003.assertWasCalled("003 handler not called while runLoop started.")
|
||||||
|
|
||||||
// Now, use the control channel to exit send and kill the goroutine.
|
// Now, use the control channel to exit send and kill the goroutine.
|
||||||
// This sneakily uses the fact that the other two goroutines that would
|
// This sneakily uses the fact that the other two goroutines that would
|
||||||
|
@ -500,8 +502,8 @@ func TestRunLoop(t *testing.T) {
|
||||||
exited.assertWasCalled("Didn't exit after signal.")
|
exited.assertWasCalled("Didn't exit after signal.")
|
||||||
|
|
||||||
// Sending more on c.in shouldn't dispatch any further events
|
// Sending more on c.in shouldn't dispatch any further events
|
||||||
c.in <- l1
|
c.in <- l2
|
||||||
h001.assertNotCalled("001 handler called after runLoop ended.")
|
h002.assertNotCalled("002 handler called after runLoop ended.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWrite(t *testing.T) {
|
func TestWrite(t *testing.T) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ package client
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fluffle/goirc/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sets up the internal event handlers to do essential IRC protocol things
|
// sets up the internal event handlers to do essential IRC protocol things
|
||||||
|
@ -41,20 +43,32 @@ func (conn *Conn) h_REGISTER(line *Line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler to trigger a CONNECTED event on receipt of numeric 001
|
// Handler to trigger a CONNECTED event on receipt of numeric 001
|
||||||
|
// :<server> 001 <nick> :Welcome message <nick>!<user>@<host>
|
||||||
func (conn *Conn) h_001(line *Line) {
|
func (conn *Conn) h_001(line *Line) {
|
||||||
// we're connected!
|
// We're connected! Defer this for control flow reasons.
|
||||||
conn.dispatch(&Line{Cmd: CONNECTED, Time: time.Now()})
|
defer conn.dispatch(&Line{Cmd: CONNECTED, Time: time.Now()})
|
||||||
// and we're being given our hostname (from the server's perspective)
|
|
||||||
t := line.Args[len(line.Args)-1]
|
// Accept the server's opinion of what our nick actually is
|
||||||
|
// and record our ident and hostname (from the server's perspective)
|
||||||
|
me, nick, t := conn.Me(), line.Target(), line.Text()
|
||||||
if idx := strings.LastIndex(t, " "); idx != -1 {
|
if idx := strings.LastIndex(t, " "); idx != -1 {
|
||||||
t = t[idx+1:]
|
t = t[idx+1:]
|
||||||
if idx = strings.Index(t, "@"); idx != -1 {
|
}
|
||||||
if conn.st != nil {
|
_, ident, host, ok := parseUserHost(t)
|
||||||
me := conn.Me()
|
|
||||||
conn.st.NickInfo(me.Nick, me.Ident, t[idx+1:], me.Name)
|
if me.Nick != nick {
|
||||||
} else {
|
logging.Warn("Server changed our nick on connect: old=%q new=%q", me.Nick, nick)
|
||||||
conn.cfg.Me.Host = t[idx+1:]
|
}
|
||||||
}
|
if conn.st != nil {
|
||||||
|
if ok {
|
||||||
|
conn.st.NickInfo(me.Nick, ident, host, me.Name)
|
||||||
|
}
|
||||||
|
conn.cfg.Me = conn.st.ReNick(me.Nick, nick)
|
||||||
|
} else {
|
||||||
|
conn.cfg.Me.Nick = nick
|
||||||
|
if ok {
|
||||||
|
conn.cfg.Me.Ident = ident
|
||||||
|
conn.cfg.Me.Host = host
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ func Test001(t *testing.T) {
|
||||||
c, s := setUp(t)
|
c, s := setUp(t)
|
||||||
defer s.tearDown()
|
defer s.tearDown()
|
||||||
|
|
||||||
l := ParseLine(":irc.server.org 001 test :Welcome to IRC test!ident@somehost.com")
|
l := ParseLine(":irc.server.org 001 newnick :Welcome to IRC newnick!ident@somehost.com")
|
||||||
// Set up a handler to detect whether connected handler is called from 001
|
// Set up a handler to detect whether connected handler is called from 001
|
||||||
hcon := false
|
hcon := false
|
||||||
c.HandleFunc("connected", func(conn *Conn, line *Line) {
|
c.HandleFunc("connected", func(conn *Conn, line *Line) {
|
||||||
|
@ -54,7 +54,12 @@ func Test001(t *testing.T) {
|
||||||
// Test state tracking first.
|
// Test state tracking first.
|
||||||
gomock.InOrder(
|
gomock.InOrder(
|
||||||
s.st.EXPECT().Me().Return(c.cfg.Me),
|
s.st.EXPECT().Me().Return(c.cfg.Me),
|
||||||
s.st.EXPECT().NickInfo("test", "test", "somehost.com", "Testing IRC"),
|
s.st.EXPECT().NickInfo("test", "ident", "somehost.com", "Testing IRC"),
|
||||||
|
s.st.EXPECT().ReNick("test", "newnick").Return(&state.Nick{
|
||||||
|
Nick: "newnick",
|
||||||
|
Ident: c.cfg.Me.Ident,
|
||||||
|
Name: c.cfg.Me.Name,
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
// Call handler with a valid 001 line
|
// Call handler with a valid 001 line
|
||||||
c.h_001(l)
|
c.h_001(l)
|
||||||
|
|
|
@ -154,11 +154,10 @@ func ParseLine(s string) *Line {
|
||||||
|
|
||||||
// src can be the hostname of the irc server or a nick!user@host
|
// src can be the hostname of the irc server or a nick!user@host
|
||||||
line.Host = line.Src
|
line.Host = line.Src
|
||||||
nidx, uidx := strings.Index(line.Src, "!"), strings.Index(line.Src, "@")
|
if n, i, h, ok := parseUserHost(line.Src); ok {
|
||||||
if uidx != -1 && nidx != -1 {
|
line.Nick = n
|
||||||
line.Nick = line.Src[:nidx]
|
line.Ident = i
|
||||||
line.Ident = line.Src[nidx+1 : uidx]
|
line.Host = h
|
||||||
line.Host = line.Src[uidx+1:]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +204,15 @@ func ParseLine(s string) *Line {
|
||||||
return line
|
return line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseUserHost(uh string) (nick, ident, host string, ok bool) {
|
||||||
|
uh = strings.TrimSpace(uh)
|
||||||
|
nidx, uidx := strings.Index(uh, "!"), strings.Index(uh, "@")
|
||||||
|
if uidx == -1 || nidx == -1 {
|
||||||
|
return "", "", "", false
|
||||||
|
}
|
||||||
|
return uh[:nidx], uh[nidx+1 : uidx], uh[uidx+1:], true
|
||||||
|
}
|
||||||
|
|
||||||
func (line *Line) argslen(minlen int) bool {
|
func (line *Line) argslen(minlen int) bool {
|
||||||
pc, _, _, _ := runtime.Caller(1)
|
pc, _, _, _ := runtime.Caller(1)
|
||||||
fn := runtime.FuncForPC(pc)
|
fn := runtime.FuncForPC(pc)
|
||||||
|
|
|
@ -184,3 +184,31 @@ func TestLineTags(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseUserHost(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in, nick, ident, host string
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"", "", "", "", false},
|
||||||
|
{" ", "", "", "", false},
|
||||||
|
{"somestring", "", "", "", false},
|
||||||
|
{" s p ", "", "", "", false},
|
||||||
|
{"foo!bar", "", "", "", false},
|
||||||
|
{"foo@baz.com", "", "", "", false},
|
||||||
|
{"foo!bar@baz.com", "foo", "bar", "baz.com", true},
|
||||||
|
{" foo!bar@baz.com", "foo", "bar", "baz.com", true},
|
||||||
|
{" foo!bar@baz.com ", "foo", "bar", "baz.com", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
nick, ident, host, ok := parseUserHost(test.in)
|
||||||
|
if test.nick != nick ||
|
||||||
|
test.ident != ident ||
|
||||||
|
test.host != host ||
|
||||||
|
test.ok != ok {
|
||||||
|
t.Errorf("%d: parseUserHost(%q) = %q, %q, %q, %t; want %q, %q, %q, %t",
|
||||||
|
i, test.in, nick, ident, host, ok, test.nick, test.ident, test.host, test.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue