Friday, May 27, 2016

Word Boundaries Regex

\b

This is the second time this week where I have had to ask myself "how did I not know about this?"

There is a regex character to identify word boundaries: \b This is a zero length match, similar to the caret and dollar sign. It finds the boundaries between words, allowing you to search for a whole word match.

Below is a sample extension method that uses this to replace words in a string.

Implementation

public static class StringExtensions
{
    private static readonly Regex WordRegex = new Regex(@"\b\w+\b", RegexOptions.Compiled);
 
    public static string ReplaceWords(
        this string input,
        string find,
        string replace,
        StringComparison comparison = StringComparison.InvariantCulture)
    {
        return WordRegex.Replace(input, m => m.Value.Equals(find, comparison)
            ? replace
            : m.Value);
    }
}

Sunday, May 22, 2016

Common Logging Extensions with Caller Information

Update: Added the BreakParameter.

I have made it an (arguably bad) habit of manually adding the class and method name as a prefix to all my log lines. It is not that I enjoy typing out the same strings over and over, it's that I do not always trust things like the NLog callsite. Using the stack frame to identify a calling method always requires a bit of cleverness on the part of the author, as you never can be totally sure when you are dealing with a wrapper class or an async call stack.

I was recently introduced to the Caller Information attributes in C# 5, and now I think I am in love.

Disclaimer: I have not used this very much yet, but I intend to start! I think that these attributes are absolutely brilliant in their simplicity: a compiler trick to insert debug information directly into your code. That is freak'n sweet, and it's performant! I am not sure how this flew under my radar, but now that I know about it....

Below is a little T4 template that I wrote up to generate overloads for Common Logging that will include caller information. To customize this for your needs, just update the the GetFormat method at the bottom of the template.

Unit Tests

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using Common.Logging.Simple;
   4:  using Xunit;
   5:   
   6:  namespace Common.Logging.Tests
   7:  {
   8:      /// <summary>
   9:      /// Tests for Common Logging extensions that use Caller Information
  10:      /// https://msdn.microsoft.com/en-us/library/mt653988.aspx
  11:      /// </summary>
  12:      public class LogCallTests
  13:      {
  14:          [Fact]
  15:          public void LogFromMethod()
  16:          {
  17:              var log = new QueueSimpleLogger();
  18:              var ex = new Exception("Boom");
  19:   
  20:              log.Debug("Hello");
  21:              log.Debug("World", ex);
  22:   
  23:              log.DebugCall("Hello");
  24:              log.DebugCall("World", ex);
  25:   
  26:              log.WarnFormat("Hello - {0}", "Zero");
  27:              log.WarnFormat("World - {0}", ex, "Zero");
  28:   
  29:              log.WarnFormatCall("Hello - {0}", "Zero");
  30:              log.WarnFormatCall("World - {0}", ex, "Zero");
  31:   
  32:              Assert.Equal(8, log.Queue.Count);
  33:   
  34:              Assert.Equal("Hello", log.Queue.Dequeue());
  35:              Assert.Equal("World - Ex: Boom", log.Queue.Dequeue());
  36:   
  37:              Assert.Equal("LogCallTests.LogFromMethod(23) - Hello", log.Queue.Dequeue());
  38:              Assert.Equal("LogCallTests.LogFromMethod(24) - World - Ex: Boom", log.Queue.Dequeue());
  39:   
  40:              Assert.Equal("Hello - Zero", log.Queue.Dequeue());
  41:              Assert.Equal("World - Zero - Ex: Boom", log.Queue.Dequeue());
  42:   
  43:              Assert.Equal("LogCallTests.LogFromMethod(29) - Hello - Zero", log.Queue.Dequeue());
  44:              Assert.Equal("LogCallTests.LogFromMethod(30) - World - Zero - Ex: Boom", log.Queue.Dequeue());
  45:          }
  46:   
  47:          [Fact]
  48:          public void LogFromAction()
  49:          {
  50:              var log = new QueueSimpleLogger();
  51:              var ex = new Exception("Boom");
  52:              Action action = () =>
  53:              {
  54:                  log.Debug("Hello");
  55:                  log.Debug("World", ex);
  56:   
  57:                  log.DebugCall("Hello");
  58:                  log.DebugCall("World", ex);
  59:   
  60:                  log.WarnFormat("Hello - {0}", "Zero");
  61:                  log.WarnFormat("World - {0}", ex, "Zero");
  62:   
  63:                  log.WarnFormatCall("Hello - {0}", "Zero");
  64:                  log.WarnFormatCall("World - {0}", ex, "Zero");
  65:              };
  66:   
  67:              action();
  68:   
  69:              Assert.Equal(8, log.Queue.Count);
  70:   
  71:              Assert.Equal("Hello", log.Queue.Dequeue());
  72:              Assert.Equal("World - Ex: Boom", log.Queue.Dequeue());
  73:   
  74:              Assert.Equal("LogCallTests.LogFromAction(57) - Hello", log.Queue.Dequeue());
  75:              Assert.Equal("LogCallTests.LogFromAction(58) - World - Ex: Boom", log.Queue.Dequeue());
  76:   
  77:              Assert.Equal("Hello - Zero", log.Queue.Dequeue());
  78:              Assert.Equal("World - Zero - Ex: Boom", log.Queue.Dequeue());
  79:   
  80:              Assert.Equal("LogCallTests.LogFromAction(63) - Hello - Zero", log.Queue.Dequeue());
  81:              Assert.Equal("LogCallTests.LogFromAction(64) - World - Zero - Ex: Boom", log.Queue.Dequeue());
  82:          }
  83:   
  84:          private class QueueSimpleLogger : AbstractSimpleLogger
  85:          {
  86:              public readonly Queue<string> Queue = new Queue<string>(); 
  87:   
  88:              public QueueSimpleLogger()
  89:                  : base(string.Empty, LogLevel.All, true, true, true, string.Empty)
  90:              {
  91:              }
  92:   
  93:              protected override void WriteInternal(LogLevel level, object message, Exception exception)
  94:              {
  95:                  var s = message.ToString();
  96:                  if (exception != null) s += " - Ex: " + exception.Message;
  97:                  Queue.Enqueue(s);
  98:              }
  99:          }
 100:      }
 101:  }

Wednesday, May 4, 2016

IResourceLoader: Balancing Semaphores

Recently I need to get balance getting resources from a restricted number of sources. So, for example...

I am getting resource R, and I have factories A, B and C creating those Rs. Each of those factories has a very limited capacity for creating those resources, and can only create two Rs at a time. It is easy to put the factories behind a semaphore and limit how many threads can be requesting resources from each factory at a time.

The challenge is evenly balancing the workload between all three factories. Also, please note that you can't just round robin the semaphores because there is no way to ensure that each operation will complete in the same amount of time.

To do this I created a generic IResourceLoader interface, and made two implementations: one to wrap a semaphore, and the other to wrap and balance a collection of IResourceLoaders. Below is the implementation, complete with unit tests; let's take a look!

Interface

public interface IResourceLoader<T>
{
    int Available { get; }
    int Count { get; }
    int MaxConcurrency { get; }
 
    Task<T> GetAsync(CancellationToken cancelToken = default(CancellationToken));
    bool TryGet(out Task<T> resource, CancellationToken cancelToken = default(CancellationToken));
}

Sunday, April 24, 2016

How to Order xUnit Tests and Collections

xUnit is an extremely extensible unit testing framework!

If you need to control the order of your unit tests, then all you have to do is implement an ITestCaseOrderer. Once implemented, you just add a TestCaseOrdererAttribute to the top of your test class to use it. Below we use a custom OrderAttribute to order the tests.

To control the order of the test collections you can do a very similar trick by implementing an ITestCollectionOrderer. However, an ITestCollection is not neccessarily associated with a specific class, so to to use attributes to order them you need to use a little reflection. Check out the sample below for details.

Implementation

/// <summary>
/// Used by CustomOrderer
/// </summary>
public class OrderAttribute : Attribute
{
    public int I { get; }
 
    public OrderAttribute(int i)
    {
        I = i;
    }
}
 
/// <summary>
/// Custom xUnit test collection orderer that uses the OrderAttribute
/// </summary>
public class CustomTestCollectionOrderer : ITestCollectionOrderer
{
    public const string TypeName = "xUnitCustom.CustomTestCollectionOrderer";
 
    public const string AssembyName = "xUnitCustom";
 
    public IEnumerable<ITestCollection> OrderTestCollections(
        IEnumerable<ITestCollection> testCollections)
    {
        return testCollections.OrderBy(GetOrder);
    }
 
    /// <summary>
    /// Test collections are not bound to a specific class, however they
    /// are named by default with the type name as a suffix. We try to
    /// get the class name from the DisplayName and then use reflection to
    /// find the class and OrderAttribute.
    /// </summary>
    private static int GetOrder(
        ITestCollection testCollection)
    {
        var i = testCollection.DisplayName.LastIndexOf(' ');
        if (i <= -1)
            return 0;
 
        var className = testCollection.DisplayName.Substring(i + 1);
        var type = Type.GetType(className);
        if (type == null)
            return 0;
 
        var attr = type.GetCustomAttribute<OrderAttribute>();
        return attr?.I ?? 0;
    }
}

Sunday, April 10, 2016

RangeSet for .NET

Update 4/13 - Added support for single value ranges.

What data structure do you use when you need to efficiently check if a number is within a large set of ranges?

If you require that the ranges do not overlap, then it is simple to keep a balanced binary tree of the ranges. Finding if a number is within one of those ranges should only take O(log n) to find. Below is an implementation of a RangedSet that uses a standard .NET SortedSet to store the ranges.

IRangeSet Interface

public interface IRangeSet<in T> where T : IComparable
{
    void AddRange(T min, T max);
 
    bool Contains(T findValue);
}

Friday, April 1, 2016

Thursday, March 31, 2016

xUnit.net: Extensions Config v3.3.0

I recently made several updates to the xunit.extensions.config library, which allows you to configure theory data from your app.config file. Here are the links to the source and the NuGet package:

New Features

  • Named Parameter Support

You no longer need to configure your data by parameter index. You can now name your data for each parameter, making the configuration much easier to read and understand.

  • AppSettings Support

You can now use the standard AppSettings section of the App.config to configure your data. If no settings are found, then the framework will fallback to trying to use the standard config section.

  • Default Namespace Option

You can now provide a default namespace for your tests. This reduced the amount of redundant text in your config file, and makes test names much more concise and easy to read.

  • Extensible Data Provider

Don't want to use the existing data providers? Would you rather use a database? Now you can! Just add an AppSettings key for "TestData.ServiceFactory" that provides the fully qualified name of a static method that returns an IConfigTestDataService, and the framework will try to use that to load configuration data.

Real Time Web Analytics