diff --git a/NullSharp.sln b/NullSharp.sln
index a6105fa..eff6bac 100644
--- a/NullSharp.sln
+++ b/NullSharp.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NullSharp", "NullSharp\NullSharp.csproj", "{573D3111-7187-42BE-912E-4147706E8829}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NullSharpTests", "NullSharpTests\NullSharpTests.csproj", "{3121E38F-B6F7-4641-9799-162EA6C8607D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -30,5 +32,17 @@ Global
{573D3111-7187-42BE-912E-4147706E8829}.Release|x64.Build.0 = Release|Any CPU
{573D3111-7187-42BE-912E-4147706E8829}.Release|x86.ActiveCfg = Release|Any CPU
{573D3111-7187-42BE-912E-4147706E8829}.Release|x86.Build.0 = Release|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Debug|x64.Build.0 = Debug|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Debug|x86.Build.0 = Debug|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Release|x64.ActiveCfg = Release|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Release|x64.Build.0 = Release|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Release|x86.ActiveCfg = Release|Any CPU
+ {3121E38F-B6F7-4641-9799-162EA6C8607D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/NullSharp/NullStream.cs b/NullSharp/NullStream.cs
index 84931b4..8c06762 100644
--- a/NullSharp/NullStream.cs
+++ b/NullSharp/NullStream.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.IO;
using System.Net.Http;
using System.Threading;
@@ -9,7 +10,7 @@ namespace NullSharp
public class NullStream : Stream
{
public const string DefaultEndpoint = "https://devnull-as-a-service.com/dev/null";
- private readonly HttpClient Client;
+ protected HttpClient Client { get; set; }
public NullStream() : this(DefaultEndpoint) { }
@@ -51,6 +52,9 @@ namespace NullSharp
public override void Write(byte[] buffer, int offset, int count) => this.WriteAsync(buffer, offset, count).Wait();
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
- => this.Client.PostAsync("", new ByteArrayContent(buffer), cancellationToken);
+ => this.Client.PostAsync(
+ "",
+ new ByteArrayContent(buffer.Skip(offset).Take(count).ToArray()),
+ cancellationToken);
}
}
diff --git a/NullSharpTests/NullSharpTests.csproj b/NullSharpTests/NullSharpTests.csproj
new file mode 100644
index 0000000..f8cb854
--- /dev/null
+++ b/NullSharpTests/NullSharpTests.csproj
@@ -0,0 +1,19 @@
+
+
+
+ netcoreapp2.2
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NullSharpTests/NullStreamTests.cs b/NullSharpTests/NullStreamTests.cs
new file mode 100644
index 0000000..e3189d7
--- /dev/null
+++ b/NullSharpTests/NullStreamTests.cs
@@ -0,0 +1,77 @@
+using System;
+using System.IO;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Xunit;
+using NullSharp;
+
+namespace NullSharpTests {
+ class MockableNullStream : NullStream {
+ public MockableNullStream() : base() { }
+ public MockableNullStream(string endpoint) : base(endpoint) { }
+
+ public HttpClient GetClient() => this.Client;
+ public void SetClient(HttpClient value) => this.Client = value;
+ }
+
+ class MockHttpClient : HttpClient {
+ public HttpRequestMessage LastMessage;
+ public override Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
+ LastMessage = request;
+ return new Task(() => new HttpResponseMessage());
+ }
+ }
+
+ public class NullStreamTests {
+ private MockableNullStream stream = new MockableNullStream();
+
+ [Fact]
+ public void DefaultEndpointTest() {
+ Assert.Equal("https://devnull-as-a-service.com/dev/null", stream.GetClient().BaseAddress.ToString());
+ Assert.Single(stream.GetClient().DefaultRequestHeaders.UserAgent);
+ Assert.Equal("NullSharp", stream.GetClient().DefaultRequestHeaders.UserAgent.ToString());
+ }
+
+ [Fact]
+ public void CustomEndpointTest() {
+ var customStream = new MockableNullStream("https://somewhere");
+ Assert.Equal("https://somewhere", customStream.GetClient().BaseAddress.ToString());
+ }
+
+ [Fact]
+ public void PropertiesTest() {
+ Assert.True(stream.CanWrite, "NullStream should be writable");
+ Assert.False(stream.CanRead, "NullStream should not be readable");
+ Assert.False(stream.CanSeek, "NullStream should not be seekable");
+ Assert.True(stream.CanTimeout, "NullStream should be able to time out");
+ }
+
+ [Fact]
+ public void TimeoutTest() {
+ stream.WriteTimeout = 1000000;
+ Assert.Equal(1000000, stream.WriteTimeout);
+ Assert.Equal(1000000, stream.GetClient().Timeout.TotalMilliseconds);
+ }
+
+ [Fact]
+ public void NotSupportedTest() {
+ Assert.Throws(() => stream.Length);
+ Assert.Throws(() => stream.SetLength(42));
+ Assert.Throws(() => stream.Seek(0, SeekOrigin.Begin));
+ Assert.Throws(() => stream.Position);
+ Assert.Throws(() => stream.Position = 42);
+ Assert.Throws(() => stream.Read(new byte[] {}, 0, 10));
+ }
+
+ [Fact]
+ public void WriteTest() {
+ stream.SetClient(new MockHttpClient() { BaseAddress = new Uri(NullStream.DefaultEndpoint) });
+ var data = new byte[] {13, 37};
+ stream.Write(data, 1, 1);
+ var request = ((MockHttpClient)stream.GetClient()).LastMessage;
+ Assert.Equal("https://devnull-as-a-service.com/dev/null", request.RequestUri.ToString());
+ Assert.IsType(request.Content);
+ Assert.Equal(new ByteArrayContent(new byte[] {37}), request.Content);
+ }
+ }
+}