using System.Text; using XFESystem.NativeRuntime.Application.Web; namespace XFESystem.Browser.Tests; public sealed class IndependentHttpEvidenceTests { private static NativeHttpResponse Read(string wire, int maximum = 4096) { byte[] bytes = Encoding.UTF8.GetBytes(wire); int position = 0; return NativeHttpProtocol.ReadResponse((buffer, offset, count) => { int copied = Math.Min(Math.Min(count, 3), bytes.Length - position); bytes.AsSpan(position, copied).CopyTo(buffer.AsSpan(offset)); position += copied; return copied; }, maximum); } [Fact] public void RealFragmentedHeadersAndChunkedUtf8BodyRetainTheirEvidence() { var response = Read("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nTransfer-Encoding: chunked\r\nX-Origin: fixture\r\n\r\n3\r\n中\r\n3\r\n文\r\n0\r\n\r\n"); Assert.Equal("中文", NativeHttpProtocol.DecodeBody(response)); Assert.Equal("HTTP/1.1 200 OK", response.StatusLine); Assert.Equal("fixture", response.Headers["x-origin"]); Assert.Equal(6, response.Body.Length); } [Theory] [InlineData("Content-Length: 1\r\nTransfer-Encoding: chunked\r\n")] [InlineData("Content-Length: 1\r\nContent-Length: 1\r\n")] [InlineData("Transfer-Encoding: gzip, chunked\r\n")] public void AmbiguousOrUnsupportedFramingNeverBecomesSuccessfulPageEvidence(string headers) { Assert.ThrowsAny(() => Read("HTTP/1.1 200 OK\r\n" + headers + "\r\nx")); } [Fact] public void TruncatedAndOversizedBodiesAreRejected() { Assert.Throws(() => Read("HTTP/1.1 200 OK\r\nContent-Length: 8\r\n\r\nx")); Assert.Throws(() => Read("HTTP/1.1 200 OK\r\nContent-Length: 20\r\n\r\n", 10)); } [Fact] public void RedirectEvidenceRetainsActualStatusAndLocation() { var response = Read("HTTP/1.1 302 Found\r\nLocation: https://other.example/\r\nContent-Length: 0\r\n\r\n"); Assert.Equal(302, response.StatusCode); Assert.Equal("https://other.example/", response.Location); Assert.Equal("HTTP/1.1 302 Found", response.StatusLine); Assert.Empty(response.Body); } }