about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Harris <ben@tilde.team>2020-05-06 02:04:00 -0400
committerBen Harris <ben@tilde.team>2020-05-06 02:04:00 -0400
commitaabf66382b7f1041b11241555af33634882f190c (patch)
treefa21b31323a83fa87e5071370326e69e7253add7
parentb3c1a9a929d5f57e3c760087ec9e9950bd1e7aff (diff)
add ISUPPORT tests
-rw-r--r--IrcStates/ISupport.cs81
-rw-r--r--IrcStates/ISupportChanModes.cs23
-rw-r--r--IrcStates/ISupportPrefix.cs27
-rw-r--r--IrcStates/README.md5
-rw-r--r--IrcStates/Server.cs6
-rw-r--r--IrcStates/Tests/ISupport.cs201
-rw-r--r--IrcStates/Tests/Motd.cs16
-rw-r--r--IrcStates/Tests/Who.cs54
-rw-r--r--README.md2
9 files changed, 411 insertions, 4 deletions
diff --git a/IrcStates/ISupport.cs b/IrcStates/ISupport.cs
index bfee9ee..b9ad502 100644
--- a/IrcStates/ISupport.cs
+++ b/IrcStates/ISupport.cs
@@ -1,8 +1,89 @@
 // ReSharper disable InconsistentNaming
 
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
 namespace IrcStates
 {
     public class ISupport
     {
+        public ISupport()
+        {
+            Raw         = new Dictionary<string, string>();
+            Modes       = 3;
+            CaseMapping = Casemap.CaseMapping.Rfc1459;
+            // TODO: add remaining defaults, change properties to normal members as needed
+        }
+
+        public Dictionary<string, string> Raw { get; set; }
+        public string Network { get; set; }
+        public ISupportChanModes ChanModes { get; set; }
+        public ISupportPrefix Prefix { get; set; }
+        public int? Modes { get; set; }
+        public Casemap.CaseMapping CaseMapping { get; set; }
+        public List<string> ChanTypes { get; set; }
+        public List<string> StatusMsg { get; set; }
+        public string CallerId { get; set; }
+        public string Excepts { get; set; }
+        public string Invex { get; set; }
+        public int? Monitor { get; set; }
+        public int? Watch { get; set; }
+        public bool Whox { get; set; }
+
+        public void Parse(IList<string> tokens)
+        {
+            foreach (var token in tokens)
+            {
+                var split = token.Split('=', 2);
+                var key   = split[0];
+                var value = split[1];
+
+                if (split.Length > 1) Raw[key] = value;
+
+                switch (split[0])
+                {
+                    case "NETWORK":
+                        Network = value;
+                        break;
+                    case "CHANMODES":
+                        ChanModes = new ISupportChanModes(value);
+                        break;
+                    case "PREFIX":
+                        Prefix = new ISupportPrefix(value);
+                        break;
+                    case "STATUSMSG":
+                        StatusMsg = new List<string> {value};
+                        break;
+                    case "MODES":
+                        Modes = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+                        break;
+                    case "MONITOR":
+                        Monitor = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+                        break;
+                    case "WATCH":
+                        Watch = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+                        break;
+                    case "CASEMAPPING":
+                        if (Enum.TryParse(value, true, out Casemap.CaseMapping caseMapping)) CaseMapping = caseMapping;
+                        break;
+                    case "CHANTYPES":
+                        ChanTypes = new List<string> {value};
+                        break;
+                    case "CALLERID":
+                        CallerId = string.IsNullOrEmpty(value) ? value : "g";
+                        break;
+                    case "EXCEPTS":
+                        Excepts = string.IsNullOrEmpty(value) ? value : "e";
+                        break;
+                    case "INVEX":
+                        Invex = string.IsNullOrEmpty(value) ? value : "I";
+                        break;
+                    case "WHOX":
+                        Whox = true;
+                        break;
+                }
+            }
+        }
     }
 }
diff --git a/IrcStates/ISupportChanModes.cs b/IrcStates/ISupportChanModes.cs
new file mode 100644
index 0000000..9bf565c
--- /dev/null
+++ b/IrcStates/ISupportChanModes.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace IrcStates
+{
+    public class ISupportChanModes
+    {
+        public ISupportChanModes(string splitVal)
+        {
+            if (splitVal == null) return;
+
+            var split = splitVal.Split(',', 4);
+            ListModes     = new List<string> {split[0]};
+            SettingBModes = new List<string> {split[1]};
+            SettingCModes = new List<string> {split[2]};
+            SettingDModes = new List<string> {split[3]};
+        }
+
+        public List<string> ListModes { get; set; }
+        public List<string> SettingBModes { get; set; }
+        public List<string> SettingCModes { get; set; }
+        public List<string> SettingDModes { get; set; }
+    }
+}
diff --git a/IrcStates/ISupportPrefix.cs b/IrcStates/ISupportPrefix.cs
new file mode 100644
index 0000000..94668e3
--- /dev/null
+++ b/IrcStates/ISupportPrefix.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+
+namespace IrcStates
+{
+    public class ISupportPrefix
+    {
+        public ISupportPrefix(string splitVal)
+        {
+            var split = splitVal.Substring(1).Split(')', 2);
+            Modes    = new List<string> {split[0]};
+            Prefixes = new List<string> {split[1]};
+        }
+
+        public List<string> Modes { get; set; }
+        public List<string> Prefixes { get; set; }
+
+        public string FromMode(string mode)
+        {
+            return Modes.Contains(mode) ? Modes[Modes.IndexOf(mode)] : null;
+        }
+
+        public string FromPrefix(string prefix)
+        {
+            return Prefixes.Contains(prefix) ? Prefixes[Prefixes.IndexOf(prefix)] : null;
+        }
+    }
+}
diff --git a/IrcStates/README.md b/IrcStates/README.md
new file mode 100644
index 0000000..60fcc44
--- /dev/null
+++ b/IrcStates/README.md
@@ -0,0 +1,5 @@
+# IrcStates
+
+port of [jesopo/ircstates](https://github.com/jesopo/ircstates)
+
+bare bones irc client state
diff --git a/IrcStates/Server.cs b/IrcStates/Server.cs
index 9371a2b..7199668 100644
--- a/IrcStates/Server.cs
+++ b/IrcStates/Server.cs
@@ -7,6 +7,7 @@ namespace IrcStates
 {
     public class Server
     {
+        public const string WhoType = "525"; // randomly generated
         private readonly StatefulDecoder _decoder;
 
         public Dictionary<string, List<Func<string, Line, Emit>>> LineHandlers;
@@ -81,5 +82,10 @@ namespace IrcStates
 
             return ret;
         }
+
+        public string CaseFold(string str)
+        {
+            return Casemap.CaseFold(ISupport.CaseMapping, str);
+        }
     }
 }
diff --git a/IrcStates/Tests/ISupport.cs b/IrcStates/Tests/ISupport.cs
index f85f087..81b3cff 100644
--- a/IrcStates/Tests/ISupport.cs
+++ b/IrcStates/Tests/ISupport.cs
@@ -1,4 +1,6 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Collections.Generic;
+using IrcTokens;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 // ReSharper disable InconsistentNaming
 
@@ -7,5 +9,202 @@ namespace IrcStates.Tests
     [TestClass]
     public class ISupport
     {
+        private Server _server;
+
+        [TestInitialize]
+        public void TestInitialize()
+        {
+            _server = new Server("test");
+            _server.ParseTokens(new Line("001 nickname"));
+        }
+
+        [TestMethod]
+        public void ChanModes()
+        {
+            CollectionAssert.AreEqual(new List<string> {"b"}, _server.ISupport.ChanModes.ListModes);
+            CollectionAssert.AreEqual(new List<string> {"k"}, _server.ISupport.ChanModes.SettingBModes);
+            CollectionAssert.AreEqual(new List<string> {"l"}, _server.ISupport.ChanModes.SettingCModes);
+            CollectionAssert.AreEqual(new List<string>
+            {
+                "i",
+                "m",
+                "n",
+                "p",
+                "s",
+                "t"
+            }, _server.ISupport.ChanModes.SettingDModes);
+
+            _server.ParseTokens(new Line("005 * CHANMODES=a,b,c,d *"));
+
+            CollectionAssert.AreEqual(new List<string> {"a"}, _server.ISupport.ChanModes.ListModes);
+            CollectionAssert.AreEqual(new List<string> {"b"}, _server.ISupport.ChanModes.SettingBModes);
+            CollectionAssert.AreEqual(new List<string> {"c"}, _server.ISupport.ChanModes.SettingCModes);
+            CollectionAssert.AreEqual(new List<string> {"d"}, _server.ISupport.ChanModes.SettingDModes);
+        }
+
+        [TestMethod]
+        public void Prefix()
+        {
+            CollectionAssert.AreEqual(new List<string> {"o", "v"}, _server.ISupport.Prefix.Modes);
+            CollectionAssert.AreEqual(new List<string> {"@", "+"}, _server.ISupport.Prefix.Prefixes);
+
+            Assert.AreEqual("@", _server.ISupport.Prefix.FromMode("o"));
+            Assert.IsNull(_server.ISupport.Prefix.FromMode("a"));
+            Assert.AreEqual("o", _server.ISupport.Prefix.FromPrefix("@"));
+            Assert.IsNull(_server.ISupport.Prefix.FromPrefix("&"));
+
+            _server.ParseTokens(new Line("005 * PREFIX=(qaohv)~&#%+ *"));
+            CollectionAssert.AreEqual(new List<string>
+            {
+                "q",
+                "a",
+                "o",
+                "h",
+                "v"
+            }, _server.ISupport.Prefix.Modes);
+            CollectionAssert.AreEqual(new List<string>
+            {
+                "~",
+                "&",
+                "@",
+                "%",
+                "+"
+            }, _server.ISupport.Prefix.Prefixes);
+            Assert.AreEqual("&", _server.ISupport.Prefix.FromMode("a"));
+            Assert.AreEqual("a", _server.ISupport.Prefix.FromPrefix("&"));
+        }
+
+        [TestMethod]
+        public void ChanTypes()
+        {
+            CollectionAssert.AreEqual(new List<string> {"#"}, _server.ISupport.ChanTypes);
+            _server.ParseTokens(new Line("005 * CHANTYPES=#& *"));
+            CollectionAssert.AreEqual(new List<string> {"#", "&"}, _server.ISupport.ChanTypes);
+        }
+
+        [TestMethod]
+        public void Modes()
+        {
+            Assert.AreEqual(3, _server.ISupport.Modes);
+
+            _server.ParseTokens(new Line("005 * MODES *"));
+            Assert.AreEqual(-1, _server.ISupport.Modes);
+
+            _server.ParseTokens(new Line("005 * MODES=5 *"));
+            Assert.AreEqual(5, _server.ISupport.Modes);
+        }
+
+        [TestMethod]
+        public void Rfc1459()
+        {
+            Assert.AreEqual(IrcStates.Casemap.CaseMapping.Rfc1459, _server.ISupport.CaseMapping);
+            _server.ParseTokens(new Line("005 * CASEMAPPING=rfc1459 *"));
+            Assert.AreEqual(IrcStates.Casemap.CaseMapping.Rfc1459, _server.ISupport.CaseMapping);
+            var lower = _server.CaseFold(@"ÀTEST[]~\");
+            Assert.AreEqual("Àtest{}^|", lower);
+        }
+
+        [TestMethod]
+        public void Ascii()
+        {
+            _server.ParseTokens(new Line("005 * CASEMAPPING=ascii *"));
+            Assert.AreEqual(IrcStates.Casemap.CaseMapping.Ascii, _server.ISupport.CaseMapping);
+            var lower = _server.CaseFold(@"ÀTEST[]~\");
+            Assert.AreEqual(@"Àtest[]~\", lower);
+        }
+
+        [TestMethod]
+        public void FallbackToRfc1459()
+        {
+            _server.ParseTokens(new Line("005 * CASEMAPPING=nonexistent *"));
+            Assert.AreEqual(IrcStates.Casemap.CaseMapping.Rfc1459, _server.ISupport.CaseMapping);
+            var lower = _server.CaseFold(@"ÀTEST[]~\");
+            Assert.AreEqual("Àtest{}^|", lower);
+        }
+
+        [TestMethod]
+        public void Network()
+        {
+            Assert.IsNull(_server.ISupport.Network);
+            _server.ParseTokens(new Line("005 * NETWORK=testnet *"));
+            Assert.AreEqual("testnet", _server.ISupport.Network);
+        }
+
+        [TestMethod]
+        public void StatusMsg()
+        {
+            CollectionAssert.AreEqual(new List<string>(), _server.ISupport.StatusMsg);
+            _server.ParseTokens(new Line("005 * STATUSMSG=&@ *"));
+            CollectionAssert.AreEqual(new List<string> {"&", "@"}, _server.ISupport.StatusMsg);
+        }
+
+        [TestMethod]
+        public void CallerId()
+        {
+            Assert.IsNull(_server.ISupport.CallerId);
+
+            _server.ParseTokens(new Line("005 * CALLERID=U *"));
+            Assert.AreEqual("U", _server.ISupport.CallerId);
+
+            _server.ParseTokens(new Line("005 * CALLERID *"));
+            Assert.AreEqual("g", _server.ISupport.CallerId);
+        }
+
+        [TestMethod]
+        public void Excepts()
+        {
+            Assert.IsNull(_server.ISupport.Excepts);
+
+            _server.ParseTokens(new Line("005 * EXCEPTS=U *"));
+            Assert.AreEqual("U", _server.ISupport.Excepts);
+
+            _server.ParseTokens(new Line("005 * EXCEPTS *"));
+            Assert.AreEqual("e", _server.ISupport.Excepts);
+        }
+
+        [TestMethod]
+        public void Invex()
+        {
+            Assert.IsNull(_server.ISupport.Invex);
+
+            _server.ParseTokens(new Line("005 * INVEX=U *"));
+            Assert.AreEqual("U", _server.ISupport.Invex);
+
+            _server.ParseTokens(new Line("005 * INVEX *"));
+            Assert.AreEqual("I", _server.ISupport.Invex);
+        }
+
+        [TestMethod]
+        public void Whox()
+        {
+            Assert.IsFalse(_server.ISupport.Whox);
+
+            _server.ParseTokens(new Line("005 * WHOX *"));
+            Assert.IsTrue(_server.ISupport.Whox);
+        }
+
+        [TestMethod]
+        public void Monitor()
+        {
+            Assert.IsNull(_server.ISupport.Monitor);
+
+            _server.ParseTokens(new Line("005 * MONITOR=123 *"));
+            Assert.AreEqual(123, _server.ISupport.Monitor);
+
+            _server.ParseTokens(new Line("005 * MONITOR *"));
+            Assert.AreEqual(-1, _server.ISupport.Monitor);
+        }
+
+        [TestMethod]
+        public void Watch()
+        {
+            Assert.IsNull(_server.ISupport.Watch);
+
+            _server.ParseTokens(new Line("005 * WATCH=123 *"));
+            Assert.AreEqual(123, _server.ISupport.Watch);
+
+            _server.ParseTokens(new Line("005 * WATCH *"));
+            Assert.AreEqual(-1, _server.ISupport.Watch);
+        }
     }
 }
diff --git a/IrcStates/Tests/Motd.cs b/IrcStates/Tests/Motd.cs
index 8ca7f07..403fa78 100644
--- a/IrcStates/Tests/Motd.cs
+++ b/IrcStates/Tests/Motd.cs
@@ -1,9 +1,23 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Collections.Generic;
+using IrcTokens;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 namespace IrcStates.Tests
 {
     [TestClass]
     public class Motd
     {
+        [TestMethod]
+        public void MessageOfTheDay()
+        {
+            var server = new Server("test");
+            server.ParseTokens(new Line("001 nickname"));
+            server.ParseTokens(new Line("375 * :start of motd"));
+            server.ParseTokens(new Line("372 * :first line of motd"));
+            server.ParseTokens(new Line("372 * :second line of motd"));
+
+            CollectionAssert.AreEqual(new List<string> {"start of motd", "first line of motd", "second line of motd"},
+                server.Motd);
+        }
     }
 }
diff --git a/IrcStates/Tests/Who.cs b/IrcStates/Tests/Who.cs
index 359991c..feee60e 100644
--- a/IrcStates/Tests/Who.cs
+++ b/IrcStates/Tests/Who.cs
@@ -1,9 +1,61 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using IrcTokens;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 namespace IrcStates.Tests
 {
     [TestClass]
     public class Who
     {
+        private Server _server;
+
+        [TestInitialize]
+        public void TestInitialize()
+        {
+            _server = new Server("test");
+            _server.ParseTokens(new Line("001 nickname"));
+            _server.ParseTokens(new Line(":nickname JOIN #chan"));
+        }
+
+        [TestMethod]
+        public void WhoResponse()
+        {
+            _server.ParseTokens(new Line("352 * #chan user host server nickname * :0 real"));
+            var user = _server.Users["nickname"];
+
+            Assert.AreEqual("user", user.UserName);
+            Assert.AreEqual("host", _server.HostName);
+            Assert.AreEqual("real", user.RealName);
+
+            Assert.AreEqual(user.UserName, _server.UserName);
+            Assert.AreEqual(user.HostName, _server.HostName);
+            Assert.AreEqual(user.RealName, _server.RealName);
+        }
+
+        [TestMethod]
+        public void Whox()
+        {
+            _server.ParseTokens(new Line($"354 * {Server.WhoType} user realip host nickname account :real"));
+            var user = _server.Users["nickname"];
+
+            Assert.AreEqual("user", user.UserName);
+            Assert.AreEqual("host", user.HostName);
+            Assert.AreEqual("real", user.RealName);
+            Assert.AreEqual("account", user.Account);
+
+            Assert.AreEqual(user.UserName, _server.UserName);
+            Assert.AreEqual(user.HostName, _server.HostName);
+            Assert.AreEqual(user.RealName, _server.RealName);
+            Assert.AreEqual(user.Account, _server.Account);
+        }
+
+        [TestMethod]
+        public void WhoxNoAccount()
+        {
+            _server.ParseTokens(new Line($"354 * {Server.WhoType} user realip host nickname 0 :real"));
+            var user = _server.Users["nickname"];
+
+            Assert.IsNull(user.Account);
+            Assert.AreEqual(user.Account, _server.Account);
+        }
     }
 }
diff --git a/README.md b/README.md
index 1a559ec..1796da2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # IrcSharp
 
-[![Build Status](https://drone.tildegit.org/api/badges/ben/irctokens/status.svg)](https://drone.tildegit.org/ben/irctokens)
+[![Build Status](https://drone.tildegit.org/api/badges/ben/ircsharp/status.svg)](https://drone.tildegit.org/ben/ircsharp)
 
 this is a collection of c\# projects to tokenize, parse, and maintain
 state for IRC clients.