From fb1f6bd98b0da5c2893b89828d84d469a6ed2e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Thu, 24 Dec 2020 09:53:10 +0100 Subject: [PATCH 1/9] Update target frameworks to latest .NET versions --- BencodeNET.Tests/BencodeNET.Tests.csproj | 4 ++-- BencodeNET/BencodeNET.csproj | 17 +++++++++++------ BencodeNET/PolyFillExtensions.cs | 2 +- BencodeNET/UtilityExtensions.cs | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/BencodeNET.Tests/BencodeNET.Tests.csproj b/BencodeNET.Tests/BencodeNET.Tests.csproj index a97dbffe45..fcab25b993 100644 --- a/BencodeNET.Tests/BencodeNET.Tests.csproj +++ b/BencodeNET.Tests/BencodeNET.Tests.csproj @@ -1,8 +1,8 @@ - net472;netcoreapp2.0;netcoreapp2.2;netcoreapp3.0 - 7.3 + net472;netcoreapp2.1;netcoreapp3.1;net5.0 + 9 diff --git a/BencodeNET/BencodeNET.csproj b/BencodeNET/BencodeNET.csproj index 1d9c1581f7..317ecc7789 100644 --- a/BencodeNET/BencodeNET.csproj +++ b/BencodeNET/BencodeNET.csproj @@ -1,8 +1,8 @@ - netstandard2.0;netcoreapp2.1;netcoreapp3.0 - 7.3 + netstandard2.0;netstandard2.1;netcoreapp2.1;net5.0 + 9 true True BencodeNET.ruleset @@ -38,17 +38,22 @@ - + - - + + + + + + + - + diff --git a/BencodeNET/PolyFillExtensions.cs b/BencodeNET/PolyFillExtensions.cs index 1f0b6080fb..ce936836f6 100644 --- a/BencodeNET/PolyFillExtensions.cs +++ b/BencodeNET/PolyFillExtensions.cs @@ -6,7 +6,7 @@ namespace BencodeNET { -#if !NETCOREAPP3_0 +#if NETSTANDARD2_0 internal static class PolyFillExtensions { public static unsafe int GetBytes(this Encoding encoding, ReadOnlySpan chars, Span bytes) diff --git a/BencodeNET/UtilityExtensions.cs b/BencodeNET/UtilityExtensions.cs index 61470c4d2f..17db284aa5 100644 --- a/BencodeNET/UtilityExtensions.cs +++ b/BencodeNET/UtilityExtensions.cs @@ -129,7 +129,7 @@ public static void WriteCharAt(this Span bytes, char c, int index) bytes[index] = (byte) c; } -#if NETCOREAPP +#if !NETSTANDARD2_0 public static string AsString(this ReadOnlySpan chars) { return new string(chars); From 99c0745fa2a864392058e0d5c1bbfce8ef91f650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Thu, 24 Dec 2020 09:53:42 +0100 Subject: [PATCH 2/9] Add missing doc for DisplayNameUtf8 --- BencodeNET/Torrents/Torrent.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BencodeNET/Torrents/Torrent.cs b/BencodeNET/Torrents/Torrent.cs index eead9c5afe..3d96f9c0c2 100644 --- a/BencodeNET/Torrents/Torrent.cs +++ b/BencodeNET/Torrents/Torrent.cs @@ -133,6 +133,11 @@ public virtual string DisplayName } } + /// + /// Returns the UTF-8 "display name" of the torrent. + /// For single-file torrents this is the file name of that file. + /// For multi-file torrents this is the directory name. + /// public virtual string DisplayNameUtf8 { get From df40d1101953afec8fe69968627b7efda3d6114e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Thu, 24 Dec 2020 09:54:07 +0100 Subject: [PATCH 3/9] Avoid initializing new empty array --- BencodeNET/Torrents/Torrent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BencodeNET/Torrents/Torrent.cs b/BencodeNET/Torrents/Torrent.cs index 3d96f9c0c2..7ebb34b0bd 100644 --- a/BencodeNET/Torrents/Torrent.cs +++ b/BencodeNET/Torrents/Torrent.cs @@ -183,7 +183,7 @@ public virtual string DisplayNameUtf8 /// A concatenation of all 20-byte SHA1 hash values (one for each piece). /// Use to get/set this value as a hex string instead. /// - public virtual byte[] Pieces { get; set; } = new byte[0]; + public virtual byte[] Pieces { get; set; } = Array.Empty(); /// /// Gets or sets from/to a hex string (without dashes), e.g. 1C115D26444AEF2A5E936133DCF8789A552BBE9F[...]. From bec1f72105bf12f37fa2352b45cb5b093ab1ce29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Thu, 24 Dec 2020 10:05:35 +0100 Subject: [PATCH 4/9] Use new C# syntaxes here and there --- BencodeNET/Objects/BString.cs | 7 +-- BencodeNET/Parsing/BNumberParser.cs | 58 +++++++++---------- BencodeNET/Parsing/BStringParser.cs | 32 +++++----- BencodeNET/Parsing/BencodeParserExtensions.cs | 48 +++++---------- BencodeNET/Torrents/Torrent.cs | 17 ++---- BencodeNET/Torrents/TorrentParser.cs | 4 +- 6 files changed, 68 insertions(+), 98 deletions(-) diff --git a/BencodeNET/Objects/BString.cs b/BencodeNET/Objects/BString.cs index 97c55ca09a..ebc8639a3f 100644 --- a/BencodeNET/Objects/BString.cs +++ b/BencodeNET/Objects/BString.cs @@ -122,10 +122,7 @@ protected override void EncodeObject(PipeWriter writer) public static bool operator ==(BString first, BString second) { - if (first is null) - return second is null; - - return first.Equals(second); + return first?.Equals(second) ?? second is null; } public static bool operator !=(BString first, BString second) => !(first == second); @@ -173,7 +170,7 @@ public override string ToString() /// public string ToString(Encoding encoding) { - encoding = encoding ?? _encoding; + encoding ??= _encoding; return encoding.GetString(Value.Span); } } diff --git a/BencodeNET/Parsing/BNumberParser.cs b/BencodeNET/Parsing/BNumberParser.cs index 2253e33a36..37eb3af395 100644 --- a/BencodeNET/Parsing/BNumberParser.cs +++ b/BencodeNET/Parsing/BNumberParser.cs @@ -45,23 +45,21 @@ public override BNumber Parse(BencodeReader reader) if (reader.ReadChar() != 'i') throw InvalidBencodeException.UnexpectedChar('i', reader.PreviousChar, startPosition); - using (var digits = MemoryPool.Shared.Rent(BNumber.MaxDigits)) + using var digits = MemoryPool.Shared.Rent(BNumber.MaxDigits); + var digitCount = 0; + for (var c = reader.ReadChar(); c != default && c != 'e'; c = reader.ReadChar()) { - var digitCount = 0; - for (var c = reader.ReadChar(); c != default && c != 'e'; c = reader.ReadChar()) - { - digits.Memory.Span[digitCount++] = c; - } + digits.Memory.Span[digitCount++] = c; + } - if (digitCount == 0) - throw NoDigitsException(startPosition); + if (digitCount == 0) + throw NoDigitsException(startPosition); - // Last read character should be 'e' - if (reader.PreviousChar != 'e') - throw InvalidBencodeException.MissingEndChar(startPosition); + // Last read character should be 'e' + if (reader.PreviousChar != 'e') + throw InvalidBencodeException.MissingEndChar(startPosition); - return ParseNumber(digits.Memory.Span.Slice(0, digitCount), startPosition); - } + return ParseNumber(digits.Memory.Span.Slice(0, digitCount), startPosition); } /// @@ -82,26 +80,24 @@ public override async ValueTask ParseAsync(PipeBencodeReader reader, Ca if (await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false) != 'i') throw InvalidBencodeException.UnexpectedChar('i', reader.PreviousChar, startPosition); - using (var memoryOwner = MemoryPool.Shared.Rent(BNumber.MaxDigits)) + using var memoryOwner = MemoryPool.Shared.Rent(BNumber.MaxDigits); + var digits = memoryOwner.Memory; + var digitCount = 0; + for (var c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false); + c != default && c != 'e'; + c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false)) { - var digits = memoryOwner.Memory; - var digitCount = 0; - for (var c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false); - c != default && c != 'e'; - c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false)) - { - digits.Span[digitCount++] = c; - } - - if (digitCount == 0) - throw NoDigitsException(startPosition); - - // Last read character should be 'e' - if (reader.PreviousChar != 'e') - throw InvalidBencodeException.MissingEndChar(startPosition); - - return ParseNumber(digits.Span.Slice(0, digitCount), startPosition); + digits.Span[digitCount++] = c; } + + if (digitCount == 0) + throw NoDigitsException(startPosition); + + // Last read character should be 'e' + if (reader.PreviousChar != 'e') + throw InvalidBencodeException.MissingEndChar(startPosition); + + return ParseNumber(digits.Span.Slice(0, digitCount), startPosition); } private BNumber ParseNumber(in ReadOnlySpan digits, long startPosition) diff --git a/BencodeNET/Parsing/BStringParser.cs b/BencodeNET/Parsing/BStringParser.cs index 4948c73304..6c87a95fbd 100644 --- a/BencodeNET/Parsing/BStringParser.cs +++ b/BencodeNET/Parsing/BStringParser.cs @@ -110,29 +110,27 @@ public override async ValueTask ParseAsync(PipeBencodeReader reader, Ca var startPosition = reader.Position; - using (var memoryOwner = MemoryPool.Shared.Rent(BString.LengthMaxDigits)) + using var memoryOwner = MemoryPool.Shared.Rent(BString.LengthMaxDigits); + var lengthString = memoryOwner.Memory; + var lengthStringCount = 0; + for (var c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false); + c != default && c.IsDigit(); + c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false)) { - var lengthString = memoryOwner.Memory; - var lengthStringCount = 0; - for (var c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false); - c != default && c.IsDigit(); - c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false)) - { - EnsureLengthStringBelowMaxLength(lengthStringCount, startPosition); + EnsureLengthStringBelowMaxLength(lengthStringCount, startPosition); - lengthString.Span[lengthStringCount++] = c; - } + lengthString.Span[lengthStringCount++] = c; + } - EnsurePreviousCharIsColon(reader.PreviousChar, reader.Position); + EnsurePreviousCharIsColon(reader.PreviousChar, reader.Position); - var stringLength = ParseStringLength(lengthString.Span, lengthStringCount, startPosition); - var bytes = new byte[stringLength]; - var bytesRead = await reader.ReadAsync(bytes, cancellationToken).ConfigureAwait(false); + var stringLength = ParseStringLength(lengthString.Span, lengthStringCount, startPosition); + var bytes = new byte[stringLength]; + var bytesRead = await reader.ReadAsync(bytes, cancellationToken).ConfigureAwait(false); - EnsureExpectedBytesRead(bytesRead, stringLength, startPosition); + EnsureExpectedBytesRead(bytesRead, stringLength, startPosition); - return new BString(bytes, Encoding); - } + return new BString(bytes, Encoding); } /// diff --git a/BencodeNET/Parsing/BencodeParserExtensions.cs b/BencodeNET/Parsing/BencodeParserExtensions.cs index 47354f9f36..5f5b18d890 100644 --- a/BencodeNET/Parsing/BencodeParserExtensions.cs +++ b/BencodeNET/Parsing/BencodeParserExtensions.cs @@ -20,10 +20,8 @@ public static class BencodeParserExtensions /// The parsed object. public static IBObject ParseString(this IBencodeParser parser, string bencodedString) { - using (var stream = bencodedString.AsStream(parser.Encoding)) - { - return parser.Parse(stream); - } + using var stream = bencodedString.AsStream(parser.Encoding); + return parser.Parse(stream); } /// @@ -34,10 +32,8 @@ public static IBObject ParseString(this IBencodeParser parser, string bencodedSt /// The parsed object. public static IBObject Parse(this IBencodeParser parser, byte[] bytes) { - using (var stream = new MemoryStream(bytes)) - { - return parser.Parse(stream); - } + using var stream = new MemoryStream(bytes); + return parser.Parse(stream); } /// @@ -48,10 +44,8 @@ public static IBObject Parse(this IBencodeParser parser, byte[] bytes) /// The parsed object. public static IBObject Parse(this IBencodeParser parser, string filePath) { - using (var stream = File.OpenRead(filePath)) - { - return parser.Parse(stream); - } + using var stream = File.OpenRead(filePath); + return parser.Parse(stream); } /// @@ -63,10 +57,8 @@ public static IBObject Parse(this IBencodeParser parser, string filePath) /// The parsed object. public static T ParseString(this IBencodeParser parser, string bencodedString) where T : class, IBObject { - using (var stream = bencodedString.AsStream(parser.Encoding)) - { - return parser.Parse(stream); - } + using var stream = bencodedString.AsStream(parser.Encoding); + return parser.Parse(stream); } /// @@ -78,10 +70,8 @@ public static T ParseString(this IBencodeParser parser, string bencodedString /// The parsed object. public static T Parse(this IBencodeParser parser, byte[] bytes) where T : class, IBObject { - using (var stream = new MemoryStream(bytes)) - { - return parser.Parse(stream); - } + using var stream = new MemoryStream(bytes); + return parser.Parse(stream); } /// @@ -92,10 +82,8 @@ public static T Parse(this IBencodeParser parser, byte[] bytes) where T : cla /// The parsed object. public static T Parse(this IBencodeParser parser, string filePath) where T : class, IBObject { - using (var stream = File.OpenRead(filePath)) - { - return parser.Parse(stream); - } + using var stream = File.OpenRead(filePath); + return parser.Parse(stream); } /// @@ -106,10 +94,8 @@ public static T Parse(this IBencodeParser parser, string filePath) where T : /// The parsed object. public static IBObject Parse(this IBencodeParser parser, Stream stream) { - using (var reader = new BencodeReader(stream, leaveOpen: true)) - { - return parser.Parse(reader); - } + using var reader = new BencodeReader(stream, leaveOpen: true); + return parser.Parse(reader); } /// @@ -121,10 +107,8 @@ public static IBObject Parse(this IBencodeParser parser, Stream stream) /// The parsed object. public static T Parse(this IBencodeParser parser, Stream stream) where T : class, IBObject { - using (var reader = new BencodeReader(stream, leaveOpen: true)) - { - return parser.Parse(reader); - } + using var reader = new BencodeReader(stream, leaveOpen: true); + return parser.Parse(reader); } /// diff --git a/BencodeNET/Torrents/Torrent.cs b/BencodeNET/Torrents/Torrent.cs index 7ebb34b0bd..684716b7e9 100644 --- a/BencodeNET/Torrents/Torrent.cs +++ b/BencodeNET/Torrents/Torrent.cs @@ -395,10 +395,7 @@ protected override ValueTask EncodeObjectAsync(PipeWriter writer, C #pragma warning disable 1591 public static bool operator ==(Torrent first, Torrent second) { - if (ReferenceEquals(first, null)) - return ReferenceEquals(second, null); - - return first.Equals(second); + return first?.Equals(second) ?? second is null; } public static bool operator !=(Torrent first, Torrent second) @@ -412,14 +409,12 @@ public override bool Equals(object other) if (obj == null) return false; - using (var ms1 = EncodeTo(new MemoryStream())) - using (var ms2 = obj.EncodeTo(new MemoryStream())) - { - var bytes1 = ms1.ToArray(); - var bytes2 = ms2.ToArray(); + using var ms1 = EncodeTo(new MemoryStream()); + using var ms2 = obj.EncodeTo(new MemoryStream()); + var bytes1 = ms1.ToArray(); + var bytes2 = ms2.ToArray(); - return bytes1.SequenceEqual(bytes2); - } + return bytes1.SequenceEqual(bytes2); } public override int GetHashCode() diff --git a/BencodeNET/Torrents/TorrentParser.cs b/BencodeNET/Torrents/TorrentParser.cs index 2fde44558c..8211f0001a 100644 --- a/BencodeNET/Torrents/TorrentParser.cs +++ b/BencodeNET/Torrents/TorrentParser.cs @@ -182,7 +182,7 @@ protected void EnsureValidTorrentData(BDictionary data) private static void EnsureFields(IList requiredFields, BDictionary data, string message = null) { - message = message ?? "Torrent is missing required field."; + message ??= "Torrent is missing required field."; foreach (var field in requiredFields.Where(field => !data.ContainsKey(field))) { @@ -192,7 +192,7 @@ private static void EnsureFields(IList requiredFields, BDictionary data, private static void EnsureFields(IList requiredFields, IEnumerable list, string message = null) { - message = message ?? "Torrent is missing required field."; + message ??= "Torrent is missing required field."; foreach (var data in list) { From 97fd37a27b9ccd7d887270a8e980ae32925c3b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Thu, 24 Dec 2020 10:08:05 +0100 Subject: [PATCH 5/9] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 990fd26215..75e0c2d098 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- Changed target frameworks to: + - .NET Standard 2.0 + - .NET Standard 2.1 + - .NET Core App 2.1 + - .NET 5.0 + ... ## [3.1.4] - 2020-03-06 From 2d7d1cd10f9a4a8b13d04ccb42d74825591b8cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Fri, 8 Jan 2021 21:05:35 +0100 Subject: [PATCH 6/9] Update Torrent.Pieces property with null-check and multiple of 20 check --- .../AutoFixture/RepeatCountAttribute.cs | 23 +++++++++++++++++++ .../AutoFixture/RepeatCountCustomization.cs | 19 +++++++++++++++ .../Torrents/TorrentParserTests.cs | 6 +++-- BencodeNET.Tests/Torrents/TorrentTests.cs | 22 ++++++++++++++++++ BencodeNET/Torrents/Torrent.cs | 19 ++++++++++++--- 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 BencodeNET.Tests/AutoFixture/RepeatCountAttribute.cs create mode 100644 BencodeNET.Tests/AutoFixture/RepeatCountCustomization.cs diff --git a/BencodeNET.Tests/AutoFixture/RepeatCountAttribute.cs b/BencodeNET.Tests/AutoFixture/RepeatCountAttribute.cs new file mode 100644 index 0000000000..f13b690274 --- /dev/null +++ b/BencodeNET.Tests/AutoFixture/RepeatCountAttribute.cs @@ -0,0 +1,23 @@ +using System; +using System.Reflection; +using AutoFixture; +using AutoFixture.Xunit2; + +namespace BencodeNET.Tests.AutoFixture +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] + public class RepeatCountAttribute : CustomizeAttribute + { + private int Count { get; } + + public RepeatCountAttribute(int count) + { + Count = count; + } + + public override ICustomization GetCustomization(ParameterInfo parameter) + { + return new RepeatCountCustomization(Count); + } + } +} diff --git a/BencodeNET.Tests/AutoFixture/RepeatCountCustomization.cs b/BencodeNET.Tests/AutoFixture/RepeatCountCustomization.cs new file mode 100644 index 0000000000..c2cd75cd38 --- /dev/null +++ b/BencodeNET.Tests/AutoFixture/RepeatCountCustomization.cs @@ -0,0 +1,19 @@ +using AutoFixture; + +namespace BencodeNET.Tests.AutoFixture +{ + public class RepeatCountCustomization : ICustomization + { + private int Count { get; } + + public RepeatCountCustomization(int count) + { + Count = count; + } + + public void Customize(IFixture fixture) + { + fixture.RepeatCount = Count; + } + } +} diff --git a/BencodeNET.Tests/Torrents/TorrentParserTests.cs b/BencodeNET.Tests/Torrents/TorrentParserTests.cs index 00e67fed3b..d753dbe08a 100644 --- a/BencodeNET.Tests/Torrents/TorrentParserTests.cs +++ b/BencodeNET.Tests/Torrents/TorrentParserTests.cs @@ -4,6 +4,7 @@ using BencodeNET.IO; using BencodeNET.Objects; using BencodeNET.Parsing; +using BencodeNET.Tests.AutoFixture; using BencodeNET.Torrents; using FluentAssertions; using NSubstitute; @@ -202,16 +203,17 @@ public void Info_PieceLength_IsParsed(long pieceSize) [Theory] [AutoMockedData] - public void Info_Pieces_IsParsed(byte[] pieces) + public void Info_Pieces_IsParsed([RepeatCount(20)] byte[] pieces) { // Arrange ParsedData = ValidSingleFileTorrentData; var info = ParsedData.Get(TorrentFields.Info); info[TorrentInfoFields.Pieces] = new BString(pieces); + pieces.Should().HaveCount(20); // Act var parser = new TorrentParser(BencodeParser); - var torrent = parser.Parse((BencodeReader)null); + var torrent = parser.Parse((BencodeReader) null); // Assert torrent.Pieces.Should().Equal(pieces); diff --git a/BencodeNET.Tests/Torrents/TorrentTests.cs b/BencodeNET.Tests/Torrents/TorrentTests.cs index aa7cc96481..0d688e9487 100644 --- a/BencodeNET.Tests/Torrents/TorrentTests.cs +++ b/BencodeNET.Tests/Torrents/TorrentTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using AutoFixture.Xunit2; using BencodeNET.Exceptions; using BencodeNET.Objects; using BencodeNET.Torrents; @@ -135,6 +136,27 @@ public void DisplayNameUtf8_UnknownFileMode_ThrowsBencodeException() act.Should().Throw(); } + [Theory] + [AutoMockedData] + public void Pieces_Setter_NullValue_ThrowsArgumentNullException([NoAutoProperties] Torrent torrent) + { + Action act = () => torrent.Pieces = null; + + act.Should().ThrowExactly(); + } + + [Theory] + [AutoMockedData] + public void Pieces_Setter_NotMultipleOf20_ThrowsArgumentException([NoAutoProperties] Torrent torrent) + { + var pieces = new byte[] { 66, 115, 135, 19, 149, 125, 229, 85, 68, 117, 252, 185, 243, 247, 139, 38, 11, 37, 60 }; + pieces.Should().NotHaveCount(20); + + Action act = () => torrent.Pieces = pieces; + + act.Should().ThrowExactly(); + } + [Fact] public void PiecesAsHexString_Get_ReturnsHexUppercaseWithoutDashes() { diff --git a/BencodeNET/Torrents/Torrent.cs b/BencodeNET/Torrents/Torrent.cs index 684716b7e9..9e5dcb7d88 100644 --- a/BencodeNET/Torrents/Torrent.cs +++ b/BencodeNET/Torrents/Torrent.cs @@ -177,13 +177,26 @@ public virtual string DisplayNameUtf8 /// public virtual long PieceSize { get; set; } - // TODO: Split into list of 20-byte hashes and rename to something appropriate? - /// /// A concatenation of all 20-byte SHA1 hash values (one for each piece). /// Use to get/set this value as a hex string instead. /// - public virtual byte[] Pieces { get; set; } = Array.Empty(); + public virtual byte[] Pieces + { + get => _pieces; + set + { + if (value is null) + throw new ArgumentNullException(nameof(value), "Pieces array cannot be null."); + + var remainder = value.Length % 20; + if (remainder is not 0) + throw new ArgumentException($"Array size has to be a multiple of 20, but length was {value.Length}"); + + _pieces = value; + } + } + private byte[] _pieces = Array.Empty(); /// /// Gets or sets from/to a hex string (without dashes), e.g. 1C115D26444AEF2A5E936133DCF8789A552BBE9F[...]. From 783b084f022a3034569469ddb6478273babf3edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Fri, 8 Jan 2021 21:06:19 +0100 Subject: [PATCH 7/9] Update packages in test project --- BencodeNET.Tests/BencodeNET.Tests.csproj | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/BencodeNET.Tests/BencodeNET.Tests.csproj b/BencodeNET.Tests/BencodeNET.Tests.csproj index fcab25b993..9decf8cab6 100644 --- a/BencodeNET.Tests/BencodeNET.Tests.csproj +++ b/BencodeNET.Tests/BencodeNET.Tests.csproj @@ -15,14 +15,19 @@ - - - - - - + + + + + + + + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 79a34125826e3d5269a9832fb693ce3154e3b10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Fri, 8 Jan 2021 21:08:52 +0100 Subject: [PATCH 8/9] Update to simplified version of AutoMockedDataAttribute --- BencodeNET.Tests/AutoMockedDataAttribute.cs | 30 +++++++++++-------- .../Torrents/TorrentParserTests.cs | 30 +++++++++---------- BencodeNET.Tests/Torrents/TorrentTests.cs | 24 +++++++-------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/BencodeNET.Tests/AutoMockedDataAttribute.cs b/BencodeNET.Tests/AutoMockedDataAttribute.cs index fb6e3c496b..3457d9bbc4 100644 --- a/BencodeNET.Tests/AutoMockedDataAttribute.cs +++ b/BencodeNET.Tests/AutoMockedDataAttribute.cs @@ -5,25 +5,31 @@ namespace BencodeNET.Tests { - public class AutoMockedDataAttribute : AutoDataAttribute + public class AutoMockedDataAttribute : CompositeDataAttribute { public AutoMockedDataAttribute() - : base(() => new Fixture().Customize(new AutoNSubstituteCustomization {ConfigureMembers = true})) + : this(new BaseAutoMockedDataAttribute()) { } - } - public class InlineAutoMockedDataAttribute : CompositeDataAttribute - { - public InlineAutoMockedDataAttribute() - : this(new AutoMockedDataAttribute()) + public AutoMockedDataAttribute(params object[] values) + : this(new BaseAutoMockedDataAttribute(), values) { } - public InlineAutoMockedDataAttribute(params object[] values) - : this(new AutoMockedDataAttribute(), values) + private AutoMockedDataAttribute(BaseAutoMockedDataAttribute baseAutoDataAttribute, params object[] values) + : base(new InlineDataAttribute(values), baseAutoDataAttribute) { } - public InlineAutoMockedDataAttribute(AutoMockedDataAttribute autoDataAttributeAttribute, params object[] values) - : base(new InlineDataAttribute(values), autoDataAttributeAttribute) - { } + private class BaseAutoMockedDataAttribute : AutoDataAttribute + { + public BaseAutoMockedDataAttribute() + : base(Configure) + { + } + + private static IFixture Configure() + { + return new Fixture().Customize(new AutoNSubstituteCustomization { ConfigureMembers = true }); + } + } } } diff --git a/BencodeNET.Tests/Torrents/TorrentParserTests.cs b/BencodeNET.Tests/Torrents/TorrentParserTests.cs index d753dbe08a..7c10c93c5c 100644 --- a/BencodeNET.Tests/Torrents/TorrentParserTests.cs +++ b/BencodeNET.Tests/Torrents/TorrentParserTests.cs @@ -130,10 +130,10 @@ public void CreationDate_InvalidValue_ReturnsEpoch() } [Theory] - [InlineAutoMockedData("utf8")] - [InlineAutoMockedData("UTF8")] - [InlineAutoMockedData("utf-8")] - [InlineAutoMockedData("UTF-8")] + [AutoMockedData("utf8")] + [AutoMockedData("UTF8")] + [AutoMockedData("utf-8")] + [AutoMockedData("UTF-8")] public void Encoding_UTF8_CanBeParsed(string encoding) { // Arrange @@ -149,8 +149,8 @@ public void Encoding_UTF8_CanBeParsed(string encoding) } [Theory] - [InlineAutoMockedData("ascii")] - [InlineAutoMockedData("ASCII")] + [AutoMockedData("ascii")] + [AutoMockedData("ASCII")] public void Encoding_ASCII_CanBeParsed(string encoding) { // Arrange @@ -166,10 +166,10 @@ public void Encoding_ASCII_CanBeParsed(string encoding) } [Theory] - [InlineAutoMockedData("")] - [InlineAutoMockedData("asdf")] - [InlineAutoMockedData("1")] - [InlineAutoMockedData("UTF 8")] + [AutoMockedData("")] + [AutoMockedData("asdf")] + [AutoMockedData("1")] + [AutoMockedData("UTF 8")] public void Encoding_InvalidValidAsNull(string encoding) { // Arrange @@ -220,11 +220,11 @@ public void Info_Pieces_IsParsed([RepeatCount(20)] byte[] pieces) } [Theory] - [InlineAutoMockedData(-1, false)] - [InlineAutoMockedData(0, false)] - [InlineAutoMockedData(1, true)] - [InlineAutoMockedData(42, false)] - [InlineAutoMockedData(12345, false)] + [AutoMockedData(-1, false)] + [AutoMockedData(0, false)] + [AutoMockedData(1, true)] + [AutoMockedData(42, false)] + [AutoMockedData(12345, false)] public void Info_Private_ShouldBeTrueOnlyIfValueIsOne(int value, bool expectedResult) { // Arrange diff --git a/BencodeNET.Tests/Torrents/TorrentTests.cs b/BencodeNET.Tests/Torrents/TorrentTests.cs index 0d688e9487..d19fc65c4a 100644 --- a/BencodeNET.Tests/Torrents/TorrentTests.cs +++ b/BencodeNET.Tests/Torrents/TorrentTests.cs @@ -189,9 +189,9 @@ public void PiecesAsHexString_Set_NullThrowsArgumentException() } [Theory] - [InlineAutoMockedData("qwer")] - [InlineAutoMockedData("123456789012345678901234567890123456789")] - [InlineAutoMockedData("12345678901234567890123456789012345678901")] + [AutoMockedData("qwer")] + [AutoMockedData("123456789012345678901234567890123456789")] + [AutoMockedData("12345678901234567890123456789012345678901")] public void PiecesAsHexString_Set_LengthNotMultipleOf40ShouldThrowArgumentException(string value) { var torrent = new Torrent(); @@ -200,15 +200,15 @@ public void PiecesAsHexString_Set_LengthNotMultipleOf40ShouldThrowArgumentExcept } [Theory] - [InlineAutoMockedData("a")] - [InlineAutoMockedData("b")] - [InlineAutoMockedData("c")] - [InlineAutoMockedData("G")] - [InlineAutoMockedData("H")] - [InlineAutoMockedData("T")] - [InlineAutoMockedData(".")] - [InlineAutoMockedData("*")] - [InlineAutoMockedData("[")] + [AutoMockedData("a")] + [AutoMockedData("b")] + [AutoMockedData("c")] + [AutoMockedData("G")] + [AutoMockedData("H")] + [AutoMockedData("T")] + [AutoMockedData(".")] + [AutoMockedData("*")] + [AutoMockedData("[")] public void PiecesAsHexString_Set_ValueWithNonUppercaseHexCharacterShouldThrowArgumentException(string value) { var torrent = new Torrent(); From c0f1313959282f5ede32cf78272e86f11a268179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kruse?= Date: Sat, 23 Jan 2021 16:55:45 +0100 Subject: [PATCH 9/9] Update changelog for v4.0.0 --- CHANGELOG.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75e0c2d098..7379d51ff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +... + +## [4.0.0] - 2021-01-23 ### Changed -- Changed target frameworks to: +- Changed supported frameworks to: - .NET Standard 2.0 - .NET Standard 2.1 - .NET Core App 2.1 - .NET 5.0 - -... +- `Torrent.Pieces` can now only be set to an array with a length which is a multiple of 20. ## [3.1.4] - 2020-03-06 ### Fixed @@ -157,8 +159,9 @@ and generally better usability; albeit a bit more complex. ## [1.0.0] - 2015-09-19 -[Unreleased]: ../../compare/v3.1.4...HEAD -[3.1.4]: ../../compare/v3.1.4...v3.1.4 +[Unreleased]: ../../compare/v4.0.0...HEAD +[4.0.0]: ../../compare/v3.1.4...v4.0.0 +[3.1.4]: ../../compare/v3.1.3...v3.1.4 [3.1.3]: ../../compare/v3.1.0...v3.1.3 [3.1.0]: ../../compare/v3.0.1...v3.1.0 [3.0.1]: ../../compare/v3.0.0...v3.0.1