Skip to content

Commit 0276e10

Browse files
committed
feat: Add async read/write support in ReplicationServlet and corresponding J2N-based async tests in TestStreamExtensions
1 parent 406940f commit 0276e10

3 files changed

Lines changed: 130 additions & 14 deletions

File tree

src/Lucene.Net.Tests.Replicator/Http/ReplicationServlet.cs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,16 @@ public void Configure(IApplicationBuilder app, IReplicationService service, Repl
5252
{
5353
// LUCENENET: This is to allow synchronous IO to happen for these requests.
5454
// LUCENENET TODO: Allow async operations from Replicator.
55-
var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
56-
if (syncIoFeature != null)
57-
{
58-
syncIoFeature.AllowSynchronousIO = true;
59-
}
55+
// var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
56+
// if (syncIoFeature != null)
57+
// {
58+
// syncIoFeature.AllowSynchronousIO = false;
59+
// }
60+
61+
// await Task.Yield();
62+
// service.Perform(context.Request, context.Response);
63+
await service.PerformAsync(context.Request, context.Response, context.RequestAborted);
6064

61-
await Task.Yield();
62-
service.Perform(context.Request, context.Response);
6365
});
6466
}
6567
}
@@ -84,14 +86,15 @@ public async Task InvokeAsync(HttpContext context)
8486
{
8587
// LUCENENET: This is to allow synchronous IO to happen for these requests.
8688
// LUCENENET TODO: Allow async operations from Replicator.
87-
var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
88-
if (syncIoFeature != null)
89-
{
90-
syncIoFeature.AllowSynchronousIO = true;
91-
}
89+
// var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
90+
// if (syncIoFeature != null)
91+
// {
92+
// syncIoFeature.AllowSynchronousIO = false;
93+
// }
9294

93-
await Task.Yield();
94-
service.Perform(context.Request, context.Response);
95+
// await Task.Yield();
96+
// service.Perform(context.Request, context.Response);
97+
await service.PerformAsync(context.Request, context.Response, context.RequestAborted);
9598

9699
// This is a terminating endpoint. Do not call the next delegate/middleware in the pipeline.
97100
}

src/Lucene.Net.Tests/Support/IO/TestStreamExtensions.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Diagnostics.CodeAnalysis;
99
using System.IO;
1010
using System.Text;
11+
using System.Threading.Tasks;
1112

1213
namespace Lucene.Net.Support.IO
1314
{
@@ -33,6 +34,8 @@ public class TestStreamExtensions : LuceneTestCase
3334
{
3435
private Stream stream;
3536

37+
private static readonly string unihw = "\u0048\u0065\u006C\u006C\u006F\u0020\u0057\u006F\u0072\u006C\u0064";
38+
3639
private const string fileString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_DataInputStream\n";
3740

3841
[Test]
@@ -115,6 +118,98 @@ public void TestReadInt64()
115118
Assert.AreEqual(9875645283333L, stream.ReadInt64(), "Incorrect long read");
116119
}
117120

121+
// Additional async tests
122+
123+
[Test]
124+
// LUCENENET note: adapted from test_writeInt()
125+
public async Task TestWriteInt32BigEndianAsync()
126+
{
127+
await stream.WriteInt32BigEndianAsync(9087589);
128+
// Reset the stream so we can read back
129+
ResetStreamForReading();
130+
int c = await stream.ReadInt32BigEndianAsync();
131+
Assert.AreEqual(9087589, c, "Incorrect int written (async)");
132+
}
133+
134+
[Test]
135+
// LUCENENET note: adapted from test_writeLong()
136+
public async Task TestWriteInt64BigEndianAsync()
137+
{
138+
await stream.WriteInt64BigEndianAsync(908755555456L);
139+
// Reset the stream so we can read back
140+
ResetStreamForReading();
141+
long c = await stream.ReadInt64BigEndianAsync();
142+
Assert.AreEqual(908755555456L, c, "Incorrect long written (async)");
143+
}
144+
145+
[Test]
146+
// LUCENENET note: adapted from test_writeUTF()
147+
public async Task TestWriteUTFAsync()
148+
{
149+
await stream.WriteUTFAsync(unihw);
150+
// Reset the stream so we can read back
151+
ResetStreamForReading();
152+
string result = await stream.ReadUTFAsync();
153+
Assert.AreEqual(unihw, result, "Incorrect string written (async)");
154+
}
155+
156+
[Test]
157+
// LUCENENET note: adapted from test_readInt()
158+
public async Task TestReadInt32BigEndianAsync()
159+
{
160+
await stream.WriteInt32BigEndianAsync(768347202);
161+
// Reset the stream so we can read back
162+
ResetStreamForReading();
163+
int result = await stream.ReadInt32BigEndianAsync();
164+
Assert.AreEqual(768347202, result, "Incorrect int read (async)");
165+
}
166+
167+
[Test]
168+
// LUCENENET note: adapted from test_readLong()
169+
public async Task TestReadInt64BigEndianAsync()
170+
{
171+
await stream.WriteInt64BigEndianAsync(9875645283333L);
172+
// Reset the stream so we can read back
173+
ResetStreamForReading();
174+
long result = await stream.ReadInt64BigEndianAsync();
175+
Assert.AreEqual(9875645283333L, result, "Incorrect long read (async)");
176+
}
177+
178+
[Test]
179+
// LUCENENET note: adapted from test_readUTF()
180+
public async Task TestReadUTFAsync()
181+
{
182+
await stream.WriteUTFAsync(unihw);
183+
184+
// Check that the length was written correctly (UTF length + 2 bytes for length header)
185+
long expectedStreamLength = CalculateExpectedUTFStreamLength(unihw);
186+
Assert.AreEqual(expectedStreamLength, stream.Length, "Failed to write string in UTF format");
187+
188+
// Reset and read the string
189+
ResetStreamForReading();
190+
string result = await stream.ReadUTFAsync();
191+
Assert.AreEqual(unihw, result, "Incorrect string read (async)");
192+
}
193+
194+
/// <summary>
195+
/// Helper method to calculate expected UTF stream length for validation
196+
/// Matches DataOutput.writeUTF() spec (Java)
197+
/// </summary>
198+
private long CalculateExpectedUTFStreamLength(string value)
199+
{
200+
long utfCount = 0;
201+
foreach (char ch in value)
202+
{
203+
if (ch > 0 && ch <= 127)
204+
utfCount++;
205+
else if (ch <= 2047)
206+
utfCount += 2;
207+
else
208+
utfCount += 3;
209+
}
210+
return utfCount + 2; // +2 for the 2-byte length header
211+
}
212+
118213
private void ResetStreamForReading() // LUCENENET - was "OpenDataInputStream" in Harmony tests
119214
{
120215
// LUCENENET specific - in the Harmony tests, there were separate streams

src/dotnet/Lucene.Net.Replicator.AspNetCore/AspNetCoreReplicationServiceExtentions.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Lucene.Net.Replicator.Http;
22
using Lucene.Net.Replicator.Http.Abstractions;
33
using Microsoft.AspNetCore.Http;
4+
using System.Threading;
5+
using System.Threading.Tasks;
46

57
namespace Lucene.Net.Replicator.AspNetCore
68
{
@@ -27,9 +29,25 @@ public static class AspNetCoreReplicationServiceExtentions
2729
/// <summary>
2830
/// Extension method that mirrors the signature of <see cref="IReplicationService.Perform"/> using AspNetCore as implementation.
2931
/// </summary>
32+
// public static void Perform(this IReplicationService self, HttpRequest request, HttpResponse response)
33+
// {
34+
// self.Perform(new AspNetCoreReplicationRequest(request), new AspNetCoreReplicationResponse(response));
35+
// }
3036
public static void Perform(this IReplicationService self, HttpRequest request, HttpResponse response)
3137
{
3238
self.Perform(new AspNetCoreReplicationRequest(request), new AspNetCoreReplicationResponse(response));
3339
}
40+
41+
public static async Task PerformAsync(
42+
this IReplicationService self,
43+
HttpRequest request,
44+
HttpResponse response,
45+
CancellationToken cancellationToken = default)
46+
{
47+
await self.PerformAsync(
48+
new AspNetCoreReplicationRequest(request),
49+
new AspNetCoreReplicationResponse(response),
50+
cancellationToken);
51+
}
3452
}
3553
}

0 commit comments

Comments
 (0)