Skip to content

Commit

Permalink
Implement Shuffle, GetString, and GetItems on Random{NumberGenerator} (
Browse files Browse the repository at this point in the history
…#78598)

* Implement Shuffle, GetString, and GetItems.

* Cleanup and additional tests

* Use where possible

* Code review feedback

* Additional uses of Random throughout tests

* Feedback on documentation

* Use ref to span to get span in string.Create.

Co-authored-by: Benjamin Moir <[email protected]>
Co-authored-by: Theodore Tsirpanis <[email protected]>
Co-authored-by: Michał Petryka <[email protected]>

* Code review feedback

* Code review feedback

* Apply suggestions from code review

Co-authored-by: Dan Moseley <[email protected]>

* Use AssertExtensions over Assert

* Improve comment

* No idea where AssertHexString came from

* Update src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs

Co-authored-by: Jeremy Barton <[email protected]>

Co-authored-by: Benjamin Moir <[email protected]>
Co-authored-by: Theodore Tsirpanis <[email protected]>
Co-authored-by: Michał Petryka <[email protected]>
Co-authored-by: Dan Moseley <[email protected]>
Co-authored-by: Stephen Toub <[email protected]>
Co-authored-by: Jeremy Barton <[email protected]>
  • Loading branch information
7 people authored Jan 12, 2023
1 parent 210a7a9 commit 05e1fe1
Show file tree
Hide file tree
Showing 21 changed files with 840 additions and 136 deletions.
22 changes: 0 additions & 22 deletions src/libraries/Common/tests/System/RandomExtensions.cs

This file was deleted.

19 changes: 3 additions & 16 deletions src/libraries/Common/tests/Tests/System/StringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3776,12 +3776,7 @@ public static void IsWhiteSpaceTrueLatin1()
Random rand = new Random(42);
for (int length = 0; length < 32; length++)
{
char[] a = new char[length];
for (int i = 0; i < length; i++)
{
a[i] = s_whiteSpaceCharacters[rand.Next(0, s_whiteSpaceCharacters.Length - 1)];
}

char[] a = rand.GetItems<char>(s_whiteSpaceCharacters, length);
string s1 = new string(a);
bool result = string.IsNullOrWhiteSpace(s1);
Assert.True(result);
Expand Down Expand Up @@ -3810,11 +3805,7 @@ public static void IsWhiteSpaceTrue()
Random rand = new Random(42);
for (int length = 0; length < 32; length++)
{
char[] a = new char[length];
for (int i = 0; i < length; i++)
{
a[i] = s_whiteSpaceCharacters[rand.Next(0, s_whiteSpaceCharacters.Length)];
}
char[] a = rand.GetItems<char>(s_whiteSpaceCharacters, length);

string s1 = new string(a);
bool result = string.IsNullOrWhiteSpace(s1);
Expand All @@ -3832,11 +3823,7 @@ public static void IsWhiteSpaceFalse()
Random rand = new Random(42);
for (int length = 1; length < 32; length++)
{
char[] a = new char[length];
for (int i = 0; i < length; i++)
{
a[i] = s_whiteSpaceCharacters[rand.Next(0, s_whiteSpaceCharacters.Length)];
}
char[] a = rand.GetItems<char>(s_whiteSpaceCharacters, length);
var span = new Span<char>(a);

// first character is not a white-space character
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Common.System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
Link="Common\System\EnumTypes.cs" />
<Compile Include="$(CommonTestPath)System\ObjectCloner.cs"
Link="Common\System\ObjectCloner.cs" />
<Compile Include="$(CommonTestPath)System\RandomExtensions.cs"
Link="Common\System\RandomExtensions.cs" />
<Compile Include="$(CommonTestPath)System\Runtime\Serialization\Formatters\BinaryFormatterHelpers.cs"
Link="Common\System\Runtime\Serialization\Formatters\BinaryFormatterHelpers.cs" />
<!-- Generic tests -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -947,14 +947,8 @@ private static void ValidateTrustAttribute(TRUSTED_DOMAIN_INFORMATION_EX domainI

internal static string CreateTrustPassword()
{
#if NETCOREAPP3_0_OR_GREATER
return string.Create<object?>(PASSWORD_LENGTH, null, static (destination, _) =>
{
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PasswordCharacterSet[RandomNumberGenerator.GetInt32(PasswordCharacterSet.Length)];
}
});
#if NET8_0_OR_GREATER
return RandomNumberGenerator.GetString(PasswordCharacterSet, PASSWORD_LENGTH);
#else
char[] cBuf = new char[PASSWORD_LENGTH];
byte[] randomBuffer = new byte[1];
Expand Down
27 changes: 7 additions & 20 deletions src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace System.IO.Tests
{
public partial class StreamReaderTests
{
private const string LowerAlpha = "abcdefghijklmnopqrstuvwxyz";

protected virtual Stream CreateStream()
{
return new MemoryStream();
Expand Down Expand Up @@ -400,12 +402,8 @@ public async Task Read_EmptySpan_ReadsNothing(int length)
[InlineData(100, 50, 101)]
public void Read_ReadsExpectedData(int readLength, int totalLength, int bufferSize)
{
var data = new char[totalLength];
var r = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)('a' + r.Next(0, 26));
}
char[] data = r.GetItems<char>(LowerAlpha, totalLength);

var result = new char[data.Length];
Span<char> dst = result;
Expand All @@ -431,12 +429,8 @@ public void Read_ReadsExpectedData(int readLength, int totalLength, int bufferSi
[InlineData(100, 50, 101)]
public void ReadBlock_ReadsExpectedData(int readLength, int totalLength, int bufferSize)
{
var data = new char[totalLength];
var r = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)('a' + r.Next(0, 26));
}
char[] data = r.GetItems<char>(LowerAlpha, totalLength);

var result = new char[data.Length];
Span<char> dst = result;
Expand All @@ -462,12 +456,8 @@ public void ReadBlock_ReadsExpectedData(int readLength, int totalLength, int buf
[InlineData(100, 50, 101)]
public async Task ReadAsync_ReadsExpectedData(int readLength, int totalLength, int bufferSize)
{
var data = new char[totalLength];
var r = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)('a' + r.Next(0, 26));
}
char[] data = r.GetItems<char>(LowerAlpha, totalLength);

var result = new char[data.Length];
Memory<char> dst = result;
Expand All @@ -493,12 +483,9 @@ public async Task ReadAsync_ReadsExpectedData(int readLength, int totalLength, i
[InlineData(100, 50, 101)]
public async Task ReadBlockAsync_ReadsExpectedData(int readLength, int totalLength, int bufferSize)
{
var data = new char[totalLength];
var r = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)('a' + r.Next(0, 26));
}
char[] data = r.GetItems<char>(LowerAlpha, totalLength);


var result = new char[data.Length];
Memory<char> dst = result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace System.IO.Tests
{
public partial class WriteTests
{
private const string LowerAlpha = "abcdefghijklmnopqrstuvwxyz";

protected virtual Stream CreateStream()
{
return new MemoryStream();
Expand Down Expand Up @@ -250,12 +252,8 @@ public void Write_Span_WritesExpectedData(int length, int writeSize, int writerB
using (var s = new MemoryStream())
using (var writer = new StreamWriter(s, Encoding.ASCII, writerBufferSize) { AutoFlush = autoFlush })
{
var data = new char[length];
var rand = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)(rand.Next(0, 26) + 'a');
}
char[] data = rand.GetItems<char>(LowerAlpha, length);

Span<char> source = data;
while (source.Length > 0)
Expand Down Expand Up @@ -283,12 +281,8 @@ public async Task Write_Memory_WritesExpectedData(int length, int writeSize, int
using (var s = new MemoryStream())
using (var writer = new StreamWriter(s, Encoding.ASCII, writerBufferSize) { AutoFlush = autoFlush })
{
var data = new char[length];
var rand = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)(rand.Next(0, 26) + 'a');
}
char[] data = rand.GetItems<char>(LowerAlpha, length);

ReadOnlyMemory<char> source = data;
while (source.Length > 0)
Expand Down Expand Up @@ -316,12 +310,8 @@ public void WriteLine_Span_WritesExpectedData(int length, int writeSize, int wri
using (var s = new MemoryStream())
using (var writer = new StreamWriter(s, Encoding.ASCII, writerBufferSize) { AutoFlush = autoFlush })
{
var data = new char[length];
var rand = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)(rand.Next(0, 26) + 'a');
}
char[] data = rand.GetItems<char>(LowerAlpha, length);

Span<char> source = data;
while (source.Length > 0)
Expand Down Expand Up @@ -349,12 +339,8 @@ public async Task WriteLineAsync_Memory_WritesExpectedData(int length, int write
using (var s = new MemoryStream())
using (var writer = new StreamWriter(s, Encoding.ASCII, writerBufferSize) { AutoFlush = autoFlush })
{
var data = new char[length];
var rand = new Random(42);
for (int i = 0; i < data.Length; i++)
{
data[i] = (char)(rand.Next(0, 26) + 'a');
}
char[] data = rand.GetItems<char>(LowerAlpha, length);

ReadOnlyMemory<char> source = data;
while (source.Length > 0)
Expand Down
7 changes: 1 addition & 6 deletions src/libraries/System.Linq/tests/Shuffler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ public static class Shuffler
public static T[] Shuffle<T>(T[] array)
{
var r = new Random(42);
int i = array.Length;
while (i > 1)
{
int j = r.Next(i--);
(array[i], array[j]) = (array[j], array[i]);
}
r.Shuffle(array);
return array;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,7 @@ private static string GetRandomAlphaNumericString()
{
const int Length = 16;
const string CharacterSet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

return string.Create<object?>(Length, null, static (destination, _) =>
{
for (int i = 0; i < destination.Length; i++)
{
destination[i] = CharacterSet[RandomNumberGenerator.GetInt32(CharacterSet.Length)];
}
});
return RandomNumberGenerator.GetString(CharacterSet, Length);
}

private static string ComputeHash(string data, string algorithm)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
public async Task GetAsync_LargeHeader_Success(string headerName, int headerValueLength)
{
var rand = new Random(42);
string headerValue = string.Concat(Enumerable.Range(0, headerValueLength).Select(_ => (char)('A' + rand.Next(26))));
string headerValue = new string(rand.GetItems<char>("ABCDEFGHIJKLMNOPQRSTUVWXYZ", headerValueLength));

const string ContentString = "hello world";
await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,7 @@ public async Task Read_FullLengthSynchronous_Success(bool transferEncodingChunke
public async Task Read_LargeLengthAsynchronous_Success(bool transferEncodingChunked)
{
var rand = new Random(42);
byte[] expected = Enumerable
.Range(0, 128*1024 + 1) // More than 128kb
.Select(_ => (byte)('a' + rand.Next(0, 26)))
.ToArray();
byte[] expected = rand.GetItems("abcdefghijklmnopqrstuvwxyz"u8, 128 * 1024 + 1);

Task<HttpListenerContext> contextTask = _listener.GetContextAsync();

Expand Down Expand Up @@ -269,10 +266,7 @@ public async Task Read_LargeLengthAsynchronous_Success(bool transferEncodingChun
public async Task Read_LargeLengthSynchronous_Success(bool transferEncodingChunked)
{
var rand = new Random(42);
byte[] expected = Enumerable
.Range(0, 128 * 1024 + 1) // More than 128kb
.Select(_ => (byte)('a' + rand.Next(0, 26)))
.ToArray();
byte[] expected = rand.GetItems("abcdefghijklmnopqrstuvwxyz"u8, 128 * 1024 + 1);

Task<HttpListenerContext> contextTask = _listener.GetContextAsync();

Expand Down
2 changes: 1 addition & 1 deletion src/libraries/System.Net.WebClient/tests/WebClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ public async Task UploadData_LargeData_Success(Uri server)
}

private static string GetRandomText(int length) =>
new string(Enumerable.Range(0, 512 * 1024).Select(_ => (char)('a' + Random.Shared.Next(0, 26))).ToArray());
new string(Random.Shared.GetItems<char>("abcdefghijklmnopqrstuvwxyz", 512 * 1024));

[OuterLoop("Uses external servers")]
[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@
<data name="Arg_EmptyArray" xml:space="preserve">
<value>Array may not be empty.</value>
</data>
<data name="Arg_EmptySpan" xml:space="preserve">
<value>Span may not be empty.</value>
</data>
<data name="Arg_EndOfStreamException" xml:space="preserve">
<value>Attempted to read past the end of the stream.</value>
</data>
Expand Down
Loading

0 comments on commit 05e1fe1

Please sign in to comment.