Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I simulate an environment where BitConverter.IsLittleEndian is the opposite for my unit tests?

I am using the two methods BitConverter.GetBytes and Array.Reverse to read and write binary data from a file due the endianness.

My unit tests are passing and the implementation seems fine.

How can I simulate an environment where BitConverter.IsLittleEndian is the opposite for my unit tests?

like image 712
Lea Hayes Avatar asked May 11 '15 10:05

Lea Hayes


1 Answers

To expand my comment: you'll need to use IoC (Inversion of Control) to inject a BitConverterEx instance where you need it. This class has a single "parameter": the endianness of the output byte[] that it will read/write.

In the end this problem is similar to the common problem "how can I mock DateTime.Now"

In the unit tests, instead of injecting a BitConverterEx you can inject the ManipulableBitConverterEx where you can control the processor flag. Or more correctly you should unit test independently the BitConverterEx and your classes, so that when you test your classes, you know that the results of BitConverterEx are correct.

public class BitConverterEx
{
    public bool ProcessorLittleEndian { get; protected set; }
    public bool DataLittleEndian { get; protected set; }

    public BitConverterEx(bool dataLittleEndian)
    {
        ProcessorLittleEndian = BitConverter.IsLittleEndian;
        DataLittleEndian = dataLittleEndian;
    }

    public byte[] GetBytes(int value)
    {
        byte[] bytes = BitConverter.GetBytes(value);

        if (DataLittleEndian != ProcessorLittleEndian)
        {
            Array.Reverse(bytes);
        }

        return bytes;
    }

    public int ToInt32(byte[] value, int startIndex)
    {
        if (DataLittleEndian == ProcessorLittleEndian)
        {
            return BitConverter.ToInt32(value, startIndex);
        }

        byte[] value2 = new byte[sizeof(int)];
        Array.Copy(value, startIndex, value2, 0, value2.Length);
        Array.Reverse(value2);
        return BitConverter.ToInt32(value2, 0);
    }
}

public class ManipulableBitConverterEx : BitConverterEx
{
    public ManipulableBitConverterEx(bool processorLittleEndian, bool dataLittleEndian)
        : base(dataLittleEndian)
    {
        ProcessorLittleEndian = processorLittleEndian;
    }
}

Note that if you need to reuse many times this class, Array.Reverse could be "slow". There are solutions to invert the endianness of data types that manipulate the single bytes using shift, or, xor, ...

like image 51
xanatos Avatar answered Oct 05 '22 12:10

xanatos