<commit_before>// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Microsoft.AspNetCore.StaticFiles
{
    public class StaticFileMiddlewareTests
    {
        [Fact]
        public async Task ReturnsNotFoundWithoutWwwroot()
        {
            var builder = new WebHostBuilder()
                .UseKestrel()
                .Configure(app => app.UseStaticFiles());

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var response = await client.GetAsync("TestDocument.txt");

                    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
                }
            }
        }

        [Fact]
        public async Task FoundFile_LastModifiedTrimsSeconds()
        {
            var builder = new WebHostBuilder()
                .UseKestrel()
                .UseWebRoot(AppContext.BaseDirectory)
                .Configure(app => app.UseStaticFiles());

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var last = File.GetLastWriteTimeUtc(Path.Combine(AppContext.BaseDirectory, "TestDocument.txt"));
                    var response = await client.GetAsync("TestDocument.txt");

                    var trimed = new DateTimeOffset(last.Year, last.Month, last.Day, last.Hour, last.Minute, last.Second, TimeSpan.Zero).ToUniversalTime();

                    Assert.Equal(response.Content.Headers.LastModified.Value, trimed);
                }
            }
        }

        [Theory]
        [MemberData(nameof(ExistingFiles))]
        public async Task FoundFile_Served_All(string baseUrl, string baseDir, string requestUrl)
        {
            await FoundFile_Served(baseUrl, baseDir, requestUrl);
        }

        [ConditionalTheory]
        [OSSkipCondition(OperatingSystems.Linux)]
        [OSSkipCondition(OperatingSystems.MacOSX)]
        [InlineData("", @".", "/testDocument.Txt")]
        [InlineData("/somedir", @".", "/somedir/Testdocument.TXT")]
        [InlineData("/SomeDir", @".", "/soMediR/testdocument.txT")]
        [InlineData("/somedir", @"SubFolder", "/somedir/Ranges.tXt")]
        public async Task FoundFile_Served_Windows(string baseUrl, string baseDir, string requestUrl)
        {
            await FoundFile_Served(baseUrl, baseDir, requestUrl);
        }

        private async Task FoundFile_Served(string baseUrl, string baseDir, string requestUrl)
        {
            var builder = new WebHostBuilder()
                .UseKestrel()
                .UseWebRoot(Path.Combine(AppContext.BaseDirectory, baseDir))
                .Configure(app => app.UseStaticFiles(new StaticFileOptions()
                {
                    RequestPath = new PathString(baseUrl),
                }));

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                var hostingEnvironment = server.Services.GetService<IHostingEnvironment>();

                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var fileInfo = hostingEnvironment.WebRootFileProvider.GetFileInfo(Path.GetFileName(requestUrl));
                    var response = await client.GetAsync(requestUrl);
                    var responseContent = await response.Content.ReadAsByteArrayAsync();

                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
                    Assert.True(response.Content.Headers.ContentLength == fileInfo.Length);
                    Assert.Equal(response.Content.Headers.ContentLength, responseContent.Length);

                    using (var stream = fileInfo.CreateReadStream())
                    {
                        var fileContents = new byte[stream.Length];
                        stream.Read(fileContents, 0, (int)stream.Length);
                        Assert.True(responseContent.SequenceEqual(fileContents));
                    }
                }
            }
        }

        [Theory]
        [MemberData(nameof(ExistingFiles))]
        public async Task HeadFile_HeadersButNotBodyServed(string baseUrl, string baseDir, string requestUrl)
        {
            var builder = new WebHostBuilder()
                .UseKestrel()
                .UseWebRoot(Path.Combine(AppContext.BaseDirectory, baseDir))
                .Configure(app => app.UseStaticFiles(new StaticFileOptions()
                {
                    RequestPath = new PathString(baseUrl),
                }));

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                var hostingEnvironment = server.Services.GetService<IHostingEnvironment>();

                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var fileInfo = hostingEnvironment.WebRootFileProvider.GetFileInfo(Path.GetFileName(requestUrl));
                    var request = new HttpRequestMessage(HttpMethod.Head, requestUrl);
                    var response = await client.SendAsync(request);

                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
                    Assert.True(response.Content.Headers.ContentLength == fileInfo.Length);
                    Assert.Empty((await response.Content.ReadAsByteArrayAsync()));
                }
            }
        }

        public static IEnumerable<object[]> ExistingFiles => new[]
        {
            new[] {"", @".", "/TestDocument.txt"},
            new[] {"/somedir", @".", "/somedir/TestDocument.txt"},
            new[] {"/SomeDir", @".", "/soMediR/TestDocument.txt"},
            new[] {"", @"SubFolder", "/ranges.txt"},
            new[] {"/somedir", @"SubFolder", "/somedir/ranges.txt"},
            new[] {"", @"SubFolder", "/Empty.txt"}
        };

        [Fact]
        public void ClientDisconnect_Kestrel_NoWriteExceptionThrown()
        {
            ClientDisconnect_NoWriteExceptionThrown(ServerType.Kestrel);
        }

        [ConditionalFact]
        [OSSkipCondition(OperatingSystems.Linux)]
        [OSSkipCondition(OperatingSystems.MacOSX)]
        public void ClientDisconnect_WebListener_NoWriteExceptionThrown()
        {
            ClientDisconnect_NoWriteExceptionThrown(ServerType.HttpSys);
        }

        private void ClientDisconnect_NoWriteExceptionThrown(ServerType serverType)
        {
            var interval = TimeSpan.FromSeconds(15);
            var requestReceived = new ManualResetEvent(false);
            var requestCacelled = new ManualResetEvent(false);
            var responseComplete = new ManualResetEvent(false);
            Exception exception = null;
            var builder = new WebHostBuilder()
                .UseWebRoot(Path.Combine(AppContext.BaseDirectory))<commit_msg>Add logging to functional tests<commit_after>// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Testing;
using Xunit;

namespace Microsoft.AspNetCore.StaticFiles
{
    public class StaticFileMiddlewareTests : LoggedTest
    {
        [Fact]
        public async Task ReturnsNotFoundWithoutWwwroot()
        {
            var builder = new WebHostBuilder()
                .ConfigureServices(services => services.AddSingleton(LoggerFactory))
                .UseKestrel()
                .Configure(app => app.UseStaticFiles());

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var response = await client.GetAsync("TestDocument.txt");

                    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
                }
            }
        }

        [Fact]
        public async Task FoundFile_LastModifiedTrimsSeconds()
        {
            var builder = new WebHostBuilder()
                .ConfigureServices(services => services.AddSingleton(LoggerFactory))
                .UseKestrel()
                .UseWebRoot(AppContext.BaseDirectory)
                .Configure(app => app.UseStaticFiles());

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var last = File.GetLastWriteTimeUtc(Path.Combine(AppContext.BaseDirectory, "TestDocument.txt"));
                    var response = await client.GetAsync("TestDocument.txt");

                    var trimed = new DateTimeOffset(last.Year, last.Month, last.Day, last.Hour, last.Minute, last.Second, TimeSpan.Zero).ToUniversalTime();

                    Assert.Equal(response.Content.Headers.LastModified.Value, trimed);
                }
            }
        }

        [Theory]
        [MemberData(nameof(ExistingFiles))]
        public async Task FoundFile_Served_All(string baseUrl, string baseDir, string requestUrl)
        {
            await FoundFile_Served(baseUrl, baseDir, requestUrl);
        }

        [ConditionalTheory]
        [OSSkipCondition(OperatingSystems.Linux)]
        [OSSkipCondition(OperatingSystems.MacOSX)]
        [InlineData("", @".", "/testDocument.Txt")]
        [InlineData("/somedir", @".", "/somedir/Testdocument.TXT")]
        [InlineData("/SomeDir", @".", "/soMediR/testdocument.txT")]
        [InlineData("/somedir", @"SubFolder", "/somedir/Ranges.tXt")]
        public async Task FoundFile_Served_Windows(string baseUrl, string baseDir, string requestUrl)
        {
            await FoundFile_Served(baseUrl, baseDir, requestUrl);
        }

        private async Task FoundFile_Served(string baseUrl, string baseDir, string requestUrl)
        {
            var builder = new WebHostBuilder()
                .ConfigureServices(services => services.AddSingleton(LoggerFactory))
                .UseKestrel()
                .UseWebRoot(Path.Combine(AppContext.BaseDirectory, baseDir))
                .Configure(app => app.UseStaticFiles(new StaticFileOptions()
                {
                    RequestPath = new PathString(baseUrl),
                }));

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                var hostingEnvironment = server.Services.GetService<IHostingEnvironment>();

                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var fileInfo = hostingEnvironment.WebRootFileProvider.GetFileInfo(Path.GetFileName(requestUrl));
                    var response = await client.GetAsync(requestUrl);
                    var responseContent = await response.Content.ReadAsByteArrayAsync();

                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
                    Assert.True(response.Content.Headers.ContentLength == fileInfo.Length);
                    Assert.Equal(response.Content.Headers.ContentLength, responseContent.Length);

                    using (var stream = fileInfo.CreateReadStream())
                    {
                        var fileContents = new byte[stream.Length];
                        stream.Read(fileContents, 0, (int)stream.Length);
                        Assert.True(responseContent.SequenceEqual(fileContents));
                    }
                }
            }
        }

        [Theory]
        [MemberData(nameof(ExistingFiles))]
        public async Task HeadFile_HeadersButNotBodyServed(string baseUrl, string baseDir, string requestUrl)
        {
            var builder = new WebHostBuilder()
                .ConfigureServices(services => services.AddSingleton(LoggerFactory))
                .UseKestrel()
                .UseWebRoot(Path.Combine(AppContext.BaseDirectory, baseDir))
                .Configure(app => app.UseStaticFiles(new StaticFileOptions()
                {
                    RequestPath = new PathString(baseUrl),
                }));

            using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel)))
            {
                var hostingEnvironment = server.Services.GetService<IHostingEnvironment>();

                using (var client = new HttpClient() { BaseAddress = new Uri(server.GetAddress()) })
                {
                    var fileInfo = hostingEnvironment.WebRootFileProvider.GetFileInfo(Path.GetFileName(requestUrl));
                    var request = new HttpRequestMessage(HttpMethod.Head, requestUrl);
                    var response = await client.SendAsync(request);

                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
                    Assert.True(response.Content.Headers.ContentLength == fileInfo.Length);
                    Assert.Empty((await response.Content.ReadAsByteArrayAsync()));
                }
            }
        }

        public static IEnumerable<object[]> ExistingFiles => new[]
        {
            new[] {"", @".", "/TestDocument.txt"},
            new[] {"/somedir", @".", "/somedir/TestDocument.txt"},
            new[] {"/SomeDir", @".", "/soMediR/TestDocument.txt"},
            new[] {"", @"SubFolder", "/ranges.txt"},
            new[] {"/somedir", @"SubFolder", "/somedir/ranges.txt"},
            new[] {"", @"SubFolder", "/Empty.txt"}
        };

        [Fact]
        public void ClientDisconnect_Kestrel_NoWriteExceptionThrown()
        {
            ClientDisconnect_NoWriteExceptionThrown(ServerType.Kestrel);
        }

        [ConditionalFact]
        [OSSkipCondition(OperatingSystems.Linux)]
        [OSSkipCondition(OperatingSystems.MacOSX)]
        public void ClientDisconnect_WebListener_NoWriteExceptionThrown()
        {
            ClientDisconnect_NoWriteExceptionThrown(ServerType.HttpSys);
        }

        private void ClientDisconnect_NoWriteExceptionThrown(ServerType serverType)
        {
            var interval = TimeSpan.FromSeconds(15);
            var requestReceived = new ManualResetEvent(false);
            var requestCacelled = new ManualResetEvent(false);
            var responseComplete = new ManualResetEvent(false);
            Exception exception = null;
            var builder = new WebHostBuilder()
                .ConfigureServices(services => services.AddSingleton(LoggerFactory))
                .UseWebRoot(Path.Combine(AppContext.BaseDirectory))
{'fraction_non_alphanumeric': 0.10310528869480834, 'fraction_numerical': 0.0006065016982047549, 'mean_word_length': 2.1961620469083156, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3232148', 'n_tokens_mistral': 4242, 'n_tokens_neox': 4078, 'n_words': 756}