public void Basic_decoding_with_known_input_isFinalBlock_false___Done(string input, int expectedWritten) { var sut = new Base64Encoder(); ReadOnlySpan <T> encoded; if (typeof(T) == typeof(byte)) { ReadOnlySpan <byte> tmp = Encoding.ASCII.GetBytes(input); encoded = MemoryMarshal.Cast <byte, T>(tmp); } else if (typeof(T) == typeof(char)) { encoded = MemoryMarshal.Cast <char, T>(input.AsSpan()); // .AsSpan() for net48 } else { throw new NotSupportedException(); // just in case new types are introduced in the future } Span <byte> data = new byte[sut.GetMaxDecodedLength(encoded.Length)]; OperationStatus status = sut.DecodeCore(encoded, data, out int consumed, out int written, isFinalBlock: false); byte[] actualData = data.Slice(0, written).ToArray(); Assert.Multiple(() => { Assert.AreEqual(OperationStatus.Done, status); Assert.AreEqual(input.Length, consumed); Assert.AreEqual(expectedWritten, written); byte[] expectedData = Convert.FromBase64String(input); CollectionAssert.AreEqual(expectedData, actualData); }); }
public void Malformed_input___status_InvalidData(string input, bool isFinalBlock, int expectedConsumed, int expectedWritten) { var sut = new Base64Encoder(); ReadOnlySpan <T> encoded; if (typeof(T) == typeof(byte)) { ReadOnlySpan <byte> tmp = Encoding.ASCII.GetBytes(input); encoded = MemoryMarshal.Cast <byte, T>(tmp); } else if (typeof(T) == typeof(char)) { encoded = MemoryMarshal.Cast <char, T>(input.AsSpan()); // AsSpan() for net48 } else { throw new NotSupportedException(); // just in case new types are introduced in the future } Span <byte> data = new byte[sut.GetMaxDecodedLength(encoded.Length)]; OperationStatus status = sut.DecodeCore(encoded, data, out int consumed, out int written, isFinalBlock); Assert.Multiple(() => { Assert.AreEqual(OperationStatus.InvalidData, status); Assert.AreEqual(expectedConsumed, consumed); Assert.AreEqual(expectedWritten, written); }); }
public void Padding_can_only_be_last_two___InvalidData(bool isFinalBlock) { var sut = new Base64Encoder(); for (int j = 0; j < 7; ++j) { Span <byte> tmp = stackalloc byte[8] { 50, 50, 50, 50, 80, 80, 80, 80 }; // valid input - "2222PPPP" Span <T> encoded = stackalloc T[tmp.Length]; T padding; if (typeof(T) == typeof(byte)) { padding = (T)(object)Base64Encoder.EncodingPad; encoded = MemoryMarshal.Cast <byte, T>(tmp); } else if (typeof(T) == typeof(char)) { padding = (T)(object)(char)Base64Encoder.EncodingPad; for (int i = 0; i < tmp.Length; ++i) { encoded[i] = (T)(object)(char)tmp[i]; } } else { throw new NotSupportedException(); // just in case new types are introduced in the future } byte[] data = new byte[sut.GetMaxDecodedLength(encoded.Length)]; encoded[j] = padding; OperationStatus status = sut.DecodeCore <T>(encoded, data, out int consumed, out int written, isFinalBlock); Assert.Multiple(() => { Assert.AreEqual(OperationStatus.InvalidData, status, "j = {0}", j); if (j < 4) { Assert.AreEqual(0, consumed, "j = {0}", j); Assert.AreEqual(0, written, "j = {0}", j); } else { Assert.AreEqual(4, consumed, "j = {0}", j); Assert.AreEqual(3, written, "j = {0}", j); #if NETCOREAPP string actual = Convert.ToBase64String(data.AsSpan(0, 3)); #else string actual = Convert.ToBase64String(data, 0, 3); #endif Assert.AreEqual("2222", actual, "j = {0}", j); } }); } }
public void EncodedLength_is_negative___throws_ArgumentOutOfRange([Values(-1, int.MinValue)] int encodedLength) { var sut = new Base64Encoder(); Exception exception = Assert.Catch(() => sut.GetMaxDecodedLength(encodedLength)); Assert.Multiple(() => { Assert.IsInstanceOf <ArgumentOutOfRangeException>(exception); string msg = $"The 'encodedLength' is outside the allowed range by the base64 standard. It must be >= 4."; StringAssert.StartsWith(msg, exception.Message); }); }
public void EncodedLength_1_to_50_given___correct_max_decoded_len() { var sut = new Base64Encoder(); Assert.Multiple(() => { for (int i = 1; i < 50; ++i) { var data = new byte[i]; string base64 = Convert.ToBase64String(data); int actual = sut.GetMaxDecodedLength(base64.Length); Assert.GreaterOrEqual(actual, i); } }); }
public void Padding_is_only_valid_for_isFinalBlock_true( [Values("2222PP==", "2222PPP=")] string encodedString, [Values(true, false)] bool isFinalBlock) { var sut = new Base64Encoder(); ReadOnlySpan <T> encoded; if (typeof(T) == typeof(byte)) { ReadOnlySpan <byte> tmp = Encoding.ASCII.GetBytes(encodedString); encoded = MemoryMarshal.Cast <byte, T>(tmp); } else if (typeof(T) == typeof(char)) { encoded = MemoryMarshal.Cast <char, T>(encodedString.AsSpan()); // .AsSpan() for net48 } else { throw new NotSupportedException(); // just in case new types are introduced in the future } Span <byte> data = new byte[sut.GetMaxDecodedLength(encoded.Length)]; OperationStatus status = sut.DecodeCore(encoded, data, out int consumed, out int written, isFinalBlock); byte[] actualData = data.Slice(0, written).ToArray(); Assert.Multiple(() => { OperationStatus expectedStatus = isFinalBlock ? OperationStatus.Done : OperationStatus.InvalidData; int expectedConsumed = isFinalBlock ? 8 : 4; int expectedWritten = isFinalBlock ? encodedString.Count(c => c == '=') == 2 ? 4 : 5 : 3; Assert.AreEqual(expectedStatus, status); Assert.AreEqual(expectedConsumed, consumed); Assert.AreEqual(expectedWritten, written); byte[] expectedData = Convert.FromBase64String(encodedString.Substring(0, consumed)); CollectionAssert.AreEqual(expectedData, actualData); }); }
public void Basic_decoding_with_invalid_input_length_isFinalBlock_false___NeedMoreData() { var sut = new Base64Encoder(); var rnd = new Random(42); for (int i = 0; i < 10; ++i) { int encodedLength; do { encodedLength = rnd.Next(100, 1_000 * 1_000); }while (encodedLength % 4 == 0); // ensure we have invalid length ReadOnlySpan <T> encoded; if (typeof(T) == typeof(byte)) { ReadOnlySpan <byte> tmp = Enumerable.Repeat((byte)'a', encodedLength).ToArray(); encoded = MemoryMarshal.Cast <byte, T>(tmp); } else if (typeof(T) == typeof(char)) { ReadOnlySpan <char> tmp = Enumerable.Repeat('a', encodedLength).ToArray(); encoded = MemoryMarshal.Cast <char, T>(tmp); } else { throw new NotSupportedException(); // just in case new types are introduced in the future } Span <byte> data = new byte[sut.GetMaxDecodedLength(encoded.Length)]; OperationStatus status = sut.DecodeCore(encoded, data, out int consumed, out int written, isFinalBlock: false); Assert.AreEqual(OperationStatus.NeedMoreData, status, "fail at i = {0}", i); } }
public void Invalid_bytes___InvalidData(bool isFinalBlock) { var sut = new Base64Encoder(); // Don't test padding ('=') here -> -1 byte[] invalidBytes = TestHelper.GetInvalidBytes(Base64Encoder.DecodingMap) .Where(b => b != Base64Encoder.EncodingPad) .ToArray(); Assume.That(invalidBytes.Length + 1, Is.EqualTo(byte.MaxValue - 64 + 1)); // +1 for padding on the left side T[] invalid = new T[invalidBytes.Length - 1]; if (typeof(T) == typeof(byte)) { invalid = invalidBytes.Select(b => (T)(object)b).ToArray(); } else if (typeof(T) == typeof(char)) { invalid = invalidBytes.Select(b => (T)(object)(char)b).ToArray(); } else { throw new NotSupportedException(); // just in case new types are introduced in the future } for (int j = 0; j < 8; ++j) { Span <byte> tmp = stackalloc byte[8] { 50, 50, 50, 50, 80, 80, 80, 80 }; // valid input - "2222PPPP" Span <T> encoded = stackalloc T[tmp.Length]; if (typeof(T) == typeof(byte)) { encoded = MemoryMarshal.Cast <byte, T>(tmp); } else if (typeof(T) == typeof(char)) { for (int i = 0; i < tmp.Length; ++i) { encoded[i] = (T)(object)(char)tmp[i]; } } else { throw new NotSupportedException(); // just in case new types are introduced in the future } byte[] data = new byte[sut.GetMaxDecodedLength(encoded.Length)]; for (int i = 0; i < invalid.Length; ++i) { encoded[j] = invalid[i]; OperationStatus status = sut.DecodeCore <T>(encoded, data, out int consumed, out int written, isFinalBlock); Assert.Multiple(() => { Assert.AreEqual(OperationStatus.InvalidData, status, "j = {0}, i = {1}", j, i); if (j < 4) { Assert.AreEqual(0, consumed, "j = {0}, i = {1}", j, i); Assert.AreEqual(0, written, "j = {0}, i = {1}", j, i); } else { Assert.AreEqual(4, consumed, "j = {0}, i = {1}", j, i); Assert.AreEqual(3, written, "j = {0}, i = {1}", j, i); #if NETCOREAPP string actual = Convert.ToBase64String(data.AsSpan(0, 3)); #else string actual = Convert.ToBase64String(data, 0, 3); #endif Assert.AreEqual("2222", actual, "j = {0}, i = {1}", j, i); } }); } } }