You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

544 lines
14 KiB
C#

using System;
using System.Collections;
using FluentAssertions;
using NUnit.Framework;
namespace Unplugged.IbmBits.Tests
{
public class IbmConverterTest
{
#region ToString()
const byte _comma = 0x6B;
const byte _bang = 0x5A;
const byte _H = 0xC8;
const byte _e = 0x85;
const byte _l = 0x93;
const byte _o = 0x96;
[Test]
public void ShouldConvertFromEbcdicToUnicode()
{
// Arrange
var bytes = new byte[] { _H, _e, _l, _l, _o, _comma };
// Act
string result = IbmConverter.ToString(bytes);
// Assert
result.Should().Be("Hello,");
}
[Test]
public void ShouldConvertFromEbcdicToUnicode2()
{
// Arrange
var bytes = new byte[] { _l, _o, _l, _bang };
// Act
string result = IbmConverter.ToString(bytes);
// Assert
result.Should().Be("lol!");
}
[Test]
public void ShouldConvertToStringGivenStartingIndex()
{
// Arrange
var bytes = new byte[] { _bang, _bang, _H, _e };
var startingIndex = 2;
// Act
string result = IbmConverter.ToString(bytes, startingIndex);
// Assert
result.Should().Be("He");
}
[Test]
public void ShouldConvertToStringGivenStartingIndex2()
{
// Arrange
var bytes = new byte[] { _H, _e, _l, _l, _o };
var startingIndex = 1;
// Act
string result = IbmConverter.ToString(bytes, startingIndex);
// Assert
result.Should().Be("ello");
}
[Test]
public void ShouldConvertToStringGivenIndexAndLength()
{
// Arrange
var bytes = new byte[] { _H, _o, _H, _o, _H, _o, _l, _e, _bang };
var startingIndex = 4;
var length = 4;
// Act
string result = IbmConverter.ToString(bytes, startingIndex, length);
// Assert
result.Should().Be("Hole");
}
[Test]
public void ShouldConvertToStringGivenIndexAndLength2()
{
// Arrange
var bytes = new byte[] { _H, _o, _H, _o, _H, _o, _l, _e, _bang };
var startingIndex = 0;
var length = 6;
// Act
string result = IbmConverter.ToString(bytes, startingIndex, length);
// Assert
result.Should().Be("HoHoHo");
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToStringGivenBytes()
{
IbmConverter.ToString(null);
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToStringGivenBytesAndIndex()
{
IbmConverter.ToString(null, 1);
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToStringGivenBytesAndIndexAndLength()
{
IbmConverter.ToString(null, 1, 1);
}
#endregion
#region GetBytes from String
[Test]
public void ShouldConvertFromUnicodeToEbcdic()
{
// Arrange
var value = "Hello,";
// Act
byte[] result = IbmConverter.GetBytes(value);
// Assert
result.Should().Equal(new byte[] { _H, _e, _l, _l, _o, _comma });
}
[Test]
public void ShouldConvertFromStringGivenStartingIndex()
{
// Arrange
var value = "lol SHe!";
var startingIndex = 5;
// Act
byte[] result = IbmConverter.GetBytes(value, startingIndex);
// Assert
result.Should().Equal(new byte[] { _H, _e, _bang });
}
[Test]
public void ShouldConvertFromStringGivenStartingIndexAndLength()
{
// Arrange
var value = "Hole in the ground";
var startingIndex = 1;
var length = 3;
// Act
byte[] result = IbmConverter.GetBytes(value, startingIndex, length);
// Assert
result.Should().Equal(new byte[] { _o, _l, _e });
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForGetBytesFromString()
{
IbmConverter.GetBytes(null, 1, 1);
}
#endregion
#region ToInt16()
[Test]
public void ShouldConvertZeroInt16()
{
// Arrange
var value = new byte[2];
// Act
Int16 result = IbmConverter.ToInt16(value);
// Assert
result.Should().Be(0);
}
[Test]
public void ShouldConvertNegativeInt16()
{
// Arrange
var value = new byte[] { 0xAB, 0xCD };
// Act
var result = IbmConverter.ToInt16(value);
// Assert
result.Should().Be(-21555);
}
[Test]
public void ShouldIgnoreTrailingBytesInt16()
{
// Arrange
var value = new byte[] { 0, 1, 99, 99 };
// Act
var result = IbmConverter.ToInt16(value);
// Assert
result.Should().Be(1);
}
[Test]
public void ShouldConvertInt16WithStartIndex()
{
// Arrange
var value = new byte[] { 99, 99, 99, 0, 1, 99 };
var startIndex = 3;
// Act
Int16 result = IbmConverter.ToInt16(value, startIndex);
// Assert
result.Should().Be(1);
}
[Test]
public void ShouldConvertAnotherInt16WithStartIndex()
{
// Arrange
var value = new byte[] { 99, 99, 2, 0, 99 };
var startIndex = 2;
// Act
Int16 result = IbmConverter.ToInt16(value, startIndex);
// Assert
result.Should().Be(512);
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToInt16()
{
IbmConverter.ToInt16(null);
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToInt16WithStartIndex()
{
IbmConverter.ToInt16(null, 1);
}
#endregion
#region GetBytes from Int16
[Test]
public void ShouldConvertFromInt16()
{
// Arrange
Int16 value = -21555;
// Act
byte[] result = IbmConverter.GetBytes(value);
// Assert
result.Should().Equal(new byte[] { 0xAB, 0xCD });
}
#endregion
#region ToInt32()
[Test]
public void ShouldConvertZeroInt32()
{
// Arrange
var bytes = new byte[4];
// Act
Int32 result = IbmConverter.ToInt32(bytes);
// Assert
result.Should().Be(0);
}
[Test]
public void ShouldConvertNegativeInt32()
{
// Arrange
var bytes = new byte[] { 0x89, 0xAB, 0xCD, 0xEF };
// Act
var result = IbmConverter.ToInt32(bytes);
// Assert
result.Should().Be(-1985229329);
}
[Test]
public void ShouldIgnoreTrailingBytesInt32()
{
// Arrange
var bytes = new byte[] { 0, 0, 0, 1, 99, 99 };
// Act
var result = IbmConverter.ToInt32(bytes);
// Assert
result.Should().Be(1);
}
[Test]
public void ShouldConvertInt32WithStartIndex()
{
// Arrange
var value = new byte[] { 99, 99, 99, 0, 0, 0, 1, 99 };
var startIndex = 3;
// Act
Int32 result = IbmConverter.ToInt32(value, startIndex);
// Assert
result.Should().Be(1);
}
[Test]
public void ShouldConvertAnotherInt32WithStartIndex()
{
// Arrange
var value = new byte[] { 99, 99, 1, 2, 4, 0, 99 };
var startIndex = 2;
// Act
var result = IbmConverter.ToInt32(value, startIndex);
// Assert
result.Should().Be(16909312);
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToInt32()
{
IbmConverter.ToInt32(null);
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToInt32WithStartIndex()
{
IbmConverter.ToInt32(null, 1);
}
#endregion
#region GetBytes from Int32
[Test]
public void ShouldConvertFromInt32()
{
// Arrange
Int32 value = -1985229329;
// Act
byte[] result = IbmConverter.GetBytes(value);
// Assert
result.Should().Equal(new byte[] { 0x89, 0xAB, 0xCD, 0xEF });
}
#endregion
#region ToSingle()
private static void VerifyToSingleReturns(float expected, byte[] value)
{
// Act
float result = IbmConverter.ToSingle(value);
// Assert
result.Should().BeInRange(expected - 0.0001f, expected + 0.0001f);
}
[Test]
public void ZeroShouldBeTheSame()
{
float expected = 0.0f;
var bytes = BitConverter.GetBytes(expected);
VerifyToSingleReturns(expected, bytes);
}
[Test]
public void One()
{
var expected = 1f;
var bytes = new byte[4];
bytes[0] = 64 + 1; // 16^1 with bias of 64
bytes[1] = 16; // 16 to the right of the decimal
VerifyToSingleReturns(expected, bytes);
}
[Test]
public void NegativeOne()
{
var expected = -1f;
var bytes = new byte[4];
bytes[0] = 128 + 64 + 1; // +128 for negative sign in first bit
bytes[1] = 16; // 16 to the right of the decimal
VerifyToSingleReturns(expected, bytes);
}
[Test]
public void SampleValueFromSegy()
{
var bytes = new byte[] { 0xc0, 0x1f, 0xf4, 0x62 };
VerifyToSingleReturns(-0.1248f, bytes);
}
[Test]
public void SampleValueFromWikipediaToSingle()
{
VerifyToSingleReturns(_wikipediaSingle, GetWikipediaSampleBytes());
}
[Test, ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowWhenArgumentNullForToSingle()
{
IbmConverter.ToSingle(null);
}
[Test]
public void VerifyFractionBytesCanBeConvertedToInt32()
{
var fractionBytes = new byte[] { 255, 255, 255, 0 };
var i = BitConverter.ToInt32(fractionBytes, 0);
var u = BitConverter.ToUInt32(fractionBytes, 0);
i.Should().Be((int)u);
}
#endregion
#region GetBytes from Single
[Test]
public void BytesFromZero()
{
VerifySingleConversion(0);
}
[Test]
public void BytesFromOne()
{
VerifySingleConversion(1f);
}
[Test]
public void BytesFromNegativeOne()
{
VerifySingleConversion(-1f);
}
[Test]
public void SampleValueToSegy()
{
VerifySingleConversion(-0.1248f);
}
[Test]
public void SampleValueFromWikipediaToBytes()
{
IbmConverter.GetBytes(_wikipediaSingle).Should().Equal(GetWikipediaSampleBytes());
}
[Test]
public void SingleConversionForRandomNumbers()
{
var random = new Random(51293);
for (int i = 0; i < 1000; i++)
{
var value = (Single)(random.NextDouble() * 100);
VerifySingleConversion(value);
VerifySingleConversion(-value);
}
}
private static void VerifySingleConversion(Single value)
{
byte[] result = IbmConverter.GetBytes(value);
var reverseValue = IbmConverter.ToSingle(result);
var epsilon = 0.0001f;
reverseValue.Should().BeInRange(value - epsilon, value + epsilon);
}
float _wikipediaSingle = -118.625f;
byte[] GetWikipediaSampleBytes()
{
// This test comes from the example described here: http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture#An_Example
// The difference is the bits have to be reversed per byte because the highest order bit is on the right
// 0100 0011 0110 1110 0000 0101 0000 0000
var bools = new bool[]
{
false, true, false, false, false, false, true, true,
false, true, true, false, true, true, true, false,
false, false, false, false, false, true, false, true,
false, false, false, false, false, false, false, false,
};
var bits = new BitArray(bools);
var bytes = new byte[4];
bits.CopyTo(bytes, 0);
return bytes;
}
#endregion
// TODO: Support for running on Big Endian architecture
#region ToDecimal
[Test]
public void DecimalZeroShouldBeTheSame()
{
var expected = (decimal) 0;
var bytes = IbmConverter.GetBytes(expected);
var result = IbmConverter.ToUnpackedDecimal(bytes, 2);
result.Should().Be(expected);
}
[Test]
public void DecimalShouldBeTheSame()
{
var expected = (decimal)123.45;
var bytes = IbmConverter.GetBytes(expected);
var result = IbmConverter.ToUnpackedDecimal(bytes, 2);
result.Should().Be(expected);
}
#endregion
}
}