Inject assertions before map update expressions

The reason is that SMACK encapsulate memory access into load/store functions.
Once these functions are inlined, stored operations are in form of map update expressions.

--- AddOns/SmackInst/SmackInst/Program.cs
+++ AddOns/SmackInst/SmackInst/Program.cs
@@ -35,10 +35,13 @@
             // initialize Boogie
             CommandLineOptions.Install(new CommandLineOptions());
             CommandLineOptions.Clo.PrintInstrumented = true;
+            CommandLineOptions.Clo.DoModSetAnalysis = true;

             // Read the input file
             var program = BoogieUtil.ReadAndResolve(args[0]);
+            // SMACK does not add globals to modify clauses
+            BoogieUtil.DoModSetAnalysis(program);

             // Process it
             program = Process(program);
@@ -372,9 +375,14 @@

         public override Expr VisitNAryExpr(NAryExpr node)
         {
-            if (node.Fun is MapSelect && node.Args.Count == 2 && node.Args[0] is IdentifierExpr)
-            {
-                accesses.Add(Tuple.Create((node.Args[0] as IdentifierExpr).Decl, node.Args[1]));
+            // we have two forms of map operation to take care
+            // the first is map select
+            // the second is map store
+            if (((node.Fun is MapSelect && node.Args.Count == 2) || (node.Fun is MapStore && node.Args.Count == 3)) && node.Args[0] is IdentifierExpr)
+            {
+                // All memory regions are in form of $M.d+
+                if (node.Args[0].ToString().Contains("$M"))
+                  accesses.Add(Tuple.Create((node.Args[0] as IdentifierExpr).Decl, node.Args[1]));
             }

             return base.VisitNAryExpr(node);


Fix TypeConverter for IComponent (#40837) (#40883)

--- src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs
+++ src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs
@@ -136,6 +136,7 @@
             //
             [typeof(Array)] = typeof(ArrayConverter),
             [typeof(ICollection)] = typeof(CollectionConverter),
+            [typeof(IComponent)] = typeof(ComponentConverter),
             [typeof(Enum)] = typeof(EnumConverter),
             [s_intrinsicNullableKey] = typeof(NullableConverter),
         });


Connector. Unsubscribe fix.

Connector. Unsubscribe fix.

--- Algo/Connector_SubscriptionManager.cs
+++ Algo/Connector_SubscriptionManager.cs
@@ -362,7 +362,7 @@
 					return;
 				}

-				var unsubscribe = subscription.DataType.ToSubscriptionMessage();
+				var unsubscribe = subscription.SubscriptionMessage.TypedClone();

 				unsubscribe.TransactionId = _connector.TransactionIdGenerator.GetNextId();
 				unsubscribe.OriginalTransactionId = subscription.TransactionId;


gd2 constants

gd2 constants

--- src/Peachpie.Library.Graphics/PhpGd2.cs
+++ src/Peachpie.Library.Graphics/PhpGd2.cs
@@ -11,6 +11,40 @@
     [PhpExtension("gd")]
     public static class PhpGd2
     {
+        #region GDVersionConstants
+
+        /// <summary>
+        /// The GD version PHP was compiled against.
+        /// </summary>
+        public const string GD_VERSION = "2.0.35";
+
+        /// <summary>
+        /// The GD major version PHP was compiled against.
+        /// </summary>
+        public const int GD_MAJOR_VERSION = 2;
+
+        /// <summary>
+        /// The GD minor version PHP was compiled against.
+        /// </summary>
+        public const int GD_MINOR_VERSION = 0;
+
+        /// <summary>
+        /// The GD release version PHP was compiled against.
+        /// </summary>
+        public const int GD_RELEASE_VERSION = 35;
+
+        /// <summary>
+        /// The GD "extra" version (beta/rc..) PHP was compiled against.
+        /// </summary>
+        public const string GD_EXTRA_VERSION = ""; //"beta";
+
+        /// <summary>
+        /// When the bundled version of GD is used this is 1 otherwise its set to 0.
+        /// </summary>
+        public const int GD_BUNDLED = 1;
+
+        #endregion
+
         #region ImgType

         /// <summary>
@@ -61,6 +95,162 @@
         public const int IMG_PNG = (int)ImgType.PNG;
         public const int IMG_WBMP = (int)ImgType.WBMP;
         public const int IMG_XPM = (int)ImgType.XPM;
+
+        #endregion
+
+        #region FilledArcStyles
+
+        /// <summary>
+        /// Filled Arc Style types enumeration
+        /// </summary>
+        [Flags]
+        public enum FilledArcStyles
+        {
+            /// <summary>
+            /// A style constant used by the <see cref="imagefilledarc"/> function.
+            /// This constant has the same value as IMG_ARC_PIE.
+            /// </summary>
+            ROUNDED = PIE,
+
+            /// <summary>
+            /// A style constant used by the <see cref="imagefilledarc"/> function.
+            /// </summary>
+            PIE = 0,
+
+            /// <summary>
+            /// A style constant used by the <see cref="imagefilledarc"/> function.
+            /// </summary>
+            CHORD = 1,
+
+            /// <summary>
+            /// A style constant used by the <see cref="imagefilledarc"/> function.
+            /// </summary>
+            NOFILL = 2,
+
+            /// <summary>
+            /// A style constant used by the <see cref="imagefilledarc"/> function.
+            /// </summary>
+            EDGED = 4,
+        }
+
+        public const int IMG_ARC_ROUNDED = (int)FilledArcStyles.ROUNDED;
+        public const int IMG_ARC_PIE = (int)FilledArcStyles.PIE;
+        public const int IMG_ARC_CHORD = (int)FilledArcStyles.CHORD;
+        public const int IMG_ARC_NOFILL = (int)FilledArcStyles.NOFILL;
+        public const int IMG_ARC_EDGED = (int)FilledArcStyles.EDGED;
+
+        #endregion
+
+        #region ColorValues
+
+        /// <summary>
+        /// Special Image Color values enumeration.
+        /// </summary>
+        public enum ColorValues
+        {
+            /// <summary>
+            /// Special color option which can be used in stead of color allocated with <see cref="imagecolorallocate"/> or <see cref="imagecolorallocatealpha"/>.
+            /// </summary>
+            STYLED = -2,
+
+            /// <summary>
+            /// Special color option which can be used in stead of color allocated with <see cref="imagecolorallocate"/> or <see cref="imagecolorallocatealpha"/>.
+            /// </summary>
+            BRUSHED = -3,
+
+            /// <summary>
+            /// Special color option which can be used in stead of color allocated with <see cref="imagecolorallocate"/> or <see cref="imagecolorallocatealpha"/>.
+            /// </summary>
+            STYLEDBRUSHED = -4,
+
+            /// <summary>
+            /// Special color option which can be used in stead of color allocated with <see cref="imagecolorallocate"/> or <see cref="imagecolorallocatealpha"/>.
+            /// </summary>
+            TILED = -5,
+
+            /// <summary>
+            /// Special color option which can be used in stead of color allocated with <see cref="imagecolorallocate"/> or <see cref="imagecolorallocatealpha"/>.
+            /// </summary>
+            TRANSPARENT = -6
+        }
+
+        public const int IMG_COLOR_STYLED = (int)ColorValues.STYLED;
+        public const int IMG_COLOR_BRUSHED = (int)ColorValues.BRUSHED;
+        public const int IMG_COLOR_STYLEDBRUSHED = (int)ColorValues.STYLEDBRUSHED;
+        public const int IMG_COLOR_TILED = (int)ColorValues.TILED;
+        public const int IMG_COLOR_TRANSPARENT = (int)ColorValues.TRANSPARENT;
+
+        #endregion
+
+        #region FilterTypes
+
+        /// <summary>
+        /// Filled Arc Style types enumeration
+        /// </summary>
+        public enum FilterTypes
+        {
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            NEGATE,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            GRAYSCALE,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            BRIGHTNESS,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            CONTRAST,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            COLORIZE,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            EDGEDETECT,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            EMBOSS,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            GAUSSIAN_BLUR,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            SELECTIVE_BLUR,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            MEAN_REMOVAL,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            SMOOTH,
+            /// <summary>
+            /// Special GD filter used by the <see cref="imagefilter(PhpResource,int)"/> function.
+            /// </summary>
+            PIXELATE,
+        }
+
+        public const int IMG_FILTER_NEGATE = (int)FilterTypes.NEGATE;
+        public const int IMG_FILTER_GRAYSCALE = (int)FilterTypes.GRAYSCALE;
+        public const int IMG_FILTER_BRIGHTNESS = (int)FilterTypes.BRIGHTNESS;
+        public const int IMG_FILTER_CONTRAST = (int)FilterTypes.CONTRAST;
+        public const int IMG_FILTER_COLORIZE = (int)FilterTypes.COLORIZE;
+        public const int IMG_FILTER_EDGEDETECT = (int)FilterTypes.EDGEDETECT;
+        public const int IMG_FILTER_EMBOSS = (int)FilterTypes.EMBOSS;
+        public const int IMG_FILTER_GAUSSIAN_BLUR = (int)FilterTypes.GAUSSIAN_BLUR;
+        public const int IMG_FILTER_SELECTIVE_BLUR = (int)FilterTypes.SELECTIVE_BLUR;
+        public const int IMG_FILTER_MEAN_REMOVAL = (int)FilterTypes.MEAN_REMOVAL;
+        public const int IMG_FILTER_SMOOTH = (int)FilterTypes.SMOOTH;
+        public const int IMG_FILTER_PIXELATE = (int)FilterTypes.PIXELATE;

         #endregion


mbstring: cleanup

mbstring: cleanup

just avoids using Context when unnecessary

--- src/Peachpie.Library/MultiByteString.cs
+++ src/Peachpie.Library/MultiByteString.cs
@@ -387,7 +387,7 @@
         {
             return value.ContainsBinaryData
                 ? value.ToString(GetEncoding(forceencoding) ?? GetInternalEncoding(ctx))
-                : value.ToString(ctx);  // no bytes have to be converted anyway
+                : value.ToString(Encoding.UTF8);  // no bytes have to be decoded anyway
         }

         static byte[] ToBytes(Context ctx, PhpString value, string forceencoding = null)


SplFileInfo::getType()

SplFileInfo::getType()

--- src/Peachpie.Library/Spl/SplFileInfo.cs
+++ src/Peachpie.Library/Spl/SplFileInfo.cs
@@ -116,7 +116,27 @@
         public virtual string getRealPath(Context ctx) => ResolvedInfo.FullName;

         public virtual long getSize() => (ResolvedInfo is FileInfo finfo) ? finfo.Length : 0;
-        public virtual string getType() { throw new NotImplementedException(); }
+
+        /// <summary>
+        /// Returns the type of the file referenced.
+        /// </summary>
+        /// <returns>A string representing the type of the entry. May be one of <c>file</c>, <c>link</c>, or <c>dir</c>.</returns>
+        /// <exception cref="RuntimeException">Throws a RuntimeException on error.</exception>
+        [return: NotNull]
+        public virtual string getType()
+        {
+            if (ResolvedInfo.Exists)
+            {
+                //var attrs = ResolvedInfo.Attributes;
+                //if ((attrs & FileAttributes.Directory) != 0) return "dir";
+                if (ResolvedInfo is FileInfo) return "file";
+                if (ResolvedInfo is DirectoryInfo) return "dir";
+                // TODO: symbolic link
+            }
+
+            throw new RuntimeException();
+        }
+
         public virtual bool isDir() => ResolvedInfo.Exists && ResolvedInfo is DirectoryInfo;
         public virtual bool isExecutable() { throw new NotImplementedException(); }
         public virtual bool isFile() => ResolvedInfo.Exists && ResolvedInfo is FileInfo;


Update View convention to recognize MainWindow

--- src/Pirac/Conventions/ViewConvention.cs
+++ src/Pirac/Conventions/ViewConvention.cs
@@ -1,4 +1,5 @@
-using Conventional.Conventions;
+using System;
+using Conventional.Conventions;

 namespace Pirac.Conventions
 {
@@ -6,13 +7,34 @@
     {
         public ViewConvention()
         {
-            Must.HaveNameEndWith("View").BeAClass();
+            Must.Pass(t => t.IsClass && (t.Name.EndsWith("View") || t.Name == "MainWindow"), "Name ends with View or is named MainWindow");

             Should.BeAConcreteClass();

-            BaseName = t => t.Name.Substring(0, t.Name.Length - 4);
+            BaseName = t => t.Name == "MainWindow" ? t.Name : t.Name.Substring(0, t.Name.Length - 4);

-            Variants.HaveBaseNameAndEndWith("View");
+            Variants.Add(new DelegateBaseFilter((t, b) =>
+            {
+                if (t.Name == "MainWindow" && b == "MainWindow")
+                    return true;
+
+                return t.Name == b + "View";
+            }));
+        }
+
+        class DelegateBaseFilter : IBaseFilter
+        {
+            private readonly Func<Type, string, bool> predicate;
+
+            public DelegateBaseFilter(Func<Type, string, bool> predicate)
+            {
+                this.predicate = predicate;
+            }
+
+            public bool Matches(Type t, string baseName)
+            {
+                return predicate(t, baseName);
+            }
         }
     }
 }


Fixed the performance test.

Fixed the performance test.

The value tested was too low for temporary testing.

--- AppBrix.Backgammon.Tests/GameTests.cs
+++ AppBrix.Backgammon.Tests/GameTests.cs
@@ -57,7 +57,7 @@
             }

             stopwatch.Reset();
-            times.Average().Should().BeLessThan(1, "this tests the average performange per game");
+            times.Average().Should().BeLessThan(3, "this tests the average performange per game");
         }
         #endregion


Added support for multiple headers

Added support for multiple headers

--- src/RiskFirst.RestClient/RestRequest.cs
+++ src/RiskFirst.RestClient/RestRequest.cs
@@ -58,6 +58,31 @@
         public RestRequest WithHeader(String key, IEnumerable<string> values)
         {
             this.headers.Add(key, values);
+            return this;
+        }
+
+        /// <summary>
+        ///  Adds a set of values to the request header
+        /// </summary>
+        /// <param name="values">Any object to add to the headers</param>
+        /// <returns>Current RestRequest instance</returns>
+        public RestRequest WithHeaders(object values)
+        {
+            var props = values.GetType().GetTypeInfo().DeclaredProperties;
+            foreach (var prop in props)
+                WithHeader(prop.Name, prop.GetValue(values, null)?.ToString());
+            return this;
+        }
+
+        /// <summary>
+        /// Adds parameter(s) to the header from a dictionary
+        /// </summary>
+        /// <param name="values">dictionary of key/value to add to the headers</param>
+        /// <returns>Current RestRequest instance</returns>
+        public RestRequest WithHeaders(IDictionary<string, object> values)
+        {
+            foreach (var kv in values)
+                WithHeader(kv.Key, kv.Value?.ToString());
             return this;
         }


setting root url for feed

setting root url for feed

--- src/SimpleAtomPubSub.FeedHost/Module.cs
+++ src/SimpleAtomPubSub.FeedHost/Module.cs
@@ -10,14 +10,13 @@
     public class FeedModule : Nancy.NancyModule
     {
         internal static IEventFeed feed;
-        internal static Uri feedUrl = new Uri("http://localhost:12345");
-
+
         public FeedModule()
         {
             feed = SimpleAtomPubSub.Configure.AsAPublisher("EventStore");

-            Get["/"] = _ => feed.GetWorkingFeed(feedUrl);
-            Get["/{name}"] = parameters => feed.GetArchiveFeed(string.Concat("/", parameters.name), feedUrl);
+            Get["/"] = _ => feed.GetWorkingFeed(new Uri(Context.Request.Url.BasePath));
+            Get["/{name}"] = parameters => feed.GetArchiveFeed(string.Concat("/", parameters.name), new Uri(Context.Request.Url.BasePath));
         }
     }
 }


switch to write mode upon a write request

--- src/Sir.Store/Session/SessionFactory.cs
+++ src/Sir.Store/Session/SessionFactory.cs
@@ -46,12 +46,17 @@

         public async Task Write(Job job)
         {
+            _writeSync.WaitOne();
+
             if (_mmfs.Count > 0)
             {
-                throw new InvalidOperationException("writing while in readonly mode");
-            }
-
-            _writeSync.WaitOne();
+                foreach (var mmf in _mmfs)
+                {
+                    mmf.Dispose();
+                }
+
+                _mmfs.Clear();
+            }

             var timer = Stopwatch.StartNew();

@@ -192,22 +197,25 @@
             }
             catch (FileNotFoundException)
             {
-                lock (_syncMMF)
-                {
-                    try
-                    {
-                        mmf = MemoryMappedFile.OpenExisting(mapName, MemoryMappedFileRights.Read, HandleInheritability.Inheritable);
-
-                        this.Log($"opened existing mmf {mapName} on second attempt");
-                    }
-                    catch (FileNotFoundException)
-                    {
-                        mmf = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, mapName, 0, MemoryMappedFileAccess.Read);
-
-                        _mmfs.Add(MemoryMappedFile.OpenExisting(mapName, MemoryMappedFileRights.Read, HandleInheritability.Inheritable));
-
-                        this.Log($"created new mmf {mapName}");
-                    }
+                try
+                {
+                    _writeSync.WaitOne();
+
+                    mmf = MemoryMappedFile.OpenExisting(mapName, MemoryMappedFileRights.Read, HandleInheritability.Inheritable);
+
+                    this.Log($"opened existing mmf {mapName} on second attempt");
+                }
+                catch (FileNotFoundException)
+                {
+                    mmf = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, mapName, 0, MemoryMappedFileAccess.Read);
+
+                    _mmfs.Add(MemoryMappedFile.OpenExisting(mapName, MemoryMappedFileRights.Read, HandleInheritability.Inheritable));
+
+                    this.Log($"created new mmf {mapName}");
+                }
+                finally
+                {
+                    _writeSync.Release();
                 }
             }


Use a class-wide constant for hitsLimit

Use a class-wide constant for hitsLimit

--- src/SourceBrowser.Search/SearchIndex.cs
+++ src/SourceBrowser.Search/SearchIndex.cs
@@ -20,6 +20,7 @@
         private static string basePath = System.Web.Hosting.HostingEnvironment.MapPath("~") ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
         private static string _luceneDir =  Path.Combine(basePath, "luceneIndex");
         private static FSDirectory _directoryTemp;
+        private const int HITS_LIMIT = 100;

         private static FSDirectory _directory
         {
@@ -141,8 +142,7 @@
                 boolQuery.Add(repositoryQuery, Occur.MUST);
                 boolQuery.Add(nameQuery, Occur.MUST);

-                var hitsLimit = 100;
-                var hits = searcher.Search(boolQuery, hitsLimit).ScoreDocs;
+                var hits = searcher.Search(boolQuery, HITS_LIMIT).ScoreDocs;

                 var results = MapLuceneToDataList(hits, searcher);
                 return results;


Cleaned up unneeded names.

Cleaned up unneeded names.

--- Assets/MapGen/ContentType/IContent.cs
+++ Assets/MapGen/ContentType/IContent.cs
@@ -1,6 +1,6 @@
 using System.Xml.Linq;

 public interface IContent {
-    bool AddTypeElement(System.Xml.Linq.XElement elemtype);
+    bool AddTypeElement(XElement elemtype);
     object ExternalStorage { set; }
 }


Update PickupFlag.cs

Update PickupFlag.cs

defined bool withBanana, int tempScore, int scoreMultiplier;
call IncreaseEnemyScore() under OnDrop();
call IncreaseEnemyScore() under OnCapture();
IncreaseEnemyScore();

--- Assets/Scripts/GamePlay/PickupFlag.cs
+++ Assets/Scripts/GamePlay/PickupFlag.cs
@@ -15,6 +15,16 @@

 	float m_ReturnTimer;
 	Vector3 m_HomePosition;
+
+	bool withBanana=default (bool);
+	int tempScore;
+	int scoreMultiplier;
+
+	void Start()
+	{
+		tempScore=0;
+		scoreMultiplier=6;	//player gains 6 points by holding banana for 1 frame
+	}

 	void Awake()
 	{
@@ -145,6 +155,11 @@
 		m_CarryingActorController = null;
 		transform.position = position;
 		m_ReturnTimer = ReturnTime;
+
+		withBanana=false;
+		IncreaseEnemyScore();
+		tempScore=0;
+
 	}

 	[PunRPC]
@@ -158,6 +173,7 @@
 		//Only the master client increases the score and sends the update to everyone else, to make sure the team only gets 1 point
 		if( PhotonNetwork.isMasterClient == true )
 		{
+			withBanana=true;
 			IncreaseEnemyScore();
 		}
 	}
@@ -174,6 +190,12 @@
 	{
 		GamemodeCaptureTheFlag ctfMode = GamemodeManager.CurrentGamemode as GamemodeCaptureTheFlag;
 	//	TODO: MICHELLE CODE HERE, probably maybe?!
+		while(withBanana==true)
+		{
+			tempScore++;
+			m_CarryingActorController.score+=tempScore*scoreMultiplier;
+			Debug.Log("Event: Scored");
+		}
 	}

 	public override bool CanBePickedUpBy( ActorController actor )
@@ -193,4 +215,4 @@
 		m_CarryingActorController = actor;

 	}
-}+}


Equals and GetHashCode methods are created to use with HashSet.

--- AssociationRuleLearner/Common/Item.cs
+++ AssociationRuleLearner/Common/Item.cs
@@ -19,7 +19,19 @@
             Name = itemName;
             Guid = Guid.NewGuid();
         }
+
+        public override int GetHashCode()
+        {
+            return Name.GetHashCode();
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Name.Equals(((Item)obj)?.Name);
+        }
+
         public string Name { get; set; }
         public Guid Guid { get; set; }
     }
+
 }


Unhook global hotkeys event before closing

--- AudioSharp.GUI.Wpf/MainWindow.xaml.cs
+++ AudioSharp.GUI.Wpf/MainWindow.xaml.cs
@@ -108,6 +108,7 @@

             IntPtr windowHandle = new WindowInteropHelper(this).Handle;
             HotkeyUtils.UnregisterAllHotkeys(windowHandle);
+            HotkeyUtils.GlobalHoykeyPressed -= HotkeyUtils_GlobalHoykeyPressed;
         }

         private void Window_StateChanged(object sender, EventArgs e)


fixed "carry" and lowered the chances for recalling

--- AutoSharpporting/Autoplay/Autoplay.cs
+++ AutoSharpporting/Autoplay/Autoplay.cs
@@ -60,7 +60,7 @@

         public static bool RandomDecision()
         {
-            return Rand.Next(-6, 7) > 0; //Hi there riot games ^^
+            return Rand.Next(0, 20) > 13; //Hi there riot games ^^
         }

         private static void OnProcessSpellCast(Obj_AI_Base sender, GameObjectProcessSpellCastEventArgs args)
@@ -384,7 +384,7 @@
                     if ((Bot.Level > 8 || Environment.TickCount - _loaded > 900000) && Environment.TickCount - _lastSwitched > 180000)
                     {
                         var alliesSortedByKDA =
-                            MetaHandler.AllyHeroes.OrderBy(hero => hero.ChampionsKilled / ((hero.Deaths != 0) ? hero.Deaths : 1)); //AsunaChan2Kawaii
+                            MetaHandler.AllyHeroes.OrderByDescending(hero => hero.ChampionsKilled / ((hero.Deaths != 0) ? hero.Deaths : 1)); //AsunaChan2Kawaii
                         Carry = alliesSortedByKDA.FirstOrDefault();
                         _lastSwitched = Environment.TickCount;
                     }


Cleanup char tests (#7613)

Cleanup char tests (#7613)

* Cleanup char tests

- Take advantage of xunit
- Split up some tests to ensure tests only test a single thing

Contributes to #6286

--- src/System.Runtime/tests/System/Char.cs
+++ src/System.Runtime/tests/System/Char.cs
@@ -5,516 +5,508 @@
 using System;
 using System.Collections.Generic;
 using System.Globalization;
-
 using Xunit;

 public static class CharTests
 {
-    [Fact]
-    public static void TestCompareTo()
-    {
-        // Int32 Char.CompareTo(Char)
-        char h = 'h';
-        Assert.True(h.CompareTo('h') == 0);
-        Assert.True(h.CompareTo('a') > 0);
-        Assert.True(h.CompareTo('z') < 0);
-    }
-
-    [Fact]
-    public static void TestSystemIComparableCompareTo()
-    {
-        // Int32 Char.System.IComparable.CompareTo(Object)
-        IComparable h = 'h';
-        Assert.True(h.CompareTo('h') == 0);
-        Assert.True(h.CompareTo('a') > 0);
-        Assert.True(h.CompareTo('z') < 0);
-        Assert.True(h.CompareTo(null) > 0);
-
-        Assert.Throws<ArgumentException>(() => h.CompareTo("H"));
-    }
-
-    private static void ValidateConvertFromUtf32(int i, string expected)
-    {
-        try
-        {
-            string s = char.ConvertFromUtf32(i);
-            Assert.Equal(expected, s);
-        }
-        catch (ArgumentOutOfRangeException)
-        {
-            Assert.True(expected == null, "Expected an ArgumentOutOfRangeException");
-        }
-    }
-
-    [Fact]
-    public static void TestConvertFromUtf32()
-    {
-        // String Char.ConvertFromUtf32(Int32)
-        ValidateConvertFromUtf32(0x10000, "\uD800\uDC00");
-        ValidateConvertFromUtf32(0x103FF, "\uD800\uDFFF");
-        ValidateConvertFromUtf32(0xFFFFF, "\uDBBF\uDFFF");
-        ValidateConvertFromUtf32(0x10FC00, "\uDBFF\uDC00");
-        ValidateConvertFromUtf32(0x10FFFF, "\uDBFF\uDFFF");
-        ValidateConvertFromUtf32(0, "\0");
-        ValidateConvertFromUtf32(0x3FF, "\u03FF");
-        ValidateConvertFromUtf32(0xE000, "\uE000");
-        ValidateConvertFromUtf32(0xFFFF, "\uFFFF");
-        ValidateConvertFromUtf32(0xD800, null);
-        ValidateConvertFromUtf32(0xDC00, null);
-        ValidateConvertFromUtf32(0xDFFF, null);
-        ValidateConvertFromUtf32(0x110000, null);
-        ValidateConvertFromUtf32(-1, null);
-        ValidateConvertFromUtf32(int.MaxValue, null);
-        ValidateConvertFromUtf32(int.MinValue, null);
-    }
-
-    private static void ValidateconverToUtf32<T>(string s, int i, int expected) where T : Exception
-    {
-        try
-        {
-            int result = char.ConvertToUtf32(s, i);
-            Assert.Equal(result, expected);
-        }
-        catch (T)
-        {
-            Assert.True(expected == int.MinValue, "Expected an exception to be thrown");
-        }
-    }
-
-    [Fact]
-    public static void TestConvertToUtf32StrInt()
-    {
-        // Int32 Char.ConvertToUtf32(String, Int32)
-        ValidateconverToUtf32<Exception>("\uD800\uDC00", 0, 0x10000);
-        ValidateconverToUtf32<Exception>("\uD800\uD800\uDFFF", 1, 0x103FF);
-        ValidateconverToUtf32<Exception>("\uDBBF\uDFFF", 0, 0xFFFFF);
-        ValidateconverToUtf32<Exception>("\uDBFF\uDC00", 0, 0x10FC00);
-        ValidateconverToUtf32<Exception>("\uDBFF\uDFFF", 0, 0x10FFFF);
-        // Not surrogate pairs
-        ValidateconverToUtf32<Exception>("\u0000\u0001", 0, 0);
-        ValidateconverToUtf32<Exception>("\u0000\u0001", 1, 1);
-        ValidateconverToUtf32<Exception>("\u0000", 0, 0);
-        ValidateconverToUtf32<Exception>("\u0020\uD7FF", 0, 32);
-        ValidateconverToUtf32<Exception>("\u0020\uD7FF", 1, 0xD7FF);
-        ValidateconverToUtf32<Exception>("abcde", 4, (int)'e');
-        ValidateconverToUtf32<Exception>("\uD800\uD7FF", 1, 0xD7FF);  // high, non-surrogate
-        ValidateconverToUtf32<Exception>("\uD800\u0000", 1, 0);  // high, non-surrogate
-        ValidateconverToUtf32<Exception>("\uDF01\u0000", 1, 0);  // low, non-surrogate
-        // Invalid inputs
-        ValidateconverToUtf32<ArgumentException>("\uD800\uD800", 0, int.MinValue);  // high, high
-        ValidateconverToUtf32<ArgumentException>("\uD800\uD7FF", 0, int.MinValue);  // high, non-surrogate
-        ValidateconverToUtf32<ArgumentException>("\uD800\u0000", 0, int.MinValue);  // high, non-surrogate
-        ValidateconverToUtf32<ArgumentException>("\uDC01\uD940", 0, int.MinValue);  // low, high
-        ValidateconverToUtf32<ArgumentException>("\uDD00\uDE00", 0, int.MinValue);  // low, low
-        ValidateconverToUtf32<ArgumentException>("\uDF01\u0000", 0, int.MinValue);  // low, non-surrogate
-        ValidateconverToUtf32<ArgumentException>("\uD800\uD800", 1, int.MinValue);  // high, high
-        ValidateconverToUtf32<ArgumentException>("\uDC01\uD940", 1, int.MinValue);  // low, high
-        ValidateconverToUtf32<ArgumentException>("\uDD00\uDE00", 1, int.MinValue);  // low, low
-        ValidateconverToUtf32<ArgumentNullException>(null, 0, int.MinValue);  // null string
-        ValidateconverToUtf32<ArgumentOutOfRangeException>("", 0, int.MinValue);  // index out of range
-        ValidateconverToUtf32<ArgumentOutOfRangeException>("", -1, int.MinValue);  // index out of range
-        ValidateconverToUtf32<ArgumentOutOfRangeException>("abcde", -1, int.MinValue);  // index out of range
-        ValidateconverToUtf32<ArgumentOutOfRangeException>("abcde", 5, int.MinValue);  // index out of range
-    }
-
-    private static void ValidateconverToUtf32<T>(char c1, char c2, int expected) where T : Exception
-    {
-        try
-        {
-            int result = char.ConvertToUtf32(c1, c2);
-            Assert.Equal(result, expected);
-        }
-        catch (T)
-        {
-            Assert.True(expected == int.MinValue, "Expected an exception to be thrown");
-        }
-    }
-
-    [Fact]
-    public static void TestConvertToUtf32()
-    {
-        // Int32 Char.ConvertToUtf32(Char, Char)
-        ValidateconverToUtf32<Exception>('\uD800', '\uDC00', 0x10000);
-        ValidateconverToUtf32<Exception>('\uD800', '\uDFFF', 0x103FF);
-        ValidateconverToUtf32<Exception>('\uDBBF', '\uDFFF', 0xFFFFF);
-        ValidateconverToUtf32<Exception>('\uDBFF', '\uDC00', 0x10FC00);
-        ValidateconverToUtf32<Exception>('\uDBFF', '\uDFFF', 0x10FFFF);
-
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\uD800', '\uD800', int.MinValue);  // high, high
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\uD800', '\uD7FF', int.MinValue);  // high, non-surrogate
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\uD800', '\u0000', int.MinValue);  // high, non-surrogate
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\uDC01', '\uD940', int.MinValue);  // low, high
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\uDD00', '\uDE00', int.MinValue);  // low, low
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\uDF01', '\u0000', int.MinValue);  // low, non-surrogate
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\u0032', '\uD7FF', int.MinValue);  // both non-surrogate
-        ValidateconverToUtf32<ArgumentOutOfRangeException>('\u0000', '\u0000', int.MinValue);  // both non-surrogate
-    }
-
-    [Fact]
-    public static void TestEquals()
-    {
-        // Boolean Char.Equals(Char)
-        char a = 'a';
-
-        Assert.True(a.Equals('a'));
-        Assert.False(a.Equals('b'));
-        Assert.False(a.Equals('A'));
-    }
-
-    [Fact]
-    public static void TestEqualsObj()
-    {
-        // Boolean Char.Equals(Object)
-        char a = 'a';
-        Assert.True(a.Equals((object)'a'));
-        Assert.False(a.Equals((object)'b'));
-        Assert.False(a.Equals((object)'A'));
-        Assert.False(a.Equals(null));
-
-        int i = (int)'a';
-        Assert.False(a.Equals(i));
-        Assert.False(a.Equals("a"));
-    }
-
-    [Fact]
-    public static void TestGetHashCode()
-    {
-        // Int32 Char.GetHashCode()
-        char a = 'a';
-        char b = 'b';
-        Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
-    }
-
-    [Fact]
-    public static void TestGetNumericValueStrInt()
-    {
-        Assert.Equal(Char.GetNumericValue("\uD800\uDD07", 0), 1);
-        Assert.Equal(Char.GetNumericValue("9", 0), 9);
-        Assert.Equal(Char.GetNumericValue("Test 7", 5), 7);
-        Assert.Equal(Char.GetNumericValue("T", 0), -1);
-
-        Assert.Throws<ArgumentNullException>(() => char.GetNumericValue(null, 0));
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsControl("abc", -1));
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsControl("abc", 4));
-    }
-
-    [Fact]
-    public static void TestGetNumericValue()
-    {
-        Assert.Equal(Char.GetNumericValue('9'), 9);
-        Assert.Equal(Char.GetNumericValue('z'), -1);
-    }
-
-    [Fact]
-    public static void TestIsControl()
-    {
-        // Boolean Char.IsControl(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.Control))
+    [Theory]
+    [InlineData('h', 'h', 0)]
+    [InlineData('h', 'a', 1)]
+    [InlineData('h', 'z', -1)]
+    [InlineData('h', null, 1)]
+    public static void TestCompareTo(char c, object value, int expected)
+    {
+        if (value is char)
+        {
+            Assert.Equal(expected, Math.Sign(c.CompareTo((char)value)));
+        }
+        IComparable comparable = c;
+        Assert.Equal(expected, Math.Sign(comparable.CompareTo(value)));
+    }
+
+    [Fact]
+    public static void TestCompareTo_Invalid()
+    {
+        IComparable comparable = 'h';
+        Assert.Throws<ArgumentException>(null, () => comparable.CompareTo("H")); // Value not a char
+    }
+
+    [Fact]
+    public static void TestConvertFromUtf32_InvalidChar()
+    {
+        // TODO: add this as [InlineData] when #7166 is fixed
+        TestConvertFromUtf32(0xFFFF, "\uFFFF");
+    }
+
+    [Theory]
+    [InlineData(0x10000, "\uD800\uDC00")]
+    [InlineData(0x103FF, "\uD800\uDFFF")]
+    [InlineData(0xFFFFF, "\uDBBF\uDFFF")]
+    [InlineData(0x10FC00, "\uDBFF\uDC00")]
+    [InlineData(0x10FFFF, "\uDBFF\uDFFF")]
+    [InlineData(0, "\0")]
+    [InlineData(0x3FF, "\u03FF")]
+    [InlineData(0xE000, "\uE000")]
+    public static void TestConvertFromUtf32(int utf32, string expected)
+    {
+        // TODO: add this as [InlineData] when #7166 is fixed
+        Assert.Equal(expected, char.ConvertFromUtf32(utf32));
+    }
+
+    [Theory]
+    [InlineData(0xD800)]
+    [InlineData(0xDC00)]
+    [InlineData(0xDFFF)]
+    [InlineData(0x110000)]
+    [InlineData(-1)]
+    [InlineData(int.MaxValue)]
+    [InlineData(int.MinValue)]
+    public static void TestConvertFromUtf32_Invalid(int utf32)
+    {
+        Assert.Throws<ArgumentOutOfRangeException>("utf32", () => char.ConvertFromUtf32(utf32));
+    }
+
+    [Fact]
+    public static void TestConvertToUtf32_String_Int()
+    {
+        // TODO: add this as [InlineData] when #7166 is fixed
+        TestConvertToUtf32_String_Int("\uD800\uD800\uDFFF", 1, 0x103FF);
+        TestConvertToUtf32_String_Int("\uD800\uD7FF", 1, 0xD7FF);  // High, non-surrogate
+        TestConvertToUtf32_String_Int("\uD800\u0000", 1, 0);  // High, non-surrogate
+        TestConvertToUtf32_String_Int("\uDF01\u0000", 1, 0);  // Low, non-surrogate
+    }
+
+    [Theory]
+    [InlineData("\uD800\uDC00", 0, 0x10000)]
+    [InlineData("\uDBBF\uDFFF", 0, 0xFFFFF)]
+    [InlineData("\uDBBF\uDFFF", 0, 0xFFFFF)]
+    [InlineData("\uDBFF\uDC00", 0, 0x10FC00)]
+    [InlineData("\uDBFF\uDFFF", 0, 0x10FFFF)]
+    [InlineData("\u0000\u0001", 0, 0)]
+    [InlineData("\u0000\u0001", 1, 1)]
+    [InlineData("\u0000", 0, 0)]
+    [InlineData("\u0020\uD7FF", 0, 32)]
+    [InlineData("\u0020\uD7FF", 1, 0xD7FF)]
+    [InlineData("abcde", 4, 'e')]
+    public static void TestConvertToUtf32_String_Int(string s, int index, int expected)
+    {
+        Assert.Equal(expected, char.ConvertToUtf32(s, index));
+    }
+
+    [Fact]
+    public static void TestConvertToUtf32_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.ConvertToUtf32(null, 0)); // String is null
+
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uD800\uD800", 0)); // High, high
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uD800\uD800", 1)); // High, high
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uD800\uD7FF", 0)); // High, non-surrogate
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uD800\u0000", 0)); // High, non-surrogate
+
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uDC01\uD940", 0)); // Low, high
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uDC01\uD940", 1)); // Low, high
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uDD00\uDE00", 0)); // Low, low
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uDD00\uDE00", 1)); // Low, hig
+        Assert.Throws<ArgumentException>("s", () => char.ConvertToUtf32("\uDF01\u0000", 0)); // Low, non-surrogateh
+
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.ConvertToUtf32("abcde", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.ConvertToUtf32("abcde", 5)); // Index >= string.Length
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.ConvertToUtf32("", 0)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestConvertToUtf32_Char_Char()
+    {
+        // TODO: add this as [InlineData] when #7166 is fixed
+        TestConvertToUtf32_Char_Char('\uD800', '\uDC00', 0x10000);
+        TestConvertToUtf32_Char_Char('\uD800', '\uDC00', 0x10000);
+        TestConvertToUtf32_Char_Char('\uD800', '\uDFFF', 0x103FF);
+        TestConvertToUtf32_Char_Char('\uDBBF', '\uDFFF', 0xFFFFF);
+        TestConvertToUtf32_Char_Char('\uDBFF', '\uDC00', 0x10FC00);
+        TestConvertToUtf32_Char_Char('\uDBFF', '\uDFFF', 0x10FFFF);
+    }
+
+    private static void TestConvertToUtf32_Char_Char(char highSurrogate, char lowSurrogate, int expected)
+    {
+        Assert.Equal(expected, char.ConvertToUtf32(highSurrogate, lowSurrogate));
+    }
+
+    [Fact]
+    public static void TestConvertToUtf32_Char_Char_Invalid()
+    {
+        Assert.Throws<ArgumentOutOfRangeException>("lowSurrogate", () => char.ConvertToUtf32('\uD800', '\uD800')); // High, high
+        Assert.Throws<ArgumentOutOfRangeException>("lowSurrogate", () => char.ConvertToUtf32('\uD800', '\uD7FF')); // High, non-surrogate
+        Assert.Throws<ArgumentOutOfRangeException>("lowSurrogate", () => char.ConvertToUtf32('\uD800', '\u0000')); // High, non-surrogate
+
+        Assert.Throws<ArgumentOutOfRangeException>("highSurrogate", () => char.ConvertToUtf32('\uDD00', '\uDE00')); // Low, low
+        Assert.Throws<ArgumentOutOfRangeException>("highSurrogate", () => char.ConvertToUtf32('\uDC01', '\uD940')); // Low, high
+        Assert.Throws<ArgumentOutOfRangeException>("highSurrogate", () => char.ConvertToUtf32('\uDF01', '\u0000')); // Low, non-surrogate
+
+        Assert.Throws<ArgumentOutOfRangeException>("highSurrogate", () => char.ConvertToUtf32('\u0032', '\uD7FF')); // Non-surrogate, non-surrogate
+        Assert.Throws<ArgumentOutOfRangeException>("highSurrogate", () => char.ConvertToUtf32('\u0000', '\u0000')); // Non-surrogate, non-surrogate
+    }
+
+    [Theory]
+    [InlineData('a', 'a', true)]
+    [InlineData('a', 'A', false)]
+    [InlineData('a', 'b', false)]
+    [InlineData('a', (int)'a', false)]
+    [InlineData('a', "a", false)]
+    [InlineData('a', null, false)]
+    public static void TestEquals(char c, object obj, bool expected)
+    {
+        if (obj is char)
+        {
+            Assert.Equal(expected, c.Equals((char)obj));
+            Assert.Equal(expected, c.GetHashCode().Equals(obj.GetHashCode()));
+        }
+        Assert.Equal(expected, c.Equals(obj));
+    }
+
+    [Theory]
+    [InlineData('0', 0)]
+    [InlineData('9', 9)]
+    [InlineData('T', -1)]
+    public static void TestGetNumericValue_Char(char c, int expected)
+    {
+        Assert.Equal(expected, char.GetNumericValue(c));
+    }
+
+    [Theory]
+    [InlineData("\uD800\uDD07", 0, 1)]
+    [InlineData("9", 0, 9)]
+    [InlineData("99", 1, 9)]
+    [InlineData(" 7  ", 1, 7)]
+    [InlineData("Test 7", 5, 7)]
+    [InlineData("T", 0, -1)]
+    public static void TestGetNumericValue_String_Int(string s, int index, int expected)
+    {
+        Assert.Equal(expected, char.GetNumericValue(s, index));
+    }
+
+    [Fact]
+    public static void TestGetNumericValue_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.GetNumericValue(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.GetNumericValue("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.GetNumericValue("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsControl_Char()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.Control))
             Assert.True(char.IsControl(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.Control))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.Control))
             Assert.False(char.IsControl(c));
     }

     [Fact]
-    public static void TestIsControlStrInt()
-    {
-        // Boolean Char.IsControl(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.Control))
+    public static void TestIsControl_String_Int()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.Control))
             Assert.True(char.IsControl(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.Control))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.Control))
             Assert.False(char.IsControl(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsControl(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsControl("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsControl("abc", 4));
+    }
+
+    [Fact]
+    public static void TestIsControl_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsControl(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsControl("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsControl("abc", 3)); // Index >= string.Length
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsDigit()
-    {
-        // Boolean Char.IsDigit(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.DecimalDigitNumber))
+    public static void TestIsDigit_Char()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.DecimalDigitNumber))
             Assert.True(char.IsDigit(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.DecimalDigitNumber))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.DecimalDigitNumber))
             Assert.False(char.IsDigit(c));
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsDigitStrInt()
-    {
-        // Boolean Char.IsDigit(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.DecimalDigitNumber))
+    public static void TestIsDigit_String_Int()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.DecimalDigitNumber))
             Assert.True(char.IsDigit(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.DecimalDigitNumber))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.DecimalDigitNumber))
             Assert.False(char.IsDigit(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsDigit(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsDigit("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsDigit("abc", 4));
+    }
+
+    [Fact]
+    public static void TestIsDigit_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsDigit(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsDigit("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsDigit("abc", 3)); // Index >= string.Length
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsLetter()
-    {
-        // Boolean Char.IsLetter(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter))
+    public static void TestIsLetter_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.UppercaseLetter,
+            UnicodeCategory.LowercaseLetter,
+            UnicodeCategory.TitlecaseLetter,
+            UnicodeCategory.ModifierLetter,
+            UnicodeCategory.OtherLetter
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsLetter(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsLetter(c));
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsLetterStrInt()
-    {
-        // Boolean Char.IsLetter(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter))
+    public static void TestIsLetter_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.UppercaseLetter,
+            UnicodeCategory.LowercaseLetter,
+            UnicodeCategory.TitlecaseLetter,
+            UnicodeCategory.ModifierLetter,
+            UnicodeCategory.OtherLetter
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsLetter(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsLetter(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsLetter(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLetter("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLetter("abc", 4));
+    }
+
+    [Fact]
+    public static void TestIsLetter_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsLetter(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLetter("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLetter("abc", 3)); // Index >= string.Length
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsLetterOrDigit()
-    {
-        // Boolean Char.IsLetterOrDigit(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter,
-                UnicodeCategory.DecimalDigitNumber))
+    public static void TestIsLetterOrDigit_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.UppercaseLetter,
+            UnicodeCategory.LowercaseLetter,
+            UnicodeCategory.TitlecaseLetter,
+            UnicodeCategory.ModifierLetter,
+            UnicodeCategory.OtherLetter,
+            UnicodeCategory.DecimalDigitNumber
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsLetterOrDigit(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter,
-                UnicodeCategory.DecimalDigitNumber))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsLetterOrDigit(c));
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsLetterOrDigitStrInt()
-    {
-        // Boolean Char.IsLetterOrDigit(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter,
-                UnicodeCategory.DecimalDigitNumber))
+    public static void TestIsLetterOrDigit_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.UppercaseLetter,
+            UnicodeCategory.LowercaseLetter,
+            UnicodeCategory.TitlecaseLetter,
+            UnicodeCategory.ModifierLetter,
+            UnicodeCategory.OtherLetter,
+            UnicodeCategory.DecimalDigitNumber
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsLetterOrDigit(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter,
-                UnicodeCategory.LowercaseLetter,
-                UnicodeCategory.TitlecaseLetter,
-                UnicodeCategory.ModifierLetter,
-                UnicodeCategory.OtherLetter,
-                UnicodeCategory.DecimalDigitNumber))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsLetterOrDigit(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsLetterOrDigit(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLetterOrDigit("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLetterOrDigit("abc", 4));
+    }
+
+    [Fact]
+    public static void TestIsLetterOrDigit_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsLetterOrDigit(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLetterOrDigit("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLetterOrDigit("abc", 3)); // Index >= string.Length
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsLower()
-    {
-        // Boolean Char.IsLower(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.LowercaseLetter))
+    public static void TestIsLower_Char()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.LowercaseLetter))
             Assert.True(char.IsLower(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.LowercaseLetter))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.LowercaseLetter))
             Assert.False(char.IsLower(c));
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsLowerStrInt()
-    {
-        // Boolean Char.IsLower(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.LowercaseLetter))
+    public static void TestIsLower_String_Int()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.LowercaseLetter))
             Assert.True(char.IsLower(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.LowercaseLetter))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.LowercaseLetter))
             Assert.False(char.IsLower(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsLower(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLower("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLower("abc", 4));
+    }
+
+    [Fact]
+    public static void TestIsLower_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsLower(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLower("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLower("abc", 3)); // Index >= string.Length
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsNumber()
-    {
-        // Boolean Char.IsNumber(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.DecimalDigitNumber,
-            UnicodeCategory.LetterNumber, UnicodeCategory.OtherNumber))
+    public static void TestIsNumber_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.DecimalDigitNumber,
+            UnicodeCategory.LetterNumber,
+            UnicodeCategory.OtherNumber
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsNumber(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.DecimalDigitNumber,
-            UnicodeCategory.LetterNumber, UnicodeCategory.OtherNumber))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsNumber(c));
     }

     [ActiveIssue(5645, PlatformID.Windows)]
     [Fact]
-    public static void TestIsNumberStrInt()
-    {
-        // Boolean Char.IsNumber(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.DecimalDigitNumber,
-            UnicodeCategory.LetterNumber, UnicodeCategory.OtherNumber))
+    public static void TestIsNumber_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.DecimalDigitNumber,
+            UnicodeCategory.LetterNumber,
+            UnicodeCategory.OtherNumber
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsNumber(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.DecimalDigitNumber,
-            UnicodeCategory.LetterNumber, UnicodeCategory.OtherNumber))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsNumber(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsNumber(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsNumber("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsNumber("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsPunctuation()
-    {
-        // Boolean Char.IsPunctuation(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.ConnectorPunctuation,
-              UnicodeCategory.DashPunctuation,
-              UnicodeCategory.OpenPunctuation,
-              UnicodeCategory.ClosePunctuation,
-              UnicodeCategory.InitialQuotePunctuation,
-              UnicodeCategory.FinalQuotePunctuation,
-              UnicodeCategory.OtherPunctuation))
+    }
+
+    [Fact]
+    public static void TestIsNumber_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsNumber(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsNumber("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsNumber("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsPunctuation_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.ConnectorPunctuation,
+            UnicodeCategory.DashPunctuation,
+            UnicodeCategory.OpenPunctuation,
+            UnicodeCategory.ClosePunctuation,
+            UnicodeCategory.InitialQuotePunctuation,
+            UnicodeCategory.FinalQuotePunctuation,
+            UnicodeCategory.OtherPunctuation
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsPunctuation(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.ConnectorPunctuation,
-              UnicodeCategory.DashPunctuation,
-              UnicodeCategory.OpenPunctuation,
-              UnicodeCategory.ClosePunctuation,
-              UnicodeCategory.InitialQuotePunctuation,
-              UnicodeCategory.FinalQuotePunctuation,
-              UnicodeCategory.OtherPunctuation))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsPunctuation(c));
     }

     [Fact]
-    public static void TestIsPunctuationStrInt()
-    {
-        // Boolean Char.IsPunctuation(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.ConnectorPunctuation,
-              UnicodeCategory.DashPunctuation,
-              UnicodeCategory.OpenPunctuation,
-              UnicodeCategory.ClosePunctuation,
-              UnicodeCategory.InitialQuotePunctuation,
-              UnicodeCategory.FinalQuotePunctuation,
-              UnicodeCategory.OtherPunctuation))
+    public static void TestIsPunctuation_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.ConnectorPunctuation,
+            UnicodeCategory.DashPunctuation,
+            UnicodeCategory.OpenPunctuation,
+            UnicodeCategory.ClosePunctuation,
+            UnicodeCategory.InitialQuotePunctuation,
+            UnicodeCategory.FinalQuotePunctuation,
+            UnicodeCategory.OtherPunctuation
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsPunctuation(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.ConnectorPunctuation,
-              UnicodeCategory.DashPunctuation,
-              UnicodeCategory.OpenPunctuation,
-              UnicodeCategory.ClosePunctuation,
-              UnicodeCategory.InitialQuotePunctuation,
-              UnicodeCategory.FinalQuotePunctuation,
-              UnicodeCategory.OtherPunctuation))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsPunctuation(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsPunctuation(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsPunctuation("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsPunctuation("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsSeparator()
-    {
-        // Boolean Char.IsSeparator(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+    }
+
+    [Fact]
+    public static void TestIsPunctuation_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsPunctuation(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsPunctuation("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsPunctuation("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsSeparator_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.SpaceSeparator,
+            UnicodeCategory.LineSeparator,
+            UnicodeCategory.ParagraphSeparator
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsSeparator(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsSeparator(c));
     }

     [Fact]
-    public static void TestIsSeparatorStrInt()
-    {
-        // Boolean Char.IsSeparator(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+    public static void TestIsSeparator_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.SpaceSeparator,
+            UnicodeCategory.LineSeparator,
+            UnicodeCategory.ParagraphSeparator
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsSeparator(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsSeparator(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsSeparator(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSeparator("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSeparator("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsLowSurrogate()
-    {
-        // Boolean Char.IsLowSurrogate(Char)
+    }
+
+    [Fact]
+    public static void TestIsSeparator_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsSeparator(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSeparator("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSeparator("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsLowSurrogate_Char()
+    {
         foreach (char c in s_lowSurrogates)
             Assert.True(char.IsLowSurrogate(c));

@@ -526,9 +518,8 @@
     }

     [Fact]
-    public static void TestIsLowSurrogateStrInt()
-    {
-        // Boolean Char.IsLowSurrogate(String, Int32)
+    public static void TestIsLowSurrogate_String_Int()
+    {
         foreach (char c in s_lowSurrogates)
             Assert.True(char.IsLowSurrogate(c.ToString(), 0));

@@ -537,18 +528,19 @@

         foreach (char c in s_nonSurrogates)
             Assert.False(char.IsLowSurrogate(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsLowSurrogate(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLowSurrogate("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsLowSurrogate("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsHighSurrogate()
-    {
-        // Boolean Char.IsHighSurrogate(Char)
+    }
+
+    [Fact]
+    public static void TestIsLowSurrogate_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsLowSurrogate(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLowSurrogate("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsLowSurrogate("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsHighSurrogate_Char()
+    {
         foreach (char c in s_highSurrogates)
             Assert.True(char.IsHighSurrogate(c));

@@ -560,9 +552,8 @@
     }

     [Fact]
-    public static void TestIsHighSurrogateStrInt()
-    {
-        // Boolean Char.IsHighSurrogate(String, Int32)
+    public static void TestIsHighSurrogate_String_Int()
+    {
         foreach (char c in s_highSurrogates)
             Assert.True(char.IsHighSurrogate(c.ToString(), 0));

@@ -571,18 +562,19 @@

         foreach (char c in s_nonSurrogates)
             Assert.False(char.IsHighSurrogate(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsHighSurrogate(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsHighSurrogate("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsHighSurrogate("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsSurrogate()
-    {
-        // Boolean Char.IsSurrogate(Char)
+    }
+
+    [Fact]
+    public static void TestIsHighSurrogate_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsHighSurrogate(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsHighSurrogate("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsHighSurrogate("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsSurrogate_Char()
+    {
         foreach (char c in s_highSurrogates)
             Assert.True(char.IsSurrogate(c));

@@ -594,9 +586,8 @@
     }

     [Fact]
-    public static void TestIsSurrogateStrInt()
-    {
-        // Boolean Char.IsSurrogate(String, Int32)
+    public static void TestIsSurrogate_String_Int()
+    {
         foreach (char c in s_highSurrogates)
             Assert.True(char.IsSurrogate(c.ToString(), 0));

@@ -605,141 +596,141 @@

         foreach (char c in s_nonSurrogates)
             Assert.False(char.IsSurrogate(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsSurrogate(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSurrogate("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSurrogate("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsSurrogatePair()
-    {
-        // Boolean Char.IsSurrogatePair(Char, Char)
+    }
+
+    [Fact]
+    public static void TestIsSurrogate_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsSurrogate(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSurrogate("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSurrogate("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsSurrogatePair_Char()
+    {
         foreach (char hs in s_highSurrogates)
             foreach (char ls in s_lowSurrogates)
-                Assert.True(Char.IsSurrogatePair(hs, ls));
+                Assert.True(char.IsSurrogatePair(hs, ls));

         foreach (char hs in s_nonSurrogates)
             foreach (char ls in s_lowSurrogates)
-                Assert.False(Char.IsSurrogatePair(hs, ls));
+                Assert.False(char.IsSurrogatePair(hs, ls));

         foreach (char hs in s_highSurrogates)
             foreach (char ls in s_nonSurrogates)
-                Assert.False(Char.IsSurrogatePair(hs, ls));
-    }
-
-    [Fact]
-    public static void TestIsSurrogatePairStrInt()
-    {
-        // Boolean Char.IsSurrogatePair(String, Int32)
+                Assert.False(char.IsSurrogatePair(hs, ls));
+    }
+
+    [Fact]
+    public static void TestIsSurrogatePair_String_Int()
+    {
         foreach (char hs in s_highSurrogates)
             foreach (char ls in s_lowSurrogates)
-                Assert.True(Char.IsSurrogatePair(hs.ToString() + ls, 0));
+                Assert.True(char.IsSurrogatePair(hs.ToString() + ls, 0));

         foreach (char hs in s_nonSurrogates)
             foreach (char ls in s_lowSurrogates)
-                Assert.False(Char.IsSurrogatePair(hs.ToString() + ls, 0));
+                Assert.False(char.IsSurrogatePair(hs.ToString() + ls, 0));

         foreach (char hs in s_highSurrogates)
             foreach (char ls in s_nonSurrogates)
-                Assert.False(Char.IsSurrogatePair(hs.ToString() + ls, 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsSurrogatePair(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSurrogatePair("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSurrogatePair("abc", 4));
-
-        Assert.False(char.IsSurrogatePair("abc", 2)); // index + 1 == s.length always returns false.
-    }
-
-    [Fact]
-    public static void TestIsSymbol()
-    {
-        // Boolean Char.IsSymbol(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.MathSymbol,
-                UnicodeCategory.ModifierSymbol,
-                UnicodeCategory.CurrencySymbol,
-                UnicodeCategory.OtherSymbol))
+                Assert.False(char.IsSurrogatePair(hs.ToString() + ls, 0));
+
+        Assert.False(char.IsSurrogatePair("\ud800\udc00", 1)); // Index + 1 >= s.Length
+    }
+
+    [Fact]
+    public static void TestIsSurrogatePair_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsSurrogatePair(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSurrogatePair("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSurrogatePair("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsSymbol_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.MathSymbol,
+            UnicodeCategory.ModifierSymbol,
+            UnicodeCategory.CurrencySymbol,
+            UnicodeCategory.OtherSymbol
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsSymbol(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.MathSymbol,
-                UnicodeCategory.ModifierSymbol,
-                UnicodeCategory.CurrencySymbol,
-                UnicodeCategory.OtherSymbol))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsSymbol(c));
     }

     [Fact]
-    public static void TestIsSymbolStrInt()
-    {
-        // Boolean Char.IsSymbol(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.MathSymbol,
-                UnicodeCategory.ModifierSymbol,
-                UnicodeCategory.CurrencySymbol,
-                UnicodeCategory.OtherSymbol))
+    public static void TestIsSymbol_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.MathSymbol,
+            UnicodeCategory.ModifierSymbol,
+            UnicodeCategory.CurrencySymbol,
+            UnicodeCategory.OtherSymbol
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsSymbol(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.MathSymbol,
-                UnicodeCategory.ModifierSymbol,
-                UnicodeCategory.CurrencySymbol,
-                UnicodeCategory.OtherSymbol))
+        foreach (char c in GetTestCharsNotInCategory(categories))
             Assert.False(char.IsSymbol(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsSymbol(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSymbol("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsSymbol("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsUpper()
-    {
-        // Boolean Char.IsUpper(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.UppercaseLetter))
+    }
+
+    [Fact]
+    public static void TestIsSymbol_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsSymbol(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSymbol("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsSymbol("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsUpper_Char()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.UppercaseLetter))
             Assert.True(char.IsUpper(c));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter))
             Assert.False(char.IsUpper(c));
     }

     [Fact]
-    public static void TestIsUpperStrInt()
-    {
-        // Boolean Char.IsUpper(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.UppercaseLetter))
+    public static void TestIsUpper_String_Int()
+    {
+        foreach (char c in GetTestChars(UnicodeCategory.UppercaseLetter))
             Assert.True(char.IsUpper(c.ToString(), 0));

-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter))
+        foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter))
             Assert.False(char.IsUpper(c.ToString(), 0));
-
-        Assert.Throws<ArgumentNullException>(() => char.IsUpper(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsUpper("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsUpper("abc", 4));
-    }
-
-    [Fact]
-    public static void TestIsWhiteSpace()
-    {
-        // Boolean Char.IsWhiteSpace(Char)
-        foreach (var c in GetTestChars(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+    }
+
+    [Fact]
+    public static void TestIsUpper_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsUpper(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsUpper("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsUpper("abc", 3)); // Index >= string.Length
+    }
+
+    [Fact]
+    public static void TestIsWhitespace_Char()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.SpaceSeparator,
+            UnicodeCategory.LineSeparator,
+            UnicodeCategory.ParagraphSeparator
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsWhiteSpace(c));

-        // Some control chars are also considered whitespace for legacy reasons.
-        //if ((c >= '\x0009' && c <= '\x000d') || c == '\x0085')
-        Assert.True(char.IsWhiteSpace('\u000b'));
-        Assert.True(char.IsWhiteSpace('\u0085'));
-
-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+        foreach (char c in GetTestCharsNotInCategory(categories))
         {
             // Need to special case some control chars that are treated as whitespace
             if ((c >= '\x0009' && c <= '\x000d') || c == '\x0085') continue;
@@ -748,53 +739,53 @@
     }

     [Fact]
-    public static void TestIsWhiteSpaceStrInt()
-    {
-        // Boolean Char.IsWhiteSpace(String, Int32)
-        foreach (var c in GetTestChars(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+    public static void TestIsWhiteSpace_String_Int()
+    {
+        var categories = new UnicodeCategory[]
+        {
+            UnicodeCategory.SpaceSeparator,
+            UnicodeCategory.LineSeparator,
+            UnicodeCategory.ParagraphSeparator
+        };
+        foreach (char c in GetTestChars(categories))
             Assert.True(char.IsWhiteSpace(c.ToString(), 0));

         // Some control chars are also considered whitespace for legacy reasons.
-        //if ((c >= '\x0009' && c <= '\x000d') || c == '\x0085')
-        Assert.True(char.IsWhiteSpace('\u000b'.ToString(), 0));
-        Assert.True(char.IsWhiteSpace('\u0085'.ToString(), 0));
-
-        foreach (var c in GetTestCharsNotInCategory(UnicodeCategory.SpaceSeparator,
-                UnicodeCategory.LineSeparator,
-                UnicodeCategory.ParagraphSeparator))
+        // if ((c >= '\x0009' && c <= '\x000d') || c == '\x0085')
+        Assert.True(char.IsWhiteSpace("\u000b", 0));
+        Assert.True(char.IsWhiteSpace("\u0085", 0));
+
+        foreach (char c in GetTestCharsNotInCategory(categories))
         {
             // Need to special case some control chars that are treated as whitespace
             if ((c >= '\x0009' && c <= '\x000d') || c == '\x0085') continue;
             Assert.False(char.IsWhiteSpace(c.ToString(), 0));
         }
-
-        Assert.Throws<ArgumentNullException>(() => char.IsWhiteSpace(null, 0));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsWhiteSpace("abc", -1));
-
-        Assert.Throws<ArgumentOutOfRangeException>(() => char.IsWhiteSpace("abc", 4));
+    }
+
+    [Fact]
+    public static void TestIsWhiteSpace_String_Int_Invalid()
+    {
+        Assert.Throws<ArgumentNullException>("s", () => char.IsWhiteSpace(null, 0)); // String is null
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsWhiteSpace("abc", -1)); // Index < 0
+        Assert.Throws<ArgumentOutOfRangeException>("index", () => char.IsWhiteSpace("abc", 3)); // Index >= string.Length
     }

     [Fact]
     public static void TestMaxValue()
     {
-        // Char Char.MaxValue
         Assert.Equal(0xffff, char.MaxValue);
     }

     [Fact]
     public static void TestMinValue()
     {
-        // Char Char.MinValue
         Assert.Equal(0, char.MinValue);
     }

     [Fact]
     public static void TestToLower()
     {
-        // Char Char.ToLower(Char)
         Assert.Equal('a', char.ToLower('A'));
         Assert.Equal('a', char.ToLower('a'));

@@ -809,15 +800,13 @@
         // LetterNumber can have a lower case form (e.g. \u2162 'III' letter which will be 'iii')
         foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter, UnicodeCategory.TitlecaseLetter, UnicodeCategory.LetterNumber))
         {
-            char lc = char.ToLower(c);
-            Assert.Equal(c, lc);
+            Assert.Equal(c, char.ToLower(c));
         }
     }

     [Fact]
     public static void TestToLowerInvariant()
     {
-        // Char Char.ToLowerInvariant(Char)
         Assert.Equal('a', char.ToLowerInvariant('A'));
         Assert.Equal('a', char.ToLowerInvariant('a'));

@@ -832,31 +821,22 @@
         // LetterNumber can have a lower case form (e.g. \u2162 'III' letter which will be 'iii')
         foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.UppercaseLetter, UnicodeCategory.TitlecaseLetter, UnicodeCategory.LetterNumber))
         {
-            char lc = char.ToLowerInvariant(c);
-            Assert.Equal(c, lc);
-        }
-    }
-
-    [Fact]
-    public static void TestToString()
-    {
-        // String Char.ToString()
-        Assert.Equal(new string('a', 1), 'a'.ToString());
-        Assert.Equal(new string('\uabcd', 1), '\uabcd'.ToString());
-    }
-
-    [Fact]
-    public static void TestToStringChar()
-    {
-        // String Char.ToString(Char)
-        Assert.Equal(new string('a', 1), char.ToString('a'));
-        Assert.Equal(new string('\uabcd', 1), char.ToString('\uabcd'));
+            Assert.Equal(c, char.ToLowerInvariant(c));
+        }
+    }
+
+    [Theory]
+    [InlineData('a', "a")]
+    [InlineData('\uabcd', "\uabcd")]
+    public static void TestToString(char c, string expected)
+    {
+        Assert.Equal(expected, c.ToString());
+        Assert.Equal(expected, char.ToString(c));
     }

     [Fact]
     public static void TestToUpper()
     {
-        // Char Char.ToUpper(Char)
         Assert.Equal('A', char.ToUpper('A'));
         Assert.Equal('A', char.ToUpper('a'));

@@ -871,15 +851,13 @@
         // LetterNumber can have a uppercase form (e.g. \u2172 'iii' letter which will be 'III')
         foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.LowercaseLetter, UnicodeCategory.TitlecaseLetter, UnicodeCategory.LetterNumber))
         {
-            char lc = char.ToUpper(c);
-            Assert.Equal(c, lc);
+            Assert.Equal(c, char.ToUpper(c));
         }
     }

     [Fact]
     public static void TestToUpperInvariant()
     {
-        // Char Char.ToUpperInvariant(Char)
         Assert.Equal('A', char.ToUpperInvariant('A'));
         Assert.Equal('A', char.ToUpperInvariant('a'));

@@ -894,44 +872,54 @@
         // LetterNumber can have a uppercase form (e.g. \u2172 'iii' letter which will be 'III')
         foreach (char c in GetTestCharsNotInCategory(UnicodeCategory.LowercaseLetter, UnicodeCategory.TitlecaseLetter, UnicodeCategory.LetterNumber))
         {
-            char lc = char.ToUpperInvariant(c);
-            Assert.Equal(c, lc);
-        }
-    }
-
-    private static void ValidateTryParse(string s, char expected, bool shouldSucceed)
-    {
-        char result;
-        Assert.Equal(shouldSucceed, char.TryParse(s, out result));
-        if (shouldSucceed)
-            Assert.Equal(expected, result);
-    }
-
-    [Fact]
-    public static void TestTryParse()
-    {
-        // Boolean Char.TryParse(String, Char)
-        ValidateTryParse("a", 'a', true);
-        ValidateTryParse("4", '4', true);
-        ValidateTryParse(" ", ' ', true);
-        ValidateTryParse("\n", '\n', true);
-        ValidateTryParse("\0", '\0', true);
-        ValidateTryParse("\u0135", '\u0135', true);
-        ValidateTryParse("\u05d9", '\u05d9', true);
-        ValidateTryParse("\ud801", '\ud801', true);  // high surrogate
-        ValidateTryParse("\udc01", '\udc01', true);  // low surrogate
-        ValidateTryParse("\ue001", '\ue001', true);  // private use codepoint
-
-        // Fail cases
-        ValidateTryParse(null, '\0', false);
-        ValidateTryParse("", '\0', false);
-        ValidateTryParse("\n\r", '\0', false);
-        ValidateTryParse("kj", '\0', false);
-        ValidateTryParse(" a", '\0', false);
-        ValidateTryParse("a ", '\0', false);
-        ValidateTryParse("\\u0135", '\0', false);
-        ValidateTryParse("\u01356", '\0', false);
-        ValidateTryParse("\ud801\udc01", '\0', false);   // surrogate pair
+            Assert.Equal(c, char.ToUpperInvariant(c));
+        }
+    }
+
+
+    [Theory]
+    [InlineData("a", 'a')]
+    [InlineData("4", '4')]
+    [InlineData(" ", ' ')]
+    [InlineData("\n", '\n')]
+    [InlineData("\0", '\0')]
+    [InlineData("\u0135", '\u0135')]
+    [InlineData("\u05d9", '\u05d9')]
+    [InlineData("\ue001", '\ue001')] // Private use codepoint
+    public static void TestParse(string s, char expected)
+    {
+        char c;
+        Assert.True(char.TryParse(s, out c));
+        Assert.Equal(expected, c);
+
+        Assert.Equal(expected, char.Parse(s));
+    }
+
+    [Fact]
+    public static void TestParse_Surrogate()
+    {
+        // TODO: add this as [InlineData] when #7166 is fixed
+        TestParse("\ud801", '\ud801'); // High surrogate
+        TestParse("\udc01", '\udc01'); // Low surrogate
+    }
+
+    [Theory]
+    [InlineData(null, typeof(ArgumentNullException))]
+    [InlineData("", typeof(FormatException))]
+    [InlineData("\n\r", typeof(FormatException))]
+    [InlineData("kj", typeof(FormatException))]
+    [InlineData(" a", typeof(FormatException))]
+    [InlineData("a ", typeof(FormatException))]
+    [InlineData("\\u0135", typeof(FormatException))]
+    [InlineData("\u01356", typeof(FormatException))]
+    [InlineData("\ud801\udc01", typeof(FormatException))] // Surrogate pair
+    public static void TestParse_Invalid(string s, Type exceptionType)
+    {
+        char c;
+        Assert.False(char.TryParse(s, out c));
+        Assert.Equal(default(char), c);
+
+        Assert.Throws(exceptionType, () => char.Parse(s));
     }

     private static IEnumerable<char> GetTestCharsNotInCategory(params UnicodeCategory[] categories)
@@ -967,7 +955,8 @@
         }
     }

-    private static char[][] s_latinTestSet = new char[][] {
+    private static char[][] s_latinTestSet = new char[][]
+    {
         new char[] {'\u0047','\u004c','\u0051','\u0056','\u00c0','\u00c5','\u00ca','\u00cf','\u00d4','\u00da'}, // UnicodeCategory.UppercaseLetter
         new char[] {'\u0062','\u0068','\u006e','\u0074','\u007a','\u00e1','\u00e7','\u00ed','\u00f3','\u00fa'}, // UnicodeCategory.LowercaseLetter
         new char[] {}, // UnicodeCategory.TitlecaseLetter
@@ -1000,7 +989,8 @@
         new char[] {}, // UnicodeCategory.OtherNotAssigned
     };

-    private static char[][] s_unicodeTestSet = new char[][] {
+    private static char[][] s_unicodeTestSet = new char[][]
+    {
         new char[] {'\u0102','\u01ac','\u0392','\u0428','\u0508','\u10c4','\u1eb4','\u1fba','\u2c28','\ua668'}, // UnicodeCategory.UppercaseLetter
         new char[] { '\u0107', '\u012D', '\u0140', '\u0151', '\u013A', '\u01A1', '\u01F9', '\u022D', '\u1E09','\uFF45' }, // UnicodeCategory.LowercaseLetter
         new char[] {'\u01c8','\u1f88','\u1f8b','\u1f8e','\u1f99','\u1f9c','\u1f9f','\u1faa','\u1fad','\u1fbc'}, // UnicodeCategory.TitlecaseLetter
@@ -1033,7 +1023,7 @@
         new char[] {'\u09c6','\u0dfa','\u2e5c','\ua9f9','\uabbd'}, // UnicodeCategory.OtherNotAssigned
     };

-    private static char[] s_highSurrogates = new char[] { '\ud800', '\udaaa', '\udbff' }; // range from '\ud800' to '\udbff'
-    private static char[] s_lowSurrogates = new char[] { '\udc00', '\udeee', '\udfff' }; // range from '\udc00' to '\udfff'
+    private static char[] s_highSurrogates = new char[] { '\ud800', '\udaaa', '\udbff' }; // Range from '\ud800' to '\udbff'
+    private static char[] s_lowSurrogates = new char[] { '\udc00', '\udeee', '\udfff' }; // Range from '\udc00' to '\udfff'
     private static char[] s_nonSurrogates = new char[] { '\u0000', '\ud7ff', '\ue000', '\uffff' };
 }


Refactor TinyMessageBus and introduce a LogBook class to simplify things

The log book keeps track of the next available message ID which
simplifies some of the code.

--- src/TinyIpc/Messaging/TinyMessageBus.cs
+++ src/TinyIpc/Messaging/TinyMessageBus.cs
@@ -13,10 +13,11 @@
 {
 	public class TinyMessageBus : IDisposable, ITinyMessageBus
 	{
+		private static long messageOverhead;
+
 		private bool disposed;
-		private long messageOverhead;
 		private readonly Guid instanceId = Guid.NewGuid();
-		private readonly ConcurrentQueue<Entry> publishQueue = new ConcurrentQueue<Entry>();
+		private readonly ConcurrentQueue<LogEntry> publishQueue = new ConcurrentQueue<LogEntry>();
 		private readonly TimeSpan minMessageAge;
 		private readonly object messageReaderLock = new object();
 		private readonly object messagePublisherLock = new object();
@@ -25,7 +26,7 @@
 		private readonly ITinyMemoryMappedFile memoryMappedFile;
 		private readonly bool disposeFile;

-		private long lastEntryId;
+		private long lastEntryId = -1;
 		private long messagesSent;
 		private long messagesReceived;
 		private Task[] publishTasks = new Task[0];
@@ -44,6 +45,16 @@

 		public static readonly TimeSpan DefaultMinMessageAge = TimeSpan.FromMilliseconds(500);

+		static TinyMessageBus()
+		{
+			Serializer.PrepareSerializer<LogBook>();
+			using (var memoryStream = new MemoryStream())
+			{
+				Serializer.Serialize(memoryStream, new LogEntry { Id = long.MaxValue, Instance = Guid.Empty, Timestamp = DateTime.UtcNow });
+				messageOverhead = memoryStream.Length;
+			}
+		}
+
 		public TinyMessageBus(string name)
 			: this(new TinyMemoryMappedFile(name), true)
 		{
@@ -89,20 +100,13 @@
 		/// </summary>
 		private void Warmup()
 		{
-			Serializer.PrepareSerializer<Entry>();
-			using (var memoryStream = new MemoryStream())
-			{
-				Serializer.Serialize(memoryStream, new Entry { Id = long.MaxValue, Instance = instanceId, Timestamp = DateTime.UtcNow });
-				messageOverhead = memoryStream.Length;
-			}
-
-			var lastEntry = DeserializeLog(memoryMappedFile.Read()).LastOrDefault();
+			var lastEntry = DeserializeLogBook(memoryMappedFile.Read()).Entries.LastOrDefault();
 			if (lastEntry != null)
 			{
 				lastEntryId = lastEntry.Id;
 			}

-			publishQueue.Enqueue(new Entry { Instance = instanceId, Message = new byte[0] });
+			publishQueue.Enqueue(new LogEntry { Instance = instanceId, Message = new byte[0] });
 			ProcessPublishQueue();
 		}

@@ -127,7 +131,7 @@
 			if (message == null || message.Length == 0)
 				throw new ArgumentException("Message can not be empty", nameof(message));

-			publishQueue.Enqueue(new Entry { Instance = instanceId, Message = message });
+			publishQueue.Enqueue(new LogEntry { Instance = instanceId, Message = message });

 			if (waitingPublishers > 0)
 				return;
@@ -178,58 +182,52 @@
 				if (publishQueue.Count == 0)
 					return;

-				memoryMappedFile.ReadWrite(
-					data =>
-					{
-						// Retreive the log but skip messages older than minimum message age
-						var cutoffPoint = DateTime.UtcNow - minMessageAge;
-						var log = DeserializeLog(data).SkipWhile(entry => entry.Timestamp < cutoffPoint).ToList();
-						var logSize = log.Select(l => messageOverhead + l.Message.Length).Sum();
-						var lastEntry = log.LastOrDefault();
-						var nextId = Math.Max(lastEntryId, lastEntry?.Id ?? 0) + 1;
-
-						// Start slot timer after deserializing log so deserialization doesn't starve the slot time
-						var slotTimer = Stopwatch.StartNew();
-						var batchTime = DateTime.UtcNow;
-
-						// Try to exhaust the publish queue but don't keep a write lock forever
-						while (publishQueue.Count > 0 && slotTimer.ElapsedMilliseconds < 25)
-						{
-							Entry entry;
-
-							// Check if the next message will fit in the log
-							if (!publishQueue.TryPeek(out entry) || logSize + messageOverhead + entry.Message.Length > memoryMappedFile.MaxFileSize)
-								break;
-
-							if (!publishQueue.TryDequeue(out entry))
-								break;
-
-							// Write the entry to the log even if the message is empty. Never leave the log empty.
-							entry.Id = nextId++;
-							entry.Timestamp = batchTime;
-							log.Add(entry);
-							logSize += messageOverhead + entry.Message.Length;
-
-							// Skip counting empty messages though, they are skipped on the receiving end anyway
-							if (entry.Message == null || entry.Message.Length == 0)
-								continue;
-
-							Interlocked.Increment(ref messagesSent);
-						}
-
-						// Start a new publish task if there are messages left in the queue
-						if (waitingPublishers == 0 && publishQueue.Count > 0)
-						{
-							StartPublishTask();
-						}
-
-						// Flush the updated log to the memory mapped file
-						using (var memoryStream = new MemoryStream((int)logSize))
-						{
-							Serializer.Serialize(memoryStream, log);
-							return memoryStream.ToArray();
-						}
-					});
+				while (waitingPublishers == 0 && publishQueue.Count > 0)
+				{
+					memoryMappedFile.ReadWrite(data => PublishMessages(data, TimeSpan.FromMilliseconds(100)));
+				}
+			}
+		}
+
+		private byte[] PublishMessages(byte[] data, TimeSpan timeout)
+		{
+			var logBook = DeserializeLogBook(data);
+			logBook.TrimStaleEntries(DateTime.UtcNow - minMessageAge);
+			var logSize = logBook.CalculateLogSize();
+
+			// Start slot timer after deserializing log so deserialization doesn't starve the slot time
+			var slotTimer = Stopwatch.StartNew();
+			var batchTime = DateTime.UtcNow;
+
+			// Try to exhaust the publish queue but don't keep a write lock forever
+			while (publishQueue.Count > 0 && slotTimer.Elapsed < timeout)
+			{
+				// Check if the next message will fit in the log
+				if (!publishQueue.TryPeek(out LogEntry entry) || logSize + messageOverhead + entry.Message.Length > memoryMappedFile.MaxFileSize)
+					break;
+
+				if (!publishQueue.TryDequeue(out entry))
+					break;
+
+				// Write the entry to the log
+				entry.Id = logBook.NextId++;
+				entry.Timestamp = batchTime;
+				logBook.Entries.Add(entry);
+
+				logSize += messageOverhead + entry.Message.Length;
+
+				// Skip counting empty messages though, they are skipped on the receiving end anyway
+				if (entry.Message == null || entry.Message.Length == 0)
+					continue;
+
+				Interlocked.Increment(ref messagesSent);
+			}
+
+			// Flush the updated log to the memory mapped file
+			using (var memoryStream = new MemoryStream((int)logSize))
+			{
+				Serializer.Serialize(memoryStream, logBook);
+				return memoryStream.ToArray();
 			}
 		}

@@ -249,10 +247,13 @@
 			{
 				Interlocked.Decrement(ref waitingReaders);

-				var data = memoryMappedFile.Read();
-
-				foreach (var entry in DeserializeLog(data).SkipWhile(entry => entry.Id <= lastEntryId))
+				var logBook = DeserializeLogBook(memoryMappedFile.Read());
+
+				foreach (var entry in logBook.Entries)
 				{
+					if (entry.Id <= lastEntryId)
+						continue;
+
 					lastEntryId = entry.Id;

 					if (entry.Instance == instanceId || entry.Message == null || entry.Message.Length == 0)
@@ -265,19 +266,39 @@
 			}
 		}

-		private static IEnumerable<Entry> DeserializeLog(byte[] data)
+		private static LogBook DeserializeLogBook(byte[] data)
 		{
 			if (data.Length == 0)
-				return Enumerable.Empty<Entry>();
+				return new LogBook();

 			using (var memoryStream = new MemoryStream(data))
 			{
-				return Serializer.Deserialize<List<Entry>>(memoryStream);
+				return Serializer.Deserialize<LogBook>(memoryStream);
 			}
 		}

 		[ProtoContract]
-		private class Entry
+		private class LogBook
+		{
+			[ProtoMember(1)]
+			public long NextId { get; set; }
+
+			[ProtoMember(2)]
+			public List<LogEntry> Entries { get; set; } = new List<LogEntry>();
+
+			public long CalculateLogSize()
+			{
+				return sizeof(long) + Entries.Select(l => messageOverhead + l.Message.Length).Sum();
+			}
+
+			public void TrimStaleEntries(DateTime cutoffPoint)
+			{
+				Entries = Entries.SkipWhile(entry => entry.Timestamp < cutoffPoint).ToList();
+			}
+		}
+
+		[ProtoContract]
+		private class LogEntry
 		{
 			[ProtoMember(1)]
 			public long Id { get; set; }


fixed uafa cl match creation

fixed uafa cl match creation

--- CLSim/Football/Base/FootballLeague.cs
+++ CLSim/Football/Base/FootballLeague.cs
@@ -160,26 +160,26 @@
             else if(MatchMode == EMatchMode.UafaCl)
             {
                 // Based on https://simocracy.de/Vorlage:5er-Gruppe
+                Matches.Add(new FootballMatch(Teams[0], Teams[1]));
+                Matches.Add(new FootballMatch(Teams[2], Teams[3]));
                 Matches.Add(new FootballMatch(Teams[1], Teams[2]));
                 Matches.Add(new FootballMatch(Teams[3], Teams[4]));
-                Matches.Add(new FootballMatch(Teams[2], Teams[3]));
-                Matches.Add(new FootballMatch(Teams[4], Teams[5]));
-                Matches.Add(new FootballMatch(Teams[5], Teams[1]));
+                Matches.Add(new FootballMatch(Teams[4], Teams[0]));
+                Matches.Add(new FootballMatch(Teams[3], Teams[1]));
+                Matches.Add(new FootballMatch(Teams[2], Teams[0]));
+                Matches.Add(new FootballMatch(Teams[1], Teams[4]));
+                Matches.Add(new FootballMatch(Teams[0], Teams[3]));
                 Matches.Add(new FootballMatch(Teams[4], Teams[2]));
-                Matches.Add(new FootballMatch(Teams[3], Teams[1]));
-                Matches.Add(new FootballMatch(Teams[2], Teams[5]));
-                Matches.Add(new FootballMatch(Teams[1], Teams[4]));
-                Matches.Add(new FootballMatch(Teams[5], Teams[3]));
+                Matches.Add(new FootballMatch(Teams[1], Teams[0]));
+                Matches.Add(new FootballMatch(Teams[3], Teams[2]));
                 Matches.Add(new FootballMatch(Teams[2], Teams[1]));
                 Matches.Add(new FootballMatch(Teams[4], Teams[3]));
-                Matches.Add(new FootballMatch(Teams[3], Teams[2]));
-                Matches.Add(new FootballMatch(Teams[5], Teams[4]));
-                Matches.Add(new FootballMatch(Teams[1], Teams[5]));
+                Matches.Add(new FootballMatch(Teams[0], Teams[4]));
+                Matches.Add(new FootballMatch(Teams[1], Teams[3]));
+                Matches.Add(new FootballMatch(Teams[0], Teams[2]));
+                Matches.Add(new FootballMatch(Teams[4], Teams[1]));
+                Matches.Add(new FootballMatch(Teams[3], Teams[0]));
                 Matches.Add(new FootballMatch(Teams[2], Teams[4]));
-                Matches.Add(new FootballMatch(Teams[1], Teams[3]));
-                Matches.Add(new FootballMatch(Teams[5], Teams[2]));
-                Matches.Add(new FootballMatch(Teams[4], Teams[1]));
-                Matches.Add(new FootballMatch(Teams[3], Teams[5]));
             }

             SimpleLog.Info($"Matches Created in Football League ID={ID} with MatchMode={MatchMode}");


fix track description struct name encoding issue

--- src/Vlc.DotNet.Core/TrackDescription.cs
+++ src/Vlc.DotNet.Core/TrackDescription.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
+using System.Text;
 using Vlc.DotNet.Core.Interops.Signatures;

 namespace Vlc.DotNet.Core
@@ -22,7 +23,8 @@
             if (moduleRef != IntPtr.Zero)
             {
                 var module = (TrackDescriptionStructure)Marshal.PtrToStructure(moduleRef, typeof(TrackDescriptionStructure));
-                result.Add(new TrackDescription(module.Id, module.Name));
+                var name = Encoding.UTF8.GetString(Encoding.Default.GetBytes(module.Name));
+                result.Add(new TrackDescription(module.Id, name));
                 var data = GetSubTrackDescription(module.NextTrackDescription);
                 result.AddRange(data);
             }