Browse Source

Fix AsyncStreamReader sending extra string and tests

pull/55/head
Ionite 1 year ago
parent
commit
883ee600fa
No known key found for this signature in database
  1. 3
      StabilityMatrix.Core/Processes/AsyncStreamReader.cs
  2. 72
      StabilityMatrix.Tests/Core/AsyncStreamReaderTests.cs

3
StabilityMatrix.Core/Processes/AsyncStreamReader.cs

@ -254,6 +254,9 @@ internal sealed class AsyncStreamReader : IDisposable
else else
{ {
// Send buffer up to this point, not including \r // Send buffer up to this point, not including \r
// But skip if there's no content
if (currentIndex == lineStart) break;
var line = _sb.ToString(lineStart, currentIndex - lineStart); var line = _sb.ToString(lineStart, currentIndex - lineStart);
lock (_messageQueue) lock (_messageQueue)
{ {

72
StabilityMatrix.Tests/Core/AsyncStreamReaderTests.cs

@ -13,62 +13,68 @@ public class AsyncStreamReaderTests
[DataTestMethod] [DataTestMethod]
// Test newlines handling for \r\n, \n // Test newlines handling for \r\n, \n
[DataRow("a\r\nb\nc", "a\r\n", "b\n", "c")] [DataRow("a\r\nb\nc", "a\r\n", "b\n", "c", null)]
// Carriage returns \r should be sent as is // Carriage returns \r should be sent as is
[DataRow("a\rb\rc", "a", "\rb", "\rc")] [DataRow("a\rb\rc", "a", "\rb", "\rc", null)]
[DataRow("a1\ra2\nb1\rb2", "a1", "\ra2\n", "b1", "\rb2")] [DataRow("a1\ra2\nb1\rb2", "a1", "\ra2\n", "b1", "\rb2", null)]
// Ansi escapes should be seperated // Ansi escapes should be seperated
[DataRow("\x1b[A\x1b[A", "\x1b[A", "\x1b[A")] [DataRow("\x1b[A\x1b[A", "\x1b[A", "\x1b[A", null)]
// Mixed Ansi and newlines // Mixed Ansi and newlines
[DataRow("a \x1b[A\r\n\r xyz", "a ", "\x1b[A", "\r\n", "\r xyz")] [DataRow("a \x1b[A\r\n\r xyz", "a ", "\x1b[A", "\r\n", "\r xyz", null)]
public async Task TestRead(string source, params string[] expected) public async Task TestRead(string source, params string?[] expected)
{ {
var queue = new Queue<string?>(expected); var results = new List<string?>();
var callback = new Action<string?>(s => var callback = new Action<string?>(s =>
{ {
Assert.IsTrue(queue.Count > 0); results.Add(s);
Assert.AreEqual(queue.Dequeue(), s);
}); });
var stream = new MemoryStream(Encoding.UTF8.GetBytes(source)); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(source));
using (var reader = new AsyncStreamReader(stream, callback, Encoding.UTF8))
// Make the reader {
using var reader = new AsyncStreamReader(stream, callback, Encoding.UTF8); // Begin read line and wait until finish
reader.BeginReadLine();
// Begin read line and wait until finish // Wait for maximum 1 second
reader.BeginReadLine(); await reader.EOF.WaitAsync(new CancellationTokenSource(1000).Token);
await reader.EOF; }
// Check if all expected strings were read // Check expected output matches
Assert.AreEqual(0, queue.Count, "Remaining: " + string.Join(", ", queue.ToArray() Assert.IsTrue(expected.SequenceEqual(results.ToArray()),
.Select(s => (s ?? "<null>").ToRepr()))); "Results [{0}] do not match expected [{1}]",
string.Join(", ", results.Select(s => s?.ToRepr() ?? "<null>")),
string.Join(", ", expected.Select(s => s?.ToRepr() ?? "<null>")));
} }
[TestMethod] [TestMethod]
public async Task TestCarriageReturnHandling() public async Task TestCarriageReturnHandling()
{ {
// The previous buffer should be sent when \r is encountered var expected = new[] {"dog\r\n", "cat", "\r123", "\r456", null};
const string source = "dog\r\ncat\r123\r456";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(source));
var queue = new Queue<string?>(new[] {"dog\r\n", "cat", "\r123", "\r456"}); var results = new List<string?>();
var callback = new Action<string?>(s => var callback = new Action<string?>(s =>
{ {
Assert.IsTrue(queue.Count > 0); results.Add(s);
Assert.AreEqual(queue.Dequeue(), s);
}); });
// Make the reader // The previous buffer should be sent when \r is encountered
using var reader = new AsyncStreamReader(stream, callback, Encoding.UTF8); const string source = "dog\r\ncat\r123\r456";
// Begin read line and wait until finish // Make the reader
reader.BeginReadLine(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(source));
await reader.EOF; using (var reader = new AsyncStreamReader(stream, callback, Encoding.UTF8))
{
// Begin read line and wait until finish
reader.BeginReadLine();
// Wait for maximum 1 second
await reader.EOF.WaitAsync(new CancellationTokenSource(1000).Token);
}
// Check if all expected strings were read // Check if all expected strings were read
Assert.AreEqual(0, queue.Count, "Remaining: " + string.Join(", ", queue.ToArray() Assert.IsTrue(expected.SequenceEqual(results.ToArray()),
.Select(s => (s ?? "<null>").ToRepr()))); "Results [{0}] do not match expected [{1}]",
string.Join(", ", results.Select(s => s?.ToRepr() ?? "<null>")),
string.Join(", ", expected.Select(s => s?.ToRepr() ?? "<null>")));
} }
} }

Loading…
Cancel
Save