From 220192da7807920ea9228a9018c307a49d9b4686 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Sat, 19 Feb 2022 12:22:03 +0200 Subject: [PATCH] fix: properly parse trailing param, fix typos, add new parser test --- irc/parser/parser.go | 21 +++-- irc/parser/parser_test.go | 161 +++++++++++++++++++++----------------- 2 files changed, 104 insertions(+), 78 deletions(-) diff --git a/irc/parser/parser.go b/irc/parser/parser.go index 35b5f81..642eb65 100644 --- a/irc/parser/parser.go +++ b/irc/parser/parser.go @@ -22,6 +22,7 @@ import ( ) type IRCMessage struct { + // TODO: prefix: that will hold the timestamp AND the server message prefix (==) Tags Tags // starts with @ | Optional Source string // starts with : | Optional Command string // can either be a string or a numeric value | Required @@ -88,19 +89,23 @@ func ParseIRCMessage(line string) (IRCMessage, bool) { params := trailingParamRegex.Split(substrs[1], 2) parameters := multipleSpacesRegex.Split(params[0], -1) - - // if there's a trailing parameter - // this parses empty params as well - if len(params) > 1 { - parameters = append(parameters, params[1]) - } + finalParams := make([]string, 0) // if we have 1 param and it starts with a colon if len(params) == 1 && params[0][0] == ':' { - parameters[0] = params[0][1:] + finalParams = append(finalParams, params[0][1:]) } - ircMessage.Parameters = parameters + // if there's regular param(s) with trailing param + // this parses empty params as well + if len(params) > 1 { + finalParams = append(parameters, params[1]) + } else { + // if we only have regular param(s) + finalParams = append(finalParams, parameters...) + } + + ircMessage.Parameters = finalParams } return ircMessage, true diff --git a/irc/parser/parser_test.go b/irc/parser/parser_test.go index ca2b0f3..548a9d5 100644 --- a/irc/parser/parser_test.go +++ b/irc/parser/parser_test.go @@ -23,9 +23,9 @@ import "testing" func TestParser(t *testing.T) { t.Run("Test simple command", func(t *testing.T) { testMessage := "foo bar baz asdf" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -48,9 +48,9 @@ func TestParser(t *testing.T) { t.Run("Test source", func(t *testing.T) { testMessage := ":coolguy foo bar baz asdf" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -77,9 +77,9 @@ func TestParser(t *testing.T) { t.Run("Test trailing param", func(t *testing.T) { testMessage := "foo bar baz :asdf quux" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -98,9 +98,9 @@ func TestParser(t *testing.T) { t.Run("Test empty trailing param", func(t *testing.T) { testMessage := "foo bar baz :" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -119,9 +119,9 @@ func TestParser(t *testing.T) { t.Run("Test multiple colons at trailing param", func(t *testing.T) { testMessage := "foo bar baz ::asdf" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -140,9 +140,9 @@ func TestParser(t *testing.T) { t.Run("Test source and trailing param", func(t *testing.T) { testMessage := ":coolguy foo bar baz :asdf quux" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -169,9 +169,9 @@ func TestParser(t *testing.T) { t.Run("Test source and trailing param with spaces", func(t *testing.T) { testMessage := ":coolguy foo bar baz : asdf quux " - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -198,9 +198,9 @@ func TestParser(t *testing.T) { t.Run("Test source and trailing param 2", func(t *testing.T) { testMessage := ":coolguy PRIVMSG bar :lol :) " - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -223,9 +223,9 @@ func TestParser(t *testing.T) { t.Run("Test source and empty trailing param", func(t *testing.T) { testMessage := ":coolguy foo bar baz :" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -252,9 +252,9 @@ func TestParser(t *testing.T) { t.Run("Test source and trailing param with spaces 2", func(t *testing.T) { testMessage := ":coolguy foo bar baz : " - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -281,9 +281,9 @@ func TestParser(t *testing.T) { t.Run("Test tags", func(t *testing.T) { testMessage := "@id=234AB;rose :dan!d@localhost PRIVMSG #chan :Hey what's up!" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -314,9 +314,9 @@ func TestParser(t *testing.T) { t.Run("Test tags 2", func(t *testing.T) { testMessage := "@a=b;c=32;k;rt=q17 foo" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -344,9 +344,9 @@ func TestParser(t *testing.T) { // TODO: fails t.Run("Test escaped tags", func(t *testing.T) { testMessage := "@a=b\\\\and\\nk;c=72\\s45;d=gh\\:764 foo" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -369,9 +369,9 @@ func TestParser(t *testing.T) { t.Run("Test tags with source", func(t *testing.T) { testMessage := "@c;h=;a=b :quux ab cd" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -404,9 +404,9 @@ func TestParser(t *testing.T) { // TODO: FAIL t.Run("Test single param with preceeding :", func(t *testing.T) { testMessage := ":src JOIN :#chan" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -417,9 +417,9 @@ func TestParser(t *testing.T) { t.Run("Test with no space as last param", func(t *testing.T) { testMessage := ":src AWAY" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -438,9 +438,9 @@ func TestParser(t *testing.T) { t.Run("Test with space as last param", func(t *testing.T) { testMessage := ":src AWAY " - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -460,9 +460,9 @@ func TestParser(t *testing.T) { t.Run("Test tab as space", func(t *testing.T) { testMessage := ":cool\tguy foo bar baz" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -485,9 +485,9 @@ func TestParser(t *testing.T) { t.Run("Test weird control codes in source", func(t *testing.T) { testMessage := ":coolguy!ag@net\x035w\x03ork.admin PRIVMSG foo :bar baz" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -510,9 +510,9 @@ func TestParser(t *testing.T) { t.Run("Test more weird control codes", func(t *testing.T) { testMessage := ":coolguy!~ag@n\x02et\x0305w\x0fork.admin PRIVMSG foo :bar baz" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -535,9 +535,9 @@ func TestParser(t *testing.T) { 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, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -580,9 +580,9 @@ func TestParser(t *testing.T) { t.Run("Test message without tags", func(t *testing.T) { testMessage := ":irc.example.com COMMAND param1 param2 :param3 param3" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -609,9 +609,9 @@ func TestParser(t *testing.T) { 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, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -655,9 +655,9 @@ func TestParser(t *testing.T) { // TODO: FAIL t.Run("Test yaml encoding with slashes", func(t *testing.T) { testMessage := "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -672,9 +672,9 @@ func TestParser(t *testing.T) { t.Run("Test broken messages 1", func(t *testing.T) { testMessage := ":gravel.mozilla.org 432 #momo :Erroneous Nickname: Illegal characters" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -697,9 +697,9 @@ func TestParser(t *testing.T) { t.Run("Test broken messages 2", func(t *testing.T) { testMessage := ":gravel.mozilla.org MODE #tckk +n " - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -722,9 +722,9 @@ func TestParser(t *testing.T) { t.Run("Test broken messages 3", func(t *testing.T) { testMessage := ":services.esper.net MODE #foo-bar +o foobar " - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -752,9 +752,9 @@ func TestParser(t *testing.T) { // TODO: FAIL t.Run("Test tags. they should be parsed char-at-a-time", func(t *testing.T) { testMessage := "@tag1=value\\\\ntest COMMAND" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -774,9 +774,9 @@ func TestParser(t *testing.T) { // TODO: FAIl t.Run("Test tag escape for char that doesn't need it", func(t *testing.T) { testMessage := "@tag1=value\\1 COMMAND" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -792,9 +792,9 @@ func TestParser(t *testing.T) { // TODO: FAIL t.Run("Test slash at end of tag", func(t *testing.T) { testMessage := "@tag1=value1\\ COMMAND" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -809,9 +809,9 @@ func TestParser(t *testing.T) { t.Run("Test duplicate tags", func(t *testing.T) { testMessage := "@tag1=1;tag2=3;tag3=4;tag1=5 COMMAND" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -834,9 +834,9 @@ func TestParser(t *testing.T) { 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, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -863,9 +863,9 @@ func TestParser(t *testing.T) { t.Run("Test: some parsers handle /MODE in a special way", func(t *testing.T) { testMessage := ":SomeOp MODE #channel :+i" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -888,9 +888,9 @@ func TestParser(t *testing.T) { t.Run("Test: some parsers handle /MODE in a special way 2", func(t *testing.T) { testMessage := ":SomeOp MODE #channel +oo SomeUser :AnotherUser" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -921,9 +921,9 @@ func TestParser(t *testing.T) { t.Run("Test multiple spaces", func(t *testing.T) { testMessage := ":src JOIN #chan :thing lol haha" - ircMessage, value := ParseIRCMessage(testMessage) + ircMessage, valid := ParseIRCMessage(testMessage) - if !value { + if !valid { t.Fatal("Invalid irc message") } @@ -943,4 +943,25 @@ func TestParser(t *testing.T) { 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") + } + }) }