Skip to content

Commit 6be17a8

Browse files
Merge pull request #99 from Traperto/refactor/better-validation
Refactor/better validation
2 parents 4f48e4a + e8c7e1a commit 6be17a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1741
-1074
lines changed

Directory.Build.props

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project>
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<Nullable>enable</Nullable>
5+
<WarningsAsErrors>true</WarningsAsErrors>
6+
<LangVersion>latest</LangVersion>
7+
</PropertyGroup>
8+
</Project>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace MagicBytesValidator.CLI.Exceptions;
2+
3+
public class InvalidProgramCallException : Exception
4+
{
5+
}

MagicBytesValidator.CLI/Imports.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Global using directives
2+
3+
global using MagicBytesValidator.CLI.Exceptions;
4+
global using MagicBytesValidator.Services;
5+
global using MagicBytesValidator.Services.Streams;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<OutputType>exe</OutputType>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<ProjectReference Include="..\MagicBytesValidator\MagicBytesValidator.csproj" />
10+
</ItemGroup>
11+
12+
</Project>

MagicBytesValidator.CLI/Program.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
namespace MagicBytesValidator.CLI;
2+
3+
public class Program
4+
{
5+
public static void Main()
6+
{
7+
Console.WriteLine();
8+
var streamFileTypeProvider = GetStreamFileTypeProvider();
9+
10+
try
11+
{
12+
var path = LoadPathFromArgs();
13+
var file = File.Open(path, FileMode.Open, FileAccess.Read);
14+
15+
var matches = streamFileTypeProvider
16+
.FindAllMatchesAsync(file, CancellationToken.None)
17+
.GetAwaiter()
18+
.GetResult()
19+
.ToList();
20+
21+
if (matches.Count == 0)
22+
{
23+
Console.WriteLine("No matches.");
24+
return;
25+
}
26+
27+
Console.WriteLine($"{"FileType",-10}| {"Extensions",-40}| {"MIME Types",-80}");
28+
Console.WriteLine(new string('-', 130));
29+
30+
foreach (var match in matches)
31+
{
32+
var mimeTypeList = string.Join(", ", match.MimeTypes);
33+
var extensionList = string.Join(", ", match.Extensions);
34+
35+
Console.WriteLine($"{match.GetType().Name,-10}| {extensionList,-40}| {mimeTypeList,-80}");
36+
}
37+
38+
Console.WriteLine();
39+
Console.WriteLine($"Unambiguous match: {(matches.Count == 1 ? "Yes" : "No")}");
40+
}
41+
catch (InvalidProgramCallException)
42+
{
43+
Console.Error.WriteLine(
44+
"""
45+
Usage: dotnet run -- [PATH]
46+
PATH must point to an existing, readable file
47+
""");
48+
}
49+
catch (FileNotFoundException)
50+
{
51+
Console.Error.WriteLine("Error: File not found");
52+
}
53+
catch (Exception exception)
54+
{
55+
Console.Error.WriteLine(
56+
"""
57+
Error: Internal Exception.
58+
This should not happen. Please file a GitHub issue with the stack trace attached:
59+
""");
60+
Console.Error.WriteLine(exception);
61+
}
62+
}
63+
64+
private static string LoadPathFromArgs()
65+
{
66+
var args = Environment.GetCommandLineArgs();
67+
if (
68+
args is not { Length: 2 }
69+
|| args is not [_, var path]
70+
|| string.IsNullOrWhiteSpace(path)
71+
)
72+
{
73+
throw new InvalidProgramCallException();
74+
}
75+
76+
return Path.GetFullPath(path);
77+
}
78+
79+
private static StreamFileTypeProvider GetStreamFileTypeProvider()
80+
{
81+
return new StreamFileTypeProvider(new Mapping());
82+
}
83+
}

MagicBytesValidator.Tests/Http/FormFileTypeProviderTests.cs renamed to MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,62 @@
1-
using System.IO;
2-
using System.Linq;
3-
using FluentAssertions;
4-
using MagicBytesValidator.Exceptions.Http;
5-
using MagicBytesValidator.Formats;
6-
using MagicBytesValidator.Services.Http;
7-
using Microsoft.AspNetCore.Http;
8-
using Xunit;
1+
using MagicBytesValidator.Services.Http;
92

103
namespace MagicBytesValidator.Tests.Http;
114

12-
public class FormFileTypeProviderTests
5+
public class FindFileTypeForFormFile
136
{
147
[Fact]
15-
public void Should_find_by_extension()
8+
public async Task Should_find_by_extension()
169
{
1710
var formFile = ProvideGifFile("trp.gif", "image/gif");
1811

1912
var sut = new FormFileTypeProvider();
2013

21-
var result = sut.FindFileTypeForFormFile(formFile);
14+
var result = await sut.FindValidatedTypeAsync(formFile, null, CancellationToken.None);
2215

2316
result.Should().BeOfType<Gif>();
2417
}
2518

2619
[Fact]
27-
public void Should_find_by_content_type()
20+
public async Task Should_find_by_content_type()
2821
{
2922
var formFile = ProvideGifFile(string.Empty, "image/gif");
3023

3124
var sut = new FormFileTypeProvider();
3225

33-
var result = sut.FindFileTypeForFormFile(formFile);
26+
var result = await sut.FindValidatedTypeAsync(formFile, null, CancellationToken.None);
3427

3528
result.Should().BeOfType<Gif>();
3629
}
3730

3831
[Fact]
39-
public void Should_return_null_on_not_found()
32+
public async Task Should_return_null_on_not_found()
4033
{
4134
var formFile = ProvideGifFile(string.Empty, "trp/nms");
4235

4336
var sut = new FormFileTypeProvider();
4437

45-
var result = sut.FindFileTypeForFormFile(formFile);
38+
var result = await sut.FindValidatedTypeAsync(formFile, null, CancellationToken.None);
4639

4740
result.Should().BeNull();
4841
}
4942

5043
[Fact]
51-
public void Should_throw_on_mismatch()
44+
public async Task Should_throw_on_mismatch()
5245
{
5346
var formFile = ProvideGifFile("trp.gif", "image/png");
5447

5548
var sut = new FormFileTypeProvider();
5649

57-
Assert.Throws<MimeTypeMismatchException>(() => sut.FindFileTypeForFormFile(formFile));
50+
await Assert.ThrowsAsync<MimeTypeMismatchException>(async () => await sut.FindValidatedTypeAsync(formFile, null, CancellationToken.None));
5851
}
5952

6053
private static IFormFile ProvideGifFile(string name, string contentType)
6154
{
62-
var fileTypeGif = new Gif();
63-
var fileContents = fileTypeGif.MagicByteSequences.First().Concat(new byte[] { 0x11, 0x12 }).ToArray();
64-
var fileStream = new MemoryStream(fileContents);
55+
byte[] gifSequence = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x11, 0x12];
56+
var fileStream = new MemoryStream(gifSequence);
6557

6658
return new FormFile(
67-
new MemoryStream(fileContents.ToArray()),
59+
new MemoryStream(gifSequence),
6860
0,
6961
fileStream.Length,
7062
name,
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
namespace MagicBytesValidator.Tests.Http;
2+
3+
public class FindValidatedTypeAsync
4+
{
5+
[Fact]
6+
public async Task Should_find_by_extension()
7+
{
8+
var formFile = ProvideGifFile("trp.gif", "image/gif");
9+
10+
var sut = new FormFileTypeProvider();
11+
12+
var result = await sut.FindValidatedTypeAsync(
13+
formFile,
14+
null,
15+
CancellationToken.None
16+
);
17+
18+
result.Should().BeOfType<Gif>();
19+
}
20+
21+
[Fact]
22+
public async Task Should_find_by_content_type()
23+
{
24+
var formFile = ProvideGifFile(string.Empty, "image/gif");
25+
26+
var sut = new FormFileTypeProvider();
27+
28+
var result = await sut.FindValidatedTypeAsync(
29+
formFile,
30+
null,
31+
CancellationToken.None
32+
);
33+
34+
result.Should().BeOfType<Gif>();
35+
}
36+
37+
[Fact]
38+
public async Task Should_return_null_on_not_found()
39+
{
40+
var formFile = ProvideGifFile(string.Empty, "trp/crly");
41+
42+
var sut = new FormFileTypeProvider();
43+
44+
var result = await sut.FindValidatedTypeAsync(
45+
formFile,
46+
null,
47+
CancellationToken.None
48+
);
49+
50+
result.Should().BeNull();
51+
}
52+
53+
[Fact]
54+
public async Task Should_throw_on_type_vs_name_mismatch()
55+
{
56+
var formFile = ProvideGifFile("trp.gif", "image/png");
57+
58+
var sut = new FormFileTypeProvider();
59+
60+
await Assert.ThrowsAsync<MimeTypeMismatchException>(async () =>
61+
await sut.FindValidatedTypeAsync(
62+
formFile,
63+
null,
64+
CancellationToken.None
65+
)
66+
);
67+
}
68+
69+
[Fact]
70+
public async Task Should_throw_on_type_vs_content_mismatch()
71+
{
72+
var formFile = ProvideGifFile("trp.png", "image/png");
73+
74+
var sut = new FormFileTypeProvider();
75+
76+
await Assert.ThrowsAsync<MimeTypeMismatchException>(async () =>
77+
await sut.FindValidatedTypeAsync(
78+
formFile,
79+
null,
80+
CancellationToken.None
81+
)
82+
);
83+
}
84+
85+
private static IFormFile ProvideGifFile(string name, string contentType)
86+
{
87+
byte[] gifSequence = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];
88+
var fileContents = gifSequence.Concat(new byte[] { 0x11, 0x12 }).ToArray();
89+
var fileStream = new MemoryStream(fileContents.ToArray());
90+
91+
return new FormFile(
92+
new MemoryStream(fileContents.ToArray()),
93+
0,
94+
fileStream.Length,
95+
name,
96+
name
97+
)
98+
{
99+
Headers = new HeaderDictionary
100+
{
101+
{ "Content-Type", contentType }
102+
}
103+
};
104+
}
105+
}

MagicBytesValidator.Tests/Imports.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Global using directives
2+
3+
global using System;
4+
global using System.IO;
5+
global using System.Linq;
6+
global using System.Threading;
7+
global using System.Threading.Tasks;
8+
global using FluentAssertions;
9+
global using MagicBytesValidator.Exceptions.Http;
10+
global using MagicBytesValidator.Formats;
11+
global using MagicBytesValidator.Models;
12+
global using MagicBytesValidator.Services;
13+
global using MagicBytesValidator.Services.Http;
14+
global using MagicBytesValidator.Services.Streams;
15+
global using Microsoft.AspNetCore.Http;
16+
global using Moq;
17+
global using Xunit;

0 commit comments

Comments
 (0)