Skip to content

Commit 4403fa4

Browse files
author
ladeak
committed
Generalizing Http3FramingStreamWriterTests
1 parent a769b99 commit 4403fa4

File tree

3 files changed

+104
-28
lines changed

3 files changed

+104
-28
lines changed

src/CHttpServer/CHttpServer/Http3/Http3DataFramingStreamWriter.cs renamed to src/CHttpServer/CHttpServer/Http3/Http3FramingStreamWriter.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CHttpServer.Http3;
77

8-
internal class Http3DataFramingStreamWriter(Stream responseStream, ArrayPool<byte>? memoryPool = null, Func<CancellationToken, Task>? onResponseStartingCallback = null) : PipeWriter
8+
internal class Http3FramingStreamWriter(Stream responseStream, byte frameType, ArrayPool<byte>? memoryPool = null, Func<CancellationToken, Task>? onResponseStartingCallback = null) : PipeWriter
99
{
1010
private readonly struct Segment()
1111
{
@@ -20,6 +20,7 @@ private readonly struct Segment()
2020
private readonly List<Segment> _segments = new List<Segment>(128) { new Segment() };
2121
private readonly ArrayPool<byte> _memoryPool = memoryPool ?? ArrayPool<byte>.Shared;
2222
private Stream _responseStream = responseStream;
23+
private readonly byte _frameType = frameType;
2324
private CancellationTokenSource? _cts;
2425
private bool _isCompleted = false;
2526
private long _unflushedBytes;
@@ -178,7 +179,7 @@ public override async ValueTask<FlushResult> FlushAsync(CancellationToken cancel
178179
}
179180
return new FlushResult(true, false);
180181
}
181-
using var _ = cancellationToken.Register(static (object? state) => { ((Http3DataFramingStreamWriter)state!).InternalCancellation.Cancel(); }, this);
182+
using var _ = cancellationToken.Register(static (object? state) => { ((Http3FramingStreamWriter)state!).InternalCancellation.Cancel(); }, this);
182183

183184
if (_onResponseStartingCallback != null)
184185
{
@@ -273,7 +274,7 @@ private void Flush()
273274
/// <returns>The length of the frame header in bytes.</returns>
274275
private int PrepareDataFrameHeader(long length)
275276
{
276-
_buffer[0] = 0;
277+
_buffer[0] = _frameType;
277278
var success = VariableLenghtIntegerDecoder.TryWrite(_buffer.AsSpan(1), length, out var writtenCount);
278279
Debug.Assert(success);
279280
return writtenCount + 1;

src/CHttpServer/CHttpServer/Http3/QPackDecoder.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Runtime.Versioning;
77
using System.Text;
88
using CHttpServer.System.Net.Http.HPack;
9+
using Microsoft.AspNetCore.Http;
910

1011
namespace CHttpServer.Http3;
1112

@@ -411,6 +412,16 @@ private bool DecodeRequiredInsertionCount(ReadOnlySequence<byte> source, IQPackH
411412
return true;
412413
}
413414

415+
/// <summary>
416+
/// Encodes a header dictionary into a response stream.
417+
/// </summary>
418+
internal void Encode(int statusCode, IHeaderDictionary headers, PipeWriter writer)
419+
{
420+
// length?
421+
// iterate headers, match _staticEncoderTable
422+
// write, wire format
423+
}
424+
414425
private static readonly KnownHeaderField[] _staticDecoderTable =
415426
[
416427
CreateHeaderField(0, ":authority", ""),

tests/CHttpServer.Tests/Http3/Http3DataFramingStreamWriterTests.cs renamed to tests/CHttpServer.Tests/Http3/Http3FramingStreamWriterTests.cs

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CHttpServer.Tests.Http3;
77

8-
public class Http3DataFramingStreamWriterTests
8+
public class Http3FramingStreamWriterTests
99
{
1010
[Theory]
1111
[InlineData(10, 2)]
@@ -17,7 +17,7 @@ public async Task GetSpan_Flush_WritesToStreamWithFrameHeader(int payloadLength,
1717
{
1818
var stream = new MemoryStream();
1919
var arrayPool = new TestArrayPool();
20-
var sut = new Http3DataFramingStreamWriter(stream, arrayPool);
20+
var sut = new Http3FramingStreamWriter(stream, 0, arrayPool);
2121
var buffer = sut.GetSpan(payloadLength);
2222
Assert.True(buffer.Length >= payloadLength);
2323
for (int i = 0; i < payloadLength; i++)
@@ -42,7 +42,7 @@ public async Task GetSpan_Flush_WritesToStreamWithFrameHeader(int payloadLength,
4242
[Fact]
4343
public void GetMemory_NoAdvance_Returns_SameMemory()
4444
{
45-
var sut = new Http3DataFramingStreamWriter(Stream.Null);
45+
var sut = new Http3FramingStreamWriter(Stream.Null, 0);
4646
var m1 = sut.GetMemory(100);
4747
m1.Span.Fill(1);
4848

@@ -59,7 +59,7 @@ public void GetMemory_NoAdvance_Returns_SameMemory()
5959
[Fact]
6060
public void GetMemory_Advance_Returns_NotSameMemory()
6161
{
62-
var sut = new Http3DataFramingStreamWriter(Stream.Null);
62+
var sut = new Http3FramingStreamWriter(Stream.Null, 0);
6363
var m1 = sut.GetMemory(100);
6464
m1.Span.Fill(1);
6565
sut.Advance(100);
@@ -80,7 +80,7 @@ public void GetMemory_Advance_Returns_NotSameMemory()
8080
public void AdvanceTooMuch_ThrowsArgumentOutOfRangeException()
8181
{
8282
var smallArrayPool = ArrayPool<byte>.Create(128, 1);
83-
var sut = new Http3DataFramingStreamWriter(Stream.Null, smallArrayPool);
83+
var sut = new Http3FramingStreamWriter(Stream.Null, 0, smallArrayPool);
8484
Assert.Throws<ArgumentOutOfRangeException>(() => sut.Advance(1));
8585

8686
sut.GetMemory(128);
@@ -93,7 +93,7 @@ public void AdvanceTooMuch_ThrowsArgumentOutOfRangeException()
9393
[Fact]
9494
public async Task WhenCompleted_CannotGetMoreMemory()
9595
{
96-
var sut = new Http3DataFramingStreamWriter(Stream.Null);
96+
var sut = new Http3FramingStreamWriter(Stream.Null, 0);
9797
sut.Complete();
9898
sut.Complete(); // It is OK to call twice.
9999
Assert.Throws<InvalidOperationException>(() => sut.GetMemory(1));
@@ -108,7 +108,7 @@ public async Task WhenCompleted_CannotGetMoreMemory()
108108
[Fact]
109109
public async Task WhenCompletedAsync_CannotGetMoreMemory()
110110
{
111-
var sut = new Http3DataFramingStreamWriter(Stream.Null);
111+
var sut = new Http3FramingStreamWriter(Stream.Null, 0);
112112
await sut.CompleteAsync();
113113
await sut.CompleteAsync(); // It is OK to call twice.
114114
Assert.Throws<InvalidOperationException>(() => sut.GetMemory(1));
@@ -124,7 +124,7 @@ public async Task WhenCompletedAsync_CannotGetMoreMemory()
124124
public async Task WriteAsync_WritesToStreamAndFlushes()
125125
{
126126
var stream = new MemoryStream();
127-
var sut = new Http3DataFramingStreamWriter(stream);
127+
var sut = new Http3FramingStreamWriter(stream, 0);
128128
byte[] data = [0, 1, 2, 3, 4, 5];
129129
await sut.WriteAsync(data, TestContext.Current.CancellationToken);
130130

@@ -145,7 +145,7 @@ public async Task WriteAsync_WritesToStreamAndFlushes()
145145
public async Task WriteAsync_GetMemory_DoesNotMix()
146146
{
147147
var stream = new MemoryStream();
148-
var sut = new Http3DataFramingStreamWriter(stream);
148+
var sut = new Http3FramingStreamWriter(stream, 0);
149149
sut.GetMemory(1);
150150
sut.Advance(1);
151151

@@ -170,7 +170,7 @@ public async Task Reset_Clears_Buffers()
170170
{
171171
var stream = new MemoryStream();
172172
var arrayPool = new TestArrayPool();
173-
var sut = new Http3DataFramingStreamWriter(stream, arrayPool);
173+
var sut = new Http3FramingStreamWriter(stream, 0, arrayPool);
174174
var memory = sut.GetSpan(1);
175175
memory[0] = 1;
176176
sut.Advance(1);
@@ -187,7 +187,7 @@ public void Complete_FlushesBuffer()
187187
{
188188
var stream = new MemoryStream();
189189
var arrayPool = new TestArrayPool();
190-
var sut = new Http3DataFramingStreamWriter(stream, arrayPool);
190+
var sut = new Http3FramingStreamWriter(stream, 0, arrayPool);
191191
var memory = sut.GetSpan(1);
192192
memory[0] = 1;
193193
sut.Advance(1);
@@ -206,7 +206,7 @@ public async Task CompleteAsync_FlushesBuffer()
206206
{
207207
var stream = new MemoryStream();
208208
var arrayPool = new TestArrayPool();
209-
var sut = new Http3DataFramingStreamWriter(stream, arrayPool);
209+
var sut = new Http3FramingStreamWriter(stream, 0, arrayPool);
210210
var memory = sut.GetSpan(1);
211211
memory[0] = 1;
212212
sut.Advance(1);
@@ -224,7 +224,7 @@ public async Task CompleteAsync_FlushesBuffer()
224224
public void MultipleAdvanceCalls()
225225
{
226226
var stream = new MemoryStream();
227-
var sut = new Http3DataFramingStreamWriter(stream);
227+
var sut = new Http3FramingStreamWriter(stream, 0);
228228
var memory = sut.GetSpan(5);
229229
memory[0] = 0;
230230
memory[1] = 1;
@@ -249,7 +249,7 @@ public void MultipleAdvanceCalls()
249249
public async Task CancelPendingFlush()
250250
{
251251
var stream = new MemoryStream();
252-
var sut = new Http3DataFramingStreamWriter(stream);
252+
var sut = new Http3FramingStreamWriter(stream, 0);
253253
var memory = sut.GetSpan(5);
254254
sut.Advance(5);
255255

@@ -269,7 +269,7 @@ public async Task CancelPendingFlushDuringButBeforeWriting()
269269
{
270270
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
271271
var stream = new WaitBeforeWriteStream(tcs);
272-
var sut = new Http3DataFramingStreamWriter(stream);
272+
var sut = new Http3FramingStreamWriter(stream, 0);
273273
var memory = sut.GetSpan(5);
274274
sut.Advance(5);
275275

@@ -289,7 +289,7 @@ public async Task CancelPendingFlushAfterWriting()
289289
{
290290
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
291291
var stream = new WaitBeforeWriteStream(tcs);
292-
var sut = new Http3DataFramingStreamWriter(stream);
292+
var sut = new Http3FramingStreamWriter(stream, 0);
293293
var memory = sut.GetSpan(5);
294294
sut.Advance(5);
295295

@@ -309,7 +309,7 @@ public async Task Flush_CancellationToken_Throws()
309309
{
310310
var stream = new MemoryStream();
311311
var arrayPool = new TestArrayPool();
312-
var sut = new Http3DataFramingStreamWriter(stream, arrayPool);
312+
var sut = new Http3FramingStreamWriter(stream, 0, arrayPool);
313313
var memory = sut.GetSpan(5);
314314
sut.Advance(5);
315315
await Assert.ThrowsAsync<TaskCanceledException>(async () => await sut.FlushAsync(new CancellationToken(true)));
@@ -332,7 +332,7 @@ public async Task Flushing_Into_ClosedStream()
332332
testStream.Close();
333333

334334
var arrayPool = new TestArrayPool();
335-
var sut = new Http3DataFramingStreamWriter(testStream, arrayPool);
335+
var sut = new Http3FramingStreamWriter(testStream, 0, arrayPool);
336336
var memory = sut.GetSpan(5);
337337
sut.Advance(5);
338338
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await sut.FlushAsync(TestContext.Current.CancellationToken));
@@ -355,7 +355,7 @@ public async Task WriteAsync_Into_ClosedStream()
355355
testStream.Close();
356356

357357
var arrayPool = new TestArrayPool();
358-
var sut = new Http3DataFramingStreamWriter(testStream, arrayPool);
358+
var sut = new Http3FramingStreamWriter(testStream, 0, arrayPool);
359359
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await sut.WriteAsync(new byte[1], TestContext.Current.CancellationToken));
360360

361361
Assert.True(sut.Completion.IsFaulted);
@@ -368,7 +368,7 @@ public async Task GetMemory_WhenDataAvailable_InSegment()
368368
// Setup a stream.
369369
var ms = new MemoryStream();
370370
var arrayPool = new TestArrayPool(32, 2);
371-
var sut = new Http3DataFramingStreamWriter(ms, arrayPool);
371+
var sut = new Http3FramingStreamWriter(ms, 0, arrayPool);
372372
Span<byte> data = [0, 1, 2, 3, 4];
373373
var memory0 = sut.GetMemory(data.Length);
374374
data.CopyTo(memory0.Span);
@@ -398,7 +398,7 @@ public async Task GetMemory_AddsNewSegments()
398398
// Setup a stream.
399399
var ms = new MemoryStream();
400400
var arrayPool = new TestArrayPool(16, 2);
401-
var sut = new Http3DataFramingStreamWriter(ms, arrayPool);
401+
var sut = new Http3FramingStreamWriter(ms, 0, arrayPool);
402402
byte[] data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
403403
var memory0 = sut.GetMemory(data.Length);
404404
data.CopyTo(memory0.Span);
@@ -428,7 +428,7 @@ public async Task GetMemory_ReturnsArrayThatWasUnusedIfTooSmall()
428428
// Setup a stream.
429429
var ms = new MemoryStream();
430430
var arrayPool = new TestArrayPool(32, 2);
431-
var sut = new Http3DataFramingStreamWriter(ms, arrayPool);
431+
var sut = new Http3FramingStreamWriter(ms, 0, arrayPool);
432432
byte[] data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
433433
var memory0 = sut.GetMemory(data.Length);
434434
data.CopyTo(memory0.Span);
@@ -463,7 +463,7 @@ Task Callback(CancellationToken token)
463463
}
464464

465465
var stream = new MemoryStream();
466-
var sut = new Http3DataFramingStreamWriter(stream, onResponseStartingCallback: Callback);
466+
var sut = new Http3FramingStreamWriter(stream, 0, onResponseStartingCallback: Callback);
467467

468468
sut.GetMemory(1);
469469
sut.Advance(1);
@@ -488,7 +488,7 @@ Task Callback(CancellationToken token)
488488
}
489489

490490
var stream = new MemoryStream();
491-
var sut = new Http3DataFramingStreamWriter(stream, onResponseStartingCallback: Callback);
491+
var sut = new Http3FramingStreamWriter(stream, 0, onResponseStartingCallback: Callback);
492492

493493
Assert.Equal(0, invocationCount);
494494
await sut.WriteAsync(new byte[1], TestContext.Current.CancellationToken);
@@ -508,14 +508,78 @@ Task Callback(CancellationToken token)
508508
}
509509

510510
var stream = new MemoryStream();
511-
var sut = new Http3DataFramingStreamWriter(stream, onResponseStartingCallback: Callback);
511+
var sut = new Http3FramingStreamWriter(stream, 0, onResponseStartingCallback: Callback);
512512
sut.GetMemory(1);
513513
sut.Advance(1);
514514
Assert.Equal(0, invocationCount);
515515
sut.Complete();
516516
Assert.Equal(1, invocationCount);
517517
}
518518

519+
[Theory]
520+
[InlineData(1)]
521+
[InlineData(4)]
522+
public async Task GetMemoryFlushAsync_Writes_FrameType(byte frameType)
523+
{
524+
var ms = new MemoryStream();
525+
var sut = new Http3FramingStreamWriter(ms, frameType);
526+
sut.GetMemory(1).Span[0] = 9;
527+
sut.Advance(1);
528+
await sut.FlushAsync(TestContext.Current.CancellationToken);
529+
530+
byte[] expected = [frameType, 99, 9];
531+
VariableLenghtIntegerDecoder.TryWrite(expected.AsSpan(1), 1, out _);
532+
533+
Assert.Equal(expected, ms.ToArray());
534+
}
535+
536+
[Fact]
537+
public void Complete_Writes_FrameType()
538+
{
539+
byte frameType = 4;
540+
var ms = new MemoryStream();
541+
var sut = new Http3FramingStreamWriter(ms, frameType);
542+
sut.GetMemory(1).Span[0] = 9;
543+
sut.Advance(1);
544+
sut.Complete();
545+
546+
byte[] expected = [frameType, 99, 9];
547+
VariableLenghtIntegerDecoder.TryWrite(expected.AsSpan(1), 1, out _);
548+
549+
Assert.Equal(expected, ms.ToArray());
550+
}
551+
552+
[Fact]
553+
public async Task CompleteAsync_Writes_FrameType()
554+
{
555+
byte frameType = 4;
556+
var ms = new MemoryStream();
557+
var sut = new Http3FramingStreamWriter(ms, frameType);
558+
sut.GetMemory(1).Span[0] = 9;
559+
sut.Advance(1);
560+
await sut.CompleteAsync();
561+
562+
byte[] expected = [frameType, 99, 9];
563+
VariableLenghtIntegerDecoder.TryWrite(expected.AsSpan(1), 1, out _);
564+
565+
Assert.Equal(expected, ms.ToArray());
566+
}
567+
568+
[Fact]
569+
public async Task WriteAsync_Writes_FrameType()
570+
{
571+
byte frameType = 4;
572+
var ms = new MemoryStream();
573+
var sut = new Http3FramingStreamWriter(ms, frameType);
574+
byte[] data = [7];
575+
await sut.WriteAsync(data, TestContext.Current.CancellationToken);
576+
577+
byte[] expected = [frameType, 99, 7];
578+
VariableLenghtIntegerDecoder.TryWrite(expected.AsSpan(1), 1, out _);
579+
580+
Assert.Equal(expected, ms.ToArray());
581+
}
582+
519583
private class WaitBeforeWriteStream(TaskCompletionSource tcs) : MemoryStream
520584
{
521585
public int WrittenBytes { get; private set; }

0 commit comments

Comments
 (0)