Skip to content

Commit

Permalink
Add integration tests (#21)
Browse files Browse the repository at this point in the history
* Add integration tests and fix some bugs that emerged

* more integration tests
  • Loading branch information
JonathanBout authored Dec 4, 2024
1 parent af1af0e commit 6fbca82
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 25 deletions.
30 changes: 30 additions & 0 deletions SimpleCDN.Tests.Integration/CustomWebApplicationFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Mvc.Testing;
using SimpleCDN.Configuration;

namespace SimpleCDN.Tests.Integration
{
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
public const string GENERATED_INDEX_ID = "!GENERATED!INDEX!";

public string DataRoot => _rootDirectory.FullName;
private readonly DirectoryInfo _rootDirectory = Directory.CreateTempSubdirectory("SimpleCDN");

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
services.Configure<CDNConfiguration>(config =>
{
config.Footer = GENERATED_INDEX_ID;
config.DataRoot = DataRoot;
});
});
}

protected override void Dispose(bool disposing)
{
Directory.Delete(DataRoot, true);
}
}
}
64 changes: 64 additions & 0 deletions SimpleCDN.Tests.Integration/EndpointTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Mvc.Testing;

namespace SimpleCDN.Tests.Integration
{
public class EndpointTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly CustomWebApplicationFactory _webApplicationFactory;

const string TEXT_FILE_NAME = "test.txt";
const string TEXT_FILE_CONTENT = "Hello, World!";

const string JSON_FILE_NAME = "data/test.json";
const string JSON_FILE_CONTENT = """{"key": "value"}""";

public EndpointTests(CustomWebApplicationFactory webApplicationFactory)
{
_webApplicationFactory = webApplicationFactory;

var dataRoot = _webApplicationFactory.DataRoot;

Directory.CreateDirectory(Path.Combine(dataRoot, "data"));

// create some files
File.WriteAllText(Path.Combine(_webApplicationFactory.DataRoot, TEXT_FILE_NAME), TEXT_FILE_CONTENT);
File.WriteAllText(Path.Combine(_webApplicationFactory.DataRoot, JSON_FILE_NAME), JSON_FILE_CONTENT);
}

[Fact]
public async Task Test_Accesible()
{
var client = _webApplicationFactory.CreateClient();

var response = await client.GetAsync("/");

Assert.True(response.IsSuccessStatusCode, response.StatusCode.ToString());
}

[Fact]
public async Task Test_AutoGeneratedIndex()
{
var client = _webApplicationFactory.CreateClient();
var response = await client.GetAsync("/");
var content = await response.Content.ReadAsStringAsync();
Assert.Contains(CustomWebApplicationFactory.GENERATED_INDEX_ID, content);
}

[Theory]
[InlineData("/" + TEXT_FILE_NAME, TEXT_FILE_CONTENT)]
[InlineData("/../" + TEXT_FILE_NAME, TEXT_FILE_CONTENT)]
[InlineData("/data/../" + TEXT_FILE_NAME, TEXT_FILE_CONTENT)]
[InlineData("/" + JSON_FILE_NAME, JSON_FILE_CONTENT)]
[InlineData("/data/../" + JSON_FILE_NAME, JSON_FILE_CONTENT)]
public async Task Test_FileExists_WithContent(string endpoint, string expectedText)
{
var client = _webApplicationFactory.CreateClient();
var response = await client.GetAsync(endpoint);

Assert.True(response.IsSuccessStatusCode, response.StatusCode.ToString());

var content = await response.Content.ReadAsStringAsync();
Assert.Contains(expectedText, content);
}
}
}
12 changes: 12 additions & 0 deletions SimpleCDN.Tests.Integration/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"SimpleCDN.Tests.Integration": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:54467;http://localhost:54468"
}
}
}
26 changes: 26 additions & 0 deletions SimpleCDN.Tests.Integration/SimpleCDN.Tests.Integration.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SimpleCDN\SimpleCDN.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions SimpleCDN.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleCDN.Tests", "SimpleCD
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{81DDED9D-158B-E303-5F62-77A2896D2A5A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleCDN.Tests.Integration", "SimpleCDN.Tests.Integration\SimpleCDN.Tests.Integration.csproj", "{F79E71E8-89D8-46F7-802C-CFDF3A77447D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -26,6 +28,10 @@ Global
{81DDED9D-158B-E303-5F62-77A2896D2A5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81DDED9D-158B-E303-5F62-77A2896D2A5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81DDED9D-158B-E303-5F62-77A2896D2A5A}.Release|Any CPU.Build.0 = Release|Any CPU
{F79E71E8-89D8-46F7-802C-CFDF3A77447D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F79E71E8-89D8-46F7-802C-CFDF3A77447D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F79E71E8-89D8-46F7-802C-CFDF3A77447D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F79E71E8-89D8-46F7-802C-CFDF3A77447D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
3 changes: 2 additions & 1 deletion SimpleCDN/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("SimpleCDN.Tests")]
[assembly: InternalsVisibleTo("SimpleCDN.Tests")]
[assembly: InternalsVisibleTo("SimpleCDN.Tests.Integration")]
3 changes: 2 additions & 1 deletion SimpleCDN/Endpoints/CDN.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ public static IEndpointRouteBuilder RegisterCDNEndpoints(this IEndpointRouteBuil

if (loader.GetFile(route) is CDNFile file)
{
var typedAccept = ctx.Request.GetTypedHeaders().Accept;
// check if the client accepts the file's media type
if (!ctx.Request.GetTypedHeaders().Accept.Contains(new MediaTypeHeaderValue(file.MediaType)))
if (typedAccept.Count > 0 && !typedAccept.Contains(new MediaTypeHeaderValue(file.MediaType)) && !typedAccept.Contains(new MediaTypeHeaderValue("*/*")))
{
return Results.StatusCode(StatusCodes.Status406NotAcceptable);
}
Expand Down
47 changes: 25 additions & 22 deletions SimpleCDN/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,39 @@
using SimpleCDN.Endpoints;
using SimpleCDN.Services;

internal partial class Program
namespace SimpleCDN
{
private static void Main(string[] args)
public class Program
{
var builder = WebApplication.CreateSlimBuilder(args);
private static void Main(string[] args)
{
var builder = WebApplication.CreateSlimBuilder(args);

// reconfigure the configuration to make sure we're using the right sources in the right order
builder.Configuration.Sources.Clear();
builder.Configuration
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddCommandLine(args);
// reconfigure the configuration to make sure we're using the right sources in the right order
builder.Configuration.Sources.Clear();
builder.Configuration
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddCommandLine(args);

builder.Services.MapConfiguration();
builder.Services.MapConfiguration();

// for now, we use a simple size-limited in-memory cache.
// In the future, we may want to give options for other cache implementations
// like Redis or Memcached.
builder.Services.AddSingleton<IDistributedCache, SizeLimitedCache>();
// for now, we use a simple size-limited in-memory cache.
// In the future, we may want to give options for other cache implementations
// like Redis or Memcached.
builder.Services.AddSingleton<IDistributedCache, SizeLimitedCache>();

builder.Services.AddSingleton<ICDNLoader, CDNLoader>();
builder.Services.AddSingleton<IIndexGenerator, IndexGenerator>();
builder.Services.AddSingleton<IPhysicalFileReader, PhysicalFileReader>();
builder.Services.AddSingleton<ICacheManager, CacheManager>();
builder.Services.AddSingleton<ICDNLoader, CDNLoader>();
builder.Services.AddSingleton<IIndexGenerator, IndexGenerator>();
builder.Services.AddSingleton<IPhysicalFileReader, PhysicalFileReader>();
builder.Services.AddSingleton<ICacheManager, CacheManager>();

var app = builder.Build();
var app = builder.Build();

app.RegisterCDNEndpoints();
app.RegisterCDNEndpoints();

app.Run();
app.Run();
}
}
}
2 changes: 1 addition & 1 deletion SimpleCDN/Services/CDNLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public partial class CDNLoader(
return GetSystemFile(path[5..]);
}

var filesystemPath = Path.Combine(DataRoot, path);
var filesystemPath = Path.Combine(DataRoot, path.TrimStart('/'));

if (!_fs.FileExists(filesystemPath))
{
Expand Down

0 comments on commit 6fbca82

Please sign in to comment.