Testing test assembly

I recently discovered that almost 50 unit tests don’t run for Mail.dll email library test suite.

Mail.dll uses NUnit as its unit testing framework, and with over 3000 tests it’s hard to spot that some are missing. The problem was that most (of those 50 that didn’t run) test methods where missing TestAttribute and 2 test classes were missing TestFixtureAttribute.

I decided that it’s time to create 2 unit tests that guard my unit test assembly.

First one checks if all public methods, in classes marked with TestFixtureAttribute, have TestAttribute applied.

Of curse we are using reflection for that.

It would be nice if we could just double click on the trace output and be taken, by VisualStudio, to the source file. Unfortunately it’s not possible, with standard .NET reflection, to get source code file name and line. I decided against using Mono.Cecil for that, especially that with R# it’s easy enough to navigate to method name.

[Test]
public void Methods_InTestFixtureTypes_HaveTestAttribute()
{
    int count = 0;
    foreach (Type type in this.GetType().Assembly.GetTypes())
    {
        if (Attribute.IsDefined(type, typeof(TestFixtureAttribute)))
        {
            foreach (MethodInfo method in type.GetMethods())
            {
                if (method.IsPublic
                    && method.IsSpecialName == false
                    && method.DeclaringType == type
                    && !Attribute.IsDefined(method, typeof(TearDownAttribute))
                    && !Attribute.IsDefined(method, typeof(SetUpAttribute))
                    && !Attribute.IsDefined(method, typeof(TestAttribute))
                    )
                {
                    Trace.WriteLine(type.FullName + "." + method.Name);
                    count++;
                }
            }
        }
    }
    Assert.AreEqual(0, count);
}

Second test checks if all public classes, that have at least one method marked with TestAttribute, have TestFixtureAttribute applied.

[Test]
public void Types_WithTestMethods_HaveTestFixtureAttribute()
{
    int count = 0;
    foreach (Type type in this.GetType().Assembly.GetTypes())
    {
        bool hasAtLeastOneTestMethod = new List<MethodInfo>(type.GetMethods()).Find(
            method => Attribute.IsDefined(method, typeof(TestAttribute))) != null;

        if (hasAtLeastOneTestMethod
            && Attribute.IsDefined(type, typeof(TestFixtureAttribute)) == false)
        {
            Trace.WriteLine(type.FullName);
            count++;
        }
    }
    Assert.AreEqual(0, count);
}

Some of you might argue that we shouldn’t be using Trace class inside the unit test. StringBuilder, WriteLine and
Assert.AreEqual(object expected, object actual, string message) are your friends in such case.

Send encrypted email using S/MIME (AES‑256)

In many cases it is required to use better that standard encryption algorithms. With Mail.dll it is easy to specify algorithm that is used for encryption. In this article we’ll show how to send S/MIME encrypted and signed email using Mail.dll email component and AES-256 and SHA-512.

If you don’t need to specify encryption algorithm you can lean on default values: send encrypted email using S/MIME.

Encryption algorithm selection is done through Algorithm property of the EncryptionConfiguration class. You can use CommonOids class static properties to retrieve common oids (object identifiers): TrippleDes (3-DES), Aes128, Aes256.

Encryption using MailBuilder

EncryptionConfiguration encryption = new EncryptionConfiguration();
encryption.Algorithm = new Oid(CommonOids.Aes256);
encryption.Certificates.Add(new X509Certificate2(...));
encryption.Certificates.Add(new X509Certificate2(...));

SignatureConfiguration signature = new SignatureConfiguration(
    new X509Certificate2(...));
signature.Algorithm = new Oid(CommonOids.Sha512);

MailBuilder builder = new MailBuilder();
builder.Text = "Encrypted and signed";
builder.EncryptWith(encryption);
builder.SignWith(signature);

IMail mail = builder.Create();

Encryption using fluent interface

EncryptionConfiguration encryption = new EncryptionConfiguration();
encryption.Algorithm = new Oid(CommonOids.Aes256);
encryption.Certificates.Add(new X509Certificate2(...));
encryption.Certificates.Add(new X509Certificate2(...));

SignatureConfiguration signature = new SignatureConfiguration(
    new X509Certificate2(...));
signature.Algorithm = new Oid(CommonOids.Sha512);

IMail mail = Mail.Text("Encrypted")
    .EncryptWith(encryption)
    .SignWith(signature)
    .Create();

Remember to encrypt your emails with both sender’s and receiver’s certificates. This way both parties are able to decrypt such emails.

Sending email using SMTP

Now we can connect to SMTP server and send the email we recently created:

using (Smtp client = new Smtp())
{
    client.Connect("smtp.example.com"); // or ConnectSSL
    client.UseBestLogin("user", "password");
    client.SendMessage(email);
    client.Close();
}

Send signed email using S/MIME (SHA‑512)

In many cases it is required to use better that standard signing algorithms. With Mail.dll it is easy to specify algorithm that is used for signing. In this article we’ll show how to send S/MIME signed email using Mail.dll email component and specific signature algorithm (SHA-512).

If you don’t need to specify signature algorithm you can lean on default values: send signed email using S/MIME.

Signature algorithm selection is done through Algorithm property of the SignatureConfiguration class. You can use CommonOids class static properties to retrieve common oids (object identifiers): Sha1, Sha256, Sha512.

Signing using fluent interface

IMail mail = Mail.Text("text")
    .From("email@in-the-certificate.com")
    .SignWith(new SignatureConfiguration(new X509Certificate2(...)) 
        { 
            Algorithm = CommonOids.Sha512
        })
    .Create();

Signing using MailBuilder

MailBuilder builder = new MailBuilder();
builder.Text = "text";
builder.From.Add(new MailBox("email@in-the-certificate.com"));
builder.SignWith(new SignatureConfiguration(certificate) 
    { 
        Algorithm = CommonOids.Sha512
    });
IMail mail = builder.Create();

Sending email using SMTP

Now we can connect to SMTP server and send the email we recently created:

using (Smtp client = new Smtp())
{
    client.Connect("smtp.example.com"); // or ConnectSSL
    client.UseBestLogin("user", "password");
    client.SendMessage(email);
    client.Close();
}

NavigateToTest VS2012 extension

You can download the extension here:
NavigateToTest Visual Studio 2012 extension

Here’s the latest version that supports Visual Studio 2012.

Extension is convention based. It matches ClassName file with ClassNameTest or ClassNameTests and vice-versa, so you can easily navigate to the test file and back.

Here are some screenshots:

Here’s the toolbar and two opened files:

You can download the extension here:
NavigateToTest Visual Studio 2012 extension

FTP file and folder permissions

You can access remote file or folder permissions using Limilabs .NET FTP library. First you should learn how to connect and download files from FTP server.

It is important to realize that originally FTP protocol didn’t have the concept of file/folder permissions build-in directly.

LIST command, that allowed listing contents of the remote server, was build around system listing commands: ls on UNIX/LINUX machines, dir on Windows.
ls returns file permissions divided into 3 groups: Owning user, owning group and others e.g.: rwxr–rw-.

When using Ftp.dll Ftp.List and Ftp.GetList methods with UNIX FTP server (or a server that imitates ls output for LIST command) you can access these UNIX permissions using UnixPermissions property on FtpItem object:

// C#

List<FtpItem> items = client.List();
UnixPermissionSet set = items[0].UnixPermissions;

bool ownerCanRead = (set.OwnerUser | UnixPermission.Read) != 0;
bool groupCanRead = (set.OwnerGroup | UnixPermission.Read) != 0;
bool othersCanRead = (set.Others | UnixPermission.Read) != 0;

bool ownerCanWrite = (set.OwnerUser | UnixPermission.Write) != 0;

' VB.NET

Dim items As List(Of FtpItem) = client.List()
Dim [set] As UnixPermissionSet = items(0).UnixPermissions

Dim ownerCanRead As Boolean = ([set].OwnerUser Or UnixPermission.Read) <> 0
Dim groupCanRead As Boolean = ([set].OwnerGroup Or UnixPermission.Read) <> 0
Dim othersCanRead As Boolean = ([set].Others Or UnixPermission.Read) <> 0

Dim ownerCanWrite As Boolean = ([set].OwnerUser Or UnixPermission.Write) <> 0

MLSD and perm fact

As FTP protocol evolved, MLSD command was introduced with RFC 3659.

MLSD standardized the way listings are returned from the server. It introduced facts concept, and in particular perm fact.
Ftp.GetList method uses MLSD command if it is available, that is if MLST extension is supported and advertised by the remote server. It is possible to force this command to be used by calling Ftp.MLSD method directly.

You can access parsed version of perm fact using FtpItem.Permission property:

// C#

List<FtpItem> items = client.GetList();
List<FtpPermission> permissions = items[0].Permissions;

bool canRead = permissions.Contains(FtpPermission.Read);
bool canWrite = permissions.Contains(FtpPermission.Write);
bool canCreateFile = permissions.Contains(FtpPermission.CreateFile);
bool canChangeFolder = permissions.Contains(FtpPermission.ChangeFolder);

' VB.NET

Dim items As List(Of FtpItem) = client.GetList()
Dim permissions As List(Of FtpPermission) = items(0).Permissions

Dim canRead As Boolean = permissions.Contains(FtpPermission.Read)
Dim canWrite As Boolean = permissions.Contains(FtpPermission.Write)
Dim canCreateFile As Boolean = permissions.Contains(FtpPermission.CreateFile)
Dim canChangeFolder As Boolean = permissions.Contains(FtpPermission.ChangeFolder)

As you can see Ftp permissions can contain additional information such as if you can select particular folder or create a file within.

Changing the permissions

There is no standardized way of changing the permissions. You’ll need SITE command (this command is used by the server to provide services specific to his system but not sufficiently universal to be included as commands in protocol) and CHMOD (again UNIX command).

Limilabs .NET FTP library contains useful shortcut for that – SiteChangeMode method:

// C#

client.SiteChangeMode("file.txt", new UnixPermissionSet(UnixPermission.Write));
' VB.NET

client.SiteChangeMode("file.txt", New UnixPermissionSet(UnixPermission.Write))

Note that the same UnixPermissionSet class can is used that is returned by FtpItem.UnixPermissions property