6 Commits

Author SHA1 Message Date
James Mills
caab002d51 Relase v1.6.4 2017-12-02 18:58:00 -08:00
James Mills
7ff892bba9 Added Drone CI test step 2017-12-02 18:56:53 -08:00
James Mills
233238b709 Adds a basic integration test suite framework (#38)
* Added a basic integration test suite framework

* Add TestConnect_RplWelcome test

* Update vendor 3rd-party deps for missing github.com/stretchr/testify/assert

* Add TestUser_PRIVMSG test

* Rename some tests

* Moar tests

* New test framework with better reliability
2017-11-28 02:15:30 -08:00
James Mills
59e0792db1 Fixed bad label value when bumping metrics for commands processed (#40) 2017-11-27 23:57:42 -08:00
James Mills
962b6645c1 Release v1.6.3 2017-11-27 19:18:58 -08:00
James Mills
cee8bf9957 Added support for multi-layer channel privacy (Public, Private and Secret) (#36) 2017-11-27 19:16:17 -08:00
16 changed files with 263 additions and 27 deletions

View File

@@ -6,9 +6,15 @@ pipeline:
build:
image: golang
commands:
- go get -d
- go get -d ./...
- go build .
test:
image: golang
commands:
- go get -d ./...
- go test ./...
docker:
image: plugins/docker
repo: r.mills.io/prologic/eris

6
.gitmodules vendored
View File

@@ -49,3 +49,9 @@
[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"]
path = vendor/github.com/thoj/go-ircevent
url = https://github.com/thoj/go-ircevent
[submodule "vendor/github.com/stretchr/testify"]
path = vendor/github.com/stretchr/testify
url = https://github.com/stretchr/testify

View File

@@ -35,9 +35,9 @@ Discussion at:
* /server irc.mills.io +6697 (*use TLS/SSL*)
* /join #lobby
Or (*not recommended*)P
Or (**not recommended**):
* /server irc.mills.io (*default port 6667, non-TLS)
* /server irc.mills.io (*default port 6667, non-TLS*)
* /join #lobby
## Features
@@ -54,6 +54,7 @@ Or (*not recommended*)P
* Simple IRC operator privileges (*overrides most things*)
* Secure connection tracking (+z) and SecureOnly user mode (+Z)
* Secure channels (+Z)
* Three layers of channel privacy, Public, Private (+p) and Secret (s)
## Quick Start

View File

@@ -374,7 +374,7 @@ func (channel *Channel) applyMode(client *Client, change *ChannelModeChange) boo
return channel.applyModeMask(client, change.mode, change.op,
NewName(change.arg))
case InviteOnly, Moderated, NoOutside, OpOnlyTopic, Private, SecureChan:
case InviteOnly, Moderated, NoOutside, OpOnlyTopic, Private, Secret, SecureChan:
return channel.applyModeFlag(client, change.mode, change.op)
case Key:

View File

@@ -119,13 +119,6 @@ func (client *Client) readloop() {
}
func (client *Client) processCommand(cmd Command) {
client.server.metrics.Counter("client", "commands").Inc()
defer func(t time.Time) {
v := client.server.metrics.SummaryVec("client", "command_duration_seconds")
v.WithLabelValues(cmd.Code().String()).Observe(time.Now().Sub(t).Seconds())
}(time.Now())
cmd.SetClient(client)
if !client.registered {
@@ -144,6 +137,13 @@ func (client *Client) processCommand(cmd Command) {
return
}
client.server.metrics.Counter("client", "commands").Inc()
defer func(t time.Time) {
v := client.server.metrics.SummaryVec("client", "command_duration_seconds")
v.WithLabelValues(cmd.Code().String()).Observe(time.Now().Sub(t).Seconds())
}(time.Now())
switch srvCmd.(type) {
case *PingCommand, *PongCommand:
client.Touch()

View File

@@ -70,7 +70,6 @@ var (
)
const (
Anonymous ChannelMode = 'a' // flag
BanMask ChannelMode = 'b' // arg
ChannelCreator ChannelMode = 'O' // flag
ChannelOperator ChannelMode = 'o' // arg
@@ -82,8 +81,6 @@ const (
NoOutside ChannelMode = 'n' // flag
OpOnlyTopic ChannelMode = 't' // flag
Private ChannelMode = 'p' // flag
Quiet ChannelMode = 'q' // flag
ReOp ChannelMode = 'r' // flag
Secret ChannelMode = 's' // flag, deprecated
UserLimit ChannelMode = 'l' // flag arg
Voice ChannelMode = 'v' // arg
@@ -93,7 +90,7 @@ const (
var (
SupportedChannelModes = ChannelModes{
BanMask, ExceptMask, InviteMask, InviteOnly, Key, NoOutside,
OpOnlyTopic, Private, UserLimit, SecureChan,
OpOnlyTopic, Private, UserLimit, Secret, SecureChan,
}
)

22
irc/privacy.go Normal file
View File

@@ -0,0 +1,22 @@
package irc
func CanSeeChannel(client *Client, channel *Channel) bool {
isPrivate := channel.flags.Has(Private)
isSecret := channel.flags.Has(Secret)
isMember := channel.members.Has(client)
isOperator := client.flags[Operator]
isRegistered := client.flags[Registered]
isSecure := client.flags[SecureConn]
if !(isSecret || isPrivate) {
return true
}
if isSecret && (isMember || isOperator) {
return true
}
if isPrivate && (isMember || isOperator || (isRegistered && isSecure)) {
return true
}
return false
}

View File

@@ -489,8 +489,13 @@ func (target *Client) RplMOTDEnd() {
}
func (target *Client) RplList(channel *Channel) {
target.NumericReply(RPL_LIST,
"%s %d :%s", channel, channel.members.Count(), channel.topic)
target.NumericReply(
RPL_LIST,
"%s %d :%s",
channel,
channel.members.Count(),
channel.topic,
)
}
func (target *Client) RplListEnd(server *Server) {
@@ -504,8 +509,12 @@ func (target *Client) RplNamReply(channel *Channel) {
}
func (target *Client) RplWhoisChannels(client *Client) {
target.MultilineReply(client.WhoisChannelsNames(), RPL_WHOISCHANNELS,
"%s :%s", client.Nick())
target.MultilineReply(
client.WhoisChannelsNames(target),
RPL_WHOISCHANNELS,
"%s :%s",
client.Nick(),
)
}
func (target *Client) RplVersion() {

View File

@@ -202,6 +202,10 @@ func (server *Server) Shutdown() {
server.Global("shutting down...")
}
func (server *Server) Stop() {
server.done <- true
}
func (server *Server) Run() {
for {
select {
@@ -212,7 +216,7 @@ func (server *Server) Run() {
// Give at least 1s for clients to see the shutdown
go func() {
time.Sleep(1 * time.Second)
server.done <- true
server.Stop()
}()
case conn := <-server.newConns:
@@ -625,10 +629,14 @@ func (msg *PrivMsgCommand) HandleServer(server *Server) {
}
}
func (client *Client) WhoisChannelsNames() []string {
func (client *Client) WhoisChannelsNames(target *Client) []string {
chstrs := make([]string, client.channels.Count())
index := 0
client.channels.Range(func(channel *Channel) bool {
if !CanSeeChannel(target, channel) {
return true
}
switch {
case channel.members.Get(client).Has(ChannelOperator):
chstrs[index] = "@" + channel.name.String()
@@ -835,7 +843,7 @@ func (msg *ListCommand) HandleServer(server *Server) {
if len(msg.channels) == 0 {
server.channels.Range(func(name Name, channel *Channel) bool {
if !client.flags[Operator] && channel.flags.Has(Private) {
if !CanSeeChannel(client, channel) {
return true
}
client.RplList(channel)
@@ -844,7 +852,7 @@ func (msg *ListCommand) HandleServer(server *Server) {
} else {
for _, chname := range msg.channels {
channel := server.channels.Get(chname)
if channel == nil || (!client.flags[Operator] && channel.flags.Has(Private)) {
if channel == nil || !CanSeeChannel(client, channel) {
client.ErrNoSuchChannel(chname)
continue
}

View File

@@ -9,7 +9,7 @@ var (
Package = "eris"
// Version release version
Version = "1.6.2"
Version = "1.6.4"
// Build will be overwritten automatically by the build system
Build = "dev"

185
main_test.go Normal file
View File

@@ -0,0 +1,185 @@
package main
import (
"flag"
"log"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/thoj/go-ircevent"
eris "github.com/prologic/eris/irc"
)
var (
done chan bool
server *eris.Server
client *irc.Connection
clients map[string]*irc.Connection
tls = flag.Bool("tls", false, "run tests with TLS")
)
func setupServer() *eris.Server {
config := &eris.Config{}
config.Network.Name = "Test"
config.Server.Name = "test"
config.Server.Description = "Test"
config.Server.Listen = []string{":6667"}
server := eris.NewServer(config)
go server.Run()
return server
}
func newClient(nick, user, name string, start bool) *irc.Connection {
client := irc.IRC(nick, user)
client.RealName = name
err := client.Connect("localhost:6667")
if err != nil {
log.Fatalf("error setting up test client: %s", err)
}
if start {
go client.Loop()
}
return client
}
func TestMain(m *testing.M) {
flag.Parse()
done = make(chan bool)
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()
for _, client := range clients {
client.Quit()
}
server.Stop()
os.Exit(result)
}
func TestConnection(t *testing.T) {
assert := assert.New(t)
var (
expected bool
actual chan bool
)
expected = true
actual = make(chan bool)
client := newClient("connect", "connect", "Connect", false)
client.AddCallback("001", func(e *irc.Event) {
defer func() { done <- true }()
actual <- true
})
time.AfterFunc(1*time.Second, func() { done <- true })
defer client.Quit()
go client.Loop()
<-done
assert.Equal(expected, <-actual)
}
func TestRplWelcome(t *testing.T) {
assert := assert.New(t)
var (
expected string
actual chan string
)
expected = "Welcome to the .* Internet Relay Network .*!.*@.*"
actual = make(chan string)
client := newClient("connect", "connect", "Connect", false)
client.AddCallback("001", func(e *irc.Event) {
defer func() { done <- true }()
actual <- e.Message()
})
time.AfterFunc(1*time.Second, func() { done <- true })
defer client.Quit()
go client.Loop()
<-done
assert.Regexp(expected, <-actual)
}
func TestUser_JOIN(t *testing.T) {
assert := assert.New(t)
var (
expected []string
actual chan string
)
expected = []string{"test", "=", "#test", "@test"}
actual = make(chan string)
client.AddCallback("353", func(e *irc.Event) {
defer func() { done <- true }()
for i := range e.Arguments {
actual <- e.Arguments[i]
}
})
time.AfterFunc(1*time.Second, func() { done <- true })
client.Join("#test")
client.SendRaw("NAMES #test")
<-done
for i := range expected {
assert.Equal(expected[i], <-actual)
}
}
func TestUser_PRIVMSG(t *testing.T) {
assert := assert.New(t)
var (
expected string
actual chan string
)
expected = "Hello World!"
actual = make(chan string)
clients["test1"].AddCallback("PRIVMSG", func(e *irc.Event) {
defer func() { done <- true }()
actual <- e.Message()
})
time.AfterFunc(1*time.Second, func() { done <- true })
client.Privmsg("test1", expected)
<-done
assert.Equal(expected, <-actual)
}

1
vendor/github.com/stretchr/testify generated vendored Submodule

1
vendor/github.com/thoj/go-ircevent generated vendored Submodule