Remove embedded logger from state tracker. Hmmmm.

This commit is contained in:
Alex Bramley 2013-01-23 22:33:01 +00:00
parent fdcbc5f3d8
commit 5bcf130805
6 changed files with 83 additions and 234 deletions

View File

@ -13,7 +13,6 @@ type Channel struct {
Modes *ChanMode Modes *ChanMode
lookup map[string]*Nick lookup map[string]*Nick
nicks map[*Nick]*ChanPrivs nicks map[*Nick]*ChanPrivs
l logging.Logger
} }
// A struct representing the modes of an IRC Channel // A struct representing the modes of an IRC Channel
@ -97,13 +96,12 @@ func init() {
* Channel methods for state management * Channel methods for state management
\******************************************************************************/ \******************************************************************************/
func NewChannel(name string, l logging.Logger) *Channel { func NewChannel(name string) *Channel {
return &Channel{ return &Channel{
Name: name, Name: name,
Modes: new(ChanMode), Modes: new(ChanMode),
nicks: make(map[*Nick]*ChanPrivs), nicks: make(map[*Nick]*ChanPrivs),
lookup: make(map[string]*Nick), lookup: make(map[string]*Nick),
l: l,
} }
} }
@ -124,7 +122,7 @@ func (ch *Channel) addNick(nk *Nick, cp *ChanPrivs) {
ch.nicks[nk] = cp ch.nicks[nk] = cp
ch.lookup[nk.Nick] = nk ch.lookup[nk.Nick] = nk
} else { } else {
ch.l.Warn("Channel.addNick(): %s already on %s.", nk.Nick, ch.Name) logging.Warn("Channel.addNick(): %s already on %s.", nk.Nick, ch.Name)
} }
} }
@ -134,7 +132,7 @@ func (ch *Channel) delNick(nk *Nick) {
delete(ch.nicks, nk) delete(ch.nicks, nk)
delete(ch.lookup, nk.Nick) delete(ch.lookup, nk.Nick)
} else { } else {
ch.l.Warn("Channel.delNick(): %s not on %s.", nk.Nick, ch.Name) logging.Warn("Channel.delNick(): %s not on %s.", nk.Nick, ch.Name)
} }
} }
@ -176,7 +174,7 @@ func (ch *Channel) ParseModes(modes string, modeargs ...string) {
} else if !modeop { } else if !modeop {
ch.Modes.Key = "" ch.Modes.Key = ""
} else { } else {
ch.l.Warn("Channel.ParseModes(): not enough arguments to "+ logging.Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", ch.Name, modestr, m) "process MODE %s %s%c", ch.Name, modestr, m)
} }
case 'l': case 'l':
@ -186,7 +184,7 @@ func (ch *Channel) ParseModes(modes string, modeargs ...string) {
} else if !modeop { } else if !modeop {
ch.Modes.Limit = 0 ch.Modes.Limit = 0
} else { } else {
ch.l.Warn("Channel.ParseModes(): not enough arguments to "+ logging.Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", ch.Name, modestr, m) "process MODE %s %s%c", ch.Name, modestr, m)
} }
case 'q', 'a', 'o', 'h', 'v': case 'q', 'a', 'o', 'h', 'v':
@ -207,15 +205,15 @@ func (ch *Channel) ParseModes(modes string, modeargs ...string) {
} }
modeargs = modeargs[1:] modeargs = modeargs[1:]
} else { } else {
ch.l.Warn("Channel.ParseModes(): untracked nick %s "+ logging.Warn("Channel.ParseModes(): untracked nick %s "+
"received MODE on channel %s", modeargs[0], ch.Name) "received MODE on channel %s", modeargs[0], ch.Name)
} }
} else { } else {
ch.l.Warn("Channel.ParseModes(): not enough arguments to "+ logging.Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", ch.Name, modestr, m) "process MODE %s %s%c", ch.Name, modestr, m)
} }
default: default:
ch.l.Info("Channel.ParseModes(): unknown mode char %c", m) logging.Info("Channel.ParseModes(): unknown mode char %c", m)
} }
} }
} }

View File

@ -5,12 +5,9 @@ import (
) )
func TestNewChannel(t *testing.T) { func TestNewChannel(t *testing.T) {
_, s := setUp(t) ch := NewChannel("#test1")
defer s.tearDown()
ch := NewChannel("#test1", s.log) if ch.Name != "#test1" {
if ch.Name != "#test1" || ch.l != s.log {
t.Errorf("Channel not created correctly by NewChannel()") t.Errorf("Channel not created correctly by NewChannel()")
} }
if len(ch.nicks) != 0 || len(ch.lookup) != 0 { if len(ch.nicks) != 0 || len(ch.lookup) != 0 {
@ -19,11 +16,8 @@ func TestNewChannel(t *testing.T) {
} }
func TestAddNick(t *testing.T) { func TestAddNick(t *testing.T) {
_, s := setUp(t) ch := NewChannel("#test1")
defer s.tearDown() nk := NewNick("test1")
ch := NewChannel("#test1", s.log)
nk := NewNick("test1", s.log)
cp := new(ChanPrivs) cp := new(ChanPrivs)
ch.addNick(nk, cp) ch.addNick(nk, cp)
@ -37,25 +31,13 @@ func TestAddNick(t *testing.T) {
if n, ok := ch.lookup["test1"]; !ok || n != nk { if n, ok := ch.lookup["test1"]; !ok || n != nk {
t.Errorf("Nick test1 not properly stored in lookup map.") t.Errorf("Nick test1 not properly stored in lookup map.")
} }
s.log.EXPECT().Warn("Channel.addNick(): %s already on %s.",
"test1", "#test1")
ch.addNick(nk, cp)
} }
func TestDelNick(t *testing.T) { func TestDelNick(t *testing.T) {
_, s := setUp(t) ch := NewChannel("#test1")
defer s.tearDown() nk := NewNick("test1")
ch := NewChannel("#test1", s.log)
nk := NewNick("test1", s.log)
cp := new(ChanPrivs) cp := new(ChanPrivs)
// Testing the error state first is easier
s.log.EXPECT().Warn("Channel.delNick(): %s not on %s.",
"test1", "#test1")
ch.delNick(nk)
ch.addNick(nk, cp) ch.addNick(nk, cp)
ch.delNick(nk) ch.delNick(nk)
if len(ch.nicks) != 0 || len(ch.lookup) != 0 { if len(ch.nicks) != 0 || len(ch.lookup) != 0 {
@ -70,14 +52,11 @@ func TestDelNick(t *testing.T) {
} }
func TestChannelParseModes(t *testing.T) { func TestChannelParseModes(t *testing.T) {
_, s := setUp(t) ch := NewChannel("#test1")
defer s.tearDown()
ch := NewChannel("#test1", s.log)
md := ch.Modes md := ch.Modes
// Channel modes can adjust channel privs too, so we need a Nick // Channel modes can adjust channel privs too, so we need a Nick
nk := NewNick("test1", s.log) nk := NewNick("test1")
cp := new(ChanPrivs) cp := new(ChanPrivs)
ch.addNick(nk, cp) ch.addNick(nk, cp)
@ -111,9 +90,7 @@ func TestChannelParseModes(t *testing.T) {
t.Errorf("Limit for channel not set correctly") t.Errorf("Limit for channel not set correctly")
} }
// enable limit incorrectly. see nick_test.go for why the byte() cast. // enable limit incorrectly
s.log.EXPECT().Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", "#test1", "+", byte('l'))
ch.ParseModes("+l") ch.ParseModes("+l")
if md.Limit != 256 { if md.Limit != 256 {
t.Errorf("Bad limit value caused limit to be unset.") t.Errorf("Bad limit value caused limit to be unset.")
@ -137,8 +114,6 @@ func TestChannelParseModes(t *testing.T) {
} }
// enable key incorrectly // enable key incorrectly
s.log.EXPECT().Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", "#test1", "+", byte('k'))
ch.ParseModes("+k") ch.ParseModes("+k")
if md.Key != "foobar" { if md.Key != "foobar" {
t.Errorf("Bad key value caused key to be unset.") t.Errorf("Bad key value caused key to be unset.")
@ -159,18 +134,8 @@ func TestChannelParseModes(t *testing.T) {
t.Errorf("Channel privileges not flipped correctly by ParseModes.") t.Errorf("Channel privileges not flipped correctly by ParseModes.")
} }
s.log.EXPECT().Warn("Channel.ParseModes(): untracked nick %s "+
"received MODE on channel %s", "test2", "#test1")
ch.ParseModes("+v", "test2")
s.log.EXPECT().Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", "#test1", "-", byte('v'))
ch.ParseModes("-v")
// Test a random mix of modes, just to be sure // Test a random mix of modes, just to be sure
md.Limit = 256 md.Limit = 256
s.log.EXPECT().Warn("Channel.ParseModes(): not enough arguments to "+
"process MODE %s %s%c", "#test1", "-", byte('h'))
ch.ParseModes("+zpt-qsl+kv-h", "test1", "foobar", "test1") ch.ParseModes("+zpt-qsl+kv-h", "test1", "foobar", "test1")
if !md.Private || md.Secret || !md.ProtectedTopic || !md.NoExternalMsg || if !md.Private || md.Secret || !md.ProtectedTopic || !md.NoExternalMsg ||
@ -184,8 +149,4 @@ func TestChannelParseModes(t *testing.T) {
// NOTE: HalfOp not actually unset above thanks to deliberate error. // NOTE: HalfOp not actually unset above thanks to deliberate error.
t.Errorf("Channel privileges not flipped correctly by ParseModes (2).") t.Errorf("Channel privileges not flipped correctly by ParseModes (2).")
} }
// Finally, check we get an info log for an unrecognised mode character
s.log.EXPECT().Info("Channel.ParseModes(): unknown mode char %c", byte('d'))
ch.ParseModes("+d")
} }

View File

@ -11,7 +11,6 @@ type Nick struct {
Modes *NickMode Modes *NickMode
lookup map[string]*Channel lookup map[string]*Channel
chans map[*Channel]*ChanPrivs chans map[*Channel]*ChanPrivs
l logging.Logger
} }
// A struct representing the modes of an IRC Nick (User Modes) // A struct representing the modes of an IRC Nick (User Modes)
@ -45,13 +44,12 @@ func init() {
* Nick methods for state management * Nick methods for state management
\******************************************************************************/ \******************************************************************************/
func NewNick(n string, l logging.Logger) *Nick { func NewNick(n string) *Nick {
return &Nick{ return &Nick{
Nick: n, Nick: n,
Modes: new(NickMode), Modes: new(NickMode),
chans: make(map[*Channel]*ChanPrivs), chans: make(map[*Channel]*ChanPrivs),
lookup: make(map[string]*Channel), lookup: make(map[string]*Channel),
l: l,
} }
} }
@ -72,7 +70,7 @@ func (nk *Nick) addChannel(ch *Channel, cp *ChanPrivs) {
nk.chans[ch] = cp nk.chans[ch] = cp
nk.lookup[ch.Name] = ch nk.lookup[ch.Name] = ch
} else { } else {
nk.l.Warn("Nick.addChannel(): %s already on %s.", nk.Nick, ch.Name) logging.Warn("Nick.addChannel(): %s already on %s.", nk.Nick, ch.Name)
} }
} }
@ -82,7 +80,7 @@ func (nk *Nick) delChannel(ch *Channel) {
delete(nk.chans, ch) delete(nk.chans, ch)
delete(nk.lookup, ch.Name) delete(nk.lookup, ch.Name)
} else { } else {
nk.l.Warn("Nick.delChannel(): %s not on %s.", nk.Nick, ch.Name) logging.Warn("Nick.delChannel(): %s not on %s.", nk.Nick, ch.Name)
} }
} }
@ -108,7 +106,7 @@ func (nk *Nick) ParseModes(modes string) {
case 'z': case 'z':
nk.Modes.SSL = modeop nk.Modes.SSL = modeop
default: default:
nk.l.Info("Nick.ParseModes(): unknown mode char %c", m) logging.Info("Nick.ParseModes(): unknown mode char %c", m)
} }
} }
} }

View File

@ -5,12 +5,9 @@ import (
) )
func TestNewNick(t *testing.T) { func TestNewNick(t *testing.T) {
_, s := setUp(t) nk := NewNick("test1")
defer s.tearDown()
nk := NewNick("test1", s.log) if nk.Nick != "test1" {
if nk.Nick != "test1" || nk.l != s.log {
t.Errorf("Nick not created correctly by NewNick()") t.Errorf("Nick not created correctly by NewNick()")
} }
if len(nk.chans) != 0 || len(nk.lookup) != 0 { if len(nk.chans) != 0 || len(nk.lookup) != 0 {
@ -19,11 +16,8 @@ func TestNewNick(t *testing.T) {
} }
func TestAddChannel(t *testing.T) { func TestAddChannel(t *testing.T) {
_, s := setUp(t) nk := NewNick("test1")
defer s.tearDown() ch := NewChannel("#test1")
nk := NewNick("test1", s.log)
ch := NewChannel("#test1", s.log)
cp := new(ChanPrivs) cp := new(ChanPrivs)
nk.addChannel(ch, cp) nk.addChannel(ch, cp)
@ -37,24 +31,13 @@ func TestAddChannel(t *testing.T) {
if c, ok := nk.lookup["#test1"]; !ok || c != ch { if c, ok := nk.lookup["#test1"]; !ok || c != ch {
t.Errorf("Channel #test1 not properly stored in lookup map.") t.Errorf("Channel #test1 not properly stored in lookup map.")
} }
s.log.EXPECT().Warn("Nick.addChannel(): %s already on %s.",
"test1", "#test1")
nk.addChannel(ch, cp)
} }
func TestDelChannel(t *testing.T) { func TestDelChannel(t *testing.T) {
_, s := setUp(t) nk := NewNick("test1")
defer s.tearDown() ch := NewChannel("#test1")
nk := NewNick("test1", s.log)
ch := NewChannel("#test1", s.log)
cp := new(ChanPrivs) cp := new(ChanPrivs)
// Testing the error state first is easier
s.log.EXPECT().Warn("Nick.delChannel(): %s not on %s.", "test1", "#test1")
nk.delChannel(ch)
nk.addChannel(ch, cp) nk.addChannel(ch, cp)
nk.delChannel(ch) nk.delChannel(ch)
if len(nk.chans) != 0 || len(nk.lookup) != 0 { if len(nk.chans) != 0 || len(nk.lookup) != 0 {
@ -69,10 +52,7 @@ func TestDelChannel(t *testing.T) {
} }
func TestNickParseModes(t *testing.T) { func TestNickParseModes(t *testing.T) {
_, s := setUp(t) nk := NewNick("test1")
defer s.tearDown()
nk := NewNick("test1", s.log)
md := nk.Modes md := nk.Modes
// Modes should all be false for a new nick // Modes should all be false for a new nick
@ -90,17 +70,4 @@ func TestNickParseModes(t *testing.T) {
if !md.Invisible || md.Oper || !md.WallOps || md.HiddenHost || !md.SSL { if !md.Invisible || md.Oper || !md.WallOps || md.HiddenHost || !md.SSL {
t.Errorf("Modes not flipped correctly by ParseModes.") t.Errorf("Modes not flipped correctly by ParseModes.")
} }
// Check that passing an unknown mode char results in an info log
// The cast to byte here is needed to pass; gomock uses reflect.DeepEqual
// to examine argument equality, but 'd' (when not implicitly coerced to a
// uint8 by the type system) is an int, whereas string("+d")[1] is not.
// This type difference (despite the values being nominally the same)
// causes the test to fail with the following confusing error.
//
// no matching expected call: *logging.MockLogger.Info([Nick.ParseModes(): unknown mode char %c [100]])
// missing call(s) to *logging.MockLogger.Info(is equal to Nick.ParseModes(): unknown mode char %c, is equal to [100])
s.log.EXPECT().Info("Nick.ParseModes(): unknown mode char %c", byte('d'))
nk.ParseModes("+d")
} }

View File

@ -35,17 +35,13 @@ type stateTracker struct {
// We need to keep state on who we are :-) // We need to keep state on who we are :-)
me *Nick me *Nick
// For great logging justice.
l logging.Logger
} }
// ... and a constructor to make it ... // ... and a constructor to make it ...
func NewTracker(mynick string, l logging.Logger) *stateTracker { func NewTracker(mynick string) *stateTracker {
st := &stateTracker{ st := &stateTracker{
chans: make(map[string]*Channel), chans: make(map[string]*Channel),
nicks: make(map[string]*Nick), nicks: make(map[string]*Nick),
l: l,
} }
st.me = st.NewNick(mynick) st.me = st.NewNick(mynick)
return st return st
@ -67,10 +63,10 @@ func (st *stateTracker) Wipe() {
// can be properly tracked for state management purposes. // can be properly tracked for state management purposes.
func (st *stateTracker) NewNick(n string) *Nick { func (st *stateTracker) NewNick(n string) *Nick {
if _, ok := st.nicks[n]; ok { if _, ok := st.nicks[n]; ok {
st.l.Warn("StateTracker.NewNick(): %s already tracked.", n) logging.Warn("StateTracker.NewNick(): %s already tracked.", n)
return nil return nil
} }
st.nicks[n] = NewNick(n, st.l) st.nicks[n] = NewNick(n)
return st.nicks[n] return st.nicks[n]
} }
@ -97,10 +93,10 @@ func (st *stateTracker) ReNick(old, neu string) {
ch.lookup[neu] = nk ch.lookup[neu] = nk
} }
} else { } else {
st.l.Warn("StateTracker.ReNick(): %s already exists.", neu) logging.Warn("StateTracker.ReNick(): %s already exists.", neu)
} }
} else { } else {
st.l.Warn("StateTracker.ReNick(): %s not tracked.", old) logging.Warn("StateTracker.ReNick(): %s not tracked.", old)
} }
} }
@ -110,17 +106,17 @@ func (st *stateTracker) DelNick(n string) {
if nk != st.me { if nk != st.me {
st.delNick(nk) st.delNick(nk)
} else { } else {
st.l.Warn("StateTracker.DelNick(): won't delete myself.") logging.Warn("StateTracker.DelNick(): won't delete myself.")
} }
} else { } else {
st.l.Warn("StateTracker.DelNick(): %s not tracked.", n) logging.Warn("StateTracker.DelNick(): %s not tracked.", n)
} }
} }
func (st *stateTracker) delNick(nk *Nick) { func (st *stateTracker) delNick(nk *Nick) {
if nk == st.me { if nk == st.me {
// Shouldn't get here => internal state tracking code is fubar. // Shouldn't get here => internal state tracking code is fubar.
st.l.Error("StateTracker.DelNick(): TRYING TO DELETE ME :-(") logging.Error("StateTracker.DelNick(): TRYING TO DELETE ME :-(")
return return
} }
delete(st.nicks, nk.Nick) delete(st.nicks, nk.Nick)
@ -130,7 +126,7 @@ func (st *stateTracker) delNick(nk *Nick) {
if len(ch.nicks) == 0 { if len(ch.nicks) == 0 {
// Deleting a nick from tracking shouldn't empty any channels as // Deleting a nick from tracking shouldn't empty any channels as
// *we* should be on the channel with them to be tracking them. // *we* should be on the channel with them to be tracking them.
st.l.Error("StateTracker.delNick(): deleting nick %s emptied "+ logging.Error("StateTracker.delNick(): deleting nick %s emptied "+
"channel %s, this shouldn't happen!", nk.Nick, ch.Name) "channel %s, this shouldn't happen!", nk.Nick, ch.Name)
} }
} }
@ -140,10 +136,10 @@ func (st *stateTracker) delNick(nk *Nick) {
// can be properly tracked for state management purposes. // can be properly tracked for state management purposes.
func (st *stateTracker) NewChannel(c string) *Channel { func (st *stateTracker) NewChannel(c string) *Channel {
if _, ok := st.chans[c]; ok { if _, ok := st.chans[c]; ok {
st.l.Warn("StateTracker.NewChannel(): %s already tracked.", c) logging.Warn("StateTracker.NewChannel(): %s already tracked.", c)
return nil return nil
} }
st.chans[c] = NewChannel(c, st.l) st.chans[c] = NewChannel(c)
return st.chans[c] return st.chans[c]
} }
@ -160,7 +156,7 @@ func (st *stateTracker) DelChannel(c string) {
if ch, ok := st.chans[c]; ok { if ch, ok := st.chans[c]; ok {
st.delChannel(ch) st.delChannel(ch)
} else { } else {
st.l.Warn("StateTracker.DelChannel(): %s not tracked.", c) logging.Warn("StateTracker.DelChannel(): %s not tracked.", c)
} }
} }
@ -195,19 +191,21 @@ func (st *stateTracker) IsOn(c, n string) (*ChanPrivs, bool) {
// Associates an already known nick with an already known channel. // Associates an already known nick with an already known channel.
func (st *stateTracker) Associate(ch *Channel, nk *Nick) *ChanPrivs { func (st *stateTracker) Associate(ch *Channel, nk *Nick) *ChanPrivs {
if ch == nil || nk == nil { if ch == nil || nk == nil {
st.l.Error("StateTracker.Associate(): passed nil values :-(") logging.Error("StateTracker.Associate(): passed nil values :-(")
return nil return nil
} else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch { } else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch {
// As we can implicitly delete both nicks and channels from being // As we can implicitly delete both nicks and channels from being
// tracked by dissociating one from the other, we should verify that // tracked by dissociating one from the other, we should verify that
// we're not being passed an old Nick or Channel. // we're not being passed an old Nick or Channel.
st.l.Error("StateTracker.Associate(): channel %s not found in "+ logging.Error("StateTracker.Associate(): channel %s not found in "+
"(or differs from) internal state.", ch.Name) "(or differs from) internal state.", ch.Name)
return nil
} else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk { } else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk {
st.l.Error("StateTracker.Associate(): nick %s not found in "+ logging.Error("StateTracker.Associate(): nick %s not found in "+
"(or differs from) internal state.", nk.Nick) "(or differs from) internal state.", nk.Nick)
return nil
} else if _, ok := nk.IsOn(ch); ok { } else if _, ok := nk.IsOn(ch); ok {
st.l.Warn("StateTracker.Associate(): %s already on %s.", logging.Warn("StateTracker.Associate(): %s already on %s.",
nk.Nick, ch.Name) nk.Nick, ch.Name)
return nil return nil
} }
@ -222,18 +220,18 @@ func (st *stateTracker) Associate(ch *Channel, nk *Nick) *ChanPrivs {
// any common channels with, and channels we're no longer on. // any common channels with, and channels we're no longer on.
func (st *stateTracker) Dissociate(ch *Channel, nk *Nick) { func (st *stateTracker) Dissociate(ch *Channel, nk *Nick) {
if ch == nil || nk == nil { if ch == nil || nk == nil {
st.l.Error("StateTracker.Dissociate(): passed nil values :-(") logging.Error("StateTracker.Dissociate(): passed nil values :-(")
} else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch { } else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch {
// As we can implicitly delete both nicks and channels from being // As we can implicitly delete both nicks and channels from being
// tracked by dissociating one from the other, we should verify that // tracked by dissociating one from the other, we should verify that
// we're not being passed an old Nick or Channel. // we're not being passed an old Nick or Channel.
st.l.Error("StateTracker.Dissociate(): channel %s not found in "+ logging.Error("StateTracker.Dissociate(): channel %s not found in "+
"(or differs from) internal state.", ch.Name) "(or differs from) internal state.", ch.Name)
} else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk { } else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk {
st.l.Error("StateTracker.Dissociate(): nick %s not found in "+ logging.Error("StateTracker.Dissociate(): nick %s not found in "+
"(or differs from) internal state.", nk.Nick) "(or differs from) internal state.", nk.Nick)
} else if _, ok := nk.IsOn(ch); !ok { } else if _, ok := nk.IsOn(ch); !ok {
st.l.Warn("StateTracker.Dissociate(): %s not on %s.", logging.Warn("StateTracker.Dissociate(): %s not on %s.",
nk.Nick, ch.Name) nk.Nick, ch.Name)
} else if nk == st.me { } else if nk == st.me {
// I'm leaving the channel for some reason, so it won't be tracked. // I'm leaving the channel for some reason, so it won't be tracked.

View File

@ -1,33 +1,19 @@
package state package state
import ( import (
"code.google.com/p/gomock/gomock"
"github.com/fluffle/golog/logging" "github.com/fluffle/golog/logging"
"testing" "testing"
) )
type testState struct { func init() {
ctrl *gomock.Controller // This is probably a dirty hack...
log *logging.MockLogger logging.InitFromFlags()
} logging.SetLogLevel(logging.LogFatal)
func setUp(t *testing.T) (*stateTracker, *testState) {
ctrl := gomock.NewController(t)
log := logging.NewMockLogger(ctrl)
return NewTracker("mynick", log), &testState{ctrl, log}
}
func (s *testState) tearDown() {
s.ctrl.Finish()
} }
func TestSTNewTracker(t *testing.T) { func TestSTNewTracker(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
if st.l != s.log {
t.Errorf("State tracker's logger not set correctly.")
}
if len(st.nicks) != 1 { if len(st.nicks) != 1 {
t.Errorf("Nick list of new tracker is not 1 (me!).") t.Errorf("Nick list of new tracker is not 1 (me!).")
} }
@ -40,28 +26,23 @@ func TestSTNewTracker(t *testing.T) {
} }
func TestSTNewNick(t *testing.T) { func TestSTNewNick(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
test1 := st.NewNick("test1") test1 := st.NewNick("test1")
if test1 == nil || test1.Nick != "test1" || test1.l != s.log { if test1 == nil || test1.Nick != "test1" {
t.Errorf("Nick object created incorrectly by NewNick.") t.Errorf("Nick object created incorrectly by NewNick.")
} }
if n, ok := st.nicks["test1"]; !ok || n != test1 || len(st.nicks) != 2 { if n, ok := st.nicks["test1"]; !ok || n != test1 || len(st.nicks) != 2 {
t.Errorf("Nick object stored incorrectly by NewNick.") t.Errorf("Nick object stored incorrectly by NewNick.")
} }
s.log.EXPECT().Warn("StateTracker.NewNick(): %s already tracked.", "test1")
if fail := st.NewNick("test1"); fail != nil { if fail := st.NewNick("test1"); fail != nil {
t.Errorf("Creating duplicate nick did not produce nil return.") t.Errorf("Creating duplicate nick did not produce nil return.")
} }
} }
func TestSTGetNick(t *testing.T) { func TestSTGetNick(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
test1 := st.NewNick("test1") test1 := st.NewNick("test1")
if n := st.GetNick("test1"); n != test1 { if n := st.GetNick("test1"); n != test1 {
@ -76,9 +57,7 @@ func TestSTGetNick(t *testing.T) {
} }
func TestSTReNick(t *testing.T) { func TestSTReNick(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
test1 := st.NewNick("test1") test1 := st.NewNick("test1")
// This channel is here to ensure that its lookup map gets updated // This channel is here to ensure that its lookup map gets updated
@ -107,8 +86,6 @@ func TestSTReNick(t *testing.T) {
} }
test2 := st.NewNick("test1") test2 := st.NewNick("test1")
s.log.EXPECT().Warn("StateTracker.ReNick(): %s already exists.", "test2")
st.ReNick("test1", "test2") st.ReNick("test1", "test2")
if n, ok := st.nicks["test2"]; !ok || n != test1 { if n, ok := st.nicks["test2"]; !ok || n != test1 {
@ -120,14 +97,10 @@ func TestSTReNick(t *testing.T) {
if len(st.nicks) != 3 { if len(st.nicks) != 3 {
t.Errorf("Nick list changed size during ReNick.") t.Errorf("Nick list changed size during ReNick.")
} }
s.log.EXPECT().Warn("StateTracker.ReNick(): %s not tracked.", "test3")
st.ReNick("test3", "test2")
} }
func TestSTDelNick(t *testing.T) { func TestSTDelNick(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
st.NewNick("test1") st.NewNick("test1")
st.DelNick("test1") st.DelNick("test1")
@ -142,17 +115,13 @@ func TestSTDelNick(t *testing.T) {
// Deleting unknown nick shouldn't work, but let's make sure we have a // Deleting unknown nick shouldn't work, but let's make sure we have a
// known nick first to catch any possible accidental removals. // known nick first to catch any possible accidental removals.
nick1 := st.NewNick("test1") nick1 := st.NewNick("test1")
s.log.EXPECT().Warn("StateTracker.DelNick(): %s not tracked.", "test2")
st.DelNick("test2") st.DelNick("test2")
if len(st.nicks) != 2 { if len(st.nicks) != 2 {
t.Errorf("Deleting unknown nick had unexpected side-effects.") t.Errorf("Deleting unknown nick had unexpected side-effects.")
} }
// Deleting my nick shouldn't work // Deleting my nick shouldn't work
s.log.EXPECT().Warn("StateTracker.DelNick(): won't delete myself.")
st.DelNick("mynick") st.DelNick("mynick")
if len(st.nicks) != 2 { if len(st.nicks) != 2 {
t.Errorf("Deleting myself had unexpected side-effects.") t.Errorf("Deleting myself had unexpected side-effects.")
} }
@ -192,8 +161,7 @@ func TestSTDelNick(t *testing.T) {
} }
func TestSTNewChannel(t *testing.T) { func TestSTNewChannel(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
if len(st.chans) != 0 { if len(st.chans) != 0 {
t.Errorf("Channel list of new tracker is non-zero length.") t.Errorf("Channel list of new tracker is non-zero length.")
@ -201,22 +169,20 @@ func TestSTNewChannel(t *testing.T) {
test1 := st.NewChannel("#test1") test1 := st.NewChannel("#test1")
if test1 == nil || test1.Name != "#test1" || test1.l != s.log { if test1 == nil || test1.Name != "#test1" {
t.Errorf("Channel object created incorrectly by NewChannel.") t.Errorf("Channel object created incorrectly by NewChannel.")
} }
if c, ok := st.chans["#test1"]; !ok || c != test1 || len(st.chans) != 1 { if c, ok := st.chans["#test1"]; !ok || c != test1 || len(st.chans) != 1 {
t.Errorf("Channel object stored incorrectly by NewChannel.") t.Errorf("Channel object stored incorrectly by NewChannel.")
} }
s.log.EXPECT().Warn("StateTracker.NewChannel(): %s already tracked.", "#test1")
if fail := st.NewChannel("#test1"); fail != nil { if fail := st.NewChannel("#test1"); fail != nil {
t.Errorf("Creating duplicate chan did not produce nil return.") t.Errorf("Creating duplicate chan did not produce nil return.")
} }
} }
func TestSTGetChannel(t *testing.T) { func TestSTGetChannel(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
test1 := st.NewChannel("#test1") test1 := st.NewChannel("#test1")
@ -232,8 +198,7 @@ func TestSTGetChannel(t *testing.T) {
} }
func TestSTDelChannel(t *testing.T) { func TestSTDelChannel(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
st.NewChannel("#test1") st.NewChannel("#test1")
st.DelChannel("#test1") st.DelChannel("#test1")
@ -248,10 +213,7 @@ func TestSTDelChannel(t *testing.T) {
// Deleting unknown nick shouldn't work, but let's make sure we have a // Deleting unknown nick shouldn't work, but let's make sure we have a
// known nick first to catch any possible accidental removals. // known nick first to catch any possible accidental removals.
chan1 := st.NewChannel("#test1") chan1 := st.NewChannel("#test1")
s.log.EXPECT().Warn("StateTracker.DelChannel(): %s not tracked.", "#test2")
st.DelChannel("#test2") st.DelChannel("#test2")
if len(st.chans) != 1 { if len(st.chans) != 1 {
t.Errorf("DelChannel had unexpected side-effects.") t.Errorf("DelChannel had unexpected side-effects.")
} }
@ -306,8 +268,7 @@ func TestSTDelChannel(t *testing.T) {
} }
func TestSTIsOn(t *testing.T) { func TestSTIsOn(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
nick1 := st.NewNick("test1") nick1 := st.NewNick("test1")
chan1 := st.NewChannel("#test1") chan1 := st.NewChannel("#test1")
@ -322,8 +283,7 @@ func TestSTIsOn(t *testing.T) {
} }
func TestSTAssociate(t *testing.T) { func TestSTAssociate(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
nick1 := st.NewNick("test1") nick1 := st.NewNick("test1")
chan1 := st.NewChannel("#test1") chan1 := st.NewChannel("#test1")
@ -337,32 +297,25 @@ func TestSTAssociate(t *testing.T) {
} }
// Test error cases // Test error cases
s.log.EXPECT().Error("StateTracker.Associate(): passed nil values :-(") if st.Associate(nil, nick1) != nil {
st.Associate(nil, nick1) t.Errorf("Associating nil *Channel did not return nil.")
}
s.log.EXPECT().Error("StateTracker.Associate(): passed nil values :-(") if st.Associate(chan1, nil) != nil {
st.Associate(chan1, nil) t.Errorf("Associating nil *Nick did not return nil.")
}
s.log.EXPECT().Warn("StateTracker.Associate(): %s already on %s.", if st.Associate(chan1, nick1) != nil {
"test1", "#test1") t.Errorf("Associating already-associated things did not return nil.")
st.Associate(chan1, nick1) }
if st.Associate(chan1, NewNick("test2")) != nil {
// nick2 deliberately created directly here. t.Errorf("Associating unknown *Nick did not return nil.")
nick2 := NewNick("test2", s.log) }
s.log.EXPECT().Error("StateTracker.Associate(): nick %s not found in "+ if st.Associate(NewChannel("#test2"), nick1) != nil {
"(or differs from) internal state.", "test2") t.Errorf("Associating unknown *Channel did not return nil.")
st.Associate(chan1, nick2) }
// chan2 deliberately created directly here.
chan2 := NewChannel("#test2", s.log)
s.log.EXPECT().Error("StateTracker.Associate(): channel %s not found in "+
"(or differs from) internal state.", "#test2")
st.Associate(chan2, nick1)
} }
func TestSTDissociate(t *testing.T) { func TestSTDissociate(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
nick1 := st.NewNick("test1") nick1 := st.NewNick("test1")
chan1 := st.NewChannel("#test1") chan1 := st.NewChannel("#test1")
@ -417,36 +370,10 @@ func TestSTDissociate(t *testing.T) {
len(st.me.chans) != 2 || len(nick1.chans) != 0 || len(st.chans) != 2 { len(st.me.chans) != 2 || len(nick1.chans) != 0 || len(st.chans) != 2 {
t.Errorf("Dissociating a nick from it's last channel went wrong.") t.Errorf("Dissociating a nick from it's last channel went wrong.")
} }
// Check error cases
// test1 was deleted above, so "re-track" it for this test.
nick1 = st.NewNick("test1")
s.log.EXPECT().Warn("StateTracker.Dissociate(): %s not on %s.",
"test1", "#test1")
st.Dissociate(chan1, nick1)
s.log.EXPECT().Error("StateTracker.Dissociate(): passed nil values :-(")
st.Dissociate(chan1, nil)
s.log.EXPECT().Error("StateTracker.Dissociate(): passed nil values :-(")
st.Dissociate(nil, nick1)
// nick3 deliberately created directly here.
nick3 := NewNick("test3", s.log)
s.log.EXPECT().Error("StateTracker.Dissociate(): nick %s not found in "+
"(or differs from) internal state.", "test3")
st.Dissociate(chan1, nick3)
// chan3 deliberately created directly here.
chan3 := NewChannel("#test3", s.log)
s.log.EXPECT().Error("StateTracker.Dissociate(): channel %s not found in "+
"(or differs from) internal state.", "#test3")
st.Dissociate(chan3, nick1)
} }
func TestSTWipe(t *testing.T) { func TestSTWipe(t *testing.T) {
st, s := setUp(t) st := NewTracker("mynick")
defer s.tearDown()
nick1 := st.NewNick("test1") nick1 := st.NewNick("test1")
nick2 := st.NewNick("test2") nick2 := st.NewNick("test2")