Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Major refactoring, part I #81

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace MagicBytesValidator.CLI.Exceptions;

public class InvalidProgramCallException : Exception
{
}
16 changes: 16 additions & 0 deletions MagicBytesValidator.CLI/MagicBytesValidator.CLI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<WarningsAsErrors>true</WarningsAsErrors>
<OutputType>exe</OutputType>
</PropertyGroup>

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

</Project>
87 changes: 87 additions & 0 deletions MagicBytesValidator.CLI/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using MagicBytesValidator.CLI.Exceptions;
using MagicBytesValidator.Services;
using MagicBytesValidator.Services.Streams;

namespace MagicBytesValidator.CLI;

public class Program
{
public static void Main()
{
Console.WriteLine();
var streamFileTypeProvider = GetStreamFileTypeProvider();

try
{
var path = LoadPathFromArgs();
var file = File.Open(path, FileMode.Open, FileAccess.Read);

var matches = streamFileTypeProvider
.FindAllMatchesAsync(file, CancellationToken.None)
.GetAwaiter()
.GetResult()
.ToList();

if (matches.Count == 0)
{
Console.WriteLine("No matches.");
return;
}

Console.WriteLine($"{"FileType",-10}| {"Extensions",-40}| {"MIME Types",-80}");
Console.WriteLine(new string('-', 130));

foreach (var match in matches)
{
var mimeTypeList = string.Join(", ", match.MimeTypes);
var extensionList = string.Join(", ", match.Extensions);

Console.WriteLine($"{match.GetType().Name,-10}| {extensionList,-40}| {mimeTypeList,-80}");
}

Console.WriteLine();
Console.WriteLine($"Unambiguous match: {(matches.Count == 1 ? "Yes" : "No")}");
}
catch (InvalidProgramCallException)
{
Console.Error.WriteLine(
"""
Usage: dotnet run -- [PATH]
PATH must point to an existing, readable file
""");
}
catch (FileNotFoundException)
{
Console.Error.WriteLine("Error: File not found");
}
catch (Exception exception)
{
Console.Error.WriteLine(
"""
Error: Internal Exception.
This should not happen. Please file a GitHub issue with the stack trace attached:
""");
Console.Error.WriteLine(exception);
}
}

private static string LoadPathFromArgs()
{
var args = Environment.GetCommandLineArgs();
if (
args is not { Length: 2 }
|| args is not [_, var path]
|| string.IsNullOrWhiteSpace(path)
)
{
throw new InvalidProgramCallException();
}

return Path.GetFullPath(path);
}

private static StreamFileTypeProvider GetStreamFileTypeProvider()
{
return new StreamFileTypeProvider(new Mapping());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace MagicBytesValidator.Tests.Http;

public class FormFileTypeProviderTests
public class FindFileTypeForFormFile
{
[Fact]
public void Should_find_by_extension()
Expand All @@ -18,7 +18,7 @@

var sut = new FormFileTypeProvider();

var result = sut.FindFileTypeForFormFile(formFile);

Check warning on line 21 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

Check warning on line 21 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

result.Should().BeOfType<Gif>();
}
Expand All @@ -30,7 +30,7 @@

var sut = new FormFileTypeProvider();

var result = sut.FindFileTypeForFormFile(formFile);

Check warning on line 33 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

Check warning on line 33 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

result.Should().BeOfType<Gif>();
}
Expand All @@ -42,7 +42,7 @@

var sut = new FormFileTypeProvider();

var result = sut.FindFileTypeForFormFile(formFile);

Check warning on line 45 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

Check warning on line 45 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

result.Should().BeNull();
}
Expand All @@ -54,7 +54,7 @@

var sut = new FormFileTypeProvider();

Assert.Throws<MimeTypeMismatchException>(() => sut.FindFileTypeForFormFile(formFile));

Check warning on line 57 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'

Check warning on line 57 in MagicBytesValidator.Tests/Http/FindFileTypeForFormFile.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

'FormFileTypeProvider.FindFileTypeForFormFile(IFormFile)' is obsolete: 'Use FindValidatedType instead.'
}

private static IFormFile ProvideGifFile(string name, string contentType)
Expand Down
116 changes: 116 additions & 0 deletions MagicBytesValidator.Tests/Http/FindValidatedTypeAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using MagicBytesValidator.Exceptions.Http;
using MagicBytesValidator.Formats;
using MagicBytesValidator.Services.Http;
using Microsoft.AspNetCore.Http;
using Xunit;

namespace MagicBytesValidator.Tests.Http;

public class FindValidatedTypeAsync
{
[Fact]
public async Task Should_find_by_extension()
{
var formFile = ProvideGifFile("trp.gif", "image/gif");

var sut = new FormFileTypeProvider();

var result = await sut.FindValidatedTypeAsync(
formFile,
null,
CancellationToken.None
);

result.Should().BeOfType<Gif>();
}

[Fact]
public async Task Should_find_by_content_type()
{
var formFile = ProvideGifFile(string.Empty, "image/gif");

var sut = new FormFileTypeProvider();

var result = await sut.FindValidatedTypeAsync(
formFile,
null,
CancellationToken.None
);

result.Should().BeOfType<Gif>();
}

[Fact]
public async Task Should_return_null_on_not_found()
{
var formFile = ProvideGifFile(string.Empty, "trp/crly");

var sut = new FormFileTypeProvider();

var result = await sut.FindValidatedTypeAsync(
formFile,
null,
CancellationToken.None
);

result.Should().BeNull();
}

[Fact]
public async Task Should_throw_on_type_vs_name_mismatch()
{
var formFile = ProvideGifFile("trp.gif", "image/png");

var sut = new FormFileTypeProvider();

await Assert.ThrowsAsync<MimeTypeMismatchException>(async () =>
await sut.FindValidatedTypeAsync(
formFile,
null,
CancellationToken.None
)
);
}

[Fact]
public async Task Should_throw_on_type_vs_content_mismatch()
{
var formFile = ProvideGifFile("trp.png", "image/png");

var sut = new FormFileTypeProvider();

await Assert.ThrowsAsync<MimeTypeMismatchException>(async () =>
await sut.FindValidatedTypeAsync(
formFile,
null,
CancellationToken.None
)
);
}

private static IFormFile ProvideGifFile(string name, string contentType)
{
var fileTypeGif = new Gif();
var fileContents = fileTypeGif.MagicByteSequences.First().Concat(new byte[] { 0x11, 0x12 }).ToArray();
var fileStream = new MemoryStream(fileContents);

return new FormFile(
new MemoryStream(fileContents.ToArray()),
0,
fileStream.Length,
name,
name
)
{
Headers = new HeaderDictionary
{
{ "Content-Type", contentType }
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

namespace MagicBytesValidator.Tests;

public class RegisterTests
public class MappingRegister
{
private readonly Mapping _mapping = new();

private readonly FileType _trpFileType = new(
private readonly IFileType _trpFileType = new FileTypeWithStartSequences(
new[] { "traperto/trp" },
new[] { "trp" },
new[]
Expand All @@ -29,7 +29,7 @@ public void Should_register_single_filetype()
[Fact]
public void Should_register_list_filetype()
{
var neonJsFileType = new FileType(
var neonJsFileType = new FileTypeWithStartSequences(
new[] { "traperto/niklasschmidt" },
new[] { "nms" },
new[]
Expand All @@ -42,7 +42,7 @@ public void Should_register_list_filetype()
}
);

var kryptobiFileType = new FileType(
var kryptobiFileType = new FileTypeWithStartSequences(
new[] { "traperto/tobiasjanssen" },
new[] { "tjn" },
new[]
Expand All @@ -69,7 +69,7 @@ public void Should_register_assembly_fileTypes()
}
}

public class AssemblyFacade : FileType
public class AssemblyFacade : FileTypeWithStartSequences
{
public AssemblyFacade() : base(
new[] { "facade/trp" },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using FluentAssertions;
using MagicBytesValidator.Formats;
using Xunit;

namespace MagicBytesValidator.Tests.Models;

public class FileTypeWithIncompleteStartSequencesMatches
{
[Fact]
public void Should_match_valid_file()
{
var sut = new Aif();

var testDataOne = new byte[] { 0x46, 0x4F, 0x52, 0x4D, 0x11, 0x12, 0x19, 0x98, 0x41, 0x49, 0x46, 0x46, 0x11 };
var testDataTwo = new byte[] { 0x46, 0x4F, 0x52, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x41, 0x49, 0x46, 0x46, 0x11 };

sut.Matches(testDataOne).Should().BeTrue();
sut.Matches(testDataTwo).Should().BeTrue();
}

[Fact]
public void Should_not_match_invalid_file()
{
var sut = new Aif();

var testData = new byte[] { 0x00, 0x4F, 0x52, 0x4D, 0x00, 0x12, 0x19, 0x98, 0x41, 0x49, 0x46, 0x46, 0x11 };

sut.Matches(testData).Should().BeFalse();
}
}
30 changes: 30 additions & 0 deletions MagicBytesValidator.Tests/Models/ZipMatches.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using FluentAssertions;
using MagicBytesValidator.Formats;
using Xunit;

namespace MagicBytesValidator.Tests.Models;

public class ZipMatches
{
private static readonly byte[] EmptyZipFileContent =
{
0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x84, 0x55, 0x57, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x54, 0x65, 0x73, 0x74, 0x2f, 0x55,
0x54, 0x0d, 0x00, 0x07, 0xf4, 0xe1, 0x33, 0x65, 0xf4, 0xe1, 0x33, 0x65, 0xf7, 0xe1, 0x33, 0x65, 0x75, 0x78,
0x0b, 0x00, 0x01, 0x04, 0xf5, 0x01, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14,
0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x84, 0x55, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed,
0x41, 0x00, 0x00, 0x00, 0x00, 0x54, 0x65, 0x73, 0x74, 0x2f, 0x55, 0x54, 0x0d, 0x00, 0x07, 0xf4, 0xe1, 0x33,
0x65, 0xf4, 0xe1, 0x33, 0x65, 0xf7, 0xe1, 0x33, 0x65, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xf5, 0x01, 0x00,
0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x53, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00
};

[Fact]
public void Should_match_valid_zip()
{
var sut = new Zip();

sut.Matches(EmptyZipFileContent).Should().BeTrue();
}
}
Loading
Loading