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).IsEquivalentTo(new Dictionary<string, IRCStates.User> {{"nickname", user}});
63 await Assert.That(_server.Channels).IsEquivalentTo(new Dictionary<string, IRCStates.Channel> {{"#chan", channel}});
64 await Assert.That(channel.Users).IsEquivalentTo(new Dictionary<string, ChannelUser> {{"nickname", chanUser}});
65 }
66
67 [Test]
68 public async Task KickSelf()
69 {
70 _server.Parse(new Line(":nickname KICK #chan nickname"));
71
72 await Assert.That(_server.Users).IsEmpty();
73 await Assert.That(_server.Channels).IsEmpty();
74 }
75
76 [Test]
77 public async Task KickOther()
78 {
79 _server.Parse(new Line(":other JOIN #chan"));
80 _server.Parse(new Line(":nickname KICK #chan other"));
81
82 var user = _server.Users["nickname"];
83 var channel = _server.Channels["#chan"];
84 var chanUser = channel.Users[user.NickNameLower];
85
86 await Assert.That(_server.Users).HasCount(1);
87 await Assert.That(_server.Channels).HasCount(1);
88 await Assert.That(user.Channels).Contains(channel.NameLower).And.HasCount(1);
89 await Assert.That(channel.Users)
90 .IsEquivalentTo(new Dictionary<string, ChannelUser> { { user.NickNameLower, chanUser } });
91 }
92
93 [Test]
94 public async Task QuitSelf()
95 {
96 _server.Parse(new Line("QUIT :i'm outta here"));
97 await Assert.That(_server.Users).IsEmpty();
98 await Assert.That(_server.Channels).IsEmpty();
99 }
100
101 [Test]
102 public async Task QuitSelfWithSource()
103 {
104 _server.Parse(new Line(":nickname QUIT :i'm outta here"));
105 await Assert.That(_server.Users).IsEmpty();
106 await Assert.That(_server.Channels).IsEmpty();
107 }
108
109 [Test]
110 public async Task QuitOther()
111 {
112 _server.Parse(new Line(":other JOIN #chan"));
113 _server.Parse(new Line(":other QUIT :see ya"));
114 await Assert.That(_server.Users).DoesNotContainKey("other");
115 }
116
117 [Test]
118 public async Task TopicText()
119 {
120 _server.Parse(new Line("332 * #chan :test"));
121 await Assert.That(_server.Channels["#chan"].Topic).IsEqualTo("test");
122 }
123
124 [Test]
125 public async Task TopicSetByAt()
126 {
127 var dt = DateTimeOffset.FromUnixTimeSeconds(1584023277).DateTime;
128 _server.Parse(new Line("333 * #chan other 1584023277"));
129
130 var channel = _server.Channels["#chan"];
131
132 await Assert.That(channel.TopicSetter).IsEqualTo("other");
133 await Assert.That(channel.TopicTime).IsEqualTo(dt);
134 }
135
136 [Test]
137 public async Task TopicCommand()
138 {
139 _server.Parse(new Line("TOPIC #chan :hello there"));
140 await Assert.That(_server.Channels["#chan"].Topic).IsEqualTo("hello there");
141 }
142
143 [Test]
144 public async Task CreationDate()
145 {
146 var dt = DateTimeOffset.FromUnixTimeSeconds(1584041889).DateTime;
147 _server.Parse(new Line("329 * #chan 1584041889"));
148 await Assert.That(_server.Channels["#chan"].Created).IsEqualTo(dt);
149 }
150
151 [Test]
152 public async Task NamesCommand()
153 {
154 _server.Parse(new Line("353 * * #chan :nickname @+other"));
155 await Assert.That(_server.Users).ContainsKey("nickname");
156 await Assert.That(_server.Users).ContainsKey("other");
157
158 var user = _server.Users["other"];
159 var channel = _server.Channels["#chan"];
160 var chanUser1 = channel.Users[user.NickNameLower];
161 var chanUser2 = channel.Users[_server.NickNameLower];
162
163 await Assert.That(channel.Users).HasCount(2);
164 await Assert.That(channel.Users[user.NickNameLower].Modes).IsEqualTo(chanUser1.Modes);
165 await Assert.That(channel.Users[_server.NickNameLower].Modes).IsEqualTo(chanUser2.Modes);
166 await Assert.That(chanUser1.Modes).IsEquivalentTo(["o", "v"]);
167 await Assert.That(user.Channels).Contains(channel.NameLower).And.HasCount(1);
168 }
169
170 [Test]
171 public async Task UserhostInNames()
172 {
173 _server.Parse(new Line("353 * * #chan :nickname!user@host other!user2@host2"));
174 await Assert.That(_server.UserName).IsEqualTo("user");
175 await Assert.That(_server.HostName).IsEqualTo("host");
176
177 var user = _server.Users["other"];
178 await Assert.That(user.UserName).IsEqualTo("user2");
179 await Assert.That(user.HostName).IsEqualTo("host2");
180 }
181
182 [Test]
183 public async Task NickAfterJoin()
184 {
185 var user = _server.Users["nickname"];
186 var channel = _server.Channels["#chan"];
187 var chanUser = channel.Users[user.NickNameLower];
188 _server.Parse(new Line(":nickname NICK nickname2"));
189 await Assert.That(channel.Users)
190 .IsEquivalentTo(new Dictionary<string, ChannelUser> { { user.NickNameLower, chanUser } });
191 }
192}