Files
gorc/irc/parser/parser_test.go

968 lines
21 KiB
Go

// gorc project
// Copyright (C) 2022 IllusionMan1212
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see https://www.gnu.org/licenses.
package parser
import "testing"
// tests provided by https://github.com/ircdocs/parser-tests/blob/master/tests/msg-split.yaml
func TestParser(t *testing.T) {
t.Run("Test simple command", func(t *testing.T) {
testMessage := "foo bar baz asdf"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing message with only command and params")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing message with only command and params (1st param)")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing message with only command and params (2nd param)")
}
if ircMessage.Parameters[2] != "asdf" {
t.Fatal("Parsing message with only command and params (3rd param)")
}
})
t.Run("Test source", func(t *testing.T) {
testMessage := ":coolguy foo bar baz asdf"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy" {
t.Fatal("Parsing regular source")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command with source")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param of regular message")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param of regular message")
}
if ircMessage.Parameters[2] != "asdf" {
t.Fatal("Parsing 3rd param of regular message")
}
})
t.Run("Test trailing param", func(t *testing.T) {
testMessage := "foo bar baz :asdf quux"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param in message with trailing param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param in message with trailing param")
}
if ircMessage.Parameters[2] != "asdf quux" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test empty trailing param", func(t *testing.T) {
testMessage := "foo bar baz :"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param in message with trailing param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param in message with trailing param")
}
if ircMessage.Parameters[2] != "" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test multiple colons at trailing param", func(t *testing.T) {
testMessage := "foo bar baz ::asdf"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param in message with trailing param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param in message with trailing param")
}
if ircMessage.Parameters[2] != ":asdf" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test source and trailing param", func(t *testing.T) {
testMessage := ":coolguy foo bar baz :asdf quux"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "asdf quux" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test source and trailing param with spaces", func(t *testing.T) {
testMessage := ":coolguy foo bar baz : asdf quux "
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != " asdf quux " {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test source and trailing param 2", func(t *testing.T) {
testMessage := ":coolguy PRIVMSG bar :lol :) "
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "PRIVMSG" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "lol :) " {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test source and empty trailing param", func(t *testing.T) {
testMessage := ":coolguy foo bar baz :"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test source and trailing param with spaces 2", func(t *testing.T) {
testMessage := ":coolguy foo bar baz : "
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != " " {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test tags", func(t *testing.T) {
testMessage := "@id=234AB;rose :dan!d@localhost PRIVMSG #chan :Hey what's up!"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["id"] != "234AB" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["rose"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Source != "dan!d@localhost" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "PRIVMSG" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "#chan" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "Hey what's up!" {
t.Fatal("Parsing 2nd param")
}
})
t.Run("Test tags 2", func(t *testing.T) {
testMessage := "@a=b;c=32;k;rt=q17 foo"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["a"] != "b" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["c"] != "32" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["k"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Tags["rt"] != "q17" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
})
// TODO: fails
t.Run("Test escaped tags", func(t *testing.T) {
testMessage := "@a=b\\\\and\\nk;c=72\\s45;d=gh\\:764 foo"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["a"] != "b\\and\nk" {
t.Fatal("Parsing escaped tag")
}
if ircMessage.Tags["c"] != "72 45" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["d"] != "gh;764" {
t.Fatal("Parsing escaped tag")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
})
t.Run("Test tags with source", func(t *testing.T) {
testMessage := "@c;h=;a=b :quux ab cd"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["c"] != "" {
t.Log(ircMessage.Tags)
t.Fatal("Parsing value-less tag")
}
if ircMessage.Tags["h"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Tags["a"] != "b" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Source != "quux" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "ab" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "cd" {
t.Fatal("Parsing param")
}
})
// TODO: FAIL
t.Run("Test single param with preceeding :", func(t *testing.T) {
testMessage := ":src JOIN :#chan"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Parameters[0] != "#chan" {
t.Fatal("Parsing a single param with a preceeding \":\"")
}
})
t.Run("Test with no space as last param", func(t *testing.T) {
testMessage := ":src AWAY"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "src" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "AWAY" {
t.Fatal("Parsing command")
}
if len(ircMessage.Parameters) > 0 {
t.Fatal("Parsing params")
}
})
t.Run("Test with space as last param", func(t *testing.T) {
testMessage := ":src AWAY "
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "src" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "AWAY" {
t.Fatal("Parsing command")
}
if len(ircMessage.Parameters) > 0 {
t.Logf("'%v'", ircMessage.Parameters[0])
t.Fatal("Parsing params")
}
})
t.Run("Test tab as space", func(t *testing.T) {
testMessage := ":cool\tguy foo bar baz"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "cool\tguy" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "foo" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "baz" {
t.Fatal("Parsing 2nd param")
}
})
t.Run("Test weird control codes in source", func(t *testing.T) {
testMessage := ":coolguy!ag@net\x035w\x03ork.admin PRIVMSG foo :bar baz"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy!ag@net\x035w\x03ork.admin" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "PRIVMSG" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "foo" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "bar baz" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test more weird control codes", func(t *testing.T) {
testMessage := ":coolguy!~ag@n\x02et\x0305w\x0fork.admin PRIVMSG foo :bar baz"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "coolguy!~ag@n\x02et\x0305w\x0fork.admin" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "PRIVMSG" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "foo" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "bar baz" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test full message", func(t *testing.T) {
testMessage := "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4= :irc.example.com COMMAND param1 param2 :param3 param3"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "value1" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["tag2"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Tags["vendor1/tag3"] != "value2" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["vendor2/tag4"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Source != "irc.example.com" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "param1" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "param2" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "param3 param3" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test message without tags", func(t *testing.T) {
testMessage := ":irc.example.com COMMAND param1 param2 :param3 param3"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "irc.example.com" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "param1" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "param2" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "param3 param3" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test message without source", func(t *testing.T) {
testMessage := "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4= COMMAND param1 param2 :param3 param3"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "value1" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["tag2"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Tags["vendor1/tag3"] != "value2" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["vendor2/tag4"] != "" {
t.Fatal("Parsing value-less tag")
}
if ircMessage.Source != "" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "param1" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "param2" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "param3 param3" {
t.Fatal("Parsing trailing param")
}
})
// TODO: FAIL
t.Run("Test yaml encoding with slashes", func(t *testing.T) {
testMessage := "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["foo"] != "\\\\;\\s \r\n" {
t.Fatal("Parsing escaped tag")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
})
t.Run("Test broken messages 1", func(t *testing.T) {
testMessage := ":gravel.mozilla.org 432 #momo :Erroneous Nickname: Illegal characters"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "gravel.mozilla.org" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "432" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "#momo" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "Erroneous Nickname: Illegal characters" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test broken messages 2", func(t *testing.T) {
testMessage := ":gravel.mozilla.org MODE #tckk +n "
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "gravel.mozilla.org" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "MODE" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "#tckk" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "+n" {
t.Fatal("Parsing 2nd param")
}
})
t.Run("Test broken messages 3", func(t *testing.T) {
testMessage := ":services.esper.net MODE #foo-bar +o foobar "
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "services.esper.net" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "MODE" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "#foo-bar" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "+o" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "foobar" {
t.Fatal("Parsing trailing param")
}
})
// TODO: FAIL
t.Run("Test tags. they should be parsed char-at-a-time", func(t *testing.T) {
testMessage := "@tag1=value\\\\ntest COMMAND"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "value\\ntest" {
t.Fatal("Parsing escaped tag")
}
if ircMessage.Source != "" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
})
// TODO: FAIl
t.Run("Test tag escape for char that doesn't need it", func(t *testing.T) {
testMessage := "@tag1=value\\1 COMMAND"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "value1" {
t.Fatal("Parsing escaped tag")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
})
// TODO: FAIL
t.Run("Test slash at end of tag", func(t *testing.T) {
testMessage := "@tag1=value1\\ COMMAND"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "value1" {
t.Fatal("Parsing escaped tag")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
})
t.Run("Test duplicate tags", func(t *testing.T) {
testMessage := "@tag1=1;tag2=3;tag3=4;tag1=5 COMMAND"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "5" {
t.Fatal("Parsing duplicate tag")
}
if ircMessage.Tags["tag2"] != "3" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["tag3"] != "4" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
})
t.Run("Test vendored tags can have the same name as unvendored tag", func(t *testing.T) {
testMessage := "@tag1=1;tag2=3;tag3=4;tag1=5;vendor/tag2=8 COMMAND"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Tags["tag1"] != "5" {
t.Fatal("Parsing duplicate tag")
}
if ircMessage.Tags["tag2"] != "3" {
t.Fatal("Parsing unvendored tag")
}
if ircMessage.Tags["tag3"] != "4" {
t.Fatal("Parsing regular tag")
}
if ircMessage.Tags["vendor/tag2"] != "8" {
t.Fatal("Parsing vendored tag")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command")
}
})
t.Run("Test: some parsers handle /MODE in a special way", func(t *testing.T) {
testMessage := ":SomeOp MODE #channel :+i"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "SomeOp" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "MODE" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "#channel" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "+i" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test: some parsers handle /MODE in a special way 2", func(t *testing.T) {
testMessage := ":SomeOp MODE #channel +oo SomeUser :AnotherUser"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "SomeOp" {
t.Fatal("Parsing source")
}
if ircMessage.Command != "MODE" {
t.Fatal("Parsing command")
}
if ircMessage.Parameters[0] != "#channel" {
t.Fatal("Parsing 1st param")
}
if ircMessage.Parameters[1] != "+oo" {
t.Fatal("Parsing 2nd param")
}
if ircMessage.Parameters[2] != "SomeUser" {
t.Fatal("Parsing 3rd param")
}
if ircMessage.Parameters[3] != "AnotherUser" {
t.Fatal("Parsing trailing param")
}
})
t.Run("Test multiple spaces", func(t *testing.T) {
testMessage := ":src JOIN #chan :thing lol haha"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "src" {
t.Fatal("Parsing source with multiple spaces in between")
}
if ircMessage.Command != "JOIN" {
t.Fatal("Parsing command with multiple spaces in between")
}
if ircMessage.Parameters[0] != "#chan" {
t.Fatal("Parsing params with multiple spaces in between")
}
if ircMessage.Parameters[1] != "thing lol haha" {
t.Fatal("Parsing trailing param with multiple spaces in between")
}
})
t.Run("Test trailing param only", func(t *testing.T) {
testMessage := ":src COMMAND :this is a trailing param"
ircMessage, valid := ParseIRCMessage(testMessage)
if !valid {
t.Fatal("Invalid irc message")
}
if ircMessage.Source != "src" {
t.Fatal("Parsing source with trailing param only")
}
if ircMessage.Command != "COMMAND" {
t.Fatal("Parsing command with trailing param only")
}
if ircMessage.Parameters[0] != "this is a trailing param" {
t.Fatal("Parsing trailing param with trailing param only")
}
})
}