gorepost/bot/plugins_test.go

872 lines
17 KiB
Go
Raw Permalink Normal View History

2015-11-17 18:46:48 +00:00
// +build go1.4
// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2015-11-17 17:44:52 +00:00
package bot
import (
"fmt"
2015-11-18 18:12:54 +00:00
"io/ioutil"
"log"
2015-11-17 17:44:52 +00:00
"os"
2015-12-08 23:08:19 +00:00
"regexp"
2015-11-17 17:44:52 +00:00
"sync"
"testing"
"time"
2015-11-17 17:44:52 +00:00
2015-12-14 14:12:18 +00:00
"github.com/arachnist/dyncfg"
2015-11-17 17:44:52 +00:00
"github.com/arachnist/gorepost/irc"
)
var eventTests = []struct {
2015-12-07 00:31:02 +00:00
desc string
2015-11-17 17:44:52 +00:00
in irc.Message
expectedOut []irc.Message
}{
2015-12-07 10:10:05 +00:00
{
desc: "seen noone",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen noone",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "nope, never",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "ping",
2015-11-17 17:44:52 +00:00
in: irc.Message{
Command: "PING",
Trailing: "foobar",
},
expectedOut: []irc.Message{
{
Command: "PONG",
Trailing: "foobar",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "invitki",
2015-11-17 17:44:52 +00:00
in: irc.Message{
Command: "INVITE",
Trailing: "#test-channel",
},
expectedOut: []irc.Message{
{
Command: "JOIN",
Params: []string{"#test-channel"},
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "channel join",
2015-11-17 17:44:52 +00:00
in: irc.Message{
Command: "001",
Context: map[string]string{
"Network": "TestNetwork",
},
},
expectedOut: []irc.Message{
{
Command: "JOIN",
Params: []string{"#testchan-1"},
},
{
Command: "JOIN",
Params: []string{"#testchan-2"},
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "msgping",
2015-11-17 17:44:52 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":ping",
2015-11-29 15:58:01 +00:00
Params: []string{"#testchan-1"},
2015-11-17 17:44:52 +00:00
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
2015-11-29 15:58:01 +00:00
Params: []string{"#testchan-1"},
2015-11-17 17:44:52 +00:00
Trailing: "pingity pong",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "nickserv",
2015-11-19 07:24:07 +00:00
in: irc.Message{
Command: "NOTICE",
Params: []string{"gorepost"},
Trailing: "This nickname is registered. Please choose a different nickname, or identify via …",
Prefix: &irc.Prefix{
Name: "NickServ",
User: "NickServ",
Host: "services.",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"NickServ"},
Trailing: "IDENTIFY test_password",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "pick",
2015-12-06 13:00:59 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":pick test",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "test",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "google",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":g google.com",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Google https://www.google.com/",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "linktitle",
in: irc.Message{
Command: "PRIVMSG",
Trailing: "https://www.google.com/",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "↳ title: Google",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "nickserv channeljoin",
2015-12-06 23:32:06 +00:00
in: irc.Message{
Command: "NOTICE",
Params: []string{"gorepost"},
Trailing: "You are now identified",
Prefix: &irc.Prefix{
Name: "NickServ",
User: "NickServ",
Host: "services.",
},
},
expectedOut: []irc.Message{
{
Command: "JOIN",
Params: []string{"#securechan-1"},
},
{
Command: "JOIN",
Params: []string{"#securechan-2"},
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "linktitle connection refused",
2015-12-06 23:58:53 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: "http://127.0.0.1:333/conn-refused",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "↳ title: error:Get http://127.0.0.1:333/conn-refused: dial tcp 127.0.0.1:333: getsockopt: connection refused",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "linktitle iso8859-2",
2015-12-06 23:58:53 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: "http://arachnist.is-a.cat/test-iso8859-2.html",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "↳ title: Tytuł używający przestarzałego kodowania znaków",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "linktitle common exploit",
2015-12-06 23:58:53 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: "http://arachnist.is-a.cat/test.html",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "↳ title: Tak Aż zbyt dobrze. Naprawdę QUIT dupa",
},
},
},
{
desc: "papież",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":papież",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
User: "test",
Host: "framework",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Papież adjective",
},
},
},
{
desc: "jan without args",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":jan",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
User: "test",
Host: "framework",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Jan Paweł II predicate małe object",
},
},
},
{
desc: "jan predicate",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":jan predicate-ł",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
User: "test",
Host: "framework",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Jan Paweł II predicate-ł małe object",
},
},
},
{
desc: "jan object",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":jan specified-object",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
User: "test",
Host: "framework",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Jan Paweł II predicate małe specified-object",
},
},
},
2015-12-10 21:53:10 +00:00
{
desc: "roll multiple",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll 1 3",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
2015-12-10 21:59:23 +00:00
Trailing: "3",
2015-12-10 21:53:10 +00:00
},
},
},
{
desc: "roll single",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll 1",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
2015-12-10 21:59:23 +00:00
Trailing: "1",
2015-12-10 21:53:10 +00:00
},
},
},
{
desc: "roll too many arguments",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll 0 1 2",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
2015-12-10 21:59:23 +00:00
Trailing: "Usage: :roll <sides int> <rolls int>, each roll is [0, n)+1, size has to be >0",
2015-12-10 22:07:18 +00:00
},
},
},
{
desc: "roll multiple strings",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll string another",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Usage: :roll <sides int> <rolls int>, each roll is [0, n)+1, size has to be >0",
},
},
},
{
desc: "roll string",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll string",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Usage: :roll <sides int> <rolls int>, each roll is [0, n)+1, size has to be >0",
2015-12-10 21:53:10 +00:00
},
},
},
2015-12-11 06:42:42 +00:00
{
desc: "roll 1000000",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll 2000000",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
Trailing: "Number of rolls and dice size is limited to 1000000",
},
},
},
2015-12-10 21:53:10 +00:00
{
desc: "roll 0",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":roll 0",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
expectedOut: []irc.Message{
{
Command: "PRIVMSG",
Params: []string{"#testchan-1"},
2015-12-10 21:59:23 +00:00
Trailing: "Usage: :roll <sides int> <rolls int>, each roll is [0, n)+1, size has to be >0",
2015-12-10 21:53:10 +00:00
},
},
},
2015-12-08 05:18:02 +00:00
}
func TestPlugins(t *testing.T) {
var r []irc.Message
var m sync.Mutex
2015-12-08 05:18:02 +00:00
var wg sync.WaitGroup
// fake irc.Conn Sender replacement
output := func(msg irc.Message) {
m.Lock()
defer m.Unlock()
2015-12-08 05:18:02 +00:00
wg.Done()
r = append(r, msg)
}
for _, e := range eventTests {
2015-12-08 23:08:19 +00:00
t.Log("Running test", e.desc)
2015-12-08 05:18:02 +00:00
r = r[:0]
wg.Add(len(e.expectedOut))
Dispatcher(output, e.in)
time.Sleep(3000000 * time.Nanosecond)
wg.Wait()
m.Lock()
2015-12-08 05:18:02 +00:00
if fmt.Sprintf("%+v", r) != fmt.Sprintf("%+v", e.expectedOut) {
t.Logf("expected: %+v\n", e.expectedOut)
t.Logf("result: %+v\n", r)
t.Fail()
}
m.Unlock()
2015-12-08 05:18:02 +00:00
}
}
var noResponseEvents = []struct {
desc string
in irc.Message
}{
2015-12-07 00:31:02 +00:00
{
desc: "linktitle missing title",
2015-12-06 23:58:53 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: "http://arachnist.is-a.cat/test-no-title.html",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
2015-12-08 23:08:19 +00:00
User: "test",
Host: "framework",
2015-12-06 23:58:53 +00:00
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "linktitle notitle",
in: irc.Message{
Command: "PRIVMSG",
Trailing: "https://www.google.com/ notitle",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
2015-12-08 23:08:19 +00:00
User: "test",
Host: "framework",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "nickserv spoof",
in: irc.Message{
Command: "NOTICE",
Params: []string{"gorepost"},
Trailing: "This nickname is registered. Please choose a different nickname, or identify via …",
Prefix: &irc.Prefix{
Name: "NickServ",
User: "NickServ",
Host: "fake.",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "nickserv other message",
in: irc.Message{
Command: "NOTICE",
Params: []string{"gorepost"},
Trailing: "Some other random message…",
Prefix: &irc.Prefix{
Name: "NickServ",
User: "NickServ",
Host: "services.",
},
},
},
2015-12-07 00:31:02 +00:00
{
desc: "non-matching",
2015-11-17 17:44:52 +00:00
in: irc.Message{
Command: "PRIVMSG",
Trailing: "foo bar baz",
2015-12-08 23:08:19 +00:00
Prefix: &irc.Prefix{
Name: "test-framework",
User: "test",
Host: "framework",
},
2015-11-17 17:44:52 +00:00
},
},
2015-12-08 23:26:03 +00:00
{
desc: "seen without arguments",
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
},
2015-11-17 17:44:52 +00:00
}
2015-12-08 05:18:02 +00:00
func TestNoResponse(t *testing.T) {
output := func(msg irc.Message) {
2015-12-08 23:26:03 +00:00
t.Logf("Got a response: %+v\n", msg)
2015-12-08 05:18:02 +00:00
t.Fail()
}
2015-12-08 05:18:02 +00:00
for _, e := range noResponseEvents {
t.Log("Running test", e.desc)
2015-11-17 17:44:52 +00:00
Dispatcher(output, e.in)
2015-12-08 05:18:02 +00:00
time.Sleep(100000000 * time.Nanosecond) // 1*10^8 => 0.1 seconds
2015-11-17 17:44:52 +00:00
}
}
2015-12-08 23:08:19 +00:00
var seenTestSeedEvents = []irc.Message{
{
Command: "JOIN",
Trailing: "",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "join",
User: "seen",
Host: "test",
},
},
{
Command: "PRIVMSG",
Trailing: "that's a text",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "privmsg",
User: "seen",
Host: "test",
},
},
{
Command: "NOTICE",
Trailing: "that's a notice",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "notice",
User: "seen",
Host: "test",
},
},
{
Command: "PART",
Trailing: "i'm leaving you",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "part",
User: "seen",
Host: "test",
},
},
{
Command: "QUIT",
Trailing: "that's a quit message",
Params: []string{},
Prefix: &irc.Prefix{
Name: "quit",
User: "seen",
Host: "test",
},
},
}
var seenTests = []struct {
in irc.Message
outRegex string
}{
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen join",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: "^Last seen join on /#testchan-1 at .* joining$",
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen privmsg",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: "^Last seen privmsg on /#testchan-1 at .* saying: that's a text$",
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen notice",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: "^Last seen notice on /#testchan-1 at .* noticing: that's a notice$",
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen part",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: "^Last seen part on /#testchan-1 at .* leaving: i'm leaving you$",
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":seen quit",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: "^Last seen quit on / at .* quitting with reasson: that's a quit message$",
},
}
func TestSeenConditions(t *testing.T) {
var wg sync.WaitGroup
failOutput := func(msg irc.Message) {
t.Log("these should not output anything")
t.Fail()
}
genOutTestFunction := func(regex string) func(irc.Message) {
return func(m irc.Message) {
t.Logf("testing regex %+v on %+v", regex, m.Trailing)
if b, _ := regexp.Match(regex, []byte(m.Trailing)); !b {
t.Log("Failed", m.Trailing)
t.Fail()
}
wg.Done()
}
}
wg.Add(len(seenTestSeedEvents))
for _, e := range seenTestSeedEvents {
2015-12-08 23:41:18 +00:00
t.Logf("Filling seen db with: %+v\n", e)
seenrecord(failOutput, e)
2015-12-08 23:08:19 +00:00
wg.Done()
}
wg.Wait()
wg.Add(len(seenTests))
for _, e := range seenTests {
seen(genOutTestFunction(e.outRegex), e.in)
2015-12-08 23:08:19 +00:00
}
wg.Wait()
}
var variableOutputTestEvents = []struct {
in irc.Message
outRegex regexp.Regexp
function func(func(irc.Message), irc.Message)
}{
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":kotki",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: *regexp.MustCompile("^http://.*tumblr"),
function: kotki,
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":cycki",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: *regexp.MustCompile("^cycki [(]nsfw[)]: http://.*"),
function: cycki,
},
2015-12-15 20:40:11 +00:00
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":bonjour",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: *regexp.MustCompile("^bonjour [(]nsfw[)]: http://.*"),
function: bonjour,
},
2015-12-16 18:29:36 +00:00
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":korwin",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: *regexp.MustCompile("^."),
function: korwin,
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: ":at",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
outRegex: *regexp.MustCompile("^at:"),
function: at,
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
2015-12-24 08:53:50 +00:00
outRegex: *regexp.MustCompile("^↳ title: Rick Astley - Never Gonna Give You Up by RickAstleyVEVO$"),
function: linktitle,
},
{
in: irc.Message{
Command: "PRIVMSG",
Trailing: "http://youtu.be/dQw4w9WgXcQ",
Params: []string{"#testchan-1"},
Prefix: &irc.Prefix{
Name: "idontexist",
},
},
2015-12-24 08:53:50 +00:00
outRegex: *regexp.MustCompile("^↳ title: Rick Astley - Never Gonna Give You Up by RickAstleyVEVO$"),
function: linktitle,
},
}
func TestFunctionsWithVariableOutput(t *testing.T) {
var wg sync.WaitGroup
genOutTestFunction := func(regex regexp.Regexp) func(irc.Message) {
return func(m irc.Message) {
t.Logf("testing regex /%v/ on %+v", regex.String(), m.Trailing)
if !regex.Match([]byte(m.Trailing)) {
t.Log("Failed", m.Trailing)
t.Fail()
}
wg.Done()
}
}
wg.Add(len(variableOutputTestEvents))
for _, e := range variableOutputTestEvents {
e.function(genOutTestFunction(e.outRegex), e.in)
}
wg.Wait()
}
2015-11-17 18:38:42 +00:00
func configLookupHelper(map[string]string) []string {
return []string{".testconfig.json"}
}
2015-11-17 17:44:52 +00:00
func TestMain(m *testing.M) {
2015-11-18 18:12:54 +00:00
log.SetOutput(ioutil.Discard)
2015-11-17 17:44:52 +00:00
os.Exit(m.Run())
}
func init() {
2015-12-14 14:15:51 +00:00
Initialize(dyncfg.New(configLookupHelper))
}