gorepost/irc/message_test.go

545 lines
11 KiB
Go

// Copyright 2014 Vic Demuzere
//
// Use of this source code is governed by the MIT license.
package irc
import (
"reflect"
"testing"
)
var messageTests = [...]*struct {
parsed *Message
rawMessage string
rawPrefix string
hostmask bool // Is it very clear that the prefix is a hostname?
server bool // Is the prefix a servername?
}{
{
parsed: &Message{
Prefix: &Prefix{
Name: "syrk",
User: "kalt",
Host: "millennium.stealth.net",
},
Command: "QUIT",
Trailing: "Gone to have lunch",
},
rawMessage: ":syrk!kalt@millennium.stealth.net QUIT :Gone to have lunch",
rawPrefix: "syrk!kalt@millennium.stealth.net",
hostmask: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "Trillian",
},
Command: "SQUIT",
Params: []string{"cm22.eng.umd.edu"},
Trailing: "Server out of control",
},
rawMessage: ":Trillian SQUIT cm22.eng.umd.edu :Server out of control",
rawPrefix: "Trillian",
server: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "WiZ",
User: "jto",
Host: "tolsun.oulu.fi",
},
Command: "JOIN",
Params: []string{"#Twilight_zone"},
},
rawMessage: ":WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone",
rawPrefix: "WiZ!jto@tolsun.oulu.fi",
hostmask: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "WiZ",
User: "jto",
Host: "tolsun.oulu.fi",
},
Command: "PART",
Params: []string{"#playzone"},
Trailing: "I lost",
},
rawMessage: ":WiZ!jto@tolsun.oulu.fi PART #playzone :I lost",
rawPrefix: "WiZ!jto@tolsun.oulu.fi",
hostmask: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "WiZ",
User: "jto",
Host: "tolsun.oulu.fi",
},
Command: "MODE",
Params: []string{"#eu-opers", "-l"},
},
rawMessage: ":WiZ!jto@tolsun.oulu.fi MODE #eu-opers -l",
rawPrefix: "WiZ!jto@tolsun.oulu.fi",
hostmask: true,
},
{
parsed: &Message{
Command: "MODE",
Params: []string{"&oulu", "+b", "*!*@*.edu", "+e", "*!*@*.bu.edu"},
},
rawMessage: "MODE &oulu +b *!*@*.edu +e *!*@*.bu.edu",
},
{
parsed: &Message{
Command: "PRIVMSG",
Params: []string{"#channel"},
Trailing: "Message with :colons!",
},
rawMessage: "PRIVMSG #channel :Message with :colons!",
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "irc.vives.lan",
},
Command: "251",
Params: []string{"test"},
Trailing: "There are 2 users and 0 services on 1 servers",
},
rawMessage: ":irc.vives.lan 251 test :There are 2 users and 0 services on 1 servers",
rawPrefix: "irc.vives.lan",
server: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "irc.vives.lan",
},
Command: "376",
Params: []string{"test"},
Trailing: "End of MOTD command",
},
rawMessage: ":irc.vives.lan 376 test :End of MOTD command",
rawPrefix: "irc.vives.lan",
server: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "irc.vives.lan",
},
Command: "250",
Params: []string{"test"},
Trailing: "Highest connection count: 1 (1 connections received)",
},
rawMessage: ":irc.vives.lan 250 test :Highest connection count: 1 (1 connections received)",
rawPrefix: "irc.vives.lan",
server: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "sorcix",
User: "~sorcix",
Host: "sorcix.users.quakenet.org",
},
Command: "PRIVMSG",
Params: []string{"#viveslan"},
Trailing: "\001ACTION is testing CTCP messages!\001",
},
rawMessage: ":sorcix!~sorcix@sorcix.users.quakenet.org PRIVMSG #viveslan :\001ACTION is testing CTCP messages!\001",
rawPrefix: "sorcix!~sorcix@sorcix.users.quakenet.org",
hostmask: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "sorcix",
User: "~sorcix",
Host: "sorcix.users.quakenet.org",
},
Command: "NOTICE",
Params: []string{"midnightfox"},
Trailing: "\001PONG 1234567890\001",
},
rawMessage: ":sorcix!~sorcix@sorcix.users.quakenet.org NOTICE midnightfox :\001PONG 1234567890\001",
rawPrefix: "sorcix!~sorcix@sorcix.users.quakenet.org",
hostmask: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "a",
User: "b",
Host: "c",
},
Command: "QUIT",
},
rawMessage: ":a!b@c QUIT",
rawPrefix: "a!b@c",
hostmask: true,
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "a",
User: "b",
},
Command: "PRIVMSG",
Trailing: "message",
},
rawMessage: ":a!b PRIVMSG :message",
rawPrefix: "a!b",
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "a",
Host: "c",
},
Command: "NOTICE",
Trailing: ":::Hey!",
},
rawMessage: ":a@c NOTICE ::::Hey!",
rawPrefix: "a@c",
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "nick",
},
Command: "PRIVMSG",
Params: []string{"$@"},
Trailing: "This message contains a\ttab!",
},
rawMessage: ":nick PRIVMSG $@ :This message contains a\ttab!",
rawPrefix: "nick",
},
{
parsed: &Message{
Command: "TEST",
Params: []string{"$@", "", "param"},
Trailing: "Trailing",
},
rawMessage: "TEST $@ param :Trailing",
},
{
rawMessage: ": PRIVMSG test :Invalid message with empty prefix.",
rawPrefix: "",
},
{
rawMessage: ": PRIVMSG test :Invalid message with space prefix",
rawPrefix: " ",
},
{
parsed: &Message{
Command: "TOPIC",
Params: []string{"#foo"},
Trailing: "",
},
rawMessage: "TOPIC #foo",
rawPrefix: "",
},
{
parsed: &Message{
Command: "TOPIC",
Params: []string{"#foo"},
Trailing: "",
EmptyTrailing: true,
},
rawMessage: "TOPIC #foo :",
rawPrefix: "",
},
{
parsed: &Message{
Prefix: &Prefix{
Name: "name",
User: "user",
Host: "example.org",
},
Command: "PRIVMSG",
Params: []string{"#test"},
Trailing: "Message with spaces at the end! ",
},
rawMessage: ":name!user@example.org PRIVMSG #test :Message with spaces at the end! ",
rawPrefix: "name!user@example.org",
hostmask: true,
},
{
parsed: &Message{
Command: "PASS",
Params: []string{"oauth:token_goes_here"},
},
rawMessage: "PASS oauth:token_goes_here",
rawPrefix: "",
},
}
// -----
// PREFIX
// -----
func TestPrefix_IsHostmask(t *testing.T) {
for i, test := range messageTests {
// Skip tests that have no prefix
if test.parsed == nil || test.parsed.Prefix == nil {
continue
}
if test.hostmask && !test.parsed.Prefix.IsHostmask() {
t.Errorf("Prefix %d should be recognized as a hostmask!", i)
}
}
}
func TestPrefix_IsServer(t *testing.T) {
for i, test := range messageTests {
// Skip tests that have no prefix
if test.parsed == nil || test.parsed.Prefix == nil {
continue
}
if test.server && !test.parsed.Prefix.IsServer() {
t.Errorf("Prefix %d should be recognized as a server!", i)
}
}
}
func TestPrefix_String(t *testing.T) {
var s string
for i, test := range messageTests {
// Skip tests that have no prefix
if test.parsed == nil || test.parsed.Prefix == nil {
continue
}
// Convert the prefix
s = test.parsed.Prefix.String()
// Result should be the same as the value in rawMessage.
if s != test.rawPrefix {
t.Errorf("Failed to stringify prefix %d:", i)
t.Logf("Output: %s", s)
t.Logf("Expected: %s", test.rawPrefix)
}
}
}
func TestPrefix_Len(t *testing.T) {
var l int
for i, test := range messageTests {
// Skip tests that have no prefix
if test.parsed == nil || test.parsed.Prefix == nil {
continue
}
l = test.parsed.Prefix.Len()
// Result should be the same as the value in rawMessage.
if l != len(test.rawPrefix) {
t.Errorf("Failed to calculate prefix length %d:", i)
t.Logf("Output: %d", l)
t.Logf("Expected: %d", len(test.rawPrefix))
}
}
}
func TestParsePrefix(t *testing.T) {
var p *Prefix
for i, test := range messageTests {
// Skip tests that have no prefix
if test.parsed == nil || test.parsed.Prefix == nil {
continue
}
// Parse the prefix
p = ParsePrefix(test.rawPrefix)
// Result struct should be the same as the value in parsed.
if *p != *test.parsed.Prefix {
t.Errorf("Failed to parse prefix %d:", i)
t.Logf("Output: %#v", p)
t.Logf("Expected: %#v", test.parsed.Prefix)
}
}
}
// -----
// MESSAGE
// -----
func TestMessage_String(t *testing.T) {
var s string
for i, test := range messageTests {
// Skip tests that have no valid struct
if test.parsed == nil {
continue
}
// Convert the prefix
s = test.parsed.String()
// Result should be the same as the value in rawMessage.
if s != test.rawMessage {
t.Errorf("Failed to stringify message %d:", i)
t.Logf("Output: %s", s)
t.Logf("Expected: %s", test.rawMessage)
}
}
}
func TestMessage_Len(t *testing.T) {
var l int
for i, test := range messageTests {
// Skip tests that have no valid struct
if test.parsed == nil {
continue
}
l = test.parsed.Len()
// Result should be the same as the value in rawMessage.
if l != len(test.rawMessage) {
t.Errorf("Failed to calculate message length %d:", i)
t.Logf("Output: %d", l)
t.Logf("Expected: %d", len(test.rawMessage))
}
}
}
func TestParseMessage(t *testing.T) {
var p *Message
for i, test := range messageTests {
// Parse the prefix
p, _ = ParseMessage(test.rawMessage)
// Result struct should be the same as the value in parsed.
if !reflect.DeepEqual(p, test.parsed) {
t.Errorf("Failed to parse message %d:", i)
t.Logf("Output: %#v", p)
t.Logf("Expected: %#v", test.parsed)
}
}
}
// -----
// MESSAGE DECODE -> ENCODE
// -----
func TestMessageDecodeEncode(t *testing.T) {
var (
p *Message
s string
)
for i, test := range messageTests {
// Skip invalid messages
if test.parsed == nil {
continue
}
// Decode the message, then encode it again.
p, _ = ParseMessage(test.rawMessage)
s = p.String()
// Result struct should be the same as the original.
if s != test.rawMessage {
t.Errorf("Message %d failed decode-encode sequence!", i)
}
}
}
// -----
// BENCHMARK
// -----
func BenchmarkPrefix_String_short(b *testing.B) {
b.ReportAllocs()
prefix := new(Prefix)
prefix.Name = "Namename"
b.ResetTimer()
for i := 0; i < b.N; i++ {
prefix.String()
}
}
func BenchmarkPrefix_String_long(b *testing.B) {
b.ReportAllocs()
prefix := new(Prefix)
prefix.Name = "Namename"
prefix.User = "Username"
prefix.Host = "Hostname"
b.ResetTimer()
for i := 0; i < b.N; i++ {
prefix.String()
}
}
func BenchmarkParsePrefix_short(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ParsePrefix("Namename")
}
}
func BenchmarkParsePrefix_long(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ParsePrefix("Namename!Username@Hostname")
}
}
func BenchmarkMessage_String(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
messageTests[0].parsed.String()
}
}
func BenchmarkParseMessage_short(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ParseMessage("COMMAND arg1 :Message\r\n")
}
}
func BenchmarkParseMessage_medium(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ParseMessage(":Namename COMMAND arg6 arg7 :Message message message\r\n")
}
}
func BenchmarkParseMessage_long(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ParseMessage(":Namename!username@hostname COMMAND arg1 arg2 arg3 arg4 arg5 arg6 arg7 :Message message message message message\r\n")
}
}