2011-08-21 12:38:51 +00:00
|
|
|
package client
|
|
|
|
|
2011-08-23 09:49:22 +00:00
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
"testing"
|
2011-08-23 09:53:52 +00:00
|
|
|
"time"
|
2011-08-23 09:49:22 +00:00
|
|
|
)
|
2011-08-21 12:38:51 +00:00
|
|
|
|
|
|
|
func setUp(t *testing.T) (*mockNetConn, *Conn) {
|
|
|
|
c := New("test", "test", "Testing IRC")
|
2011-08-24 12:53:28 +00:00
|
|
|
c.State = t
|
|
|
|
|
2011-08-24 12:55:18 +00:00
|
|
|
// Assert some basic things about the initial state of the Conn struct
|
|
|
|
if c.Me.Nick != "test" ||
|
|
|
|
c.Me.Ident != "test" ||
|
|
|
|
c.Me.Name != "Testing IRC" ||
|
|
|
|
c.Me.Host != "" {
|
|
|
|
t.Errorf("Conn.Me not correctly initialised.")
|
|
|
|
}
|
|
|
|
if len(c.chans) != 0 {
|
|
|
|
t.Errorf("Some channels are already known:")
|
|
|
|
for _, ch := range c.chans {
|
|
|
|
t.Logf(ch.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(c.nicks) != 1 {
|
|
|
|
t.Errorf("Other Nicks than ourselves exist:")
|
|
|
|
for _, n := range c.nicks {
|
|
|
|
t.Logf(n.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-21 12:38:51 +00:00
|
|
|
m := MockNetConn(t)
|
|
|
|
c.sock = m
|
|
|
|
c.postConnect()
|
2011-08-24 12:55:18 +00:00
|
|
|
c.Flood = true // Tests can take a while otherwise
|
|
|
|
c.Connected = true
|
2011-08-21 12:38:51 +00:00
|
|
|
return m, c
|
|
|
|
}
|
2011-08-22 22:23:29 +00:00
|
|
|
|
2011-08-23 09:53:52 +00:00
|
|
|
func tearDown(m *mockNetConn, c *Conn) {
|
|
|
|
// This is enough to cause all the associated goroutines in m and c stop
|
|
|
|
// (tested below in TestShutdown to make sure this is the case)
|
|
|
|
m.Close()
|
|
|
|
}
|
|
|
|
|
2011-08-24 12:53:28 +00:00
|
|
|
func (conn *Conn) ExpectError() {
|
|
|
|
// With the current error handling, we could block on reading the Err
|
|
|
|
// channel, so ensure we don't wait forever with a 5ms timeout.
|
|
|
|
t := conn.State.(*testing.T)
|
|
|
|
timer := time.NewTimer(5e6)
|
|
|
|
select {
|
|
|
|
case <-timer.C:
|
|
|
|
t.Errorf("Error expected on Err channel, none received.")
|
|
|
|
case <-conn.Err:
|
|
|
|
timer.Stop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (conn *Conn) ExpectNoErrors() {
|
|
|
|
t := conn.State.(*testing.T)
|
|
|
|
timer := time.NewTimer(5e6)
|
|
|
|
select {
|
|
|
|
case <-timer.C:
|
|
|
|
case err := <-conn.Err:
|
|
|
|
timer.Stop()
|
|
|
|
t.Errorf("No error expected on Err channel, received:\n\t%s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-23 09:53:52 +00:00
|
|
|
func TestShutdown(t *testing.T) {
|
|
|
|
_, c := setUp(t)
|
|
|
|
|
|
|
|
// Setup a mock event dispatcher to test correct triggering of "disconnected"
|
|
|
|
flag := false
|
|
|
|
c.Dispatcher = WasEventDispatched("disconnected", &flag)
|
|
|
|
|
|
|
|
// Call shutdown manually
|
|
|
|
c.shutdown()
|
|
|
|
|
|
|
|
// Check that we get an EOF from Read()
|
|
|
|
timer := time.NewTimer(5e6)
|
|
|
|
select {
|
|
|
|
case <-timer.C:
|
|
|
|
t.Errorf("No error received for shutdown.")
|
|
|
|
case err := <-c.Err:
|
|
|
|
timer.Stop()
|
|
|
|
if err.String() != "irc.recv(): EOF" {
|
|
|
|
t.Errorf("Expected EOF, got: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the connection no longer thinks it's connected
|
|
|
|
if c.Connected {
|
|
|
|
t.Errorf("Conn still thinks it's connected to the server.")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the "disconnected" event fired correctly
|
|
|
|
if !flag {
|
|
|
|
t.Errorf("Calling Close() didn't result in dispatch of disconnected event.")
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(fluffle): Try to work out a way of testing that the background
|
|
|
|
// goroutines were *actually* stopped? Test m a bit more?
|
|
|
|
}
|
|
|
|
|
|
|
|
// Practically the same as the above test, but shutdown is called implicitly
|
|
|
|
// by recv() getting an EOF from the mock connection.
|
|
|
|
func TestEOF(t *testing.T) {
|
|
|
|
m, c := setUp(t)
|
|
|
|
|
|
|
|
// Setup a mock event dispatcher to test correct triggering of "disconnected"
|
|
|
|
flag := false
|
|
|
|
c.Dispatcher = WasEventDispatched("disconnected", &flag)
|
|
|
|
|
|
|
|
// Simulate EOF from server
|
|
|
|
m.Close()
|
|
|
|
|
|
|
|
// Check that we get an EOF from Read()
|
|
|
|
timer := time.NewTimer(5e6)
|
|
|
|
select {
|
|
|
|
case <-timer.C:
|
|
|
|
t.Errorf("No error received for shutdown.")
|
|
|
|
case err := <-c.Err:
|
|
|
|
timer.Stop()
|
|
|
|
if err.String() != "irc.recv(): EOF" {
|
|
|
|
t.Errorf("Expected EOF, got: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the connection no longer thinks it's connected
|
|
|
|
if c.Connected {
|
|
|
|
t.Errorf("Conn still thinks it's connected to the server.")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the "disconnected" event fired correctly
|
|
|
|
if !flag {
|
|
|
|
t.Errorf("Calling Close() didn't result in dispatch of disconnected event.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-22 22:23:29 +00:00
|
|
|
// Mock dispatcher to verify that events are triggered successfully
|
|
|
|
type mockDispatcher func(string, ...interface{})
|
|
|
|
|
|
|
|
func (d mockDispatcher) Dispatch(name string, ev ...interface{}) {
|
|
|
|
d(name, ev...)
|
|
|
|
}
|
2011-08-23 09:49:22 +00:00
|
|
|
|
|
|
|
func WasEventDispatched(name string, flag *bool) mockDispatcher {
|
|
|
|
return mockDispatcher(func(n string, ev ...interface{}) {
|
|
|
|
if n == strings.ToLower(name) {
|
|
|
|
*flag = true
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|