diff --git a/README.md b/README.md index fc6c8dc..b9d440e 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,9 @@ GoIRC Client Framework Pretty simple, really: - goinstall github.com/fluffle/goirc + go get github.com/fluffle/goirc/client -You can build the test client also with: - - make - ./gobot - -This will connect to freenode and join `#go-nuts` by default, so be careful ;-) +There is some example code that demonstrates usage of the library in `client.go`. This will connect to freenode and join `#go-nuts` by default, so be careful ;-) ### Using the framework diff --git a/client/connection.go b/client/connection.go index d92de24..abe6ba3 100644 --- a/client/connection.go +++ b/client/connection.go @@ -3,20 +3,16 @@ package client import ( "bufio" "crypto/tls" - "github.com/fluffle/goevent/event" - "github.com/fluffle/golog/logging" - "github.com/fluffle/goirc/state" + "errors" "fmt" + "github.com/fluffle/goevent/event" + "github.com/fluffle/goirc/state" + "github.com/fluffle/golog/logging" "net" - "os" "strings" "time" ) -const ( - second = int64(1e9) -) - // An IRC connection is represented by this struct. type Conn struct { // Connection Hostname and Nickname @@ -57,14 +53,12 @@ type Conn struct { // Client->server ping frequency, in seconds. Defaults to 3m. PingFreq int64 - // Socket timeout, in seconds. Default to 5m. - Timeout int64 - // Set this to true to disable flood protection and false to re-enable Flood bool // Internal counters for flood protection - badness, lastsent int64 + badness time.Duration + lastsent time.Time } // Creates a new IRC connection object, but doesn't connect to anything so @@ -90,22 +84,21 @@ func Client(nick, ident, name string, return nil } conn := &Conn{ - ER: r, - ED: r, - l: l, - st: false, - in: make(chan *Line, 32), - out: make(chan string, 32), - cSend: make(chan bool), - cLoop: make(chan bool), - cPing: make(chan bool), - SSL: false, - SSLConfig: nil, - PingFreq: 180, - Timeout: 300, - Flood: false, - badness: 0, - lastsent: 0, + ER: r, + ED: r, + l: l, + st: false, + in: make(chan *Line, 32), + out: make(chan string, 32), + cSend: make(chan bool), + cLoop: make(chan bool), + cPing: make(chan bool), + SSL: false, + SSLConfig: nil, + PingFreq: 180, + Flood: false, + badness: 0, + lastsent: time.Now(), } conn.addIntHandlers() conn.Me = state.NewNick(nick, l) @@ -151,9 +144,9 @@ func (conn *Conn) initialise() { // on the connection to the IRC server, set Conn.SSL to true before calling // Connect(). The port will default to 6697 if ssl is enabled, and 6667 // otherwise. You can also provide an optional connect password. -func (conn *Conn) Connect(host string, pass ...string) os.Error { +func (conn *Conn) Connect(host string, pass ...string) error { if conn.Connected { - return os.NewError(fmt.Sprintf( + return errors.New(fmt.Sprintf( "irc.Connect(): already connected to %s, cannot connect to %s", conn.Host, host)) } @@ -196,7 +189,6 @@ func (conn *Conn) postConnect() { conn.io = bufio.NewReadWriter( bufio.NewReader(conn.sock), bufio.NewWriter(conn.sock)) - conn.sock.SetTimeout(conn.Timeout * second) go conn.send() go conn.recv() if conn.PingFreq > 0 { @@ -231,7 +223,7 @@ func (conn *Conn) recv() { for { s, err := conn.io.ReadString('\n') if err != nil { - conn.l.Error("irc.recv(): %s", err.String()) + conn.l.Error("irc.recv(): %s", err.Error()) conn.shutdown() return } @@ -239,7 +231,7 @@ func (conn *Conn) recv() { conn.l.Debug("<- %s", s) if line := parseLine(s); line != nil { - line.Time = time.LocalTime() + line.Time = time.Now() conn.in <- line } else { conn.l.Warn("irc.recv(): problems parsing line:\n %s", s) @@ -278,21 +270,21 @@ func (conn *Conn) runLoop() { // using Hybrid's algorithm to rate limit if conn.Flood is false. func (conn *Conn) write(line string) { if !conn.Flood { - if t := conn.rateLimit(int64(len(line))); t != 0 { + if t := conn.rateLimit(len(line)); t != 0 { // sleep for the current line's time value before sending it conn.l.Debug("irc.rateLimit(): Flood! Sleeping for %.2f secs.", - float64(t)/float64(second)) + t.Seconds()) <-time.After(t) } } if _, err := conn.io.WriteString(line + "\r\n"); err != nil { - conn.l.Error("irc.send(): %s", err.String()) + conn.l.Error("irc.send(): %s", err.Error()) conn.shutdown() return } if err := conn.io.Flush(); err != nil { - conn.l.Error("irc.send(): %s", err.String()) + conn.l.Error("irc.send(): %s", err.Error()) conn.shutdown() return } @@ -300,19 +292,19 @@ func (conn *Conn) write(line string) { } // Implement Hybrid's flood control algorithm to rate-limit outgoing lines. -func (conn *Conn) rateLimit(chars int64) int64 { +func (conn *Conn) rateLimit(chars int) time.Duration { // Hybrid's algorithm allows for 2 seconds per line and an additional // 1/120 of a second per character on that line. - linetime := 2*second + chars*second/120 - elapsed := time.Nanoseconds() - conn.lastsent + linetime := 2*time.Second + time.Duration(chars)*time.Second/120 + elapsed := time.Now().Sub(conn.lastsent) if conn.badness += linetime - elapsed; conn.badness < 0 { // negative badness times are badness... - conn.badness = int64(0) + conn.badness = 0 } - conn.lastsent = time.Nanoseconds() + conn.lastsent = time.Now() // If we've sent more than 10 second's worth of lines according to the // calculation above, then we're at risk of "Excess Flood". - if conn.badness > 10*second { + if conn.badness > 10*time.Second { return linetime } return 0 diff --git a/client/connection_test.go b/client/connection_test.go index 1c519ac..488638c 100644 --- a/client/connection_test.go +++ b/client/connection_test.go @@ -5,7 +5,7 @@ import ( "github.com/fluffle/goevent/event" "github.com/fluffle/golog/logging" "github.com/fluffle/goirc/state" - "gomock.googlecode.com/hg/gomock" + gomock "github.com/dsymonds/gomock/gomock" "strings" "testing" "time" @@ -92,8 +92,12 @@ func TestClientAndStateTracking(t *testing.T) { l := logging.NewMockLogger(ctrl) st := state.NewMockStateTracker(ctrl) - for n, h := range intHandlers { - r.EXPECT().AddHandler(h, n) + for n, _ := range intHandlers { + // We can't use EXPECT() here as comparisons of functions are + // no longer valid in Go, which causes reflect.DeepEqual to bail. + // Instead, ignore the function arg and just ensure that all the + // handler names are correctly passed to AddHandler. + ctrl.RecordCall(r, "AddHandler", gomock.Any(), []string{n}) } c := Client("test", "test", "Testing IRC", r, l) @@ -110,8 +114,9 @@ func TestClientAndStateTracking(t *testing.T) { } // OK, while we're here with a mock event registry... - for n, h := range stHandlers { - r.EXPECT().AddHandler(h, n) + for n, _ := range stHandlers { + // See above. + ctrl.RecordCall(r, "AddHandler", gomock.Any(), []string{n}) } c.EnableStateTracking() @@ -128,8 +133,9 @@ func TestClientAndStateTracking(t *testing.T) { me := c.Me c.ST = st st.EXPECT().Wipe() - for n, h := range stHandlers { - r.EXPECT().DelHandler(h, n) + for n, _ := range stHandlers { + // See above. + ctrl.RecordCall(r, "DelHandler", gomock.Any(), []string{n}) } c.DisableStateTracking() if c.st || c.ST != nil || c.Me != me { @@ -412,8 +418,8 @@ func TestWrite(t *testing.T) { s.nc.Expect("yo momma") // Flood control is disabled -- setUp sets c.Flood = true -- so we should - // not have set c.badness or c.lastsent at this point. - if c.badness != 0 || c.lastsent != 0 { + // not have set c.badness at this point. + if c.badness != 0 { t.Errorf("Flood control used when Flood = true.") } @@ -421,8 +427,8 @@ func TestWrite(t *testing.T) { c.write("she so useless") s.nc.Expect("she so useless") - // The lastsent time should have been updated now. - if c.lastsent == 0 { + // The lastsent time should have been updated very recently... + if time.Now().Sub(c.lastsent) > time.Millisecond { t.Errorf("Flood control not used when Flood = false.") } @@ -449,24 +455,40 @@ func TestRateLimit(t *testing.T) { c, s := setUp(t) defer s.tearDown() - if c.badness != 0 || c.lastsent != 0 { + if c.badness != 0 { t.Errorf("Bad initial values for rate limit variables.") } - // badness will still be 0 because lastsent was 0 before rateLimit. - if l := c.rateLimit(60); l != 0 || c.badness != 0 || c.lastsent == 0 { - t.Errorf("Rate limit variables not updated correctly after rateLimit.") + // We'll be needing this later... + abs := func(i time.Duration) time.Duration { + if (i < 0) { + return -i + } + return i } + + // Since the changes to the time module, c.lastsent is now a time.Time. + // It's initialised on client creation to time.Now() which for the purposes + // of this test was probably around 1.2 ms ago. This is inconvenient. + // Making it >10s ago effectively clears out the inconsistency, as this + // makes elapsed > linetime and thus zeros c.badness and resets c.lastsent. + c.lastsent = time.Now().Add(-10 * time.Second) + if l := c.rateLimit(60); l != 0 || c.badness != 0 { + t.Errorf("Rate limit got non-zero badness from long-ago lastsent.") + } + // So, time at the nanosecond resolution is a bit of a bitch. Choosing 60 // characters as the line length means we should be increasing badness by // 2.5 seconds minus the delta between the two ratelimit calls. This should - // be minimal but it's guaranteed that it won't be zero. Use 1us as a fuzz. - // This seems to be the minimum timer resolution, on my laptop at least... - if l := c.rateLimit(60); l != 0 || c.badness - int64(25*1e8) > 1e3 { + // be minimal but it's guaranteed that it won't be zero. Use 10us as a fuzz. + if l := c.rateLimit(60); l != 0 || abs(c.badness - 25*1e8) > 10 * time.Microsecond { t.Errorf("Rate limit calculating badness incorrectly.") } - // At this point, we can tip over the badness scale, with a bit of help. - if l := c.rateLimit(360); l == 80*1e8 || c.badness - int64(105*1e8) > 1e3 { + // At this point, we can tip over the badness scale, with a bit of help. + // 720 chars => +8 seconds of badness => 10.5 seconds => ratelimit + if l := c.rateLimit(720); l != 8 * time.Second || + abs(c.badness - 105*1e8) > 10 * time.Microsecond { t.Errorf("Rate limit failed to return correct limiting values.") + t.Errorf("l=%d, badness=%d", l, c.badness) } } diff --git a/client/handlers_test.go b/client/handlers_test.go index e4b3e78..55e21d6 100644 --- a/client/handlers_test.go +++ b/client/handlers_test.go @@ -2,7 +2,7 @@ package client import ( "github.com/fluffle/goirc/state" - "gomock.googlecode.com/hg/gomock" + gomock "github.com/dsymonds/gomock/gomock" "testing" ) diff --git a/client/line.go b/client/line.go index 789d3cc..706d373 100644 --- a/client/line.go +++ b/client/line.go @@ -14,7 +14,7 @@ type Line struct { Nick, Ident, Host, Src string Cmd, Raw string Args []string - Time *time.Time + Time time.Time } // NOTE: this doesn't copy l.Time (this should be read-only anyway) diff --git a/client/mocknetconn_test.go b/client/mocknetconn_test.go index 596efbf..76835f9 100644 --- a/client/mocknetconn_test.go +++ b/client/mocknetconn_test.go @@ -1,6 +1,7 @@ package client import ( + "io" "net" "os" "strings" @@ -23,7 +24,7 @@ type mockNetConn struct { rc chan bool closed bool - rt, wt int64 + rt, wt time.Time } func MockNetConn(t *testing.T) *mockNetConn { @@ -96,9 +97,9 @@ func (m *mockNetConn) ExpectNothing() { } // Implement net.Conn interface -func (m *mockNetConn) Read(b []byte) (int, os.Error) { +func (m *mockNetConn) Read(b []byte) (int, error) { if m.closed { - return 0, os.EINVAL + return 0, os.ErrInvalid } l := 0 select { @@ -106,14 +107,14 @@ func (m *mockNetConn) Read(b []byte) (int, os.Error) { l = len(s) copy(b, s) case <-m.closers[mockReadCloser]: - return 0, os.EOF + return 0, io.EOF } return l, nil } -func (m *mockNetConn) Write(s []byte) (int, os.Error) { +func (m *mockNetConn) Write(s []byte) (int, error) { if m.closed { - return 0, os.EINVAL + return 0, os.ErrInvalid } b := make([]byte, len(s)) copy(b, s) @@ -121,9 +122,9 @@ func (m *mockNetConn) Write(s []byte) (int, os.Error) { return len(s), nil } -func (m *mockNetConn) Close() os.Error { +func (m *mockNetConn) Close() error { if m.closed { - return os.EINVAL + return os.ErrInvalid } // Shut down *ALL* the goroutines! // This will trigger an EOF event in Read() too @@ -142,18 +143,18 @@ func (m *mockNetConn) RemoteAddr() net.Addr { return &net.IPAddr{net.IPv4(127, 0, 0, 1)} } -func (m *mockNetConn) SetTimeout(ns int64) os.Error { - m.rt = ns - m.wt = ns +func (m *mockNetConn) SetDeadline(t time.Time) error { + m.rt = t + m.wt = t return nil } -func (m *mockNetConn) SetReadTimeout(ns int64) os.Error { - m.rt = ns +func (m *mockNetConn) SetReadDeadline(t time.Time) error { + m.rt = t return nil } -func (m *mockNetConn) SetWriteTimeout(ns int64) os.Error { - m.wt = ns +func (m *mockNetConn) SetWriteDeadline(t time.Time) error { + m.wt = t return nil } diff --git a/state/channel.go b/state/channel.go index 8d50e52..e25c4b9 100644 --- a/state/channel.go +++ b/state/channel.go @@ -11,9 +11,9 @@ import ( type Channel struct { Name, Topic string Modes *ChanMode - lookup map[string]*Nick + lookup map[string]*Nick nicks map[*Nick]*ChanPrivs - l logging.Logger + l logging.Logger } // A struct representing the modes of an IRC Channel @@ -93,11 +93,11 @@ func init() { func NewChannel(name string, l logging.Logger) *Channel { return &Channel{ - Name: name, - Modes: new(ChanMode), - nicks: make(map[*Nick]*ChanPrivs), + Name: name, + Modes: new(ChanMode), + nicks: make(map[*Nick]*ChanPrivs), lookup: make(map[string]*Nick), - l: l, + l: l, } } @@ -125,8 +125,8 @@ func (ch *Channel) addNick(nk *Nick, cp *ChanPrivs) { // Disassociates a Nick from a Channel. func (ch *Channel) delNick(nk *Nick) { if _, ok := ch.nicks[nk]; ok { - ch.nicks[nk] = nil, false - ch.lookup[nk.Nick] = nil, false + delete(ch.nicks, nk) + delete(ch.lookup, nk.Nick) } else { ch.l.Warn("Channel.delNick(): %s not on %s.", nk.Nick, ch.Name) } @@ -181,7 +181,7 @@ func (ch *Channel) ParseModes(modes string, modeargs ...string) { } case 'q', 'a', 'o', 'h', 'v': if len(modeargs) != 0 { - if nk, ok := ch.lookup[modeargs[0]]; ok { + if nk, ok := ch.lookup[modeargs[0]]; ok { cp := ch.nicks[nk] switch m { case 'q': diff --git a/state/mock_tracker.go b/state/mock_tracker.go index b223432..1ad2469 100644 --- a/state/mock_tracker.go +++ b/state/mock_tracker.go @@ -4,7 +4,7 @@ package state import ( - gomock "gomock.googlecode.com/hg/gomock" + gomock "github.com/dsymonds/gomock/gomock" ) // Mock of StateTracker interface @@ -24,127 +24,127 @@ func NewMockStateTracker(ctrl *gomock.Controller) *MockStateTracker { return mock } -func (m *MockStateTracker) EXPECT() *_MockStateTrackerRecorder { - return m.recorder +func (_m *MockStateTracker) EXPECT() *_MockStateTrackerRecorder { + return _m.recorder } -func (m *MockStateTracker) NewNick(nick string) *Nick { - ret := m.ctrl.Call(m, "NewNick", nick) +func (_m *MockStateTracker) NewNick(nick string) *Nick { + ret := _m.ctrl.Call(_m, "NewNick", nick) ret0, _ := ret[0].(*Nick) return ret0 } -func (mr *_MockStateTrackerRecorder) NewNick(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "NewNick", arg0) +func (_mr *_MockStateTrackerRecorder) NewNick(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "NewNick", arg0) } -func (m *MockStateTracker) GetNick(nick string) *Nick { - ret := m.ctrl.Call(m, "GetNick", nick) +func (_m *MockStateTracker) GetNick(nick string) *Nick { + ret := _m.ctrl.Call(_m, "GetNick", nick) ret0, _ := ret[0].(*Nick) return ret0 } -func (mr *_MockStateTrackerRecorder) GetNick(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "GetNick", arg0) +func (_mr *_MockStateTrackerRecorder) GetNick(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "GetNick", arg0) } -func (m *MockStateTracker) ReNick(old string, neu string) { - m.ctrl.Call(m, "ReNick", old, neu) +func (_m *MockStateTracker) ReNick(old string, neu string) { + _m.ctrl.Call(_m, "ReNick", old, neu) } -func (mr *_MockStateTrackerRecorder) ReNick(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "ReNick", arg0, arg1) +func (_mr *_MockStateTrackerRecorder) ReNick(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "ReNick", arg0, arg1) } -func (m *MockStateTracker) DelNick(nick string) { - m.ctrl.Call(m, "DelNick", nick) +func (_m *MockStateTracker) DelNick(nick string) { + _m.ctrl.Call(_m, "DelNick", nick) } -func (mr *_MockStateTrackerRecorder) DelNick(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "DelNick", arg0) +func (_mr *_MockStateTrackerRecorder) DelNick(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "DelNick", arg0) } -func (m *MockStateTracker) NewChannel(channel string) *Channel { - ret := m.ctrl.Call(m, "NewChannel", channel) +func (_m *MockStateTracker) NewChannel(channel string) *Channel { + ret := _m.ctrl.Call(_m, "NewChannel", channel) ret0, _ := ret[0].(*Channel) return ret0 } -func (mr *_MockStateTrackerRecorder) NewChannel(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "NewChannel", arg0) +func (_mr *_MockStateTrackerRecorder) NewChannel(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "NewChannel", arg0) } -func (m *MockStateTracker) GetChannel(channel string) *Channel { - ret := m.ctrl.Call(m, "GetChannel", channel) +func (_m *MockStateTracker) GetChannel(channel string) *Channel { + ret := _m.ctrl.Call(_m, "GetChannel", channel) ret0, _ := ret[0].(*Channel) return ret0 } -func (mr *_MockStateTrackerRecorder) GetChannel(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "GetChannel", arg0) +func (_mr *_MockStateTrackerRecorder) GetChannel(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "GetChannel", arg0) } -func (m *MockStateTracker) DelChannel(channel string) { - m.ctrl.Call(m, "DelChannel", channel) +func (_m *MockStateTracker) DelChannel(channel string) { + _m.ctrl.Call(_m, "DelChannel", channel) } -func (mr *_MockStateTrackerRecorder) DelChannel(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "DelChannel", arg0) +func (_mr *_MockStateTrackerRecorder) DelChannel(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "DelChannel", arg0) } -func (m *MockStateTracker) Me() *Nick { - ret := m.ctrl.Call(m, "Me") +func (_m *MockStateTracker) Me() *Nick { + ret := _m.ctrl.Call(_m, "Me") ret0, _ := ret[0].(*Nick) return ret0 } -func (mr *_MockStateTrackerRecorder) Me() *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Me") +func (_mr *_MockStateTrackerRecorder) Me() *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Me") } -func (m *MockStateTracker) IsOn(channel string, nick string) (*ChanPrivs, bool) { - ret := m.ctrl.Call(m, "IsOn", channel, nick) +func (_m *MockStateTracker) IsOn(channel string, nick string) (*ChanPrivs, bool) { + ret := _m.ctrl.Call(_m, "IsOn", channel, nick) ret0, _ := ret[0].(*ChanPrivs) ret1, _ := ret[1].(bool) return ret0, ret1 } -func (mr *_MockStateTrackerRecorder) IsOn(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "IsOn", arg0, arg1) +func (_mr *_MockStateTrackerRecorder) IsOn(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "IsOn", arg0, arg1) } -func (m *MockStateTracker) Associate(channel *Channel, nick *Nick) *ChanPrivs { - ret := m.ctrl.Call(m, "Associate", channel, nick) +func (_m *MockStateTracker) Associate(channel *Channel, nick *Nick) *ChanPrivs { + ret := _m.ctrl.Call(_m, "Associate", channel, nick) ret0, _ := ret[0].(*ChanPrivs) return ret0 } -func (mr *_MockStateTrackerRecorder) Associate(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Associate", arg0, arg1) +func (_mr *_MockStateTrackerRecorder) Associate(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Associate", arg0, arg1) } -func (m *MockStateTracker) Dissociate(channel *Channel, nick *Nick) { - m.ctrl.Call(m, "Dissociate", channel, nick) +func (_m *MockStateTracker) Dissociate(channel *Channel, nick *Nick) { + _m.ctrl.Call(_m, "Dissociate", channel, nick) } -func (mr *_MockStateTrackerRecorder) Dissociate(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Dissociate", arg0, arg1) +func (_mr *_MockStateTrackerRecorder) Dissociate(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Dissociate", arg0, arg1) } -func (m *MockStateTracker) Wipe() { - m.ctrl.Call(m, "Wipe") +func (_m *MockStateTracker) Wipe() { + _m.ctrl.Call(_m, "Wipe") } -func (mr *_MockStateTrackerRecorder) Wipe() *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Wipe") +func (_mr *_MockStateTrackerRecorder) Wipe() *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Wipe") } -func (m *MockStateTracker) String() string { - ret := m.ctrl.Call(m, "String") +func (_m *MockStateTracker) String() string { + ret := _m.ctrl.Call(_m, "String") ret0, _ := ret[0].(string) return ret0 } -func (mr *_MockStateTrackerRecorder) String() *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "String") +func (_mr *_MockStateTrackerRecorder) String() *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "String") } diff --git a/state/nick.go b/state/nick.go index 5fed228..457bec1 100644 --- a/state/nick.go +++ b/state/nick.go @@ -9,9 +9,9 @@ import ( type Nick struct { Nick, Ident, Host, Name string Modes *NickMode - lookup map[string]*Channel + lookup map[string]*Channel chans map[*Channel]*ChanPrivs - l logging.Logger + l logging.Logger } // A struct representing the modes of an IRC Nick (User Modes) @@ -46,11 +46,11 @@ func init() { func NewNick(n string, l logging.Logger) *Nick { return &Nick{ - Nick: n, - Modes: new(NickMode), - chans: make(map[*Channel]*ChanPrivs), + Nick: n, + Modes: new(NickMode), + chans: make(map[*Channel]*ChanPrivs), lookup: make(map[string]*Channel), - l: l, + l: l, } } @@ -78,8 +78,8 @@ func (nk *Nick) addChannel(ch *Channel, cp *ChanPrivs) { // Disassociates a Channel from a Nick. func (nk *Nick) delChannel(ch *Channel) { if _, ok := nk.chans[ch]; ok { - nk.chans[ch] = nil, false - nk.lookup[ch.Name] = nil, false + delete(nk.chans, ch) + delete(nk.lookup, ch.Name) } else { nk.l.Warn("Nick.delChannel(): %s not on %s.", nk.Nick, ch.Name) } diff --git a/state/tracker.go b/state/tracker.go index 8ac7e80..d168b78 100644 --- a/state/tracker.go +++ b/state/tracker.go @@ -45,7 +45,7 @@ func NewTracker(mynick string, l logging.Logger) *stateTracker { st := &stateTracker{ chans: make(map[string]*Channel), nicks: make(map[string]*Nick), - l: l, + l: l, } st.me = st.NewNick(mynick) return st @@ -88,12 +88,12 @@ func (st *stateTracker) ReNick(old, neu string) { if nk, ok := st.nicks[old]; ok { if _, ok := st.nicks[neu]; !ok { nk.Nick = neu - st.nicks[old] = nil, false + delete(st.nicks, old) st.nicks[neu] = nk for ch, _ := range nk.chans { // We also need to update the lookup maps of all the channels // the nick is on, to keep things in sync. - ch.lookup[old] = nil, false + delete(ch.lookup, old) ch.lookup[neu] = nk } } else { @@ -123,7 +123,7 @@ func (st *stateTracker) delNick(nk *Nick) { st.l.Error("StateTracker.DelNick(): TRYING TO DELETE ME :-(") return } - st.nicks[nk.Nick] = nil, false + delete(st.nicks, nk.Nick) for ch, _ := range nk.chans { nk.delChannel(ch) ch.delNick(nk) @@ -165,7 +165,7 @@ func (st *stateTracker) DelChannel(c string) { } func (st *stateTracker) delChannel(ch *Channel) { - st.chans[ch.Name] = nil, false + delete(st.chans, ch.Name) for nk, _ := range ch.nicks { ch.delNick(nk) nk.delChannel(ch) diff --git a/state/tracker_test.go b/state/tracker_test.go index 30d7856..fd4699a 100644 --- a/state/tracker_test.go +++ b/state/tracker_test.go @@ -2,7 +2,7 @@ package state import ( "github.com/fluffle/golog/logging" - "gomock.googlecode.com/hg/gomock" + gomock "github.com/dsymonds/gomock/gomock" "testing" )