Skip to content

Commit 94ea801

Browse files
committed
PR Feedback (Including PipeReader Property)
1 parent 1461ee4 commit 94ea801

File tree

2 files changed

+46
-12
lines changed

2 files changed

+46
-12
lines changed

src/Components/Server/src/Circuits/RemoteJSDataStream.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,14 @@ private RemoteJSDataStream(
8282

8383
_pipe = new Pipe(new PipeOptions(pauseWriterThreshold: pauseIncomingBytesThreshold, resumeWriterThreshold: resumeIncomingBytesThreshold));
8484
_pipeReaderStream = _pipe.Reader.AsStream();
85+
PipeReader = _pipe.Reader;
8586
}
8687

88+
/// <summary>
89+
/// Gets a <see cref="PipeReader"/> to directly read data sent by the JavaScript client.
90+
/// </summary>
91+
public PipeReader PipeReader { get; }
92+
8793
private async Task<bool> ReceiveData(long chunkId, byte[] chunk, string error)
8894
{
8995
try
@@ -201,7 +207,7 @@ private async Task ThrowOnTimeout()
201207
if (!_disposed && (DateTimeOffset.UtcNow >= _lastDataReceivedTime.Add(_jsInteropDefaultCallTimeout)))
202208
{
203209
// Dispose of the stream if a chunk isn't received within the jsInteropDefaultCallTimeout.
204-
var timeoutException = new TimeoutException("Did not receive any data in the alloted time.");
210+
var timeoutException = new TimeoutException("Did not receive any data in the allotted time.");
205211
await CompletePipeAndDisposeStream(timeoutException);
206212
_runtime.RaiseUnhandledException(timeoutException);
207213
}

src/Components/Server/test/Circuits/RemoteJSDataStreamTest.cs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class RemoteJSDataStreamTest
2020
private static readonly TestRemoteJSRuntime _jsRuntime = new(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
2121

2222
[Fact]
23-
public async void CreateRemoteJSDataStreamAsync_CreatesStream()
23+
public async Task CreateRemoteJSDataStreamAsync_CreatesStream()
2424
{
2525
// Arrange
2626
var jsStreamReference = Mock.Of<IJSStreamReference>();
@@ -33,7 +33,7 @@ public async void CreateRemoteJSDataStreamAsync_CreatesStream()
3333
}
3434

3535
[Fact]
36-
public async void ReceiveData_DoesNotFindStream()
36+
public async Task ReceiveData_DoesNotFindStream()
3737
{
3838
// Arrange
3939
var chunk = new byte[] { 3, 5, 6, 7 };
@@ -47,7 +47,7 @@ public async void ReceiveData_DoesNotFindStream()
4747
}
4848

4949
[Fact]
50-
public async void ReceiveData_SuccessReadsBackStream()
50+
public async Task ReceiveData_SuccessReadsBackStream()
5151
{
5252
// Arrange
5353
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
@@ -75,7 +75,35 @@ public async void ReceiveData_SuccessReadsBackStream()
7575
}
7676

7777
[Fact]
78-
public async void ReceiveData_WithError()
78+
public async Task ReceiveData_SuccessReadsBackPipeReader()
79+
{
80+
// Arrange
81+
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
82+
var remoteJSDataStream = await CreateRemoteJSDataStreamAsync(jsRuntime);
83+
var streamId = GetStreamId(remoteJSDataStream, jsRuntime);
84+
var chunk = new byte[100];
85+
var random = new Random();
86+
random.NextBytes(chunk);
87+
88+
var sendDataTask = Task.Run(async () =>
89+
{
90+
// Act 1
91+
var success = await RemoteJSDataStream.ReceiveData(jsRuntime, streamId, chunkId: 0, chunk, error: null);
92+
return success;
93+
});
94+
95+
// Act & Assert 2
96+
using var memoryStream = new MemoryStream();
97+
await remoteJSDataStream.PipeReader.CopyToAsync(memoryStream);
98+
Assert.Equal(chunk, memoryStream.ToArray());
99+
100+
// Act & Assert 3
101+
var sendDataCompleted = await sendDataTask;
102+
Assert.True(sendDataCompleted);
103+
}
104+
105+
[Fact]
106+
public async Task ReceiveData_WithError()
79107
{
80108
// Arrange
81109
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
@@ -93,7 +121,7 @@ public async void ReceiveData_WithError()
93121
}
94122

95123
[Fact]
96-
public async void ReceiveData_WithZeroLengthChunk()
124+
public async Task ReceiveData_WithZeroLengthChunk()
97125
{
98126
// Arrange
99127
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
@@ -112,7 +140,7 @@ public async void ReceiveData_WithZeroLengthChunk()
112140
}
113141

114142
[Fact]
115-
public async void ReceiveData_ProvidedWithMoreBytesThanRemaining()
143+
public async Task ReceiveData_ProvidedWithMoreBytesThanRemaining()
116144
{
117145
// Arrange
118146
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
@@ -132,7 +160,7 @@ public async void ReceiveData_ProvidedWithMoreBytesThanRemaining()
132160
}
133161

134162
[Fact]
135-
public async void ReceiveData_ProvidedWithOutOfOrderChunk_SimulatesSignalRDisconnect()
163+
public async Task ReceiveData_ProvidedWithOutOfOrderChunk_SimulatesSignalRDisconnect()
136164
{
137165
// Arrange
138166
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
@@ -156,7 +184,7 @@ public async void ReceiveData_ProvidedWithOutOfOrderChunk_SimulatesSignalRDiscon
156184
}
157185

158186
[Fact]
159-
public async void ReceiveData_NoDataProvidedBeforeTimeout_StreamDisposed()
187+
public async Task ReceiveData_NoDataProvidedBeforeTimeout_StreamDisposed()
160188
{
161189
// Arrange
162190
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
@@ -190,7 +218,7 @@ public async void ReceiveData_NoDataProvidedBeforeTimeout_StreamDisposed()
190218
// Confirm exception also raised on pipe reader
191219
using var mem = new MemoryStream();
192220
var ex = await Assert.ThrowsAsync<TimeoutException>(async () => await remoteJSDataStream.CopyToAsync(mem));
193-
Assert.Equal("Did not receive any data in the alloted time.", ex.Message);
221+
Assert.Equal("Did not receive any data in the allotted time.", ex.Message);
194222

195223
// Act & Assert 3
196224
// Ensures stream is disposed after the timeout and any additional chunks aren't accepted
@@ -199,14 +227,14 @@ public async void ReceiveData_NoDataProvidedBeforeTimeout_StreamDisposed()
199227
}
200228

201229
[Fact]
202-
public async void ReceiveData_ReceivesDataThenTimesout_StreamDisposed()
230+
public async Task ReceiveData_ReceivesDataThenTimesout_StreamDisposed()
203231
{
204232
// Arrange
205233
var jsRuntime = new TestRemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions()), Mock.Of<ILogger<RemoteJSRuntime>>());
206234
var timeoutExceptionRaisedSemaphore = new SemaphoreSlim(initialCount: 0, maxCount: 1);
207235
jsRuntime.UnhandledException += (_, ex) =>
208236
{
209-
Assert.Equal("Did not receive any data in the alloted time.", ex.Message);
237+
Assert.Equal("Did not receive any data in the allotted time.", ex.Message);
210238
Assert.IsType<TimeoutException>(ex);
211239
timeoutExceptionRaisedSemaphore.Release();
212240
};

0 commit comments

Comments
 (0)