Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of stateful CBOR writer and reader classes #32803

Merged
merged 33 commits into from
Mar 4, 2020
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c220624
initial CborReader commit
eiriktsarpalis Feb 21, 2020
301e593
rename PositiveInteger to UnsignedInteger
eiriktsarpalis Feb 25, 2020
d70f5ae
fix indices in unsigned integer encoding
eiriktsarpalis Feb 25, 2020
ecbd659
use an enum for AdditionalInfo constants
eiriktsarpalis Feb 25, 2020
21dfcb7
s/ArgumentException/InvalidOperationException/
eiriktsarpalis Feb 25, 2020
a262a37
make utf8 decoder throw on invalid bytes
eiriktsarpalis Feb 25, 2020
6924fe6
remove property-based tests
eiriktsarpalis Feb 25, 2020
b4d2ebb
address style
eiriktsarpalis Feb 25, 2020
03e9616
just copy the header struct for now
eiriktsarpalis Feb 25, 2020
544872d
s/CborReader/CborValueReader/
eiriktsarpalis Feb 25, 2020
5b75a0a
address feedback
eiriktsarpalis Feb 26, 2020
5d361b0
add more test cases in the happy path
eiriktsarpalis Feb 27, 2020
e08abd1
remove using declaration
eiriktsarpalis Feb 27, 2020
dd72ca4
fix the seed parameter
eiriktsarpalis Feb 27, 2020
16ef7d8
add `EnsureBuffer()` method in reader
eiriktsarpalis Feb 27, 2020
865d964
add tests for artihmetic overflow and type exceptions
eiriktsarpalis Feb 27, 2020
5138baa
rename CborDateItem to CborInitialByte and expose reader Peek() methods
eiriktsarpalis Feb 27, 2020
a30e79e
add tests for non-canonical integer encodings
eiriktsarpalis Feb 27, 2020
a63e6e5
use hex representation when asserting byte array equality
eiriktsarpalis Feb 27, 2020
adc4263
add format and invalidop exception tests
eiriktsarpalis Feb 27, 2020
3fa2dcf
consistent test terminology
eiriktsarpalis Feb 27, 2020
4752629
add invalid unicode writing test
eiriktsarpalis Feb 27, 2020
3ebc62f
add string reader failure tests
eiriktsarpalis Feb 28, 2020
bb05802
fix failing test
eiriktsarpalis Feb 28, 2020
659f888
add peek tests
eiriktsarpalis Feb 28, 2020
339262e
implement ReadCborNegativeIntegerEncoding(); remove TryRead() methods…
eiriktsarpalis Mar 3, 2020
f662113
add span overloads for string reader methods
eiriktsarpalis Mar 3, 2020
2ea14e1
update string reader span overload signatures
eiriktsarpalis Mar 3, 2020
c5c4587
add format and invalidop exception tests for TryRead() string methods
eiriktsarpalis Mar 3, 2020
882f9d7
add tests for failure modes
eiriktsarpalis Mar 3, 2020
f13cea7
Update src/libraries/System.Security.Cryptography.Encoding/tests/Cbor…
eiriktsarpalis Mar 3, 2020
fe8fe24
Update src/libraries/System.Security.Cryptography.Encoding/tests/Cbor…
eiriktsarpalis Mar 3, 2020
29f4142
fix build
eiriktsarpalis Mar 3, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable
using System;
using Test.Cryptography;
using Xunit;

namespace System.Security.Cryptography.Encoding.Tests.Cbor
{
public partial class CborReaderTests
{
// Data points taken from https://tools.ietf.org/html/rfc7049#appendix-A
// Additional pairs generated using http://cbor.me/

[Theory]
[InlineData(0, "00")]
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
[InlineData(1, "01")]
[InlineData(10, "0a")]
[InlineData(23, "17")]
[InlineData(24, "1818")]
[InlineData(25, "1819")]
[InlineData(100, "1864")]
[InlineData(1000, "1903e8")]
[InlineData(1000000, "1a000f4240")]
[InlineData(1000000000000, "1b000000e8d4a51000")]
[InlineData(-1, "20")]
[InlineData(-10, "29")]
[InlineData(-24, "37")]
[InlineData(-100, "3863")]
[InlineData(-1000, "3903e7")]
[InlineData(byte.MaxValue, "18ff")]
[InlineData(byte.MaxValue + 1, "190100")]
[InlineData(-1 - byte.MaxValue, "38ff")]
[InlineData(-2 - byte.MaxValue, "390100")]
[InlineData(ushort.MaxValue, "19ffff")]
[InlineData(ushort.MaxValue + 1, "1a00010000")]
[InlineData(-1 - ushort.MaxValue, "39ffff")]
[InlineData(-2 - ushort.MaxValue, "3a00010000")]
[InlineData(uint.MaxValue, "1affffffff")]
[InlineData((long)uint.MaxValue + 1, "1b0000000100000000")]
[InlineData(-1 - uint.MaxValue, "3affffffff")]
[InlineData(-2 - uint.MaxValue, "3b0000000100000000")]
[InlineData(long.MinValue, "3b7fffffffffffffff")]
[InlineData(long.MaxValue, "1b7fffffffffffffff")]
public static void ReadInt64_SingleValue_HappyPath(long expectedResult, string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
var reader = new CborValueReader(data);
long actualResult = reader.ReadInt64();
Assert.Equal(expectedResult, actualResult);
}

[Theory]
[InlineData(0, "00")]
[InlineData(1, "01")]
[InlineData(10, "0a")]
[InlineData(23, "17")]
[InlineData(24, "1818")]
[InlineData(25, "1819")]
[InlineData(100, "1864")]
[InlineData(1000, "1903e8")]
[InlineData(1000000, "1a000f4240")]
[InlineData(1000000000000, "1b000000e8d4a51000")]
[InlineData(byte.MaxValue, "18ff")]
[InlineData(byte.MaxValue + 1, "190100")]
[InlineData(ushort.MaxValue, "19ffff")]
[InlineData(ushort.MaxValue + 1, "1a00010000")]
[InlineData(uint.MaxValue, "1affffffff")]
[InlineData((ulong)uint.MaxValue + 1, "1b0000000100000000")]
[InlineData(long.MaxValue, "1b7fffffffffffffff")]
[InlineData(ulong.MaxValue, "1bffffffffffffffff")]
public static void ReadUInt64_SingleValue_HappyPath(ulong expectedResult, string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
var reader = new CborValueReader(data);
ulong actualResult = reader.ReadUInt64();
Assert.Equal(expectedResult, actualResult);
}

[Theory]
[InlineData(0, "20")]
[InlineData(9, "29")]
[InlineData(23, "37")]
[InlineData(99, "3863")]
[InlineData(999, "3903e7")]
[InlineData(byte.MaxValue, "38ff")]
[InlineData(ushort.MaxValue, "39ffff")]
[InlineData(uint.MaxValue, "3affffffff")]
[InlineData(ulong.MaxValue, "3bffffffffffffffff")]
public static void ReadCborNegativeIntegerEncoding_SingleValue_HappyPath(ulong expectedResult, string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
var reader = new CborValueReader(data);
ulong actualResult = reader.ReadCborNegativeIntegerEncoding();
Assert.Equal(expectedResult, actualResult);
}

[Theory]
// all possible definite-length encodings for the value 23
[InlineData("17")]
[InlineData("1817")]
[InlineData("190017")]
[InlineData("1a00000017")]
[InlineData("1b0000000000000017")]
public static void ReadUInt64_SingleValue_ShouldSupportNonCanonicalEncodings(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
var reader = new CborValueReader(data);
ulong result = reader.ReadUInt64();
Assert.Equal(23ul, result);
}

[Theory]
// all possible definite-length encodings for the value -24
[InlineData("37")]
[InlineData("3817")]
[InlineData("390017")]
[InlineData("3a00000017")]
[InlineData("3b0000000000000017")]
public static void ReadInt64_SingleValue_ShouldSupportNonCanonicalEncodings(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
var reader = new CborValueReader(data);
long result = reader.ReadInt64();
Assert.Equal(-24, result);
}


[Theory]
[InlineData("1b8000000000000000")] // long.MaxValue + 1
[InlineData("3b8000000000000000")] // long.MinValue - 1
[InlineData("1bffffffffffffffff")] // ulong.MaxValue
public static void ReadInt64_OutOfRangeValues_ShouldThrowOverflowException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
Assert.Throws<OverflowException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadInt64();
});
}

[Theory]
[InlineData("20")] // -1
[InlineData("3863")] // -100
[InlineData("3b7fffffffffffffff")] // long.MinValue
public static void ReadUInt64_OutOfRangeValues_ShouldThrowOverflowException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
Assert.Throws<OverflowException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadUInt64();
});
}

[Theory]
[InlineData("40")] // empty text string
[InlineData("60")] // empty byte string
[InlineData("f6")] // null
[InlineData("80")] // []
[InlineData("a0")] // {}
[InlineData("f97e00")] // NaN
[InlineData("fb3ff199999999999a")] // 1.1
public static void ReadInt64_InvalidTypes_ShouldThrowInvalidOperationException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
InvalidOperationException exn = Assert.Throws<InvalidOperationException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadInt64();
});

Assert.Equal("Data item major type mismatch.", exn.Message);
}

[Theory]
[InlineData("40")] // empty byte string
[InlineData("60")] // empty text string
[InlineData("f6")] // null
[InlineData("80")] // []
[InlineData("a0")] // {}
[InlineData("f97e00")] // NaN
[InlineData("fb3ff199999999999a")] // 1.1
public static void ReadUInt64_InvalidTypes_ShouldThrowInvalidOperationException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
InvalidOperationException exn = Assert.Throws<InvalidOperationException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadUInt64();
});

Assert.Equal("Data item major type mismatch.", exn.Message);
}

[Theory]
[InlineData("00")] // 0
[InlineData("17")] // 23
[InlineData("40")] // empty byte string
[InlineData("60")] // empty text string
[InlineData("f6")] // null
[InlineData("80")] // []
[InlineData("a0")] // {}
[InlineData("f97e00")] // NaN
[InlineData("fb3ff199999999999a")] // 1.1
public static void ReadCborNegativeIntegerEncoding_InvalidTypes_ShouldThrowInvalidOperationException(string hexEncoding)
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
{
byte[] data = hexEncoding.HexToByteArray();
InvalidOperationException exn = Assert.Throws<InvalidOperationException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadCborNegativeIntegerEncoding();
});

Assert.Equal("Data item major type mismatch.", exn.Message);
}

[Theory]
// Invalid initial bytes with numeric major type
[InlineData("1c")]
[InlineData("1d")]
[InlineData("1e")]
[InlineData("3c")]
[InlineData("3d")]
[InlineData("3e")]
// valid initial bytes missing required data
[InlineData("18")]
[InlineData("1912")]
[InlineData("1a000000")]
[InlineData("1b00000000000000")]
[InlineData("38")]
[InlineData("3912")]
[InlineData("3a000000")]
[InlineData("3b00000000000000")]
public static void ReadInt64_InvalidData_ShouldThrowFormatException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
Assert.Throws<FormatException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadInt64();
});
}

[Theory]
// Invalid initial bytes with numeric major type
[InlineData("3c")]
[InlineData("3d")]
[InlineData("3e")]
// valid initial bytes missing required data
[InlineData("38")]
[InlineData("3912")]
[InlineData("3a000000")]
[InlineData("3b00000000000000")]
public static void ReadCborNegativeIntegerEncoding_InvalidData_ShouldThrowFormatException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
Assert.Throws<FormatException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadCborNegativeIntegerEncoding();
});
}

[Theory]
[InlineData("1f")]
[InlineData("3f")]
public static void ReadInt64_IndefiniteLengthIntegers_ShouldThrowNotImplementedException(string hexEncoding)
{
byte[] data = hexEncoding.HexToByteArray();
Assert.Throws<NotImplementedException>(() =>
{
var reader = new CborValueReader(data);
reader.ReadInt64();
});
}
}
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
}
Loading