IRC parsing, tokenization, and state handling in C#
1namespace IRCSharp.Tests.State;
2
3public class Channel
4{
5 private readonly Server _server = new("test");
6
7 public Channel()
8 {
9 _server.Parse(new Line("001 nickname"));
10 _server.Parse(new Line(":nickname JOIN #chan"));
11 }
12
13 [Test]
14 public async Task JoinSelf()
15 {
16 await Assert.That(_server.Channels).ContainsKey("#chan");
17 await Assert.That(_server.Users).ContainsKey("nickname");
18 await Assert.That(_server.Channels).HasCount(1);
19 await Assert.That(_server.Users).HasCount(1);
20
21 var user = _server.Users["nickname"];
22 var chan = _server.Channels["#chan"];
23 await Assert.That(chan.Users).ContainsKey(user.NickNameLower).And.HasCount(1);
24 await Assert.That(user.Channels).Contains(chan.NameLower).And.HasCount(1);
25 }
26
27 [Test]
28 public async Task JoinOther()
29 {
30 _server.Parse(new Line(":other JOIN #chan"));
31
32 await Assert.That(_server.Users).HasCount(2);
33 await Assert.That(_server.Users).ContainsKey("other");
34
35 var channel = _server.Channels["#chan"];
36 await Assert.That(channel.Users).HasCount(2);
37
38 var user = _server.Users["other"];
39 await Assert.That(user.Channels).Contains(channel.NameLower).And.HasCount(1);
40 }
41
42 [Test]
43 public async Task PartSelf()
44 {
45 _server.Parse(new Line(":nickname PART #chan"));
46
47 await Assert.That(_server.Users).IsEmpty();
48 await Assert.That(_server.Channels).IsEmpty();
49 }
50
51 [Test]
52 public async Task PartOther()
53 {
54 _server.Parse(new Line(":other JOIN #chan"));
55 _server.Parse(new Line(":other PART #chan"));
56
57 var user = _server.Users["nickname"];
58 var channel = _server.Channels["#chan"];
59 var chanUser = channel.Users[user.NickNameLower];
60
61 await Assert.That(user.Channels).Contains(channel.NameLower).And.HasCount(1);
62 await Assert.That(_server.Users)
63 .IsEquivalentTo(new Dictionary<string, IRCStates.User> { { "nickname", user } });
64 await Assert.That(_server.Channels)
65 .IsEquivalentTo(new Dictionary<string, IRCStates.Channel> { { "#chan", channel } });
66 await Assert.That(channel.Users)
67 .IsEquivalentTo(new Dictionary<string, ChannelUser> { { "nickname", chanUser } });
68 }
69
70 [Test]
71 public async Task KickSelf()
72 {
73 _server.Parse(new Line(":nickname KICK #chan nickname"));
74
75 await Assert.That(_server.Users).IsEmpty();
76 await Assert.That(_server.Channels).IsEmpty();
77 }
78
79 [Test]
80 public async Task KickOther()
81 {
82 _server.Parse(new Line(":other JOIN #chan"));
83 _server.Parse(new Line(":nickname KICK #chan other"));
84
85 var user = _server.Users["nickname"];
86 var channel = _server.Channels["#chan"];
87 var chanUser = channel.Users[user.NickNameLower];
88
89 await Assert.That(_server.Users).HasCount(1);
90 await Assert.That(_server.Channels).HasCount(1);
91 await Assert.That(user.Channels).Contains(channel.NameLower).And.HasCount(1);
92 await Assert.That(channel.Users)
93 .IsEquivalentTo(new Dictionary<string, ChannelUser> { { user.NickNameLower, chanUser } });
94 }
95
96 [Test]
97 public async Task QuitSelf()
98 {
99 _server.Parse(new Line("QUIT :i'm outta here"));
100 await Assert.That(_server.Users).IsEmpty();
101 await Assert.That(_server.Channels).IsEmpty();
102 }
103
104 [Test]
105 public async Task QuitSelfWithSource()
106 {
107 _server.Parse(new Line(":nickname QUIT :i'm outta here"));
108 await Assert.That(_server.Users).IsEmpty();
109 await Assert.That(_server.Channels).IsEmpty();
110 }
111
112 [Test]
113 public async Task QuitOther()
114 {
115 _server.Parse(new Line(":other JOIN #chan"));
116 _server.Parse(new Line(":other QUIT :see ya"));
117 await Assert.That(_server.Users).DoesNotContainKey("other");
118 }
119
120 [Test]
121 public async Task TopicText()
122 {
123 _server.Parse(new Line("332 * #chan :test"));
124 await Assert.That(_server.Channels["#chan"].Topic).IsEqualTo("test");
125 }
126
127 [Test]
128 public async Task TopicSetByAt()
129 {
130 var dt = DateTimeOffset.FromUnixTimeSeconds(1584023277).DateTime;
131 _server.Parse(new Line("333 * #chan other 1584023277"));
132
133 var channel = _server.Channels["#chan"];
134
135 await Assert.That(channel.TopicSetter).IsEqualTo("other");
136 await Assert.That(channel.TopicTime).IsEqualTo(dt);
137 }
138
139 [Test]
140 public async Task TopicCommand()
141 {
142 _server.Parse(new Line("TOPIC #chan :hello there"));
143 await Assert.That(_server.Channels["#chan"].Topic).IsEqualTo("hello there");
144 }
145
146 [Test]
147 public async Task CreationDate()
148 {
149 var dt = DateTimeOffset.FromUnixTimeSeconds(1584041889).DateTime;
150 _server.Parse(new Line("329 * #chan 1584041889"));
151 await Assert.That(_server.Channels["#chan"].Created).IsEqualTo(dt);
152 }
153
154 [Test]
155 public async Task NamesCommand()
156 {
157 _server.Parse(new Line("353 * * #chan :nickname @+other"));
158 await Assert.That(_server.Users).ContainsKey("nickname");
159 await Assert.That(_server.Users).ContainsKey("other");
160
161 var user = _server.Users["other"];
162 var channel = _server.Channels["#chan"];
163 var chanUser1 = channel.Users[user.NickNameLower];
164 var chanUser2 = channel.Users[_server.NickNameLower];
165
166 await Assert.That(channel.Users).HasCount(2);
167 await Assert.That(channel.Users[user.NickNameLower].Modes).IsEqualTo(chanUser1.Modes);
168 await Assert.That(channel.Users[_server.NickNameLower].Modes).IsEqualTo(chanUser2.Modes);
169 await Assert.That(chanUser1.Modes).IsEquivalentTo(["o", "v"]);
170 await Assert.That(user.Channels).Contains(channel.NameLower).And.HasCount(1);
171 }
172
173 [Test]
174 public async Task UserhostInNames()
175 {
176 _server.Parse(new Line("353 * * #chan :nickname!user@host other!user2@host2"));
177 await Assert.That(_server.UserName).IsEqualTo("user");
178 await Assert.That(_server.HostName).IsEqualTo("host");
179
180 var user = _server.Users["other"];
181 await Assert.That(user.UserName).IsEqualTo("user2");
182 await Assert.That(user.HostName).IsEqualTo("host2");
183 }
184
185 [Test]
186 public async Task NickAfterJoin()
187 {
188 var user = _server.Users["nickname"];
189 var channel = _server.Channels["#chan"];
190 var chanUser = channel.Users[user.NickNameLower];
191 _server.Parse(new Line(":nickname NICK nickname2"));
192 await Assert.That(channel.Users)
193 .IsEquivalentTo(new Dictionary<string, ChannelUser> { { user.NickNameLower, chanUser } });
194 }
195}