Skip to content

Commit

Permalink
Merge pull request #8 from vicheanath/git-repo
Browse files Browse the repository at this point in the history
Add Service Test
  • Loading branch information
vicheanath authored Sep 13, 2024
2 parents 355919a + ebecd06 commit dd4c525
Show file tree
Hide file tree
Showing 10 changed files with 476 additions and 32 deletions.
2 changes: 2 additions & 0 deletions src/SearchBugs.Domain/Git/GitErrors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ public static class GitErrors
public static Error BranchNotFound = new Error("Git.BranchNotFound", "Branch not found.");

public static Error CommitNotFound = new Error("Git.CommitNotFound", "Commit not found.");

public static Error RepositoryNotFound = new Error("Git.RepositoryNotFound", "Repository not found.");
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
<ProjectReference Include="..\SearchBugs.Domain\SearchBugs.Domain.csproj" />
<ProjectReference Include="..\Shared\Shared.csproj" />
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>SearchBugs.Infrastructure.UnitTests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Project>
17 changes: 17 additions & 0 deletions src/SearchBugs.Infrastructure/Services/DataEncryptionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ internal sealed class DataEncryptionService : IDataEncryptionService
{
public string Encrypt(string plainText, string key)
{
if (string.IsNullOrEmpty(plainText))
{
throw new ArgumentNullException(nameof(plainText));
}
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
Expand All @@ -31,6 +39,15 @@ public string Encrypt(string plainText, string key)

public string Decrypt(string cipherText, string key)
{
if (string.IsNullOrEmpty(cipherText))
{
throw new ArgumentNullException(nameof(cipherText));
}

if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
Expand Down
50 changes: 29 additions & 21 deletions src/SearchBugs.Infrastructure/Services/GitHttpService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,22 @@ public GitHttpService(IOptions<GitOptions> gitOptions, IHttpContextAccessor http

public async Task Handle(string repositoryName, CancellationToken cancellationToken = default)
{
var gitPath = Path.Combine(_gitOptions.BasePath, repositoryName);

using var process = new Process();
process.StartInfo = new ProcessStartInfo
try
{
FileName = "git",
Arguments = "http-backend --stateless-rpc --advertise-refs",
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = gitPath,
EnvironmentVariables =
var gitPath = Path.Combine(_gitOptions.BasePath, repositoryName);

using var process = new Process();
process.StartInfo = new ProcessStartInfo
{
FileName = "git",
Arguments = "http-backend --stateless-rpc --advertise-refs",
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = gitPath,
EnvironmentVariables =
{
{ "GIT_HTTP_EXPORT_ALL", "1" },
{ "HTTP_GIT_PROTOCOL", _httpContext.Request.Headers["Git-Protocol"] },
Expand All @@ -51,17 +53,23 @@ public async Task Handle(string repositoryName, CancellationToken cancellationTo
{ "GIT_COMMITTER_NAME", _httpContext.User.Identity?.Name },
{ "GIT_COMMITTER_EMAIL", "TODO: some email" },
},
};
process.Start();
};
process.Start();

var pipeWriter = PipeWriter.Create(process.StandardInput.BaseStream);
await _httpContext.Request.BodyReader.CopyToAsync(pipeWriter, cancellationToken);
var pipeWriter = PipeWriter.Create(process.StandardInput.BaseStream);
await _httpContext.Request.BodyReader.CopyToAsync(pipeWriter, cancellationToken);

var pipeReader = PipeReader.Create(process.StandardOutput.BaseStream);
await ReadResponse(pipeReader, cancellationToken);
var pipeReader = PipeReader.Create(process.StandardOutput.BaseStream);
await ReadResponse(pipeReader, cancellationToken);

await pipeReader.CopyToAsync(_httpContext.Response.BodyWriter, cancellationToken);
await pipeReader.CompleteAsync();
await pipeReader.CopyToAsync(_httpContext.Response.BodyWriter, cancellationToken);
await pipeReader.CompleteAsync();
}
catch (Exception ex)
{
_httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
await _httpContext.Response.WriteAsync(ex.Message);
}
}

private async Task ReadResponse(PipeReader pipeReader, CancellationToken cancellationToken)
Expand Down
15 changes: 8 additions & 7 deletions src/SearchBugs.Infrastructure/Services/GitRepositoryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ public GitRepositoryService(IOptions<GitOptions> gitOptions)
public Result<IEnumerable<GitTreeItem>> ListTree(string commitSha, string repoPath)
{
var _repoPath = Path.Combine(_basePath, repoPath);
using (var repo = new Repository(_basePath))
if (!Directory.Exists(_repoPath)) return Result.Failure<IEnumerable<GitTreeItem>>(GitErrors.RepositoryNotFound);
using (var repo = new Repository(_repoPath))
{
var commit = repo.Lookup<Commit>(commitSha) ?? repo.Head.Tip;
if (commit == null) return Result.Failure<IEnumerable<GitTreeItem>>(GitErrors.InvalidCommitPath);
var tree = commit.Tree;

if (tree == null) return Result.Failure<IEnumerable<GitTreeItem>>(GitErrors.InvalidCommitPath);

return tree.Select(entry => new GitTreeItem
{
Path = entry.Path,
Expand All @@ -36,14 +36,15 @@ public Result<IEnumerable<GitTreeItem>> ListTree(string commitSha, string repoPa
}
}

public Result<string> GetFileContent(string commitSha, string filePath)
public Result<string> GetFileContent(string repoPath, string commitSha, string filePath)
{
var _repoPath = Path.Combine(_basePath, filePath);
var _repoPath = Path.Combine(_basePath, repoPath);
using (var repo = new Repository(_repoPath))
{
var commit = repo.Lookup<Commit>(commitSha) ?? repo.Head.Tip;
var blob = commit[filePath]?.Target as Blob;
var commit = repo.Lookup<Commit>(commitSha);
if (commit == null) return Result.Failure<string>(GitErrors.InvalidCommitPath);

var blob = commit[filePath]?.Target as Blob;
if (blob == null) return Result.Failure<string>(GitErrors.FileNotFound);

return blob.GetContentText();
Expand Down
28 changes: 28 additions & 0 deletions test/SearchBugs.Infrastructure.UnitTests/Data/Options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Microsoft.Extensions.Options;
using SearchBugs.Infrastructure.Options;

namespace SearchBugs.Infrastructure.UnitTests.Data;

public class OptionsTest : IOptions<GitOptions>, IDisposable
{
public GitOptions Value => new GitOptions
{
BasePath = Path.Combine(Directory.GetCurrentDirectory(), "Repositories")
};

public OptionsTest()
{
if (!Directory.Exists(Value.BasePath))
{
Directory.CreateDirectory(Value.BasePath);
}
}

public void Dispose()
{
if (Directory.Exists(Value.BasePath))
{
Directory.Delete(Value.BasePath, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,24 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.12.1" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\SearchBugs.Domain\SearchBugs.Domain.csproj" />
<ProjectReference Include="..\..\src\SearchBugs.Infrastructure\SearchBugs.Infrastructure.csproj" />
<ProjectReference Include="..\..\src\Shared\Shared.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using FluentAssertions;
using SearchBugs.Infrastructure.Services;

namespace SearchBugs.Infrastructure.UnitTests.ServiceTest;

public class DataEncryptionServiceTest
{
[Fact]
public void Encrypt_WhenCalled_ReturnEncryptedString()
{
// Arrange
var service = new DataEncryptionService();
var plainText = "Hello World";
var _32ByteKey = "XdhXLy^{8Pzs~O!Jm*MJLg^NA)4;(44m";

// Act
var encryptedText = service.Encrypt(plainText, _32ByteKey);

// Assert
encryptedText.Should().NotBe(plainText);
encryptedText.Should().NotBeNullOrEmpty();
}

[Fact]
public void Decrypt_WhenCalled_ReturnDecryptedString()
{
// Arrange
var service = new DataEncryptionService();
var plainText = "Hello World";
var _32ByteKey = "XdhXLy^{8Pzs~O!Jm*MJLg^NA)4;(44m";

// Act
var encryptedText = service.Encrypt(plainText, _32ByteKey);
var decryptedText = service.Decrypt(encryptedText, _32ByteKey);

// Assert
decryptedText.Should().Be(plainText);
}

[Fact]
public void Encrypt_WhenPlainTextIsNull_ThrowArgumentNullException()
{
// Arrange
var service = new DataEncryptionService();
var _32ByteKey = "XdhXLy^{8Pzs~O!Jm*MJLg^NA)4;(44m";

// Act
Action act = () => service.Encrypt(null, _32ByteKey);

// Assert
act.Should().Throw<ArgumentNullException>().WithMessage("Value cannot be null. (Parameter 'plainText')");
}


[Fact]
public void Encrypt_WhenKeyIsNull_ThrowArgumentNullException()
{
// Arrange
var service = new DataEncryptionService();
var plainText = "Hello World";

// Act
Action act = () => service.Encrypt(plainText, null);

// Assert
act.Should().Throw<ArgumentNullException>().WithMessage("Value cannot be null. (Parameter 'key')");
}

[Fact]
public void Decrypt_WhenCipherTextIsNull_ThrowArgumentNullException()
{
// Arrange
var service = new DataEncryptionService();
var _32ByteKey = "XdhXLy^{8Pzs~O!Jm*MJLg^NA)4;(44m";

// Act
Action act = () => service.Decrypt(null, _32ByteKey);

// Assert
act.Should().Throw<ArgumentNullException>().WithMessage("Value cannot be null. (Parameter 'cipherText')");
}

[Fact]
public void Decrypt_WhenKeyIsNull_ThrowArgumentNullException()
{
// Arrange
var service = new DataEncryptionService();
var plainText = "Hello World";

// Act
Action act = () => service.Decrypt(plainText, null);

// Assert
act.Should().Throw<ArgumentNullException>().WithMessage("Value cannot be null. (Parameter 'key')");
}
}
Loading

0 comments on commit dd4c525

Please sign in to comment.