IRC parsing, tokenization, and state handling in C#
1namespace IRCSharp.Tests.Tokenization;
2
3public class Tokenization
4{
5 [Test]
6 public async Task TagsMissing()
7 {
8 var line = new Line("PRIVMSG #channel");
9 await Assert.That(line.Tags).IsNull();
10 }
11
12 [Test]
13 public async Task TagsMissingValue()
14 {
15 var line = new Line("@id= PRIVMSG #channel");
16 await Assert.That(line.Tags["id"]).IsEmpty();
17 }
18
19 [Test]
20 public async Task TagsMissingEqual()
21 {
22 var line = new Line("@id PRIVMSG #channel");
23 await Assert.That(line.Tags["id"]).IsNull();
24 }
25
26 [Test]
27 public async Task TagsUnescape()
28 {
29 var line = new Line(@"@id=1\\\:\r\n\s2 PRIVMSG #channel");
30 await Assert.That(line.Tags["id"]).IsEqualTo("1\\;\r\n 2");
31 }
32
33 [Test]
34 public async Task TagsOverlap()
35 {
36 var line = new Line(@"@id=1\\\s\\s PRIVMSG #channel");
37 await Assert.That(line.Tags["id"]).IsEqualTo(@"1\ \s");
38 }
39
40 [Test]
41 public async Task TagsLoneEndSlash()
42 {
43 var line = new Line("@id=1\\ PRIVMSG #channel");
44 await Assert.That(line.Tags["id"]).IsEqualTo("1");
45 }
46
47 [Test]
48 public async Task SourceWithoutTags()
49 {
50 var line = new Line(":nick!user@host PRIVMSG #channel");
51 await Assert.That(line.Source).IsEqualTo("nick!user@host");
52 }
53
54 [Test]
55 public async Task SourceWithTags()
56 {
57 var line = new Line("@id=123 :nick!user@host PRIVMSG #channel");
58 await Assert.That(line.Source).IsEqualTo("nick!user@host");
59 }
60
61 [Test]
62 public async Task SourceMissingWithoutTags()
63 {
64 var line = new Line("PRIVMSG #channel");
65 await Assert.That(line.Source).IsNull();
66 }
67
68 [Test]
69 public async Task SourceMissingWithTags()
70 {
71 var line = new Line("@id=123 PRIVMSG #channel");
72 await Assert.That(line.Source).IsNull();
73 }
74
75 [Test]
76 public async Task Command()
77 {
78 var line = new Line("privmsg #channel");
79 await Assert.That(line.Command).IsEqualTo("PRIVMSG");
80 }
81
82 [Test]
83 public async Task ParamsTrailing()
84 {
85 var line = new Line("PRIVMSG #channel :hello world");
86 await Assert.That(line.Params).IsEquivalentTo(["#channel", "hello world"]);
87 }
88
89 [Test]
90 public async Task ParamsOnlyTrailing()
91 {
92 var line = new Line("PRIVMSG :hello world");
93 await Assert.That(line.Params).IsEquivalentTo(["hello world"]);
94 }
95
96 [Test]
97 public async Task ParamsMissing()
98 {
99 var line = new Line("PRIVMSG");
100 await Assert.That(line.Command).IsEqualTo("PRIVMSG");
101 await Assert.That(line.Params).IsEmpty();
102 }
103
104 [Test]
105 public async Task AllTokens()
106 {
107 var line = new Line("@id=123 :nick!user@host PRIVMSG #channel :hello world");
108 await Assert.That(line.Tags).IsEquivalentTo(new Dictionary<string, string> { { "id", "123" } });
109 await Assert.That(line.Source).IsEqualTo("nick!user@host");
110 await Assert.That(line.Command).IsEqualTo("PRIVMSG");
111 await Assert.That(line.Params).IsEquivalentTo(["#channel", "hello world"]);
112 }
113
114 [Test]
115 public async Task NulByte()
116 {
117 var decoder = new IRCTokens.StatefulDecoder();
118 var bytes = ":nick!user@host PRIVMSG #channel :hello\0world"u8;
119 var line = decoder.Push(bytes.ToArray(), bytes.Length).First();
120
121 await Assert.That(line.Params).IsEquivalentTo(["#channel", "hello"]);
122 }
123}