Initial commit: Add project files
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
namespace KArtSell.ArchitectureTests;
|
||||
|
||||
public sealed class RepositoryRulesTests
|
||||
{
|
||||
[Fact]
|
||||
public void Prohibited_source_patterns_are_not_introduced()
|
||||
{
|
||||
var repositoryRoot = FindRepositoryRoot();
|
||||
var sourceFiles = Directory.EnumerateFiles(repositoryRoot, "*.cs", SearchOption.AllDirectories)
|
||||
.Where(x => !IsGeneratedOrTestOutput(x))
|
||||
.ToArray();
|
||||
|
||||
AssertNoPattern(sourceFiles, "IGenericRepository", "Generic repository is prohibited.");
|
||||
AssertNoPattern(sourceFiles, "DateTime.Now", "Use IClock and MarketCalendar.");
|
||||
AssertNoPattern(sourceFiles, "DateTime.UtcNow", "Use IClock and MarketCalendar.");
|
||||
AssertNoPattern(sourceFiles, "IServiceProvider.GetService", "Service locator is prohibited.");
|
||||
AssertNoPattern(sourceFiles, "AllowAnonymous()", "Module endpoints cannot be anonymous.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Domain_files_do_not_reference_infrastructure_frameworks()
|
||||
{
|
||||
var root = FindRepositoryRoot();
|
||||
var domainFiles = Directory.EnumerateFiles(
|
||||
Path.Combine(root, "src"),
|
||||
"*.cs",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(path => path.Contains(
|
||||
$"{Path.DirectorySeparatorChar}Domain{Path.DirectorySeparatorChar}",
|
||||
StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
||||
foreach (var prohibited in new[]
|
||||
{
|
||||
"using Dapper", "using Npgsql", "using FastEndpoints", "using Hangfire",
|
||||
"HttpContext", "DbConnection", "IServiceCollection"
|
||||
})
|
||||
{
|
||||
AssertNoPattern(domainFiles, prohibited,
|
||||
$"Domain cannot depend on infrastructure framework: {prohibited}.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sql_does_not_use_select_star_or_unqualified_signal_tables()
|
||||
{
|
||||
var repositoryRoot = FindRepositoryRoot();
|
||||
var files = Directory.EnumerateFiles(repositoryRoot, "*.*", SearchOption.AllDirectories)
|
||||
.Where(x => x.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)
|
||||
|| x.EndsWith(".sql", StringComparison.OrdinalIgnoreCase))
|
||||
.Where(x => !IsGeneratedOrTestOutput(x))
|
||||
.ToArray();
|
||||
|
||||
var selectStar = files.Where(x =>
|
||||
File.ReadAllText(x).Contains("select *", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
Assert.True(selectStar.Length == 0,
|
||||
"SELECT * is prohibited: " + string.Join(", ", selectStar));
|
||||
|
||||
var unqualified = files.Where(x =>
|
||||
{
|
||||
var text = File.ReadAllText(x);
|
||||
return text.Contains(" from signal_decision", StringComparison.OrdinalIgnoreCase)
|
||||
|| text.Contains(" into signal_decision", StringComparison.OrdinalIgnoreCase)
|
||||
|| text.Contains(" from evidence_snapshot", StringComparison.OrdinalIgnoreCase);
|
||||
}).ToArray();
|
||||
Assert.True(unqualified.Length == 0,
|
||||
"SignalEngine SQL must be schema-qualified: " + string.Join(", ", unqualified));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Every_module_endpoint_declares_roles_or_policies()
|
||||
{
|
||||
var root = FindRepositoryRoot();
|
||||
var endpoints = Directory.EnumerateFiles(
|
||||
Path.Combine(root, "src"),
|
||||
"Endpoint.cs",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(path => path.Contains(
|
||||
$"{Path.DirectorySeparatorChar}Modules{Path.DirectorySeparatorChar}",
|
||||
StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
||||
var violations = endpoints.Where(path =>
|
||||
{
|
||||
var text = File.ReadAllText(path);
|
||||
return !text.Contains("Roles(", StringComparison.Ordinal)
|
||||
&& !text.Contains("Policies(", StringComparison.Ordinal);
|
||||
}).ToArray();
|
||||
|
||||
Assert.True(violations.Length == 0,
|
||||
"Every module endpoint must declare Roles or Policies: " + string.Join(", ", violations));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accidental_placeholder_files_are_not_committed()
|
||||
{
|
||||
var root = FindRepositoryRoot();
|
||||
var names = Directory.EnumerateFiles(root, "*", SearchOption.AllDirectories)
|
||||
.Where(path => !IsGeneratedOrTestOutput(path))
|
||||
.Where(path => Path.GetFileName(path).Equals("testfile", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).EndsWith(".tmp", StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
|
||||
Assert.True(names.Length == 0,
|
||||
"Placeholder files are prohibited: " + string.Join(", ", names));
|
||||
}
|
||||
|
||||
private static void AssertNoPattern(IEnumerable<string> files, string pattern, string message)
|
||||
{
|
||||
var violations = files
|
||||
.Where(path => File.ReadAllText(path).Contains(pattern, StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
Assert.True(violations.Length == 0, message + " " + string.Join(", ", violations));
|
||||
}
|
||||
|
||||
private static bool IsGeneratedOrTestOutput(string path)
|
||||
=> path.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}", StringComparison.Ordinal)
|
||||
|| path.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}", StringComparison.Ordinal)
|
||||
|| path.Contains($"{Path.DirectorySeparatorChar}tests{Path.DirectorySeparatorChar}", StringComparison.Ordinal)
|
||||
|| path.Contains($"{Path.DirectorySeparatorChar}attachments{Path.DirectorySeparatorChar}", StringComparison.Ordinal)
|
||||
|| path.Contains($"{Path.DirectorySeparatorChar}research{Path.DirectorySeparatorChar}original{Path.DirectorySeparatorChar}", StringComparison.Ordinal);
|
||||
|
||||
private static string FindRepositoryRoot()
|
||||
{
|
||||
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (directory is not null && !File.Exists(Path.Combine(directory.FullName, "Directory.Build.props")))
|
||||
{
|
||||
directory = directory.Parent;
|
||||
}
|
||||
|
||||
return directory?.FullName
|
||||
?? throw new InvalidOperationException("Repository root not found.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user