feat: add overloads that allow to the the buffer size for the copy
This commit is contained in:
parent
77199944fe
commit
cce841a06e
3 changed files with 152 additions and 28 deletions
|
|
@ -64,6 +64,42 @@ internal sealed class PipingTests
|
||||||
await Assert.That(result.StandardOutput.Trim()).IsEqualTo("Hello World!");
|
await Assert.That(result.StandardOutput.Trim()).IsEqualTo("Hello World!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task I_can_execute_a_command_and_pipe_the_stdin_from_a_stream_with_a_custom_buffer_size()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var source = new MemoryStream("Hello World!"u8.ToArray());
|
||||||
|
|
||||||
|
var cmd = PipeSource.FromStream(source, 1) |
|
||||||
|
new Command(Testing.Fixture.Program.FilePath)
|
||||||
|
.WithArguments("echo-stdin");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await cmd.ExecuteBufferedAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await Assert.That(result.StandardOutput.Trim()).IsEqualTo("Hello World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task I_can_execute_a_command_and_pipe_the_stdin_from_a_file_with_a_custom_buffer_size()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var dir = TestTempDirectory.Create();
|
||||||
|
var filePath = Path.Combine(dir.Path, "input.txt");
|
||||||
|
await File.WriteAllTextAsync(filePath, "Hello World!");
|
||||||
|
|
||||||
|
var cmd = PipeSource.FromFile(filePath, 1) |
|
||||||
|
new Command(Testing.Fixture.Program.FilePath)
|
||||||
|
.WithArguments("echo-stdin");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await cmd.ExecuteBufferedAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await Assert.That(result.StandardOutput.Trim()).IsEqualTo("Hello World!");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task I_can_execute_a_command_and_pipe_the_stdin_from_memory()
|
public async Task I_can_execute_a_command_and_pipe_the_stdin_from_memory()
|
||||||
{
|
{
|
||||||
|
|
@ -220,6 +256,43 @@ internal sealed class PipingTests
|
||||||
await Assert.That(stream.Length).IsEqualTo(100_000);
|
await Assert.That(stream.Length).IsEqualTo(100_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task I_can_execute_a_command_and_pipe_the_stdout_into_a_stream_with_a_custom_buffer_size()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var stream = new MemoryStream();
|
||||||
|
var target = PipeTarget.ToStream(stream, 1);
|
||||||
|
|
||||||
|
var cmd = new Command(Testing.Fixture.Program.FilePath)
|
||||||
|
.WithArguments(["generate", "blob", "--length", "100000"]) |
|
||||||
|
target;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await cmd.ExecuteAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await Assert.That(stream.Length).IsEqualTo(100_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task I_can_execute_a_command_and_pipe_the_stdout_into_a_file_with_a_custom_buffer_size()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var dir = TestTempDirectory.Create();
|
||||||
|
var filePath = Path.Combine(dir.Path, "output.bin");
|
||||||
|
var target = PipeTarget.ToFile(filePath, 1);
|
||||||
|
|
||||||
|
var cmd = new Command(Testing.Fixture.Program.FilePath)
|
||||||
|
.WithArguments(["generate", "blob", "--length", "100000"]) |
|
||||||
|
target;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await cmd.ExecuteAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await Assert.That(new FileInfo(filePath).Length).IsEqualTo(100_000);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task I_can_execute_a_command_and_pipe_the_stdout_into_a_string_builder()
|
public async Task I_can_execute_a_command_and_pipe_the_stdout_into_a_string_builder()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,14 @@ public abstract partial class PipeSource
|
||||||
return Create(stream.CopyToAsync);
|
return Create(stream.CopyToAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a pipe source that reads from the specified stream.
|
||||||
|
/// </summary>
|
||||||
|
public static PipeSource FromStream(Stream stream, int bufferSize)
|
||||||
|
{
|
||||||
|
return Create((target, token) => stream.CopyToAsync(target, bufferSize, token));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe source that reads from the specified file.
|
/// Creates a pipe source that reads from the specified file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -79,6 +87,18 @@ public abstract partial class PipeSource
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a pipe source that reads from the specified file.
|
||||||
|
/// </summary>
|
||||||
|
public static PipeSource FromFile(string filePath, int bufferSize)
|
||||||
|
{
|
||||||
|
return Create(async (destination, cancellationToken) =>
|
||||||
|
{
|
||||||
|
await using var source = File.OpenRead(filePath);
|
||||||
|
await source.CopyToAsync(destination, bufferSize, cancellationToken);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe source that reads from the specified memory buffer.
|
/// Creates a pipe source that reads from the specified memory buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -89,11 +109,12 @@ public abstract partial class PipeSource
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe source that reads from the specified byte array.
|
/// Creates a pipe source that reads from the specified string.
|
||||||
|
/// Uses <see cref="Console.InputEncoding" /> for encoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static PipeSource FromBytes(byte[] data)
|
public static PipeSource FromString(string str)
|
||||||
{
|
{
|
||||||
return FromBytes((ReadOnlyMemory<byte>)data);
|
return FromString(str, Console.InputEncoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -104,15 +125,6 @@ public abstract partial class PipeSource
|
||||||
return FromBytes(encoding.GetBytes(str));
|
return FromBytes(encoding.GetBytes(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a pipe source that reads from the specified string.
|
|
||||||
/// Uses <see cref="Console.InputEncoding" /> for encoding.
|
|
||||||
/// </summary>
|
|
||||||
public static PipeSource FromString(string str)
|
|
||||||
{
|
|
||||||
return FromString(str, Console.InputEncoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe source that reads from the standard output of the specified command.
|
/// Creates a pipe source that reads from the standard output of the specified command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,17 @@ public partial class PipeTarget
|
||||||
await origin.CopyToAsync(stream, cancellationToken));
|
await origin.CopyToAsync(stream, cancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a pipe target that writes to the specified stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream to which the contents of the source will be copied.</param>
|
||||||
|
/// <param name="bufferSize">The size, in bytes, of the buffer. This value must be greater than zero. The default size is 81920.</param>
|
||||||
|
public static PipeTarget ToStream(Stream stream, int bufferSize)
|
||||||
|
{
|
||||||
|
return Create(async (origin, cancellationToken) =>
|
||||||
|
await origin.CopyToAsync(stream, bufferSize, cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe target that writes to the specified file.
|
/// Creates a pipe target that writes to the specified file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -162,11 +173,48 @@ public partial class PipeTarget
|
||||||
{
|
{
|
||||||
return Create(async (origin, cancellationToken) =>
|
return Create(async (origin, cancellationToken) =>
|
||||||
{
|
{
|
||||||
await using var target = File.Create(filePath);
|
var options = new FileStreamOptions
|
||||||
|
{
|
||||||
|
Access = FileAccess.Write,
|
||||||
|
Mode = FileMode.Create,
|
||||||
|
Share = FileShare.Read,
|
||||||
|
Options = FileOptions.Asynchronous
|
||||||
|
};
|
||||||
|
await using var target = new FileStream(filePath, options);
|
||||||
await origin.CopyToAsync(target, cancellationToken);
|
await origin.CopyToAsync(target, cancellationToken);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a pipe target that writes to the specified file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">The path and name of the file to create and write the content to.</param>
|
||||||
|
/// <param name="bufferSize">The size, in bytes, of the buffer. This value must be greater than zero. The default size is 81920.</param>
|
||||||
|
public static PipeTarget ToFile(string filePath, int bufferSize)
|
||||||
|
{
|
||||||
|
return Create(async (origin, cancellationToken) =>
|
||||||
|
{
|
||||||
|
var options = new FileStreamOptions
|
||||||
|
{
|
||||||
|
Access = FileAccess.Write,
|
||||||
|
Mode = FileMode.Create,
|
||||||
|
Share = FileShare.Read,
|
||||||
|
Options = FileOptions.Asynchronous
|
||||||
|
};
|
||||||
|
await using var target = new FileStream(filePath, options);
|
||||||
|
await origin.CopyToAsync(target, bufferSize, cancellationToken);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a pipe target that writes to the specified string builder.
|
||||||
|
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
||||||
|
/// </summary>
|
||||||
|
public static PipeTarget ToStringBuilder(StringBuilder stringBuilder)
|
||||||
|
{
|
||||||
|
return ToStringBuilder(stringBuilder, Console.OutputEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe target that writes to the specified string builder.
|
/// Creates a pipe target that writes to the specified string builder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -191,12 +239,12 @@ public partial class PipeTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe target that writes to the specified string builder.
|
/// Creates a pipe target that invokes the specified asynchronous delegate on every line written to the stream.
|
||||||
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static PipeTarget ToStringBuilder(StringBuilder stringBuilder)
|
public static PipeTarget ToDelegate(Func<string, CancellationToken, Task> func)
|
||||||
{
|
{
|
||||||
return ToStringBuilder(stringBuilder, Console.OutputEncoding);
|
return ToDelegate(func, Console.OutputEncoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -218,7 +266,7 @@ public partial class PipeTarget
|
||||||
/// Creates a pipe target that invokes the specified asynchronous delegate on every line written to the stream.
|
/// Creates a pipe target that invokes the specified asynchronous delegate on every line written to the stream.
|
||||||
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static PipeTarget ToDelegate(Func<string, CancellationToken, Task> func)
|
public static PipeTarget ToDelegate(Func<string, Task> func)
|
||||||
{
|
{
|
||||||
return ToDelegate(func, Console.OutputEncoding);
|
return ToDelegate(func, Console.OutputEncoding);
|
||||||
}
|
}
|
||||||
|
|
@ -232,12 +280,12 @@ public partial class PipeTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe target that invokes the specified asynchronous delegate on every line written to the stream.
|
/// Creates a pipe target that invokes the specified synchronous delegate on every line written to the stream.
|
||||||
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static PipeTarget ToDelegate(Func<string, Task> func)
|
public static PipeTarget ToDelegate(Action<string> action)
|
||||||
{
|
{
|
||||||
return ToDelegate(func, Console.OutputEncoding);
|
return ToDelegate(action, Console.OutputEncoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -253,15 +301,6 @@ public partial class PipeTarget
|
||||||
}, encoding);
|
}, encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a pipe target that invokes the specified synchronous delegate on every line written to the stream.
|
|
||||||
/// Uses <see cref="Console.OutputEncoding" /> for decoding.
|
|
||||||
/// </summary>
|
|
||||||
public static PipeTarget ToDelegate(Action<string> action)
|
|
||||||
{
|
|
||||||
return ToDelegate(action, Console.OutputEncoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a pipe target that replicates data over multiple inner targets.
|
/// Creates a pipe target that replicates data over multiple inner targets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue