12 Commits

Author SHA1 Message Date
James Mills
0e07999cb2 Add TestSASL 2017-12-06 02:12:31 -08:00
James Mills
79c60eafaf Added some topic tests 2017-12-06 02:02:23 -08:00
James Mills
0ec9aaa5eb Fix all tests :D yay 2017-12-06 01:49:15 -08:00
James Mills
90910a20b1 Removed use of deadlock sync package 2017-12-03 23:30:20 -08:00
James Mills
43e4726461 Update vendored 3rd-party deps 2017-12-03 20:34:48 -08:00
James Mills
493b58459d Bah humbut 2017-12-03 20:22:23 -08:00
James Mills
d53b08b3a0 Added TestChannel_BadChannelKey and TestChannel_GoodChannelKey tests 2017-12-03 18:06:16 -08:00
James Mills
8ba7a2c1e2 Added TestChannel_NoExternal test 2017-12-03 17:41:56 -08:00
James Mills
aed917ea2f Fuck it 2017-12-03 17:28:55 -08:00
James Mills
94bbfe4baf Try to fix TestChannel_PRIVMSG test 2017-12-03 16:11:23 -08:00
James Mills
8732f70630 Refactored integration testing framework for better timtouts and added TestChannel_InviteOnly test 2017-12-03 14:34:31 -08:00
James Mills
b7f798d600 Added TestChannel_PRIVMSG test 2017-12-03 13:01:11 -08:00
17 changed files with 415 additions and 76 deletions

12
.gitmodules vendored
View File

@@ -43,15 +43,15 @@
[submodule "vendor/github.com/prometheus/procfs"] [submodule "vendor/github.com/prometheus/procfs"]
path = vendor/github.com/prometheus/procfs path = vendor/github.com/prometheus/procfs
url = https://github.com/prometheus/procfs url = https://github.com/prometheus/procfs
[submodule "vendor/github.com/sasha-s/go-deadlock"]
path = vendor/github.com/sasha-s/go-deadlock
url = https://github.com/sasha-s/go-deadlock
[submodule "vendor/github.com/petermattis/goid"]
path = vendor/github.com/petermattis/goid
url = https://github.com/petermattis/goid
[submodule "vendor/github.com/thoj/go-ircevent"] [submodule "vendor/github.com/thoj/go-ircevent"]
path = vendor/github.com/thoj/go-ircevent path = vendor/github.com/thoj/go-ircevent
url = https://github.com/thoj/go-ircevent url = https://github.com/thoj/go-ircevent
[submodule "vendor/github.com/stretchr/testify"] [submodule "vendor/github.com/stretchr/testify"]
path = vendor/github.com/stretchr/testify path = vendor/github.com/stretchr/testify
url = https://github.com/stretchr/testify url = https://github.com/stretchr/testify
[submodule "vendor/github.com/renstrom/shortuuid"]
path = vendor/github.com/renstrom/shortuuid
url = https://github.com/renstrom/shortuuid
[submodule "vendor/github.com/satori/go.uuid"]
path = vendor/github.com/satori/go.uuid
url = https://github.com/satori/go.uuid

View File

@@ -72,8 +72,14 @@ func NewClient(server *Server, conn net.Conn) *Client {
// //
func (client *Client) writeloop() { func (client *Client) writeloop() {
for reply := range client.replies { for {
client.socket.Write(reply) select {
case reply, ok := <-client.replies:
if !ok || reply == "" || client.socket == nil {
return
}
client.socket.Write(reply)
}
} }
} }

View File

@@ -4,9 +4,7 @@ import (
"errors" "errors"
"regexp" "regexp"
"strings" "strings"
//"sync" "sync"
sync "github.com/sasha-s/go-deadlock"
"github.com/DanielOaks/girc-go/ircmatch" "github.com/DanielOaks/girc-go/ircmatch"
) )

View File

@@ -4,9 +4,7 @@ import (
"errors" "errors"
"io/ioutil" "io/ioutil"
"log" "log"
//"sync" "sync"
sync "github.com/sasha-s/go-deadlock"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"

View File

@@ -4,9 +4,8 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
//"sync" "sync"
sync "github.com/sasha-s/go-deadlock"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )

View File

@@ -2,9 +2,7 @@ package irc
import ( import (
"bytes" "bytes"
//"sync" "sync"
sync "github.com/sasha-s/go-deadlock"
) )
type SaslState struct { type SaslState struct {

View File

@@ -3,9 +3,7 @@ package irc
import ( import (
"fmt" "fmt"
"strings" "strings"
//"sync" "sync"
sync "github.com/sasha-s/go-deadlock"
) )
// //

View File

@@ -1,9 +1,7 @@
package irc package irc
import ( import (
//"sync" "sync"
sync "github.com/sasha-s/go-deadlock"
) )
type WhoWasList struct { type WhoWasList struct {

View File

@@ -2,25 +2,29 @@ package main
import ( import (
"flag" "flag"
"log" "fmt"
"os" "os"
"strings"
"testing" "testing"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/renstrom/shortuuid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/thoj/go-ircevent" "github.com/thoj/go-ircevent"
eris "github.com/prologic/eris/irc" eris "github.com/prologic/eris/irc"
) )
const (
TIMEOUT = 3 * time.Second
)
var ( var (
done chan bool
server *eris.Server server *eris.Server
client *irc.Connection debug = flag.Bool("d", false, "enable debug logging")
clients map[string]*irc.Connection
tls = flag.Bool("tls", false, "run tests with TLS")
) )
func setupServer() *eris.Server { func setupServer() *eris.Server {
@@ -31,6 +35,11 @@ func setupServer() *eris.Server {
config.Server.Description = "Test" config.Server.Description = "Test"
config.Server.Listen = []string{":6667"} config.Server.Listen = []string{":6667"}
// SASL
config.Account = map[string]*eris.PassConfig{
"admin": &eris.PassConfig{"JDJhJDA0JGtUU1JVc1JOUy9DbEh1WEdvYVlMdGVnclp6YnA3NDBOZGY1WUZhdTZtRzVmb1VKdXQ5ckZD"},
}
server := eris.NewServer(config) server := eris.NewServer(config)
go server.Run() go server.Run()
@@ -38,9 +47,21 @@ func setupServer() *eris.Server {
return server return server
} }
func newClient(nick, user, name string, start bool) *irc.Connection { func randomValidName() string {
client := irc.IRC(nick, user) var name eris.Name
client.RealName = name for {
name = eris.NewName(shortuuid.New())
if name.IsNickname() {
break
}
}
return name.String()
}
func newClient(start bool) *irc.Connection {
name := randomValidName()
client := irc.IRC(name, name)
client.RealName = fmt.Sprintf("Test Client: %s", name)
err := client.Connect("localhost:6667") err := client.Connect("localhost:6667")
if err != nil { if err != nil {
@@ -57,21 +78,16 @@ func newClient(nick, user, name string, start bool) *irc.Connection {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
done = make(chan bool) if *debug {
log.SetLevel(log.DebugLevel)
} else {
log.SetLevel(log.WarnLevel)
}
server = setupServer() server = setupServer()
client = newClient("test", "test", "Test", true)
clients = make(map[string]*irc.Connection)
clients["test1"] = newClient("test1", "test", "Test 1", true)
clients["test2"] = newClient("test2", "test", "Test 2", true)
result := m.Run() result := m.Run()
for _, client := range clients {
client.Quit()
}
server.Stop() server.Stop()
os.Exit(result) os.Exit(result)
@@ -88,20 +104,46 @@ func TestConnection(t *testing.T) {
expected = true expected = true
actual = make(chan bool) actual = make(chan bool)
client := newClient("connect", "connect", "Connect", false) client := newClient(false)
client.AddCallback("001", func(e *irc.Event) { client.AddCallback("001", func(e *irc.Event) {
defer func() { done <- true }()
actual <- true actual <- true
}) })
time.AfterFunc(1*time.Second, func() { done <- true })
defer client.Quit() defer client.Quit()
go client.Loop() go client.Loop()
<-done
assert.Equal(expected, <-actual) select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestSASL(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client := newClient(false)
client.SASLLogin = "admin"
client.SASLPassword = "admin"
client.AddCallback("001", func(e *irc.Event) {
actual <- true
})
defer client.Quit()
go client.Loop()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
} }
func TestRplWelcome(t *testing.T) { func TestRplWelcome(t *testing.T) {
@@ -115,20 +157,21 @@ func TestRplWelcome(t *testing.T) {
expected = "Welcome to the .* Internet Relay Network .*!.*@.*" expected = "Welcome to the .* Internet Relay Network .*!.*@.*"
actual = make(chan string) actual = make(chan string)
client := newClient("connect", "connect", "Connect", false) client := newClient(false)
client.AddCallback("001", func(e *irc.Event) { client.AddCallback("001", func(e *irc.Event) {
defer func() { done <- true }()
actual <- e.Message() actual <- e.Message()
}) })
time.AfterFunc(1*time.Second, func() { done <- true })
defer client.Quit() defer client.Quit()
go client.Loop() go client.Loop()
<-done
assert.Regexp(expected, <-actual) select {
case res := <-actual:
assert.Regexp(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
} }
func TestUser_JOIN(t *testing.T) { func TestUser_JOIN(t *testing.T) {
@@ -139,24 +182,75 @@ func TestUser_JOIN(t *testing.T) {
actual chan string actual chan string
) )
expected = []string{"test", "=", "#test", "@test"}
actual = make(chan string) actual = make(chan string)
client.AddCallback("353", func(e *irc.Event) { client := newClient(true)
defer func() { done <- true }()
client.AddCallback("001", func(e *irc.Event) {
expected = []string{e.Arguments[0], "=", "#join", fmt.Sprintf("@%s", e.Arguments[0])}
})
client.AddCallback("353", func(e *irc.Event) {
for i := range e.Arguments { for i := range e.Arguments {
actual <- e.Arguments[i] actual <- e.Arguments[i]
} }
}) })
time.AfterFunc(1*time.Second, func() { done <- true }) defer client.Quit()
client.Join("#test")
client.SendRaw("NAMES #test") client.Join("#join")
<-done client.SendRaw("NAMES #join")
for i := range expected { for i := range expected {
assert.Equal(expected[i], <-actual) select {
case res := <-actual:
assert.Equal(expected[i], res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
}
func TestChannel_InviteOnly(t *testing.T) {
assert := assert.New(t)
var (
expected bool
actual chan bool
)
expected = true
actual = make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("324", func(e *irc.Event) {
if strings.Contains(e.Arguments[2], "i") {
client2.Join("#inviteonly")
} else {
client1.Mode("#inviteonly")
}
})
client2.AddCallback("473", func(e *irc.Event) {
actual <- true
})
client2.AddCallback("JOIN", func(e *irc.Event) {
actual <- false
})
defer client1.Quit()
defer client2.Quit()
client1.Join("#inviteonly")
client1.Mode("#inviteonly", "+i")
client1.Mode("#inviteonly")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
} }
} }
@@ -171,15 +265,265 @@ func TestUser_PRIVMSG(t *testing.T) {
expected = "Hello World!" expected = "Hello World!"
actual = make(chan string) actual = make(chan string)
clients["test1"].AddCallback("PRIVMSG", func(e *irc.Event) { client1 := newClient(true)
defer func() { done <- true }() client2 := newClient(true)
client1.AddCallback("001", func(e *irc.Event) {
client1.Privmsg(client2.GetNick(), expected)
})
client1.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message() actual <- e.Message()
}) })
time.AfterFunc(1*time.Second, func() { done <- true }) client2.AddCallback("001", func(e *irc.Event) {
client.Privmsg("test1", expected) client2.Privmsg(client1.GetNick(), expected)
<-done })
client2.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
assert.Equal(expected, <-actual) defer client1.Quit()
defer client2.Quit()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_PRIVMSG(t *testing.T) {
assert := assert.New(t)
var (
expected string
actual chan string
)
expected = "Hello World!"
actual = make(chan string)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("JOIN", func(e *irc.Event) {
client1.Privmsg(e.Arguments[0], expected)
})
client2.AddCallback("JOIN", func(e *irc.Event) {
client2.Privmsg(e.Arguments[0], expected)
})
client1.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
client2.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
defer client1.Quit()
defer client2.Quit()
client1.Join("#channelprivmsg")
client2.Join("#channelprivmsg")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_NoExternal(t *testing.T) {
assert := assert.New(t)
var (
expected bool
actual chan bool
)
expected = true
actual = make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("JOIN", func(e *irc.Event) {
channel := e.Arguments[0]
if channel == "#noexternal" {
if e.Nick == client1.GetNick() {
client2.Privmsg("#noexternal", "FooBar!")
} else {
assert.Fail(fmt.Sprintf("unexpected user %s joined %s", e.Nick, channel))
}
} else {
assert.Fail(fmt.Sprintf("unexpected channel %s", channel))
}
})
client2.AddCallback("PRIVMSG", func(e *irc.Event) {
if e.Arguments[0] == "#noexternal" {
actual <- false
}
})
client2.AddCallback("404", func(e *irc.Event) {
actual <- true
})
defer client1.Quit()
defer client2.Quit()
client1.Join("#noexternal")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_SetTopic_InvalidChannel(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(true)
defer client1.Quit()
client1.AddCallback("403", func(e *irc.Event) {
actual <- true
})
client1.SendRaw("TOPIC #invalidchannel :FooBar")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_SetTopic_NotOnChannel(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
defer client1.Quit()
defer client2.Quit()
client1.AddCallback("442", func(e *irc.Event) {
actual <- true
})
client2.AddCallback("JOIN", func(e *irc.Event) {
client1.SendRaw("TOPIC #notonchannel :FooBar")
})
client2.Join("#notonchannel")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_BadChannelKey(t *testing.T) {
assert := assert.New(t)
var (
expected bool
actual chan bool
)
expected = true
actual = make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("324", func(e *irc.Event) {
if strings.Contains(e.Arguments[2], "k") {
client2.Join(e.Arguments[1])
} else {
client1.Mode("#badchannelkey")
}
})
client2.AddCallback("JOIN", func(e *irc.Event) {
if e.Nick == client2.GetNick() && e.Arguments[0] == "#badchannelkey" {
actual <- false
}
})
client2.AddCallback("475", func(e *irc.Event) {
actual <- true
})
defer client1.Quit()
defer client2.Quit()
client1.Join("#badchannelkey")
client1.Mode("#badchannelkey", "+k", "opensesame")
client1.Mode("#badchannelkey")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_GoodChannelKey(t *testing.T) {
assert := assert.New(t)
var (
expected bool
actual chan bool
)
expected = true
actual = make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("324", func(e *irc.Event) {
if strings.Contains(e.Arguments[2], "k") {
client2.SendRawf("JOIN %s :opensesame", e.Arguments[1])
} else {
client1.Mode("#goodchannelkey")
}
})
client2.AddCallback("JOIN", func(e *irc.Event) {
if e.Nick == client2.GetNick() && e.Arguments[0] == "#goodchannelkey" {
actual <- true
}
})
client2.AddCallback("475", func(e *irc.Event) {
actual <- false
})
defer client1.Quit()
defer client2.Quit()
client1.Join("#goodchannelkey")
client1.Mode("#goodchannelkey", "+k", "opensesame")
client1.Mode("#goodchannelkey")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
} }

1
vendor/github.com/satori/go.uuid generated vendored Submodule